]> git.pld-linux.org Git - packages/lighttpd.git/blob - lighttpd-branch.diff
- svn 1173
[packages/lighttpd.git] / lighttpd-branch.diff
1 --- ../lighttpd-1.4.11/NEWS     2006-03-09 19:34:33.000000000 +0200
2 +++ lighttpd-1.4.12/NEWS        2006-07-11 22:07:54.000000000 +0300
3 @@ -3,6 +3,23 @@
4  NEWS
5  ====
6  
7 +- 1.4.12 - 2006-..-..
8 +
9 +  * added handling of Content-Range to PUT requests in mod_webdav
10 +  * added handling of ETag and If-Modified-Since to mod_compress if 
11 +    cache-dir is not set
12 +  * added experimental LOCK support for mod_webdav 
13 +  * added support for X-Sendfile as addition to X-LIGHTTPD-send-file.
14 +    This allows compatibility with mod_xsendfile for apache
15 +    (http://celebnamer.celebworld.ws/stuff/mod_xsendfile/)
16 +  * fixed handling of If-Modified-Since if Etag is not set
17 +  * fixed hanging fastcgi connections
18 +  * fixed stalling SSL POST requests 
19 +  * fixed round-robin load-balancing in mod_proxy
20 +  * TODO: add fail-over to mod-proxy
21 +  * TODO: fix CACHE_HIT/MISS in mod_cml
22 +  * TODO: finish LOCK/UNLOCK in mod_webdav
23 +
24  - 1.4.11 - 2006-03-09
25  
26    * added ability to specify which ip address spawn-fci listens on 
27 --- ../lighttpd-1.4.11/configure.in     2006-03-04 16:32:38.000000000 +0200
28 +++ lighttpd-1.4.12/configure.in        2006-07-15 22:43:22.000000000 +0300
29 @@ -1,7 +1,7 @@
30  #                                               -*- Autoconf -*-
31  # Process this file with autoconf to produce a configure script.
32  AC_PREREQ(2.57)
33 -AC_INIT(lighttpd, 1.4.11, jan@kneschke.de)
34 +AC_INIT(lighttpd, 1.4.12, jan@kneschke.de)
35  AC_CONFIG_SRCDIR([src/server.c])
36  
37  AC_CANONICAL_TARGET
38 @@ -66,7 +66,7 @@
39  AC_TYPE_PID_T
40  AC_TYPE_SIZE_T
41  
42 -AC_CHECK_MEMBER(struct tm.tm_gmtoff,AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm]),,[#include <time.h>])
43 +AC_CHECK_MEMBER(struct tm.tm_gmtoff,[AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm])],,[#include <time.h>])
44  AC_CHECK_TYPES(struct sockaddr_storage,,,[#include <sys/socket.h>])
45  AC_CHECK_TYPES(socklen_t,,,[#include <sys/types.h>
46  #include <sys/socket.h>])
47 @@ -339,6 +339,22 @@
48      AC_DEFINE([HAVE_SQLITE3], [1], [libsqlite3])
49      AC_DEFINE([HAVE_SQLITE3_H], [1], [sqlite3.h])
50   ])
51 +
52 + AC_MSG_CHECKING(for locks in mod_webdav)
53 + AC_ARG_WITH(webdav-locks, AC_HELP_STRING([--with-webdav-locks],[locks in mod_webdav]),
54 + [WITH_WEBDAV_LOCKS=$withval],[WITH_WEBDAV_LOCKS=no])
55 + AC_MSG_RESULT([$WITH_WEBDAV_LOCKS])
56 +
57 + if test "$WITH_WEBDAV_LOCKS" != "no"; then
58 +   AC_CHECK_LIB(uuid, uuid_unparse, [
59 +         AC_CHECK_HEADERS([uuid/uuid.h],[
60 +                 UUID_LIB=-luuid
61 +                 AC_DEFINE([HAVE_UUID], [1], [libuuid])
62 +                AC_DEFINE([HAVE_UUID_H], [1], [uuid/uuid.h is available])
63 +         ])
64 + ])
65 +
66 + fi
67  fi
68  
69  dnl Check for gdbm
70 @@ -381,30 +397,11 @@
71  
72  AC_MSG_RESULT($WITH_LUA)
73  if test "$WITH_LUA" != "no"; then
74 - AC_PATH_PROG(LUACONFIG, lua-config)
75 -
76 - if test x"$LUACONFIG" != x; then
77 -   LUA_CFLAGS=`$LUACONFIG --include`
78 -   LUA_LIBS=`$LUACONFIG --libs --extralibs`
79 + # try pkgconfig
80 + PKG_CHECK_MODULES(LUA, lua >= 5.1, [
81     AC_DEFINE([HAVE_LUA], [1], [liblua])
82     AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
83 - else
84 -   AC_CHECK_LIB(lua, lua_open, [
85 -     AC_CHECK_HEADERS([lua.h],[
86 -       LUA_LIBS="-llua -llualib"
87 -       AC_DEFINE([HAVE_LUA], [1], [liblua])
88 -       AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
89 -     ])
90 -   ])
91 - fi
92 -
93 - if test x"$LUA_LIBS" = x; then
94 -   # try pkgconfig
95 -   PKG_CHECK_MODULES(LUA, lua, [
96 -     AC_DEFINE([HAVE_LUA], [1], [liblua])
97 -     AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
98 -   ])
99 - fi
100 + ])
101  
102   AC_SUBST(LUA_CFLAGS)
103   AC_SUBST(LUA_LIBS)
104 @@ -440,7 +437,7 @@
105  esac
106  
107  AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
108 -                 strdup strerror strstr strtol sendfile  getopt socket \
109 +                 strdup strerror strstr strtol sendfile  getopt socket lstat \
110                   gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
111                   getuid select signal pathconf madvise posix_fadvise posix_madvise \
112                   writev sigaction sendfile64 send_file kqueue port_create localtime_r])
113 @@ -538,7 +535,7 @@
114  AC_OUTPUT
115  
116  
117 -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" 
118 +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" 
119  
120  plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
121  features="regex-conditionals"
122 @@ -642,6 +639,14 @@
123         disable_feature="$disable_feature $features"
124  fi
125  
126 +features="webdav-locks"
127 +if test "x$UUID_LIB" \!= x; then
128 +       enable_feature="$enable_feature $features"
129 +else
130 +       disable_feature="$disable_feature $features"
131 +fi
132 +
133 +
134  ## output
135  
136  $ECHO
137 --- ../lighttpd-1.4.11/cygwin/lighttpd.README   2006-03-07 14:22:19.000000000 +0200
138 +++ lighttpd-1.4.12/cygwin/lighttpd.README      2006-07-11 22:08:04.000000000 +0300
139 @@ -1,114 +1,114 @@
140 -lighttpd\r
141 -------------------------------------------\r
142 -A fast, secure and flexible webserver\r
143 -\r
144 -Runtime requirements:\r
145 -  cygwin-1.5.10 or newer\r
146 -  crypt-1.1 or newer\r
147 -  libbz2_1-1.0.2 or newer\r
148 -  libpcre0-4.5 or newer\r
149 -  openssl-0.9.7d or newer\r
150 -  zlib-1.2.1 or newer\r
151 -\r
152 -Build requirements:\r
153 -  cygwin-1.5.10 or newer\r
154 -  gcc-3.3.1-3 or newer\r
155 -  binutils-20030901-1 or newer\r
156 -  crypt\r
157 -  openssl-devel\r
158 -  openssl\r
159 -  openldap\r
160 -  openldap-devel\r
161 -  zlib\r
162 -  bzip2\r
163 -\r
164 -Canonical homepage:\r
165 -  http://jan.kneschke.de/projects/lighttpd/\r
166 -\r
167 -Canonical download:\r
168 -  http://jan.kneschke.de/projects/lighttpd/download\r
169 -\r
170 -------------------------------------\r
171 -\r
172 -Build instructions:\r
173 -  unpack lighttpd-1.4.11-<REL>-src.tar.bz2\r
174 -    if you use setup to install this src package, it will be\r
175 -        unpacked under /usr/src automatically\r
176 -  cd /usr/src\r
177 -  ./lighttpd-1.4.11-<REL>.sh all\r
178 -\r
179 -This will create:\r
180 -  /usr/src/lighttpd-1.4.11-<REL>.tar.bz2\r
181 -  /usr/src/lighttpd-1.4.11-<REL>-src.tar.bz2\r
182 -\r
183 -Or use './lighttpd-1.4.11-<REL>.sh prep' to get a patched source directory\r
184 -\r
185 --------------------------------------------\r
186 -\r
187 -Files included in the binary distribution:\r
188 -\r
189 -  /etc/lighttpd/lighttpd.conf.default\r
190 -  /usr/lib/cyglightcomp.dll\r
191 -  /usr/lib/lighttpd/mod_access.dll\r
192 -  /usr/lib/lighttpd/mod_accesslog.dll\r
193 -  /usr/lib/lighttpd/mod_auth.dll\r
194 -  /usr/lib/lighttpd/mod_cgi.dll\r
195 -  /usr/lib/lighttpd/mod_compress.dll\r
196 -  /usr/lib/lighttpd/mod_evhost.dll\r
197 -  /usr/lib/lighttpd/mod_expire.dll\r
198 -  /usr/lib/lighttpd/mod_fastcgi.dll\r
199 -  /usr/lib/lighttpd/mod_httptls.dll\r
200 -  /usr/lib/lighttpd/mod_maps.dll\r
201 -  /usr/lib/lighttpd/mod_proxy.dll\r
202 -  /usr/lib/lighttpd/mod_redirect.dll\r
203 -  /usr/lib/lighttpd/mod_rewrite.dll\r
204 -  /usr/lib/lighttpd/mod_rrdtool.dll\r
205 -  /usr/lib/lighttpd/mod_secdownload.dll\r
206 -  /usr/lib/lighttpd/mod_simple_vhost.dll\r
207 -  /usr/lib/lighttpd/mod_ssi.dll\r
208 -  /usr/lib/lighttpd/mod_status.dll\r
209 -  /usr/lib/lighttpd/mod_usertrack.dll\r
210 -  /usr/sbin/lighttpd.exe\r
211 -  /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
212 -  /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
213 -  /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
214 -  /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
215 -  /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
216 -  /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
217 -  /usr/share/doc/lighttpd-1.3.0/compress.txt\r
218 -  /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
219 -  /usr/share/doc/lighttpd-1.3.0/COPYING\r
220 -  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
221 -  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
222 -  /usr/share/doc/lighttpd-1.3.0/features.txt\r
223 -  /usr/share/doc/lighttpd-1.3.0/INSTALL\r
224 -  /usr/share/doc/lighttpd-1.3.0/NEWS\r
225 -  /usr/share/doc/lighttpd-1.3.0/performance.txt\r
226 -  /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
227 -  /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
228 -  /usr/share/doc/lighttpd-1.3.0/README\r
229 -  /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
230 -  /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
231 -  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
232 -  /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
233 -  /usr/share/doc/lighttpd-1.3.0/security.txt\r
234 -  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
235 -  /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
236 -  /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
237 -  /usr/share/doc/lighttpd-1.3.0/state.txt\r
238 -  /usr/share/man/man1/lighttpd.1.gz\r
239 -\r
240 -------------------\r
241 -\r
242 -Port Notes:\r
243 -\r
244 -----------  lighttpd-1.3.1-1 -----------\r
245 -\r
246 -Updated to 1.3.1\r
247 -\r
248 -----------  lighttpd-1.3.0-1 -----------\r
249 -Initial release\r
250 -\r
251 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
252 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
253 -\r
254 +lighttpd
255 +------------------------------------------
256 +A fast, secure and flexible webserver
257 +
258 +Runtime requirements:
259 +  cygwin-1.5.10 or newer
260 +  crypt-1.1 or newer
261 +  libbz2_1-1.0.2 or newer
262 +  libpcre0-4.5 or newer
263 +  openssl-0.9.7d or newer
264 +  zlib-1.2.1 or newer
265 +
266 +Build requirements:
267 +  cygwin-1.5.10 or newer
268 +  gcc-3.3.1-3 or newer
269 +  binutils-20030901-1 or newer
270 +  crypt
271 +  openssl-devel
272 +  openssl
273 +  openldap
274 +  openldap-devel
275 +  zlib
276 +  bzip2
277 +
278 +Canonical homepage:
279 +  http://jan.kneschke.de/projects/lighttpd/
280 +
281 +Canonical download:
282 +  http://jan.kneschke.de/projects/lighttpd/download
283 +
284 +------------------------------------
285 +
286 +Build instructions:
287 +  unpack lighttpd-1.4.12-<REL>-src.tar.bz2
288 +    if you use setup to install this src package, it will be
289 +        unpacked under /usr/src automatically
290 +  cd /usr/src
291 +  ./lighttpd-1.4.12-<REL>.sh all
292 +
293 +This will create:
294 +  /usr/src/lighttpd-1.4.12-<REL>.tar.bz2
295 +  /usr/src/lighttpd-1.4.12-<REL>-src.tar.bz2
296 +
297 +Or use './lighttpd-1.4.12-<REL>.sh prep' to get a patched source directory
298 +
299 +-------------------------------------------
300 +
301 +Files included in the binary distribution:
302 +
303 +  /etc/lighttpd/lighttpd.conf.default
304 +  /usr/lib/cyglightcomp.dll
305 +  /usr/lib/lighttpd/mod_access.dll
306 +  /usr/lib/lighttpd/mod_accesslog.dll
307 +  /usr/lib/lighttpd/mod_auth.dll
308 +  /usr/lib/lighttpd/mod_cgi.dll
309 +  /usr/lib/lighttpd/mod_compress.dll
310 +  /usr/lib/lighttpd/mod_evhost.dll
311 +  /usr/lib/lighttpd/mod_expire.dll
312 +  /usr/lib/lighttpd/mod_fastcgi.dll
313 +  /usr/lib/lighttpd/mod_httptls.dll
314 +  /usr/lib/lighttpd/mod_maps.dll
315 +  /usr/lib/lighttpd/mod_proxy.dll
316 +  /usr/lib/lighttpd/mod_redirect.dll
317 +  /usr/lib/lighttpd/mod_rewrite.dll
318 +  /usr/lib/lighttpd/mod_rrdtool.dll
319 +  /usr/lib/lighttpd/mod_secdownload.dll
320 +  /usr/lib/lighttpd/mod_simple_vhost.dll
321 +  /usr/lib/lighttpd/mod_ssi.dll
322 +  /usr/lib/lighttpd/mod_status.dll
323 +  /usr/lib/lighttpd/mod_usertrack.dll
324 +  /usr/sbin/lighttpd.exe
325 +  /usr/share/doc/Cygwin/lighttpd-1.3.0.README
326 +  /usr/share/doc/lighttpd-1.3.0/accesslog.txt
327 +  /usr/share/doc/lighttpd-1.3.0/authentification.txt
328 +  /usr/share/doc/lighttpd-1.3.0/AUTHORS
329 +  /usr/share/doc/lighttpd-1.3.0/cgi.txt
330 +  /usr/share/doc/lighttpd-1.3.0/ChangeLog
331 +  /usr/share/doc/lighttpd-1.3.0/compress.txt
332 +  /usr/share/doc/lighttpd-1.3.0/configuration.txt
333 +  /usr/share/doc/lighttpd-1.3.0/COPYING
334 +  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
335 +  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
336 +  /usr/share/doc/lighttpd-1.3.0/features.txt
337 +  /usr/share/doc/lighttpd-1.3.0/INSTALL
338 +  /usr/share/doc/lighttpd-1.3.0/NEWS
339 +  /usr/share/doc/lighttpd-1.3.0/performance.txt
340 +  /usr/share/doc/lighttpd-1.3.0/plugins.txt
341 +  /usr/share/doc/lighttpd-1.3.0/proxy.txt
342 +  /usr/share/doc/lighttpd-1.3.0/README
343 +  /usr/share/doc/lighttpd-1.3.0/redirect.txt
344 +  /usr/share/doc/lighttpd-1.3.0/rewrite.txt
345 +  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
346 +  /usr/share/doc/lighttpd-1.3.0/secdownload.txt
347 +  /usr/share/doc/lighttpd-1.3.0/security.txt
348 +  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
349 +  /usr/share/doc/lighttpd-1.3.0/skeleton.txt
350 +  /usr/share/doc/lighttpd-1.3.0/ssi.txt
351 +  /usr/share/doc/lighttpd-1.3.0/state.txt
352 +  /usr/share/man/man1/lighttpd.1.gz
353 +
354 +------------------
355 +
356 +Port Notes:
357 +
358 +----------  lighttpd-1.3.1-1 -----------
359 +
360 +Updated to 1.3.1
361 +
362 +----------  lighttpd-1.3.0-1 -----------
363 +Initial release
364 +
365 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
366 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
367 +
368 --- ../lighttpd-1.4.11/cygwin/lighttpd.README.in        2005-08-11 01:26:59.000000000 +0300
369 +++ lighttpd-1.4.12/cygwin/lighttpd.README.in   2006-07-11 22:07:53.000000000 +0300
370 @@ -1,114 +1,114 @@
371 -lighttpd\r
372 -------------------------------------------\r
373 -A fast, secure and flexible webserver\r
374 -\r
375 -Runtime requirements:\r
376 -  cygwin-1.5.10 or newer\r
377 -  crypt-1.1 or newer\r
378 -  libbz2_1-1.0.2 or newer\r
379 -  libpcre0-4.5 or newer\r
380 -  openssl-0.9.7d or newer\r
381 -  zlib-1.2.1 or newer\r
382 -\r
383 -Build requirements:\r
384 -  cygwin-1.5.10 or newer\r
385 -  gcc-3.3.1-3 or newer\r
386 -  binutils-20030901-1 or newer\r
387 -  crypt\r
388 -  openssl-devel\r
389 -  openssl\r
390 -  openldap\r
391 -  openldap-devel\r
392 -  zlib\r
393 -  bzip2\r
394 -\r
395 -Canonical homepage:\r
396 -  http://jan.kneschke.de/projects/lighttpd/\r
397 -\r
398 -Canonical download:\r
399 -  http://jan.kneschke.de/projects/lighttpd/download\r
400 -\r
401 -------------------------------------\r
402 -\r
403 -Build instructions:\r
404 -  unpack lighttpd-@VERSION@-<REL>-src.tar.bz2\r
405 -    if you use setup to install this src package, it will be\r
406 -        unpacked under /usr/src automatically\r
407 -  cd /usr/src\r
408 -  ./lighttpd-@VERSION@-<REL>.sh all\r
409 -\r
410 -This will create:\r
411 -  /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2\r
412 -  /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2\r
413 -\r
414 -Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory\r
415 -\r
416 --------------------------------------------\r
417 -\r
418 -Files included in the binary distribution:\r
419 -\r
420 -  /etc/lighttpd/lighttpd.conf.default\r
421 -  /usr/lib/cyglightcomp.dll\r
422 -  /usr/lib/lighttpd/mod_access.dll\r
423 -  /usr/lib/lighttpd/mod_accesslog.dll\r
424 -  /usr/lib/lighttpd/mod_auth.dll\r
425 -  /usr/lib/lighttpd/mod_cgi.dll\r
426 -  /usr/lib/lighttpd/mod_compress.dll\r
427 -  /usr/lib/lighttpd/mod_evhost.dll\r
428 -  /usr/lib/lighttpd/mod_expire.dll\r
429 -  /usr/lib/lighttpd/mod_fastcgi.dll\r
430 -  /usr/lib/lighttpd/mod_httptls.dll\r
431 -  /usr/lib/lighttpd/mod_maps.dll\r
432 -  /usr/lib/lighttpd/mod_proxy.dll\r
433 -  /usr/lib/lighttpd/mod_redirect.dll\r
434 -  /usr/lib/lighttpd/mod_rewrite.dll\r
435 -  /usr/lib/lighttpd/mod_rrdtool.dll\r
436 -  /usr/lib/lighttpd/mod_secdownload.dll\r
437 -  /usr/lib/lighttpd/mod_simple_vhost.dll\r
438 -  /usr/lib/lighttpd/mod_ssi.dll\r
439 -  /usr/lib/lighttpd/mod_status.dll\r
440 -  /usr/lib/lighttpd/mod_usertrack.dll\r
441 -  /usr/sbin/lighttpd.exe\r
442 -  /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
443 -  /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
444 -  /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
445 -  /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
446 -  /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
447 -  /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
448 -  /usr/share/doc/lighttpd-1.3.0/compress.txt\r
449 -  /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
450 -  /usr/share/doc/lighttpd-1.3.0/COPYING\r
451 -  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
452 -  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
453 -  /usr/share/doc/lighttpd-1.3.0/features.txt\r
454 -  /usr/share/doc/lighttpd-1.3.0/INSTALL\r
455 -  /usr/share/doc/lighttpd-1.3.0/NEWS\r
456 -  /usr/share/doc/lighttpd-1.3.0/performance.txt\r
457 -  /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
458 -  /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
459 -  /usr/share/doc/lighttpd-1.3.0/README\r
460 -  /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
461 -  /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
462 -  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
463 -  /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
464 -  /usr/share/doc/lighttpd-1.3.0/security.txt\r
465 -  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
466 -  /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
467 -  /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
468 -  /usr/share/doc/lighttpd-1.3.0/state.txt\r
469 -  /usr/share/man/man1/lighttpd.1.gz\r
470 -\r
471 -------------------\r
472 -\r
473 -Port Notes:\r
474 -\r
475 -----------  lighttpd-1.3.1-1 -----------\r
476 -\r
477 -Updated to 1.3.1\r
478 -\r
479 -----------  lighttpd-1.3.0-1 -----------\r
480 -Initial release\r
481 -\r
482 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
483 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
484 -\r
485 +lighttpd
486 +------------------------------------------
487 +A fast, secure and flexible webserver
488 +
489 +Runtime requirements:
490 +  cygwin-1.5.10 or newer
491 +  crypt-1.1 or newer
492 +  libbz2_1-1.0.2 or newer
493 +  libpcre0-4.5 or newer
494 +  openssl-0.9.7d or newer
495 +  zlib-1.2.1 or newer
496 +
497 +Build requirements:
498 +  cygwin-1.5.10 or newer
499 +  gcc-3.3.1-3 or newer
500 +  binutils-20030901-1 or newer
501 +  crypt
502 +  openssl-devel
503 +  openssl
504 +  openldap
505 +  openldap-devel
506 +  zlib
507 +  bzip2
508 +
509 +Canonical homepage:
510 +  http://jan.kneschke.de/projects/lighttpd/
511 +
512 +Canonical download:
513 +  http://jan.kneschke.de/projects/lighttpd/download
514 +
515 +------------------------------------
516 +
517 +Build instructions:
518 +  unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
519 +    if you use setup to install this src package, it will be
520 +        unpacked under /usr/src automatically
521 +  cd /usr/src
522 +  ./lighttpd-@VERSION@-<REL>.sh all
523 +
524 +This will create:
525 +  /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
526 +  /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
527 +
528 +Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
529 +
530 +-------------------------------------------
531 +
532 +Files included in the binary distribution:
533 +
534 +  /etc/lighttpd/lighttpd.conf.default
535 +  /usr/lib/cyglightcomp.dll
536 +  /usr/lib/lighttpd/mod_access.dll
537 +  /usr/lib/lighttpd/mod_accesslog.dll
538 +  /usr/lib/lighttpd/mod_auth.dll
539 +  /usr/lib/lighttpd/mod_cgi.dll
540 +  /usr/lib/lighttpd/mod_compress.dll
541 +  /usr/lib/lighttpd/mod_evhost.dll
542 +  /usr/lib/lighttpd/mod_expire.dll
543 +  /usr/lib/lighttpd/mod_fastcgi.dll
544 +  /usr/lib/lighttpd/mod_httptls.dll
545 +  /usr/lib/lighttpd/mod_maps.dll
546 +  /usr/lib/lighttpd/mod_proxy.dll
547 +  /usr/lib/lighttpd/mod_redirect.dll
548 +  /usr/lib/lighttpd/mod_rewrite.dll
549 +  /usr/lib/lighttpd/mod_rrdtool.dll
550 +  /usr/lib/lighttpd/mod_secdownload.dll
551 +  /usr/lib/lighttpd/mod_simple_vhost.dll
552 +  /usr/lib/lighttpd/mod_ssi.dll
553 +  /usr/lib/lighttpd/mod_status.dll
554 +  /usr/lib/lighttpd/mod_usertrack.dll
555 +  /usr/sbin/lighttpd.exe
556 +  /usr/share/doc/Cygwin/lighttpd-1.3.0.README
557 +  /usr/share/doc/lighttpd-1.3.0/accesslog.txt
558 +  /usr/share/doc/lighttpd-1.3.0/authentification.txt
559 +  /usr/share/doc/lighttpd-1.3.0/AUTHORS
560 +  /usr/share/doc/lighttpd-1.3.0/cgi.txt
561 +  /usr/share/doc/lighttpd-1.3.0/ChangeLog
562 +  /usr/share/doc/lighttpd-1.3.0/compress.txt
563 +  /usr/share/doc/lighttpd-1.3.0/configuration.txt
564 +  /usr/share/doc/lighttpd-1.3.0/COPYING
565 +  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
566 +  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
567 +  /usr/share/doc/lighttpd-1.3.0/features.txt
568 +  /usr/share/doc/lighttpd-1.3.0/INSTALL
569 +  /usr/share/doc/lighttpd-1.3.0/NEWS
570 +  /usr/share/doc/lighttpd-1.3.0/performance.txt
571 +  /usr/share/doc/lighttpd-1.3.0/plugins.txt
572 +  /usr/share/doc/lighttpd-1.3.0/proxy.txt
573 +  /usr/share/doc/lighttpd-1.3.0/README
574 +  /usr/share/doc/lighttpd-1.3.0/redirect.txt
575 +  /usr/share/doc/lighttpd-1.3.0/rewrite.txt
576 +  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
577 +  /usr/share/doc/lighttpd-1.3.0/secdownload.txt
578 +  /usr/share/doc/lighttpd-1.3.0/security.txt
579 +  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
580 +  /usr/share/doc/lighttpd-1.3.0/skeleton.txt
581 +  /usr/share/doc/lighttpd-1.3.0/ssi.txt
582 +  /usr/share/doc/lighttpd-1.3.0/state.txt
583 +  /usr/share/man/man1/lighttpd.1.gz
584 +
585 +------------------
586 +
587 +Port Notes:
588 +
589 +----------  lighttpd-1.3.1-1 -----------
590 +
591 +Updated to 1.3.1
592 +
593 +----------  lighttpd-1.3.0-1 -----------
594 +Initial release
595 +
596 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
597 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
598 +
599 --- ../lighttpd-1.4.11/doc/authentication.txt   2006-01-12 20:34:26.000000000 +0200
600 +++ lighttpd-1.4.12/doc/authentication.txt      2006-07-11 22:07:54.000000000 +0300
601 @@ -7,8 +7,8 @@
602  ----------------
603  
604  :Author: Jan Kneschke
605 -:Date: $Date$
606 -:Revision: $Revision$
607 +:Date: $Date$
608 +:Revision: $Revision$
609  
610  :abstract:
611    The auth module provides ...
612 --- ../lighttpd-1.4.11/doc/compress.txt 2005-08-11 01:26:16.000000000 +0300
613 +++ lighttpd-1.4.12/doc/compress.txt    2006-07-11 22:07:54.000000000 +0300
614 @@ -22,12 +22,38 @@
615  ===========
616  
617  Output compression reduces the network load and can improve the overall
618 -throughput of the webserver. 
619 +throughput of the webserver. All major http-clients support compression by
620 +announcing it in the Accept-Encoding header. This is used to negotiate the 
621 +most suitable compression method. We support deflate, gzip and bzip2.
622  
623 -Only static content is supported up to now.
624 +deflate (RFC1950, RFC1951) and gzip (RFC1952) depend on zlib while bzip2 
625 +depends on libbzip2. bzip2 is only supported by lynx and some other console
626 +text-browsers.
627  
628 -The server negotiates automaticly which compression method is used.
629 -Supported are gzip, deflate, bzip.
630 +Currently we limit to compression support to static files.
631 +
632 +Caching
633 +-------
634 +
635 +mod_compress can stored compressed files on disk to optimized the compression
636 +on a second request away. As soon as compress.cache-dir is set the files are
637 +compressed. 
638 +
639 +The names of the cache files are made of the filename, the compression method
640 +and the etag associated to the file.
641 +
642 +Cleaning the cache is left to the user. A cron job deleting files older than
643 +10 days should do fine.
644 +
645 +Limitations
646 +-----------
647 +
648 +The module limits the compression of files to files larger than 128 Byte and
649 +smaller than 128 MByte.
650 +
651 +The lower limit is set as small files tend to become larger by compressing due
652 +to the compression headers, the upper limit is set to work sensable with
653 +memory and cpu-time.
654  
655  Options
656  =======
657 @@ -47,15 +73,28 @@
658    Default: not set, compress the file for every request
659  
660  compress.filetype
661 -  mimetypes where might get compressed
662 +  mimetypes which might get compressed
663    
664    e.g.: ::
665    
666      compress.filetype           = ("text/plain", "text/html")
667  
668 +  Keep in mind that compressed JavaScript and CSS files are broken in some
669 +  browsers.
670 +
671    Default: not set
672  
673 +compress.max-file-size 
674 +  maximum size of the original file to be compressed kBytes.
675 +
676 +  This is meant to protect the server against DoSing as compressing large
677 +  (let's say 1Gbyte) takes a lot of time and would delay the whole operation
678 +  of the server.
679  
680 +  There is a hard upper limit of 128Mbyte.
681 +
682 +  Default: unlimited (== hard-limit of 128MByte)
683 +  
684  Compressing Dynamic Content
685  ===========================
686  
687 --- ../lighttpd-1.4.11/doc/configuration.txt    2006-03-09 02:10:40.000000000 +0200
688 +++ lighttpd-1.4.12/doc/configuration.txt       2006-07-11 22:07:54.000000000 +0300
689 @@ -7,8 +7,8 @@
690  ------------
691  
692  :Author: Jan Kneschke
693 -:Date: $Date$
694 -:Revision: $Revision$
695 +:Date: $Date$
696 +:Revision: $Revision$
697  
698  :abstract:
699    the layout of the configuration file
700 @@ -511,3 +511,10 @@
701  
702  debug.log-request-handling
703    default: disabled 
704 +
705 +debug.log-condition-handling
706 +  default: disabled 
707 +
708 +debug.log-condition-cache-handling
709 +  for developers only
710 +  default: disabled 
711 --- ../lighttpd-1.4.11/doc/fastcgi.txt  2006-02-16 17:03:52.000000000 +0200
712 +++ lighttpd-1.4.12/doc/fastcgi.txt     2006-07-11 22:07:54.000000000 +0300
713 @@ -144,8 +144,8 @@
714                  PHP can extract PATH_INFO from it (default: disabled)
715    :"disable-time": time to wait before a disabled backend is checked
716                  again
717 -  :"allow-x-send-file": controls if X-LIGHTTPD-send-file headers
718 -                are allowed 
719 +  :"allow-x-send-file": controls if X-LIGHTTPD-send-file and X-Sendfile
720 +                headers are allowed 
721  
722    If bin-path is set:
723  
724 --- ../lighttpd-1.4.11/doc/lighttpd.conf        2006-03-04 14:41:12.000000000 +0200
725 +++ lighttpd-1.4.12/doc/lighttpd.conf   2006-07-11 22:07:54.000000000 +0300
726 @@ -172,10 +172,11 @@
727  #dir-listing.activate       = "enable"
728  
729  ## enable debugging
730 -#debug.log-request-header   = "enable"
731 -#debug.log-response-header  = "enable"
732 -#debug.log-request-handling = "enable"
733 -#debug.log-file-not-found   = "enable"
734 +#debug.log-request-header     = "enable"
735 +#debug.log-response-header    = "enable"
736 +#debug.log-request-handling   = "enable"
737 +#debug.log-file-not-found     = "enable"
738 +#debug.log-condition-handling = "enable"
739  
740  ### only root can use these options
741  #
742 --- ../lighttpd-1.4.11/doc/performance.txt      2006-02-02 13:01:08.000000000 +0200
743 +++ lighttpd-1.4.12/doc/performance.txt 2006-07-11 22:07:54.000000000 +0300
744 @@ -183,6 +183,8 @@
745  
746    server.stat-cache-engine = "fam"   # either fam, simple or disabled
747  
748 +See http://oss.sgi.com/projects/fam/faq.html for information about FAM.
749 +See http://www.gnome.org/~veillard/gamin/overview.html for information about gamin.
750  
751  Platform-Specific Notes
752  =======================
753 --- ../lighttpd-1.4.11/doc/secdownload.txt      2005-12-20 15:58:58.000000000 +0200
754 +++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-11 22:07:54.000000000 +0300
755 @@ -118,7 +118,7 @@
756    $secret = "verysecret";
757    $uri_prefix = "/dl/";
758    
759 -  # filename
760 +  # filename, make sure it's started with a "/" or you'll get 404 in the browser
761    $f = "/secret-file.txt";
762    
763    # current timestamp
764 --- ../lighttpd-1.4.11/lighttpd.spec    2006-03-07 14:22:18.000000000 +0200
765 +++ lighttpd-1.4.12/lighttpd.spec       2006-07-11 22:07:58.000000000 +0300
766 @@ -1,6 +1,6 @@
767  Summary: A fast webserver with minimal memory-footprint (lighttpd)
768  Name: lighttpd
769 -Version: 1.4.11
770 +Version: 1.4.12
771  Release: 1
772  Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
773  Packager: Jan Kneschke <jan@kneschke.de>
774 --- ../lighttpd-1.4.11/openwrt/control  2006-03-07 14:22:19.000000000 +0200
775 +++ lighttpd-1.4.12/openwrt/control     2006-07-11 22:08:05.000000000 +0300
776 @@ -1,8 +1,8 @@
777  Package: lighttpd
778 -Version: 1.4.11
779 +Version: 1.4.12
780  Architecture: mipsel
781  Maintainer: Jan Kneschke <jan@kneschke.de>
782 -Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.11.tar.gz
783 +Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.12.tar.gz
784  Section: net
785  Priority: optional
786  Depends:
787 --- ../lighttpd-1.4.11/openwrt/lighttpd.mk      2006-03-07 14:22:19.000000000 +0200
788 +++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-11 22:08:05.000000000 +0300
789 @@ -10,7 +10,7 @@
790  
791  #  For this example we'll use a fairly simple package that compiles easily
792  #  and has sources available for download at sourceforge
793 -LIGHTTPD=lighttpd-1.4.11
794 +LIGHTTPD=lighttpd-1.4.12
795  LIGHTTPD_TARGET=.built
796  LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
797  LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
798 --- ../lighttpd-1.4.11/src/Makefile.am  2006-03-07 14:20:20.000000000 +0200
799 +++ lighttpd-1.4.12/src/Makefile.am     2006-07-15 22:43:21.000000000 +0300
800 @@ -16,18 +16,24 @@
801  else
802  configparser.y: lemon
803  mod_ssi_exprparser.y: lemon
804 +http_resp_parser.y: lemon
805  
806  configparser.c configparser.h: configparser.y
807         rm -f configparser.h
808 -       $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
809 +       $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
810 +
811 +http_resp_parser.c http_resp_parser.h: http_resp_parser.y
812 +       rm -f http_resp_parser.h
813 +       $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
814  
815  mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y 
816         rm -f mod_ssi_exprparser.h
817 -       $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
818 +       $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
819  endif
820  
821  configfile.c: configparser.h
822  mod_ssi_expr.c: mod_ssi_exprparser.h
823 +http_resp.c: http_resp_parser.h
824  
825  common_src=buffer.c log.c \
826        keyvalue.c chunk.c  \
827 @@ -46,7 +52,7 @@
828        network_write.c network_linux_sendfile.c \
829        network_freebsd_sendfile.c network_writev.c \
830        network_solaris_sendfilev.c network_openssl.c \
831 -      splaytree.c 
832 +      splaytree.c http_resp.c http_resp_parser.c 
833        
834  src = server.c response.c connections.c network.c \
835        configfile.c configparser.c request.c proc_open.c
836 @@ -82,9 +88,9 @@
837  
838  lib_LTLIBRARIES += mod_webdav.la
839  mod_webdav_la_SOURCES = mod_webdav.c
840 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
841 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS) 
842  mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
843 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
844 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
845  
846  lib_LTLIBRARIES += mod_cml.la
847  mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
848 @@ -103,6 +109,11 @@
849  mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
850  mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
851  
852 +lib_LTLIBRARIES += mod_sql_vhost_core.la
853 +mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
854 +mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
855 +mod_sql_vhost_core_la_LIBADD = $(common_libadd)
856 +
857  lib_LTLIBRARIES += mod_cgi.la
858  mod_cgi_la_SOURCES = mod_cgi.c 
859  mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
860 @@ -240,7 +251,8 @@
861        mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
862        configparser.h mod_ssi_exprparser.h \
863        sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
864 -      splaytree.h proc_open.h
865 +      splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h \
866 +      sys-files.h sys-process.h sys-strings.h http_resp_parser.h
867  
868  DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
869  
870 @@ -267,4 +279,4 @@
871  #ajp_SOURCES = ajp.c
872  
873  noinst_HEADERS   = $(hdr)
874 -EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c
875 +EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c http_resp_parser.y
876 --- ../lighttpd-1.4.11/src/array.c      2005-11-18 13:58:32.000000000 +0200
877 +++ lighttpd-1.4.12/src/array.c 2006-07-11 22:07:51.000000000 +0300
878 @@ -11,12 +11,12 @@
879  
880  array *array_init(void) {
881         array *a;
882 -       
883 +
884         a = calloc(1, sizeof(*a));
885         assert(a);
886 -       
887 +
888         a->next_power_of_2 = 1;
889 -       
890 +
891         return a;
892  }
893  
894 @@ -43,29 +43,29 @@
895  void array_free(array *a) {
896         size_t i;
897         if (!a) return;
898 -       
899 +
900         if (!a->is_weakref) {
901                 for (i = 0; i < a->size; i++) {
902                         if (a->data[i]) a->data[i]->free(a->data[i]);
903                 }
904         }
905 -       
906 +
907         if (a->data) free(a->data);
908         if (a->sorted) free(a->sorted);
909 -       
910 +
911         free(a);
912  }
913  
914  void array_reset(array *a) {
915         size_t i;
916         if (!a) return;
917 -       
918 +
919         if (!a->is_weakref) {
920                 for (i = 0; i < a->used; i++) {
921                         a->data[i]->reset(a->data[i]);
922                 }
923         }
924 -       
925 +
926         a->used = 0;
927  }
928  
929 @@ -84,20 +84,20 @@
930  static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
931         int ndx = -1;
932         int i, pos = 0;
933 -       
934 +
935         if (key == NULL) return -1;
936 -       
937 +
938         /* try to find the string */
939         for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
940                 int cmp;
941 -               
942 +
943                 if (pos < 0) {
944                         pos += i;
945                 } else if (pos >= (int)a->used) {
946                         pos -= i;
947                 } else {
948                         cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
949 -                       
950 +
951                         if (cmp == 0) {
952                                 /* found */
953                                 ndx = a->sorted[pos];
954 @@ -110,46 +110,46 @@
955                 }
956                 if (i == 0) break;
957         }
958 -       
959 +
960         if (rndx) *rndx = pos;
961 -       
962 +
963         return ndx;
964  }
965  
966  data_unset *array_get_element(array *a, const char *key) {
967         int ndx;
968 -       
969 +
970         if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
971                 /* found, leave here */
972 -               
973 +
974                 return a->data[ndx];
975 -       } 
976 -       
977 +       }
978 +
979         return NULL;
980  }
981  
982  data_unset *array_get_unused_element(array *a, data_type_t t) {
983         data_unset *ds = NULL;
984 -       
985 +
986         UNUSED(t);
987  
988         if (a->size == 0) return NULL;
989 -       
990 +
991         if (a->used == a->size) return NULL;
992  
993         if (a->data[a->used]) {
994                 ds = a->data[a->used];
995 -               
996 +
997                 a->data[a->used] = NULL;
998         }
999 -       
1000 +
1001         return ds;
1002  }
1003  
1004  /* replace or insert data, return the old one with the same key */
1005  data_unset *array_replace(array *a, data_unset *du) {
1006         int ndx;
1007 -       
1008 +
1009         if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
1010                 array_insert_unique(a, du);
1011                 return NULL;
1012 @@ -164,13 +164,13 @@
1013         int ndx = -1;
1014         int pos = 0;
1015         size_t j;
1016 -       
1017 -       /* generate unique index if neccesary */
1018 +
1019 +       /* generate unique index if necessary */
1020         if (str->key->used == 0 || str->is_index_key) {
1021                 buffer_copy_long(str->key, a->unique_ndx++);
1022                 str->is_index_key = 1;
1023         }
1024 -       
1025 +
1026         /* try to find the string */
1027         if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
1028                 /* found, leave here */
1029 @@ -181,14 +181,14 @@
1030                 }
1031                 return 0;
1032         }
1033 -       
1034 +
1035         /* insert */
1036 -       
1037 +
1038         if (a->used+1 > INT_MAX) {
1039                 /* we can't handle more then INT_MAX entries: see array_get_index() */
1040                 return -1;
1041         }
1042 -       
1043 +
1044         if (a->size == 0) {
1045                 a->size   = 16;
1046                 a->data   = malloc(sizeof(*a->data)     * a->size);
1047 @@ -204,27 +204,27 @@
1048                 assert(a->sorted);
1049                 for (j = a->used; j < a->size; j++) a->data[j] = NULL;
1050         }
1051 -       
1052 +
1053         ndx = (int) a->used;
1054 -       
1055 +
1056         a->data[a->used++] = str;
1057 -       
1058 +
1059         if (pos != ndx &&
1060 -           ((pos < 0) || 
1061 +           ((pos < 0) ||
1062              buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
1063                 pos++;
1064 -       } 
1065 -       
1066 -       /* move everything on step to the right */
1067 +       }
1068 +
1069 +       /* move everything one step to the right */
1070         if (pos != ndx) {
1071                 memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
1072         }
1073 -       
1074 +
1075         /* insert */
1076         a->sorted[pos] = ndx;
1077 -       
1078 +
1079         if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
1080 -       
1081 +
1082         return 0;
1083  }
1084  
1085 @@ -254,7 +254,7 @@
1086         size_t i;
1087         size_t maxlen;
1088         int oneline = 1;
1089 -       
1090 +
1091         if (a->used > 5) {
1092                 oneline = 0;
1093         }
1094 @@ -314,7 +314,7 @@
1095         }
1096         array_print_indent(depth);
1097         fprintf(stderr, ")");
1098 -       
1099 +
1100         return 0;
1101  }
1102  
1103 @@ -323,47 +323,47 @@
1104         array *a;
1105         data_string *ds;
1106         data_count *dc;
1107 -       
1108 +
1109         UNUSED(argc);
1110         UNUSED(argv);
1111  
1112         a = array_init();
1113 -       
1114 +
1115         ds = data_string_init();
1116         buffer_copy_string(ds->key, "abc");
1117         buffer_copy_string(ds->value, "alfrag");
1118 -       
1119 +
1120         array_insert_unique(a, (data_unset *)ds);
1121 -       
1122 +
1123         ds = data_string_init();
1124         buffer_copy_string(ds->key, "abc");
1125         buffer_copy_string(ds->value, "hameplman");
1126 -       
1127 +
1128         array_insert_unique(a, (data_unset *)ds);
1129 -       
1130 +
1131         ds = data_string_init();
1132         buffer_copy_string(ds->key, "123");
1133         buffer_copy_string(ds->value, "alfrag");
1134 -       
1135 +
1136         array_insert_unique(a, (data_unset *)ds);
1137 -       
1138 +
1139         dc = data_count_init();
1140         buffer_copy_string(dc->key, "def");
1141 -       
1142 +
1143         array_insert_unique(a, (data_unset *)dc);
1144 -       
1145 +
1146         dc = data_count_init();
1147         buffer_copy_string(dc->key, "def");
1148 -       
1149 +
1150         array_insert_unique(a, (data_unset *)dc);
1151 -       
1152 +
1153         array_print(a, 0);
1154 -       
1155 +
1156         array_free(a);
1157 -       
1158 +
1159         fprintf(stderr, "%d\n",
1160                buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
1161 -       
1162 +
1163         return 0;
1164  }
1165  #endif
1166 --- ../lighttpd-1.4.11/src/array.h      2005-09-23 21:24:18.000000000 +0300
1167 +++ lighttpd-1.4.12/src/array.h 2006-07-11 22:07:51.000000000 +0300
1168 @@ -16,7 +16,7 @@
1169  #define DATA_UNSET \
1170         data_type_t type; \
1171         buffer *key; \
1172 -       int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
1173 +       int is_index_key; /* 1 if key is an array index (auto-generated keys) */ \
1174         struct data_unset *(*copy)(const struct data_unset *src); \
1175         void (* free)(struct data_unset *p); \
1176         void (* reset)(struct data_unset *p); \
1177 @@ -29,21 +29,21 @@
1178  
1179  typedef struct {
1180         data_unset  **data;
1181 -       
1182 +
1183         size_t *sorted;
1184 -       
1185 +
1186         size_t used;
1187         size_t size;
1188 -       
1189 +
1190         size_t unique_ndx;
1191 -       
1192 +
1193         size_t next_power_of_2;
1194         int is_weakref; /* data is weakref, don't bother the data */
1195  } array;
1196  
1197  typedef struct {
1198         DATA_UNSET;
1199 -       
1200 +
1201         int count;
1202  } data_count;
1203  
1204 @@ -51,7 +51,7 @@
1205  
1206  typedef struct {
1207         DATA_UNSET;
1208 -       
1209 +
1210         buffer *value;
1211  } data_string;
1212  
1213 @@ -60,7 +60,7 @@
1214  
1215  typedef struct {
1216         DATA_UNSET;
1217 -       
1218 +
1219         array *value;
1220  } data_array;
1221  
1222 @@ -74,7 +74,7 @@
1223         COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP
1224  } comp_key_t;
1225  
1226 -/* $HTTP["host"] ==    "incremental.home.kneschke.de" { ... } 
1227 +/* $HTTP["host"] ==    "incremental.home.kneschke.de" { ... }
1228   * for print:   comp_key      op    string
1229   * for compare: comp          cond  string/regex
1230   */
1231 @@ -82,15 +82,15 @@
1232  typedef struct _data_config data_config;
1233  struct _data_config {
1234         DATA_UNSET;
1235 -       
1236 +
1237         array *value;
1238 -       
1239 +
1240         buffer *comp_key;
1241         comp_key_t comp;
1242 -       
1243 +
1244         config_cond_t cond;
1245         buffer *op;
1246 -       
1247 +
1248         int context_ndx; /* more or less like an id */
1249         array *childs;
1250         /* nested */
1251 @@ -98,7 +98,7 @@
1252         /* for chaining only */
1253         data_config *prev;
1254         data_config *next;
1255 -       
1256 +
1257         buffer *string;
1258  #ifdef HAVE_PCRE_H
1259         pcre   *regex;
1260 @@ -110,7 +110,7 @@
1261  
1262  typedef struct {
1263         DATA_UNSET;
1264 -       
1265 +
1266         int value;
1267  } data_integer;
1268  
1269 @@ -120,13 +120,13 @@
1270         DATA_UNSET;
1271  
1272         buffer *host;
1273 -       
1274 +
1275         unsigned short port;
1276  
1277         time_t disable_ts;
1278         int is_disabled;
1279         size_t balance;
1280 -               
1281 +
1282         int usage; /* fair-balancing needs the no. of connections active on this host */
1283         int last_used_ndx; /* round robin */
1284  } data_fastcgi;
1285 --- ../lighttpd-1.4.11/src/base.h       2006-01-11 16:51:04.000000000 +0200
1286 +++ lighttpd-1.4.12/src/base.h  2006-07-15 22:43:21.000000000 +0300
1287 @@ -2,7 +2,6 @@
1288  #define _BASE_H_
1289  
1290  #include <sys/types.h>
1291 -#include <sys/time.h>
1292  #include <sys/stat.h>
1293  
1294  #ifdef HAVE_CONFIG_H
1295 @@ -26,10 +25,9 @@
1296  #include "sys-socket.h"
1297  #include "splaytree.h"
1298  
1299 -
1300  #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
1301  # define USE_OPENSSL
1302 -# include <openssl/ssl.h> 
1303 +# include <openssl/ssl.h>
1304  #endif
1305  
1306  #ifdef HAVE_FAM_H
1307 @@ -40,10 +38,6 @@
1308  # define O_BINARY 0
1309  #endif
1310  
1311 -#ifndef O_LARGEFILE
1312 -# define O_LARGEFILE 0
1313 -#endif
1314 -
1315  #ifndef SIZE_MAX
1316  # ifdef SIZE_T_MAX
1317  #  define SIZE_MAX SIZE_T_MAX
1318 @@ -70,7 +64,8 @@
1319  
1320  /* solaris and NetBSD 1.3.x again */
1321  #if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t))
1322 -# define uint32_t u_int32_t
1323 +/* # define uint32_t u_int32_t */
1324 +typedef unsigned __int32 uint32_t;
1325  #endif
1326  
1327  
1328 @@ -80,24 +75,24 @@
1329  
1330  #include "settings.h"
1331  
1332 -typedef enum { T_CONFIG_UNSET, 
1333 -               T_CONFIG_STRING, 
1334 -               T_CONFIG_SHORT, 
1335 -               T_CONFIG_BOOLEAN, 
1336 -               T_CONFIG_ARRAY, 
1337 -               T_CONFIG_LOCAL, 
1338 +typedef enum { T_CONFIG_UNSET,
1339 +               T_CONFIG_STRING,
1340 +               T_CONFIG_SHORT,
1341 +               T_CONFIG_BOOLEAN,
1342 +               T_CONFIG_ARRAY,
1343 +               T_CONFIG_LOCAL,
1344                 T_CONFIG_DEPRECATED
1345  } config_values_type_t;
1346  
1347 -typedef enum { T_CONFIG_SCOPE_UNSET, 
1348 -               T_CONFIG_SCOPE_SERVER, 
1349 +typedef enum { T_CONFIG_SCOPE_UNSET,
1350 +               T_CONFIG_SCOPE_SERVER,
1351                 T_CONFIG_SCOPE_CONNECTION
1352  } config_scope_type_t;
1353  
1354  typedef struct {
1355         const char *key;
1356         void *destination;
1357 -       
1358 +
1359         config_values_type_t type;
1360         config_scope_type_t scope;
1361  } config_values_t;
1362 @@ -118,18 +113,6 @@
1363         short factor;
1364  } fcgi_connections;
1365  
1366 -
1367 -typedef union {
1368 -#ifdef HAVE_IPV6
1369 -       struct sockaddr_in6 ipv6;
1370 -#endif
1371 -       struct sockaddr_in ipv4;
1372 -#ifdef HAVE_SYS_UN_H
1373 -       struct sockaddr_un un;
1374 -#endif
1375 -       struct sockaddr plain;
1376 -} sock_addr;
1377 -
1378  /* fcgi_response_header contains ... */
1379  #define HTTP_STATUS         BV(0)
1380  #define HTTP_CONNECTION     BV(1)
1381 @@ -142,40 +125,40 @@
1382         /* the request-line */
1383         buffer *request;
1384         buffer *uri;
1385 -       
1386 +
1387         buffer *orig_uri;
1388 -       
1389 +
1390         http_method_t  http_method;
1391         http_version_t http_version;
1392 -       
1393 +
1394         buffer *request_line;
1395 -       
1396 +
1397         /* strings to the header */
1398         buffer *http_host; /* not alloced */
1399         const char   *http_range;
1400         const char   *http_content_type;
1401         const char   *http_if_modified_since;
1402         const char   *http_if_none_match;
1403 -       
1404 +
1405         array  *headers;
1406 -       
1407 +
1408         /* CONTENT */
1409         size_t content_length; /* returned by strtoul() */
1410 -       
1411 +
1412         /* internal representation */
1413         int     accept_encoding;
1414 -       
1415 +
1416         /* internal */
1417         buffer *pathinfo;
1418  } request;
1419  
1420  typedef struct {
1421         off_t   content_length;
1422 -       int     keep_alive;               /* used by  the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */
1423 -       
1424 +       int     keep_alive;               /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
1425 +
1426         array  *headers;
1427 -       
1428 -       enum { 
1429 +
1430 +       enum {
1431                 HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
1432         } transfer_encoding;
1433  } response;
1434 @@ -191,21 +174,21 @@
1435  typedef struct {
1436         buffer *path;
1437         buffer *basedir; /* path = "(basedir)(.*)" */
1438 -       
1439 +
1440         buffer *doc_root; /* path = doc_root + rel_path */
1441         buffer *rel_path;
1442 -       
1443 +
1444         buffer *etag;
1445  } physical;
1446  
1447  typedef struct {
1448         buffer *name;
1449         buffer *etag;
1450 -       
1451 +
1452         struct stat st;
1453 -       
1454 +
1455         time_t stat_ts;
1456 -       
1457 +
1458  #ifdef HAVE_FAM_H
1459         int    dir_version;
1460         int    dir_ndx;
1461 @@ -215,8 +198,8 @@
1462  } stat_cache_entry;
1463  
1464  typedef struct {
1465 -       splay_tree *files; /* the nodes of the tree are stat_cache_entry's */
1466 -       
1467 +       splay_tree *files; /* the nodes of the tree are stat_cache_entries */
1468 +
1469         buffer *dir_name; /* for building the dirname from the filename */
1470  #ifdef HAVE_FAM_H
1471         splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */
1472 @@ -228,7 +211,7 @@
1473  
1474  typedef struct {
1475         array *mimetypes;
1476 -       
1477 +
1478         /* virtual-servers */
1479         buffer *document_root;
1480         buffer *server_name;
1481 @@ -236,7 +219,7 @@
1482         buffer *server_tag;
1483         buffer *dirlist_encoding;
1484         buffer *errorfile_prefix;
1485 -       
1486 +
1487         unsigned short max_keep_alive_requests;
1488         unsigned short max_keep_alive_idle;
1489         unsigned short max_read_idle;
1490 @@ -244,16 +227,17 @@
1491         unsigned short use_xattr;
1492         unsigned short follow_symlink;
1493         unsigned short range_requests;
1494 -       
1495 +
1496         /* debug */
1497 -       
1498 +
1499         unsigned short log_file_not_found;
1500         unsigned short log_request_header;
1501         unsigned short log_request_handling;
1502         unsigned short log_response_header;
1503         unsigned short log_condition_handling;
1504 -       
1505 -       
1506 +       unsigned short log_condition_cache_handling;
1507 +
1508 +
1509         /* server wide */
1510         buffer *ssl_pemfile;
1511         buffer *ssl_ca_file;
1512 @@ -268,22 +252,22 @@
1513         /* configside */
1514         unsigned short global_kbytes_per_second; /*  */
1515  
1516 -       off_t  global_bytes_per_second_cnt; 
1517 +       off_t  global_bytes_per_second_cnt;
1518         /* server-wide traffic-shaper
1519 -        * 
1520 +        *
1521          * each context has the counter which is inited once
1522 -        * a second by the global_kbytes_per_second config-var
1523 +        * per second by the global_kbytes_per_second config-var
1524          *
1525          * as soon as global_kbytes_per_second gets below 0
1526          * the connected conns are "offline" a little bit
1527          *
1528          * the problem:
1529 -        * we somehow have to loose our "we are writable" signal 
1530 +        * we somehow have to lose our "we are writable" signal
1531          * on the way.
1532 -        * 
1533 +        *
1534          */
1535         off_t *global_bytes_per_second_cnt_ptr; /*  */
1536 -       
1537 +
1538  #ifdef USE_OPENSSL
1539         SSL_CTX *ssl_ctx;
1540  #endif
1541 @@ -291,18 +275,18 @@
1542  
1543  /* the order of the items should be the same as they are processed
1544   * read before write as we use this later */
1545 -typedef enum { 
1546 -       CON_STATE_CONNECT, 
1547 -       CON_STATE_REQUEST_START, 
1548 -       CON_STATE_READ, 
1549 -       CON_STATE_REQUEST_END, 
1550 -       CON_STATE_READ_POST, 
1551 -       CON_STATE_HANDLE_REQUEST, 
1552 -       CON_STATE_RESPONSE_START, 
1553 -       CON_STATE_WRITE, 
1554 -       CON_STATE_RESPONSE_END, 
1555 -       CON_STATE_ERROR, 
1556 -       CON_STATE_CLOSE 
1557 +typedef enum {
1558 +       CON_STATE_CONNECT,
1559 +       CON_STATE_REQUEST_START,
1560 +       CON_STATE_READ,
1561 +       CON_STATE_REQUEST_END,
1562 +       CON_STATE_READ_POST,
1563 +       CON_STATE_HANDLE_REQUEST,
1564 +       CON_STATE_RESPONSE_START,
1565 +       CON_STATE_WRITE,
1566 +       CON_STATE_RESPONSE_END,
1567 +       CON_STATE_ERROR,
1568 +       CON_STATE_CLOSE
1569  } connection_state_t;
1570  
1571  typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
1572 @@ -315,88 +299,88 @@
1573  
1574  typedef struct {
1575         connection_state_t state;
1576 -       
1577 +
1578         /* timestamps */
1579         time_t read_idle_ts;
1580         time_t close_timeout_ts;
1581         time_t write_request_ts;
1582 -       
1583 +
1584         time_t connection_start;
1585         time_t request_start;
1586 -       
1587 +
1588         struct timeval start_tv;
1589 -       
1590 +
1591         size_t request_count;        /* number of requests handled in this connection */
1592         size_t loops_per_request;    /* to catch endless loops in a single request
1593 -                                     * 
1594 +                                     *
1595                                       * used by mod_rewrite, mod_fastcgi, ... and others
1596                                       * this is self-protection
1597                                       */
1598 -       
1599 +
1600         int fd;                      /* the FD for this connection */
1601         int fde_ndx;                 /* index for the fdevent-handler */
1602         int ndx;                     /* reverse mapping to server->connection[ndx] */
1603 -       
1604 +
1605         /* fd states */
1606         int is_readable;
1607         int is_writable;
1608 -       
1609 -       int     keep_alive;           /* only request.c can enable it, all other just disable */
1610 -       
1611 +
1612 +       int     keep_alive;           /* only request.c can enable it, all others just disable */
1613 +
1614         int file_started;
1615         int file_finished;
1616 -       
1617 +
1618         chunkqueue *write_queue;      /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
1619         chunkqueue *read_queue;       /* a small queue for low-level read ( HTTP request ) [ mem ] */
1620         chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/
1621 -       
1622 +
1623         int traffic_limit_reached;
1624 -       
1625 +
1626         off_t bytes_written;          /* used by mod_accesslog, mod_rrd */
1627         off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */
1628         off_t bytes_read;             /* used by mod_accesslog, mod_rrd */
1629         off_t bytes_header;
1630 -       
1631 +
1632         int http_status;
1633 -       
1634 +
1635         sock_addr dst_addr;
1636         buffer *dst_addr_buf;
1637  
1638         /* request */
1639         buffer *parse_request;
1640         unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */
1641 -       
1642 +
1643         request  request;
1644         request_uri uri;
1645 -       physical physical; 
1646 +       physical physical;
1647         response response;
1648 -       
1649 +
1650         size_t header_len;
1651 -       
1652 +
1653         buffer *authed_user;
1654         array  *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
1655 -       
1656 +
1657         /* response */
1658         int    got_response;
1659 -       
1660 +
1661         int    in_joblist;
1662 -       
1663 +
1664         connection_type mode;
1665 -       
1666 +
1667         void **plugin_ctx;           /* plugin connection specific config */
1668 -       
1669 +
1670         specific_config conf;        /* global connection specific config */
1671         cond_cache_t *cond_cache;
1672 -       
1673 +
1674         buffer *server_name;
1675 -       
1676 +
1677         /* error-handler */
1678         buffer *error_handler;
1679         int error_handler_saved_status;
1680         int in_error_handler;
1681 -       
1682 +
1683         void *srv_socket;   /* reference to the server-socket (typecast to server_socket) */
1684 -       
1685 +
1686  #ifdef USE_OPENSSL
1687         SSL *ssl;
1688  #endif
1689 @@ -439,39 +423,48 @@
1690         size_t size;
1691  } buffer_plugin;
1692  
1693 +typedef enum {
1694 +    NETWORK_STATUS_UNSET,
1695 +    NETWORK_STATUS_SUCCESS,
1696 +    NETWORK_STATUS_FATAL_ERROR,
1697 +    NETWORK_STATUS_CONNECTION_CLOSE,
1698 +    NETWORK_STATUS_WAIT_FOR_EVENT,
1699 +    NETWORK_STATUS_INTERRUPTED
1700 +} network_status_t;
1701 +
1702  typedef struct {
1703         unsigned short port;
1704         buffer *bindhost;
1705 -       
1706 +
1707         buffer *errorlog_file;
1708         unsigned short errorlog_use_syslog;
1709 -       
1710 +
1711         unsigned short dont_daemonize;
1712         buffer *changeroot;
1713         buffer *username;
1714         buffer *groupname;
1715 -       
1716 +
1717         buffer *pid_file;
1718 -       
1719 +
1720         buffer *event_handler;
1721 -       
1722 +
1723         buffer *modules_dir;
1724         buffer *network_backend;
1725         array *modules;
1726         array *upload_tempdirs;
1727 -       
1728 +
1729         unsigned short max_worker;
1730         unsigned short max_fds;
1731         unsigned short max_conns;
1732         unsigned short max_request_size;
1733 -       
1734 +
1735         unsigned short log_request_header_on_error;
1736         unsigned short log_state_handling;
1737 -       
1738 -       enum { STAT_CACHE_ENGINE_UNSET, 
1739 -                       STAT_CACHE_ENGINE_NONE, 
1740 -                       STAT_CACHE_ENGINE_SIMPLE, 
1741 -                       STAT_CACHE_ENGINE_FAM 
1742 +
1743 +       enum { STAT_CACHE_ENGINE_UNSET,
1744 +                       STAT_CACHE_ENGINE_NONE,
1745 +                       STAT_CACHE_ENGINE_SIMPLE,
1746 +                       STAT_CACHE_ENGINE_FAM
1747         } stat_cache_engine;
1748         unsigned short enable_cores;
1749  } server_config;
1750 @@ -480,14 +473,14 @@
1751         sock_addr addr;
1752         int       fd;
1753         int       fde_ndx;
1754 -       
1755 +
1756         buffer *ssl_pemfile;
1757         buffer *ssl_ca_file;
1758         unsigned short use_ipv6;
1759         unsigned short is_ssl;
1760 -       
1761 +
1762         buffer *srv_token;
1763 -       
1764 +
1765  #ifdef USE_OPENSSL
1766         SSL_CTX *ssl_ctx;
1767  #endif
1768 @@ -495,37 +488,37 @@
1769  
1770  typedef struct {
1771         server_socket **ptr;
1772 -       
1773 +
1774         size_t size;
1775         size_t used;
1776  } server_socket_array;
1777  
1778  typedef struct server {
1779         server_socket_array srv_sockets;
1780 -       
1781 +
1782         /* the errorlog */
1783         int errorlog_fd;
1784         enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
1785         buffer *errorlog_buf;
1786 -       
1787 +
1788         fdevents *ev, *ev_ins;
1789 -       
1790 +
1791         buffer_plugin plugins;
1792         void *plugin_slots;
1793 -       
1794 +
1795         /* counters */
1796         int con_opened;
1797         int con_read;
1798         int con_written;
1799         int con_closed;
1800 -       
1801 +
1802         int ssl_is_init;
1803 -       
1804 +
1805         int max_fds;    /* max possible fds */
1806         int cur_fds;    /* currently used fds */
1807         int want_fds;   /* waiting fds */
1808         int sockets_disabled;
1809 -       
1810 +
1811         size_t max_conns;
1812  
1813         /* buffers */
1814 @@ -533,13 +526,13 @@
1815         buffer *response_header;
1816         buffer *response_range;
1817         buffer *tmp_buf;
1818 -       
1819 +
1820         buffer *tmp_chunk_len;
1821 -       
1822 +
1823         buffer *empty_string; /* is necessary for cond_match */
1824  
1825         buffer *cond_check_buf;
1826 -       
1827 +
1828         /* caches */
1829  #ifdef HAVE_IPV6
1830         inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
1831 @@ -547,31 +540,31 @@
1832         mtime_cache_type mtime_cache[FILE_CACHE_MAX];
1833  
1834         array *split_vals;
1835 -       
1836 +
1837         /* Timestamps */
1838         time_t cur_ts;
1839         time_t last_generated_date_ts;
1840         time_t last_generated_debug_ts;
1841         time_t startup_ts;
1842 -       
1843 +
1844         buffer *ts_debug_str;
1845         buffer *ts_date_str;
1846 -       
1847 +
1848         /* config-file */
1849         array *config;
1850         array *config_touched;
1851 -       
1852 +
1853         array *config_context;
1854         specific_config **config_storage;
1855 -       
1856 +
1857         server_config  srvconf;
1858 -       
1859 +
1860         int config_deprecated;
1861 -       
1862 +
1863         connections *conns;
1864         connections *joblist;
1865         connections *fdwaitqueue;
1866 -       
1867 +
1868         stat_cache  *stat_cache;
1869  
1870         /**
1871 @@ -588,18 +581,20 @@
1872          *   fastcgi.backend.<key>.disconnects = ...
1873          */
1874         array *status;
1875 -       
1876 +
1877         fdevent_handler_t event_handler;
1878  
1879 -       int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1880 -       int (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1881 +       network_status_t (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1882 +       network_status_t (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1883  #ifdef USE_OPENSSL
1884 -       int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
1885 -       int (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
1886 +       network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
1887 +       network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
1888  #endif
1889  
1890 +#ifdef HAVE_PWD_H
1891         uid_t uid;
1892         gid_t gid;
1893 +#endif
1894  } server;
1895  
1896  
1897 --- ../lighttpd-1.4.11/src/buffer.c     2006-01-13 00:00:45.000000000 +0200
1898 +++ lighttpd-1.4.12/src/buffer.c        2006-07-11 22:07:52.000000000 +0300
1899 @@ -12,20 +12,20 @@
1900  
1901  
1902  /**
1903 - * init the buffer 
1904 - * 
1905 + * init the buffer
1906 + *
1907   */
1908  
1909  buffer* buffer_init(void) {
1910         buffer *b;
1911 -       
1912 +
1913         b = malloc(sizeof(*b));
1914         assert(b);
1915 -       
1916 +
1917         b->ptr = NULL;
1918         b->size = 0;
1919         b->used = 0;
1920 -       
1921 +
1922         return b;
1923  }
1924  
1925 @@ -36,8 +36,8 @@
1926  }
1927  
1928  /**
1929 - * free the buffer 
1930 - * 
1931 + * free the buffer
1932 + *
1933   */
1934  
1935  void buffer_free(buffer *b) {
1936 @@ -49,39 +49,39 @@
1937  
1938  void buffer_reset(buffer *b) {
1939         if (!b) return;
1940 -       
1941 +
1942         /* limit don't reuse buffer larger than ... bytes */
1943         if (b->size > BUFFER_MAX_REUSE_SIZE) {
1944                 free(b->ptr);
1945                 b->ptr = NULL;
1946                 b->size = 0;
1947         }
1948 -       
1949 +
1950         b->used = 0;
1951  }
1952  
1953  
1954  /**
1955 - * 
1956 - * allocate (if neccessary) enough space for 'size' bytes and 
1957 + *
1958 + * allocate (if necessary) enough space for 'size' bytes and
1959   * set the 'used' counter to 0
1960 - * 
1961 + *
1962   */
1963  
1964  #define BUFFER_PIECE_SIZE 64
1965  
1966  int buffer_prepare_copy(buffer *b, size_t size) {
1967         if (!b) return -1;
1968 -       
1969 -       if ((0 == b->size) || 
1970 +
1971 +       if ((0 == b->size) ||
1972             (size > b->size)) {
1973                 if (b->size) free(b->ptr);
1974 -               
1975 +
1976                 b->size = size;
1977 -               
1978 -               /* always allocate a multiply of BUFFER_PIECE_SIZE */
1979 +
1980 +               /* always allocate a multiple of BUFFER_PIECE_SIZE */
1981                 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
1982 -               
1983 +
1984                 b->ptr = malloc(b->size);
1985                 assert(b->ptr);
1986         }
1987 @@ -90,30 +90,30 @@
1988  }
1989  
1990  /**
1991 - * 
1992 - * increase the internal buffer (if neccessary) to append another 'size' byte
1993 + *
1994 + * increase the internal buffer (if necessary) to append another 'size' byte
1995   * ->used isn't changed
1996 - * 
1997 + *
1998   */
1999  
2000  int buffer_prepare_append(buffer *b, size_t size) {
2001         if (!b) return -1;
2002 -       
2003 +
2004         if (0 == b->size) {
2005                 b->size = size;
2006 -               
2007 -               /* always allocate a multiply of BUFFER_PIECE_SIZE */
2008 +
2009 +               /* always allocate a multiple of BUFFER_PIECE_SIZE */
2010                 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2011 -               
2012 +
2013                 b->ptr = malloc(b->size);
2014                 b->used = 0;
2015                 assert(b->ptr);
2016         } else if (b->used + size > b->size) {
2017                 b->size += size;
2018 -               
2019 -               /* always allocate a multiply of BUFFER_PIECE_SIZE */
2020 +
2021 +               /* always allocate a multiple of BUFFER_PIECE_SIZE */
2022                 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2023 -               
2024 +
2025                 b->ptr = realloc(b->ptr, b->size);
2026                 assert(b->ptr);
2027         }
2028 @@ -122,7 +122,7 @@
2029  
2030  int buffer_copy_string(buffer *b, const char *s) {
2031         size_t s_len;
2032 -       
2033 +
2034         if (!s || !b) return -1;
2035  
2036         s_len = strlen(s) + 1;
2037 @@ -136,26 +136,26 @@
2038  
2039  int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
2040         if (!s || !b) return -1;
2041 -#if 0  
2042 -       /* removed optimization as we have to keep the empty string 
2043 +#if 0
2044 +       /* removed optimization as we have to keep the empty string
2045          * in some cases for the config handling
2046 -        * 
2047 +        *
2048          * url.access-deny = ( "" )
2049          */
2050         if (s_len == 0) return 0;
2051 -#endif 
2052 +#endif
2053         buffer_prepare_copy(b, s_len + 1);
2054 -       
2055 +
2056         memcpy(b->ptr, s, s_len);
2057         b->ptr[s_len] = '\0';
2058         b->used = s_len + 1;
2059 -       
2060 +
2061         return 0;
2062  }
2063  
2064  int buffer_copy_string_buffer(buffer *b, const buffer *src) {
2065         if (!src) return -1;
2066 -       
2067 +
2068         if (src->used == 0) {
2069                 b->used = 0;
2070                 return 0;
2071 @@ -201,10 +201,10 @@
2072  
2073  /**
2074   * append a string to the end of the buffer
2075 - * 
2076 - * the resulting buffer is terminated with a '\0' 
2077 - * s is treated as a un-terminated string (a \0 is handled a normal character)
2078 - * 
2079 + *
2080 + * the resulting buffer is terminated with a '\0'
2081 + * s is treated as an un-terminated string (a \0 is handled as a normal character)
2082 + *
2083   * @param b a buffer
2084   * @param s the string
2085   * @param s_len size of the string (without the terminating \0)
2086 @@ -228,7 +228,7 @@
2087  int buffer_append_string_buffer(buffer *b, const buffer *src) {
2088         if (!src) return -1;
2089         if (src->used == 0) return 0;
2090 -       
2091 +
2092         return buffer_append_string_len(b, src->ptr, src->used - 1);
2093  }
2094  
2095 @@ -245,9 +245,9 @@
2096  
2097  int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
2098         if (!s || !b) return -1;
2099 -       
2100 +
2101         b->used = 0;
2102 -       
2103 +
2104         return buffer_append_memory(b, s, s_len);
2105  }
2106  
2107 @@ -402,46 +402,115 @@
2108  
2109  
2110  /**
2111 - * init the buffer 
2112 - * 
2113 + * init the ptr buffer
2114 + *
2115 + */
2116 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer)
2117 +{
2118 +       buffer_ptr *l = calloc(1, sizeof(buffer_ptr));
2119 +       l->free = freer;
2120 +
2121 +       return l;
2122 +}
2123 +
2124 +/**
2125 + * free the buffer_array
2126 + *
2127 + */
2128 +void buffer_ptr_free(buffer_ptr *l)
2129 +{
2130 +       if (NULL != l) {
2131 +               buffer_ptr_clear(l);
2132 +               free(l);
2133 +       }
2134 +}
2135 +
2136 +void buffer_ptr_clear(buffer_ptr *l)
2137 +{
2138 +       assert(NULL != l);
2139 +
2140 +       if (l->free && l->used) {
2141 +               size_t i;
2142 +               for (i = 0; i < l->used; i ++) {
2143 +                       l->free(l->ptr[i]);
2144 +               }
2145 +       }
2146 +
2147 +       if (l->ptr) {
2148 +               free(l->ptr);
2149 +               l->ptr = NULL;
2150 +       }
2151 +       l->used = 0;
2152 +       l->size = 0;
2153 +}
2154 +
2155 +void buffer_ptr_append(buffer_ptr* l, void *item)
2156 +{
2157 +       assert(NULL != l);
2158 +       if (l->ptr == NULL) {
2159 +               l->size = 16;
2160 +               l->ptr = (void **)malloc(sizeof(void *) * l->size);
2161 +       }
2162 +       else if (l->used == l->size) {
2163 +               l->size += 16;
2164 +               l->ptr = realloc(l->ptr, sizeof(void *) * l->size);
2165 +       }
2166 +       l->ptr[l->used++] = item;
2167 +}
2168 +
2169 +void *buffer_ptr_pop(buffer_ptr* l)
2170 +{
2171 +       assert(NULL != l && l->used > 0);
2172 +       return l->ptr[--l->used];
2173 +}
2174 +
2175 +void *buffer_ptr_top(buffer_ptr* l)
2176 +{
2177 +       assert(NULL != l && l->used > 0);
2178 +       return l->ptr[l->used-1];
2179 +}
2180 +
2181 +/**
2182 + * init the buffer
2183 + *
2184   */
2185  
2186  buffer_array* buffer_array_init(void) {
2187         buffer_array *b;
2188 -       
2189 +
2190         b = malloc(sizeof(*b));
2191 -       
2192 +
2193         assert(b);
2194         b->ptr = NULL;
2195         b->size = 0;
2196         b->used = 0;
2197 -       
2198 +
2199         return b;
2200  }
2201  
2202  void buffer_array_reset(buffer_array *b) {
2203         size_t i;
2204 -       
2205 +
2206         if (!b) return;
2207 -       
2208 +
2209         /* if they are too large, reduce them */
2210         for (i = 0; i < b->used; i++) {
2211                 buffer_reset(b->ptr[i]);
2212         }
2213 -       
2214 +
2215         b->used = 0;
2216  }
2217  
2218  
2219  /**
2220 - * free the buffer_array 
2221 - * 
2222 + * free the buffer_array
2223 + *
2224   */
2225  
2226  void buffer_array_free(buffer_array *b) {
2227         size_t i;
2228         if (!b) return;
2229 -       
2230 +
2231         for (i = 0; i < b->size; i++) {
2232                 if (b->ptr[i]) buffer_free(b->ptr[i]);
2233         }
2234 @@ -451,7 +520,7 @@
2235  
2236  buffer *buffer_array_append_get_buffer(buffer_array *b) {
2237         size_t i;
2238 -       
2239 +
2240         if (b->size == 0) {
2241                 b->size = 16;
2242                 b->ptr = malloc(sizeof(*b->ptr) * b->size);
2243 @@ -467,13 +536,13 @@
2244                         b->ptr[i] = NULL;
2245                 }
2246         }
2247 -       
2248 +
2249         if (b->ptr[b->used] == NULL) {
2250                 b->ptr[b->used] = buffer_init();
2251         }
2252 -       
2253 +
2254         b->ptr[b->used]->used = 0;
2255 -       
2256 +
2257         return b->ptr[b->used++];
2258  }
2259  
2260 @@ -482,23 +551,23 @@
2261         size_t i;
2262         if (len == 0) return NULL;
2263         if (needle == NULL) return NULL;
2264 -       
2265 +
2266         if (b->used < len) return NULL;
2267 -       
2268 +
2269         for(i = 0; i < b->used - len; i++) {
2270                 if (0 == memcmp(b->ptr + i, needle, len)) {
2271                         return b->ptr + i;
2272                 }
2273         }
2274 -       
2275 +
2276         return NULL;
2277  }
2278  
2279  buffer *buffer_init_string(const char *str) {
2280         buffer *b = buffer_init();
2281 -       
2282 +
2283         buffer_copy_string(b, str);
2284 -       
2285 +
2286         return b;
2287  }
2288  
2289 @@ -507,8 +576,8 @@
2290  }
2291  
2292  /**
2293 - * check if two buffer contain the same data
2294 - * 
2295 + * check if two buffers contain the same data
2296 + *
2297   * HISTORY: this function was pretty much optimized, but didn't handled
2298   * alignment properly.
2299   */
2300 @@ -522,100 +591,100 @@
2301  
2302  int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
2303         buffer b;
2304 -       
2305 +
2306         b.ptr = (char *)s;
2307         b.used = b_len + 1;
2308 -       
2309 +
2310         return buffer_is_equal(a, &b);
2311  }
2312  
2313  /* simple-assumption:
2314 - * 
2315 - * most parts are equal and doing a case conversion needs time
2316 - * 
2317 + *
2318 + * most parts are equal and doing a case conversion takes time
2319 + *
2320   */
2321  int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
2322         size_t ndx = 0, max_ndx;
2323         size_t *al, *bl;
2324         size_t mask = sizeof(*al) - 1;
2325 -       
2326 +
2327         al = (size_t *)a;
2328         bl = (size_t *)b;
2329 -       
2330 -       /* is the alignment correct ? */
2331 +
2332 +       /* is the alignment correct? */
2333         if ( ((size_t)al & mask) == 0 &&
2334              ((size_t)bl & mask) == 0 ) {
2335 -               
2336 +
2337                 max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
2338 -               
2339 +
2340                 for (; ndx < max_ndx; ndx += sizeof(*al)) {
2341                         if (*al != *bl) break;
2342                         al++; bl++;
2343 -                       
2344 +
2345                 }
2346 -               
2347 +
2348         }
2349 -       
2350 +
2351         a = (char *)al;
2352         b = (char *)bl;
2353 -       
2354 +
2355         max_ndx = ((a_len < b_len) ? a_len : b_len);
2356 -       
2357 +
2358         for (; ndx < max_ndx; ndx++) {
2359                 char a1 = *a++, b1 = *b++;
2360 -               
2361 +
2362                 if (a1 != b1) {
2363                         if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z'))
2364                                 a1 |= 32;
2365                         else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z'))
2366                                 b1 |= 32;
2367                         if ((a1 - b1) != 0) return (a1 - b1);
2368 -                       
2369 +
2370                 }
2371         }
2372 -       
2373 +
2374         return 0;
2375  }
2376  
2377  
2378  /**
2379   * check if the rightmost bytes of the string are equal.
2380 - * 
2381 - * 
2382 + *
2383 + *
2384   */
2385  
2386  int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
2387         /* no, len -> equal */
2388         if (len == 0) return 1;
2389 -       
2390 +
2391         /* len > 0, but empty buffers -> not equal */
2392         if (b1->used == 0 || b2->used == 0) return 0;
2393 -       
2394 +
2395         /* buffers too small -> not equal */
2396 -       if (b1->used - 1 < len || b1->used - 1 < len) return 0;
2397 -       
2398 -       if (0 == strncmp(b1->ptr + b1->used - 1 - len, 
2399 +       if (b1->used - 1 < len || b2->used - 1 < len) return 0;
2400 +
2401 +       if (0 == strncmp(b1->ptr + b1->used - 1 - len,
2402                          b2->ptr + b2->used - 1 - len, len)) {
2403                 return 1;
2404         }
2405 -       
2406 +
2407         return 0;
2408  }
2409  
2410  int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
2411         size_t i;
2412 -       
2413 +
2414         /* BO protection */
2415         if (in_len * 2 < in_len) return -1;
2416 -       
2417 +
2418         buffer_prepare_copy(b, in_len * 2 + 1);
2419 -       
2420 +
2421         for (i = 0; i < in_len; i++) {
2422                 b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
2423                 b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
2424         }
2425         b->ptr[b->used++] = '\0';
2426 -       
2427 +
2428         return 0;
2429  }
2430  
2431 @@ -624,7 +693,7 @@
2432         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2433         */
2434         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2435 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2436 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2437         1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1,  /*  20 -  2F space " # $ % & ' + , / */
2438         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,  /*  30 -  3F : ; = ? @ < > */
2439         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2440 @@ -646,7 +715,7 @@
2441         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2442         */
2443         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2444 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2445 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2446         1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,  /*  20 -  2F space " # $ % & ' + , / */
2447         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,  /*  30 -  3F : ; = ? @ < > */
2448         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2449 @@ -668,7 +737,7 @@
2450         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2451         */
2452         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2453 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2454 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2455         0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  20 -  2F & */
2456         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  /*  30 -  3F < > */
2457         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2458 @@ -690,7 +759,7 @@
2459         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2460         */
2461         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2462 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2463 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2464         0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  20 -  2F & */
2465         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  /*  30 -  3F < > */
2466         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2467 @@ -712,12 +781,12 @@
2468         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2469         */
2470         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2471 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2472 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  20 -  2F */ 
2473 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  30 -  3F */ 
2474 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  40 -  4F */ 
2475 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  50 -  5F */ 
2476 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  60 -  6F */ 
2477 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2478 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  20 -  2F */
2479 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  30 -  3F */
2480 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  40 -  4F */
2481 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  50 -  5F */
2482 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  60 -  6F */
2483         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  70 -  7F */
2484         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  80 -  8F */
2485         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  90 -  9F */
2486 @@ -734,13 +803,13 @@
2487         unsigned char *ds, *d;
2488         size_t d_len, ndx;
2489         const char *map = NULL;
2490 -       
2491 +
2492         if (!s || !b) return -1;
2493 -       
2494 +
2495         if (b->ptr[b->used - 1] != '\0') {
2496                 SEGFAULT();
2497         }
2498 -       
2499 +
2500         if (s_len == 0) return 0;
2501  
2502         switch(encoding) {
2503 @@ -760,12 +829,12 @@
2504                 map = encoded_chars_hex;
2505                 break;
2506         case ENCODING_UNSET:
2507 -               break;
2508 +               return buffer_append_string_len(b, s, s_len);
2509         }
2510  
2511         assert(map != NULL);
2512 -       
2513 -       /* count to-be-encoded-characters */
2514 +
2515 +       /* count to-be-encoded characters */
2516         for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2517                 if (map[*ds]) {
2518                         switch(encoding) {
2519 @@ -787,9 +856,9 @@
2520                         d_len ++;
2521                 }
2522         }
2523 -       
2524 +
2525         buffer_prepare_append(b, d_len);
2526 -       
2527 +
2528         for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2529                 if (map[*ds]) {
2530                         switch(encoding) {
2531 @@ -820,16 +889,16 @@
2532                 }
2533         }
2534  
2535 -       /* terminate buffer and calculate new length */ 
2536 +       /* terminate buffer and calculate new length */
2537         b->ptr[b->used + d_len - 1] = '\0';
2538 -       
2539 +
2540         b->used += d_len;
2541  
2542         return 0;
2543  }
2544  
2545  
2546 -/* decodes url-special-chars inplace.
2547 +/* decodes url-special chars in-place.
2548   * replaces non-printable characters with '_'
2549   */
2550  
2551 @@ -854,10 +923,10 @@
2552                                 low = hex2int(*(src + 2));
2553                                 if (low != 0xFF) {
2554                                         high = (high << 4) | low;
2555 -                                       
2556 -                                       /* map control-characters out */        
2557 +
2558 +                                       /* map out control characters */
2559                                         if (high < 32 || high == 127) high = '_';
2560 -                                       
2561 +
2562                                         *dst = high;
2563                                         src += 2;
2564                                 }
2565 @@ -891,7 +960,7 @@
2566   * /abc/./xyz       gets  /abc/xyz
2567   * /abc//xyz        gets  /abc/xyz
2568   *
2569 - * NOTE: src and dest can point to the same buffer, in which case,
2570 + * NOTE: src and dest can point to the same buffer, in which case
2571   *       the operation is performed in-place.
2572   */
2573  
2574 @@ -979,7 +1048,7 @@
2575  
2576  int light_isxdigit(int c) {
2577         if (light_isdigit(c)) return 1;
2578 -       
2579 +
2580         c |= 32;
2581         return (c >= 'a' && c <= 'f');
2582  }
2583 @@ -993,31 +1062,56 @@
2584         return light_isdigit(c) || light_isalpha(c);
2585  }
2586  
2587 +#undef BUFFER_CTYPE_FUNC
2588 +#define BUFFER_CTYPE_FUNC(type) \
2589 +       int buffer_is##type(buffer *b) { \
2590 +               size_t i, len; \
2591 +               if (b->used < 2) return 0; \
2592 +               /* strlen */ \
2593 +               len = b->used - 1; \
2594 +               /* c-string only */ \
2595 +               if (b->ptr[len] != '\0') { \
2596 +                       return 0; \
2597 +               } \
2598 +               /* check on the whole string */ \
2599 +               for (i = 0; i < len; i ++) { \
2600 +                       if (!light_is##type(b->ptr[i])) { \
2601 +                               return 0; \
2602 +                       } \
2603 +               } \
2604 +               return 1; \
2605 +       }
2606 +
2607 +BUFFER_CTYPE_FUNC(digit)
2608 +BUFFER_CTYPE_FUNC(xdigit)
2609 +BUFFER_CTYPE_FUNC(alpha)
2610 +BUFFER_CTYPE_FUNC(alnum)
2611 +
2612  int buffer_to_lower(buffer *b) {
2613         char *c;
2614 -       
2615 +
2616         if (b->used == 0) return 0;
2617 -       
2618 +
2619         for (c = b->ptr; *c; c++) {
2620                 if (*c >= 'A' && *c <= 'Z') {
2621                         *c |= 32;
2622                 }
2623         }
2624 -       
2625 +
2626         return 0;
2627  }
2628  
2629  
2630  int buffer_to_upper(buffer *b) {
2631         char *c;
2632 -       
2633 +
2634         if (b->used == 0) return 0;
2635 -       
2636 +
2637         for (c = b->ptr; *c; c++) {
2638                 if (*c >= 'a' && *c <= 'z') {
2639                         *c &= ~32;
2640                 }
2641         }
2642 -       
2643 +
2644         return 0;
2645  }
2646 --- ../lighttpd-1.4.11/src/buffer.h     2006-01-13 00:00:45.000000000 +0200
2647 +++ lighttpd-1.4.12/src/buffer.h        2006-07-11 22:07:52.000000000 +0300
2648 @@ -12,27 +12,44 @@
2649  
2650  typedef struct {
2651         char *ptr;
2652 -       
2653 +
2654         size_t used;
2655         size_t size;
2656  } buffer;
2657  
2658 +
2659 +typedef void (*buffer_ptr_free_t)(void *p);
2660 +
2661 +typedef struct {
2662 +       void **ptr;
2663 +       size_t size;
2664 +       size_t used;
2665 +       buffer_ptr_free_t free;
2666 +} buffer_ptr;
2667 +
2668  typedef struct {
2669         buffer **ptr;
2670 -       
2671 +
2672         size_t used;
2673         size_t size;
2674  } buffer_array;
2675  
2676  typedef struct {
2677         char *ptr;
2678 -       
2679 -       size_t offset; /* input-pointer */
2680 -       
2681 -       size_t used;   /* output-pointer */
2682 +
2683 +       size_t offset; /* input pointer */
2684 +
2685 +       size_t used;   /* output pointer */
2686         size_t size;
2687  } read_buffer;
2688  
2689 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer);
2690 +void buffer_ptr_free(buffer_ptr *b);
2691 +void buffer_ptr_clear(buffer_ptr *b);
2692 +void buffer_ptr_append(buffer_ptr *b, void *item);
2693 +void *buffer_ptr_pop(buffer_ptr *b);
2694 +void *buffer_ptr_top(buffer_ptr *b);
2695 +
2696  buffer_array* buffer_array_init(void);
2697  void buffer_array_free(buffer_array *b);
2698  void buffer_array_reset(buffer_array *b);
2699 @@ -43,7 +60,7 @@
2700  buffer* buffer_init_string(const char *str);
2701  void buffer_free(buffer *b);
2702  void buffer_reset(buffer *b);
2703 -       
2704 +
2705  int buffer_prepare_copy(buffer *b, size_t size);
2706  int buffer_prepare_append(buffer *b, size_t size);
2707  
2708 @@ -85,9 +102,9 @@
2709  
2710  typedef enum {
2711         ENCODING_UNSET,
2712 -       ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of a href */
2713 -       ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus coding / too as %2F */
2714 -       ENCODING_HTML,    /* & becomes &amp; and so on */
2715 +       ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of an href */
2716 +       ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus encoding "/" as "%2F" */
2717 +       ENCODING_HTML,    /* "&" becomes "&amp;" and so on */
2718         ENCODING_MINIMAL_XML, /* minimal encoding for xml */
2719         ENCODING_HEX      /* encode string as hex */
2720  } buffer_encoding_t;
2721 @@ -111,19 +128,21 @@
2722  int light_isalpha(int c);
2723  int light_isalnum(int c);
2724  
2725 +#define BUFFER_CTYPE_FUNC(type) int buffer_is##type(buffer *b);
2726 +BUFFER_CTYPE_FUNC(digit)
2727 +BUFFER_CTYPE_FUNC(xdigit)
2728 +BUFFER_CTYPE_FUNC(alpha)
2729 +BUFFER_CTYPE_FUNC(alnum)
2730 +
2731  #define BUFFER_APPEND_STRING_CONST(x, y) \
2732         buffer_append_string_len(x, y, sizeof(y) - 1)
2733  
2734  #define BUFFER_COPY_STRING_CONST(x, y) \
2735         buffer_copy_string_len(x, y, sizeof(y) - 1)
2736  
2737 -#define BUFFER_APPEND_SLASH(x) \
2738 -       if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); }
2739 -
2740  #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
2741  #define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0
2742  
2743 -
2744  #define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0)
2745  #define UNUSED(x) ( (void)(x) )
2746  
2747 --- ../lighttpd-1.4.11/src/chunk.c      2005-11-18 15:18:19.000000000 +0200
2748 +++ lighttpd-1.4.12/src/chunk.c 2006-07-11 22:07:51.000000000 +0300
2749 @@ -1,16 +1,14 @@
2750  /**
2751   * the network chunk-API
2752 - * 
2753 - * 
2754 + *
2755 + *
2756   */
2757  
2758  #include <sys/types.h>
2759  #include <sys/stat.h>
2760 -#include <sys/mman.h>
2761  
2762  #include <stdlib.h>
2763  #include <fcntl.h>
2764 -#include <unistd.h>
2765  
2766  #include <stdio.h>
2767  #include <errno.h>
2768 @@ -18,36 +16,39 @@
2769  
2770  #include "chunk.h"
2771  
2772 +#include "sys-mmap.h"
2773 +#include "sys-files.h"
2774 +
2775  chunkqueue *chunkqueue_init(void) {
2776         chunkqueue *cq;
2777 -       
2778 +
2779         cq = calloc(1, sizeof(*cq));
2780 -       
2781 +
2782         cq->first = NULL;
2783         cq->last = NULL;
2784 -       
2785 +
2786         cq->unused = NULL;
2787 -       
2788 +
2789         return cq;
2790  }
2791  
2792  static chunk *chunk_init(void) {
2793         chunk *c;
2794 -       
2795 +
2796         c = calloc(1, sizeof(*c));
2797 -       
2798 +
2799         c->mem = buffer_init();
2800         c->file.name = buffer_init();
2801         c->file.fd = -1;
2802         c->file.mmap.start = MAP_FAILED;
2803         c->next = NULL;
2804 -       
2805 +
2806         return c;
2807  }
2808  
2809  static void chunk_free(chunk *c) {
2810         if (!c) return;
2811 -       
2812 +
2813         buffer_free(c->mem);
2814         buffer_free(c->file.name);
2815  
2816 @@ -56,13 +57,13 @@
2817  
2818  static void chunk_reset(chunk *c) {
2819         if (!c) return;
2820 -       
2821 +
2822         buffer_reset(c->mem);
2823  
2824         if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
2825                 unlink(c->file.name->ptr);
2826         }
2827 -       
2828 +
2829         buffer_reset(c->file.name);
2830  
2831         if (c->file.fd != -1) {
2832 @@ -78,28 +79,28 @@
2833  
2834  void chunkqueue_free(chunkqueue *cq) {
2835         chunk *c, *pc;
2836 -       
2837 +
2838         if (!cq) return;
2839 -       
2840 +
2841         for (c = cq->first; c; ) {
2842                 pc = c;
2843                 c = c->next;
2844                 chunk_free(pc);
2845         }
2846 -       
2847 +
2848         for (c = cq->unused; c; ) {
2849                 pc = c;
2850                 c = c->next;
2851                 chunk_free(pc);
2852         }
2853 -       
2854 +
2855         free(cq);
2856  }
2857  
2858  static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) {
2859         chunk *c;
2860 -       
2861 -       /* check if we have a unused chunk */
2862 +
2863 +       /* check if we have an unused chunk */
2864         if (!cq->unused) {
2865                 c = chunk_init();
2866         } else {
2867 @@ -109,18 +110,18 @@
2868                 c->next = NULL;
2869                 cq->unused_chunks--;
2870         }
2871 -       
2872 +
2873         return c;
2874  }
2875  
2876  static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
2877         c->next = cq->first;
2878         cq->first = c;
2879 -       
2880 +
2881         if (cq->last == NULL) {
2882                 cq->last = c;
2883         }
2884 -       
2885 +
2886         return 0;
2887  }
2888  
2889 @@ -129,19 +130,19 @@
2890                 cq->last->next = c;
2891         }
2892         cq->last = c;
2893 -       
2894 +
2895         if (cq->first == NULL) {
2896                 cq->first = c;
2897         }
2898 -       
2899 +
2900         return 0;
2901  }
2902  
2903  void chunkqueue_reset(chunkqueue *cq) {
2904         chunk *c;
2905         /* move everything to the unused queue */
2906 -       
2907 -       /* mark all read written */ 
2908 +
2909 +       /* mark all read written */
2910         for (c = cq->first; c; c = c->next) {
2911                 switch(c->type) {
2912                 case MEM_CHUNK:
2913 @@ -150,7 +151,7 @@
2914                 case FILE_CHUNK:
2915                         c->offset = c->file.length;
2916                         break;
2917 -               default: 
2918 +               default:
2919                         break;
2920                 }
2921         }
2922 @@ -162,93 +163,93 @@
2923  
2924  int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
2925         chunk *c;
2926 -       
2927 +
2928         if (len == 0) return 0;
2929 -       
2930 +
2931         c = chunkqueue_get_unused_chunk(cq);
2932 -       
2933 +
2934         c->type = FILE_CHUNK;
2935 -       
2936 +
2937         buffer_copy_string_buffer(c->file.name, fn);
2938         c->file.start = offset;
2939         c->file.length = len;
2940         c->offset = 0;
2941 -       
2942 +
2943         chunkqueue_append_chunk(cq, c);
2944 -       
2945 +
2946         return 0;
2947  }
2948  
2949  int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
2950         chunk *c;
2951 -       
2952 +
2953         if (mem->used == 0) return 0;
2954 -       
2955 +
2956         c = chunkqueue_get_unused_chunk(cq);
2957         c->type = MEM_CHUNK;
2958         c->offset = 0;
2959         buffer_copy_string_buffer(c->mem, mem);
2960 -       
2961 +
2962         chunkqueue_append_chunk(cq, c);
2963 -       
2964 +
2965         return 0;
2966  }
2967  
2968  int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
2969         chunk *c;
2970 -       
2971 +
2972         if (mem->used == 0) return 0;
2973 -       
2974 +
2975         c = chunkqueue_get_unused_chunk(cq);
2976         c->type = MEM_CHUNK;
2977         c->offset = 0;
2978         buffer_copy_string_buffer(c->mem, mem);
2979 -       
2980 +
2981         chunkqueue_prepend_chunk(cq, c);
2982 -       
2983 +
2984         return 0;
2985  }
2986  
2987  int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
2988         chunk *c;
2989 -       
2990 +
2991         if (len == 0) return 0;
2992 -       
2993 +
2994         c = chunkqueue_get_unused_chunk(cq);
2995         c->type = MEM_CHUNK;
2996         c->offset = 0;
2997         buffer_copy_string_len(c->mem, mem, len - 1);
2998 -       
2999 +
3000         chunkqueue_append_chunk(cq, c);
3001 -       
3002 +
3003         return 0;
3004  }
3005  
3006  buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
3007         chunk *c;
3008 -       
3009 +
3010         c = chunkqueue_get_unused_chunk(cq);
3011 -       
3012 +
3013         c->type = MEM_CHUNK;
3014         c->offset = 0;
3015         buffer_reset(c->mem);
3016 -       
3017 +
3018         chunkqueue_prepend_chunk(cq, c);
3019 -       
3020 +
3021         return c->mem;
3022  }
3023  
3024  buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
3025         chunk *c;
3026 -       
3027 +
3028         c = chunkqueue_get_unused_chunk(cq);
3029 -       
3030 +
3031         c->type = MEM_CHUNK;
3032         c->offset = 0;
3033         buffer_reset(c->mem);
3034 -       
3035 +
3036         chunkqueue_append_chunk(cq, c);
3037 -       
3038 +
3039         return c->mem;
3040  }
3041  
3042 @@ -263,7 +264,7 @@
3043  chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
3044         chunk *c;
3045         buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
3046 -       
3047 +
3048         c = chunkqueue_get_unused_chunk(cq);
3049  
3050         c->type = FILE_CHUNK;
3051 @@ -273,12 +274,12 @@
3052                 size_t i;
3053  
3054                 /* we have several tempdirs, only if all of them fail we jump out */
3055 -               
3056 +
3057                 for (i = 0; i < cq->tempdirs->used; i++) {
3058                         data_string *ds = (data_string *)cq->tempdirs->data[i];
3059  
3060                         buffer_copy_string_buffer(template, ds->value);
3061 -                       BUFFER_APPEND_SLASH(template);
3062 +                       PATHNAME_APPEND_SLASH(template);
3063                         BUFFER_APPEND_STRING_CONST(template, "lighttpd-upload-XXXXXX");
3064  
3065                         if (-1 != (c->file.fd = mkstemp(template->ptr))) {
3066 @@ -300,7 +301,7 @@
3067         chunkqueue_append_chunk(cq, c);
3068  
3069         buffer_free(template);
3070 -       
3071 +
3072         return c;
3073  }
3074  
3075 @@ -308,7 +309,7 @@
3076  off_t chunkqueue_length(chunkqueue *cq) {
3077         off_t len = 0;
3078         chunk *c;
3079 -       
3080 +
3081         for (c = cq->first; c; c = c->next) {
3082                 switch (c->type) {
3083                 case MEM_CHUNK:
3084 @@ -321,14 +322,14 @@
3085                         break;
3086                 }
3087         }
3088 -       
3089 +
3090         return len;
3091  }
3092  
3093  off_t chunkqueue_written(chunkqueue *cq) {
3094         off_t len = 0;
3095         chunk *c;
3096 -       
3097 +
3098         for (c = cq->first; c; c = c->next) {
3099                 switch (c->type) {
3100                 case MEM_CHUNK:
3101 @@ -339,7 +340,7 @@
3102                         break;
3103                 }
3104         }
3105 -       
3106 +
3107         return len;
3108  }
3109  
3110 @@ -358,9 +359,9 @@
3111                         if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
3112                         break;
3113                 case FILE_CHUNK:
3114 -                       if (c->offset == c->file.length) is_finished = 1; 
3115 +                       if (c->offset == c->file.length) is_finished = 1;
3116                         break;
3117 -               default: 
3118 +               default:
3119                         break;
3120                 }
3121  
3122 --- ../lighttpd-1.4.11/src/chunk.h      2005-11-01 09:32:21.000000000 +0200
3123 +++ lighttpd-1.4.12/src/chunk.h 2006-07-11 22:07:51.000000000 +0300
3124 @@ -6,7 +6,7 @@
3125  
3126  typedef struct chunk {
3127         enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
3128 -       
3129 +
3130         buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
3131  
3132         struct {
3133 @@ -16,28 +16,28 @@
3134                 off_t  length; /* octets to send from the starting offset */
3135  
3136                 int    fd;
3137 -               struct { 
3138 +               struct {
3139                         char   *start; /* the start pointer of the mmap'ed area */
3140                         size_t length; /* size of the mmap'ed area */
3141 -                       off_t  offset; /* start is <n> octet away from the start of the file */
3142 +                       off_t  offset; /* start is <n> octets away from the start of the file */
3143                 } mmap;
3144  
3145 -               int is_temp; /* file is temporary and will be deleted if on cleanup */
3146 +               int is_temp; /* file is temporary and will be deleted on cleanup */
3147         } file;
3148 -       
3149 -       off_t  offset; /* octets sent from this chunk 
3150 -                         the size of the chunk is either 
3151 +
3152 +       off_t  offset; /* octets sent from this chunk
3153 +                         the size of the chunk is either
3154                           - mem-chunk: mem->used - 1
3155                           - file-chunk: file.length
3156                         */
3157 -       
3158 +
3159         struct chunk *next;
3160  } chunk;
3161  
3162  typedef struct {
3163         chunk *first;
3164         chunk *last;
3165 -       
3166 +
3167         chunk *unused;
3168         size_t unused_chunks;
3169  
3170 --- ../lighttpd-1.4.11/src/configfile-glue.c    2006-03-03 20:14:56.000000000 +0200
3171 +++ lighttpd-1.4.12/src/configfile-glue.c       2006-07-11 22:07:51.000000000 +0300
3172 @@ -1,4 +1,5 @@
3173  #include <string.h>
3174 +#include <ctype.h>
3175  
3176  #include "base.h"
3177  #include "buffer.h"
3178 @@ -11,10 +12,10 @@
3179   * are the external interface of lighttpd. The functions
3180   * are used by the server itself and the plugins.
3181   *
3182 - * The main-goal is to have a small library in the end 
3183 - * which is linked against both and which will define 
3184 + * The main-goal is to have a small library in the end
3185 + * which is linked against both and which will define
3186   * the interface itself in the end.
3187 - * 
3188 + *
3189   */
3190  
3191  
3192 @@ -24,56 +25,60 @@
3193  int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
3194         size_t i;
3195         data_unset *du;
3196 -       
3197 +
3198         for (i = 0; cv[i].key; i++) {
3199 -               
3200 +
3201                 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3202                         /* no found */
3203 -                       
3204 +
3205                         continue;
3206                 }
3207 -               
3208 +
3209                 switch (cv[i].type) {
3210                 case T_CONFIG_ARRAY:
3211                         if (du->type == TYPE_ARRAY) {
3212                                 size_t j;
3213                                 data_array *da = (data_array *)du;
3214 -                               
3215 +
3216                                 for (j = 0; j < da->value->used; j++) {
3217                                         if (da->value->data[j]->type == TYPE_STRING) {
3218                                                 data_string *ds = data_string_init();
3219 -                                               
3220 +
3221                                                 buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
3222                                                 if (!da->is_index_key) {
3223                                                         /* the id's were generated automaticly, as we copy now we might have to renumber them
3224 -                                                        * this is used to prepend server.modules by mod_indexfiles as it has to be loaded 
3225 +                                                        * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
3226                                                          * before mod_fastcgi and friends */
3227                                                         buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
3228                                                 }
3229 -                                               
3230 +
3231                                                 array_insert_unique(cv[i].destination, (data_unset *)ds);
3232                                         } else {
3233 -                                               log_error_write(srv, __FILE__, __LINE__, "sssd", 
3234 -                                                               "the key of and array can only be a string or a integer, variable:", 
3235 -                                                               cv[i].key, "type:", da->value->data[j]->type); 
3236 -                                               
3237 +                                               log_error_write(srv, __FILE__, __LINE__, "sssd",
3238 +                                                               "the key of and array can only be a string or a integer, variable:",
3239 +                                                               cv[i].key, "type:", da->value->data[j]->type);
3240 +
3241                                                 return -1;
3242                                         }
3243                                 }
3244                         } else {
3245                                 log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
3246 -                               
3247 +
3248                                 return -1;
3249                         }
3250                         break;
3251                 case T_CONFIG_STRING:
3252                         if (du->type == TYPE_STRING) {
3253                                 data_string *ds = (data_string *)du;
3254 -                               
3255 +
3256                                 buffer_copy_string_buffer(cv[i].destination, ds->value);
3257 +                       } else if (du->type == TYPE_INTEGER) {
3258 +                               data_integer *di = (data_integer *)du;
3259 +
3260 +                               buffer_copy_long(cv[i].destination, di->value);
3261                         } else {
3262                                 log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
3263 -                               
3264 +
3265                                 return -1;
3266                         }
3267                         break;
3268 @@ -81,15 +86,20 @@
3269                         switch(du->type) {
3270                         case TYPE_INTEGER: {
3271                                 data_integer *di = (data_integer *)du;
3272 -                               
3273 +
3274                                 *((unsigned short *)(cv[i].destination)) = di->value;
3275                                 break;
3276                         }
3277                         case TYPE_STRING: {
3278                                 data_string *ds = (data_string *)du;
3279 -                                       
3280 +
3281 +                               if (buffer_isdigit(ds->value)) {
3282 +                                       *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
3283 +                                       break;
3284 +                               }
3285 +
3286                                 log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
3287 -                               
3288 +
3289                                 return -1;
3290                         }
3291                         default:
3292 @@ -100,19 +110,19 @@
3293                 case T_CONFIG_BOOLEAN:
3294                         if (du->type == TYPE_STRING) {
3295                                 data_string *ds = (data_string *)du;
3296 -                               
3297 +
3298                                 if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
3299                                         *((unsigned short *)(cv[i].destination)) = 1;
3300                                 } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
3301                                         *((unsigned short *)(cv[i].destination)) = 0;
3302                                 } else {
3303                                         log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
3304 -                                               
3305 +
3306                                         return -1;
3307                                 }
3308                         } else {
3309                                 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
3310 -                               
3311 +
3312                                 return -1;
3313                         }
3314                         break;
3315 @@ -121,9 +131,9 @@
3316                         break;
3317                 case T_CONFIG_DEPRECATED:
3318                         log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
3319 -                       
3320 +
3321                         srv->config_deprecated = 1;
3322 -                       
3323 +
3324                         break;
3325                 }
3326         }
3327 @@ -133,25 +143,25 @@
3328  int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
3329         size_t i;
3330         data_unset *du;
3331 -       
3332 +
3333         for (i = 0; cv[i].key; i++) {
3334                 data_string *touched;
3335 -               
3336 +
3337                 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3338                         /* no found */
3339 -                       
3340 +
3341                         continue;
3342                 }
3343 -               
3344 +
3345                 /* touched */
3346                 touched = data_string_init();
3347 -               
3348 +
3349                 buffer_copy_string(touched->value, "");
3350                 buffer_copy_string_buffer(touched->key, du->key);
3351 -               
3352 +
3353                 array_insert_unique(srv->config_touched, (data_unset *)touched);
3354         }
3355 -       
3356 +
3357         return config_insert_values_internal(srv, ca, cv);
3358  }
3359  
3360 @@ -191,25 +201,25 @@
3361         }
3362  
3363         /* pass the rules */
3364 -       
3365 +
3366         switch (dc->comp) {
3367         case COMP_HTTP_HOST: {
3368                 char *ck_colon = NULL, *val_colon = NULL;
3369 -               
3370 +
3371                 if (!buffer_is_empty(con->uri.authority)) {
3372 -               
3373 -                       /* 
3374 +
3375 +                       /*
3376                          * append server-port to the HTTP_POST if necessary
3377                          */
3378 -                       
3379 +
3380                         l = con->uri.authority;
3381 -                       
3382 +
3383                         switch(dc->cond) {
3384                         case CONFIG_COND_NE:
3385                         case CONFIG_COND_EQ:
3386                                 ck_colon = strchr(dc->string->ptr, ':');
3387                                 val_colon = strchr(l->ptr, ':');
3388 -                               
3389 +
3390                                 if (ck_colon == val_colon) {
3391                                         /* nothing to do with it */
3392                                         break;
3393 @@ -230,21 +240,21 @@
3394                                 break;
3395                         }
3396                 } else {
3397 -                       l = NULL;
3398 +                       l = srv->empty_string;
3399                 }
3400                 break;
3401         }
3402         case COMP_HTTP_REMOTEIP: {
3403                 char *nm_slash;
3404 -               /* handle remoteip limitations 
3405 -                * 
3406 +               /* handle remoteip limitations
3407 +                *
3408                  * "10.0.0.1" is provided for all comparisions
3409 -                * 
3410 +                *
3411                  * only for == and != we support
3412 -                * 
3413 +                *
3414                  * "10.0.0.1/24"
3415                  */
3416 -               
3417 +
3418                 if ((dc->cond == CONFIG_COND_EQ ||
3419                      dc->cond == CONFIG_COND_NE) &&
3420                     (con->dst_addr.plain.sa_family == AF_INET) &&
3421 @@ -253,41 +263,48 @@
3422                         long nm;
3423                         char *err;
3424                         struct in_addr val_inp;
3425 -                       
3426 +
3427 +                       if (con->conf.log_condition_handling) {
3428 +                               l = srv->empty_string;
3429 +
3430 +                               log_error_write(srv, __FILE__, __LINE__,  "bsbsb", dc->comp_key,
3431 +                                               "(", l, ") compare to", dc->string);
3432 +                       }
3433 +
3434                         if (*(nm_slash+1) == '\0') {
3435                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
3436 -                                       
3437 +
3438                                 return COND_RESULT_FALSE;
3439                         }
3440 -                       
3441 +
3442                         nm_bits = strtol(nm_slash + 1, &err, 10);
3443 -                       
3444 +
3445                         if (*err) {
3446                                 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
3447 -                               
3448 +
3449                                 return COND_RESULT_FALSE;
3450                         }
3451 -                       
3452 +
3453                         /* take IP convert to the native */
3454                         buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
3455 -#ifdef __WIN32                 
3456 +#ifdef _WIN32
3457                         if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
3458                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3459 -                               
3460 +
3461                                 return COND_RESULT_FALSE;
3462                         }
3463  
3464  #else
3465                         if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
3466                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3467 -                               
3468 +
3469                                 return COND_RESULT_FALSE;
3470                         }
3471  #endif
3472 -                       
3473 +
3474                         /* build netmask */
3475                         nm = htonl(~((1 << (32 - nm_bits)) - 1));
3476 -                       
3477 +
3478                         if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
3479                                 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
3480                         } else {
3481 @@ -308,7 +325,7 @@
3482  
3483         case COMP_HTTP_REFERER: {
3484                 data_string *ds;
3485 -               
3486 +
3487                 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
3488                         l = ds->value;
3489                 } else {
3490 @@ -338,7 +355,7 @@
3491         default:
3492                 return COND_RESULT_FALSE;
3493         }
3494 -       
3495 +
3496         if (NULL == l) {
3497                 if (con->conf.log_condition_handling) {
3498                         log_error_write(srv, __FILE__, __LINE__,  "bsbs", dc->comp_key,
3499 @@ -346,10 +363,10 @@
3500                 }
3501                 return COND_RESULT_FALSE;
3502         }
3503 -       
3504 +
3505         if (con->conf.log_condition_handling) {
3506                 log_error_write(srv, __FILE__, __LINE__,  "bsbsb", dc->comp_key,
3507 -                               "(", l, ") compare to ", dc->string);
3508 +                               "(", l, ") compare to", dc->string);
3509         }
3510         switch(dc->cond) {
3511         case CONFIG_COND_NE:
3512 @@ -365,13 +382,13 @@
3513         case CONFIG_COND_MATCH: {
3514                 cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
3515                 int n;
3516 -               
3517 +
3518  #ifndef elementsof
3519  #define elementsof(x) (sizeof(x) / sizeof(x[0]))
3520  #endif
3521                 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
3522                                 cache->matches, elementsof(cache->matches));
3523 -               
3524 +
3525                 cache->patterncount = n;
3526                 if (n > 0) {
3527                         cache->comp_value = l;
3528 @@ -387,7 +404,7 @@
3529                 /* no way */
3530                 break;
3531         }
3532 -       
3533 +
3534         return COND_RESULT_FALSE;
3535  }
3536  
3537 @@ -395,6 +412,9 @@
3538         cond_cache_t *caches = con->cond_cache;
3539  
3540         if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
3541 +               if (con->conf.log_condition_handling) {
3542 +                       log_error_write(srv, __FILE__, __LINE__,  "sds",  "=== start of", dc->context_ndx, "condition block ===");
3543 +               }
3544                 if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
3545                         if (dc->next) {
3546                                 data_config *c;
3547 @@ -409,11 +429,11 @@
3548                 }
3549                 if (con->conf.log_condition_handling) {
3550                         log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3551 -                                       "(uncached) result:",
3552 +                                       "result:",
3553                                         caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3554                 }
3555         } else {
3556 -               if (con->conf.log_condition_handling) {
3557 +               if (con->conf.log_condition_cache_handling) {
3558                         log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3559                                         "(cached) result:",
3560                                         caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3561 @@ -423,9 +443,6 @@
3562  }
3563  
3564  int config_check_cond(server *srv, connection *con, data_config *dc) {
3565 -       if (con->conf.log_condition_handling) {
3566 -               log_error_write(srv, __FILE__, __LINE__,  "s",  "=== start of condition block ===");
3567 -       }
3568         return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
3569  }
3570  
3571 @@ -443,3 +460,85 @@
3572         return 1;
3573  }
3574  
3575 +/* return <0 on error
3576 + * return 0-x if matched (and replaced)
3577 + */
3578 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result)
3579 +{
3580 +#ifdef HAVE_PCRE_H
3581 +       pcre *match;
3582 +       pcre_extra *extra;
3583 +       const char *pattern;
3584 +       size_t pattern_len;
3585 +       int n;
3586 +       size_t i;
3587 +       pcre_keyvalue *kv;
3588 +# define N 10
3589 +       int ovec[N * 3];
3590 +
3591 +       for (i = 0; i < kvb->used; i++) {
3592 +               kv = kvb->kv[i];
3593 +
3594 +               match       = kv->key;
3595 +               extra       = kv->key_extra;
3596 +               pattern     = kv->value->ptr;
3597 +               pattern_len = kv->value->used - 1;
3598 +
3599 +               if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
3600 +                       if (n != PCRE_ERROR_NOMATCH) {
3601 +                               return n;
3602 +                       }
3603 +               } else {
3604 +                       const char **list;
3605 +                       size_t start, end;
3606 +                       size_t k;
3607 +
3608 +                       /* it matched */
3609 +                       pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
3610 +
3611 +                       /* search for $[0-9] */
3612 +
3613 +                       buffer_reset(result);
3614 +
3615 +                       start = 0; end = pattern_len;
3616 +                       for (k = 0; k < pattern_len; k++) {
3617 +                               if ((pattern[k] == '$' || pattern[k] == '%') &&
3618 +                                   isdigit((unsigned char)pattern[k + 1])) {
3619 +                                       /* got one */
3620 +
3621 +                                       size_t num = pattern[k + 1] - '0';
3622 +
3623 +                                       end = k;
3624 +
3625 +                                       buffer_append_string_len(result, pattern + start, end - start);
3626 +
3627 +                                       if (pattern[k] == '$') {
3628 +                                               /* n is always > 0 */
3629 +                                               if (num < (size_t)n) {
3630 +                                                       buffer_append_string(result, list[num]);
3631 +                                               }
3632 +                                       } else {
3633 +                                               config_append_cond_match_buffer(con, context, result, num);
3634 +                                       }
3635 +
3636 +                                       k++;
3637 +                                       start = k + 1;
3638 +                               }
3639 +                       }
3640 +
3641 +                       buffer_append_string_len(result, pattern + start, pattern_len - start);
3642 +
3643 +                       pcre_free(list);
3644 +
3645 +                       return i;
3646 +               }
3647 +       }
3648 +
3649 +       return PCRE_ERROR_NOMATCH;
3650 +#undef N
3651 +#else
3652 +       UNUSED(kvb);
3653 +       return -2;
3654 +#endif
3655 +}
3656 +
3657 --- ../lighttpd-1.4.11/src/configfile.c 2006-02-15 14:26:42.000000000 +0200
3658 +++ lighttpd-1.4.12/src/configfile.c    2006-07-15 22:43:21.000000000 +0300
3659 @@ -2,7 +2,6 @@
3660  
3661  #include <stdlib.h>
3662  #include <fcntl.h>
3663 -#include <unistd.h>
3664  #include <errno.h>
3665  #include <string.h>
3666  #include <stdio.h>
3667 @@ -13,21 +12,24 @@
3668  #include "log.h"
3669  #include "stream.h"
3670  #include "plugin.h"
3671 -#ifdef USE_LICENSE
3672 -#include "license.h"
3673 -#endif
3674 -
3675  #include "configparser.h"
3676  #include "configfile.h"
3677  #include "proc_open.h"
3678  
3679 +#include "sys-files.h"
3680 +#include "sys-process.h"
3681 +
3682 +#ifndef PATH_MAX
3683 +/* win32 */
3684 +#define PATH_MAX 64
3685 +#endif
3686  
3687  static int config_insert(server *srv) {
3688         size_t i;
3689         int ret = 0;
3690         buffer *stat_cache_string;
3691 -       
3692 -       config_values_t cv[] = { 
3693 +
3694 +       config_values_t cv[] = {
3695                 { "server.bind",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 0 */
3696                 { "server.errorlog",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 1 */
3697                 { "server.errorfile-prefix",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 2 */
3698 @@ -38,7 +40,7 @@
3699                 { "server.tag",                  NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 7 */
3700                 { "server.use-ipv6",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
3701                 { "server.modules",              NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER },       /* 9 */
3702 -               
3703 +
3704                 { "server.event-handler",        NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 10 */
3705                 { "server.pid-file",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 11 */
3706                 { "server.max-request-size",     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 12 */
3707 @@ -49,7 +51,7 @@
3708                 { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
3709                 { "server.name",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 18 */
3710                 { "server.max-keep-alive-idle",  NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 19 */
3711 -               
3712 +
3713                 { "server.max-read-idle",        NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 20 */
3714                 { "server.max-write-idle",       NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 21 */
3715                 { "server.error-handler-404",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 22 */
3716 @@ -60,19 +62,19 @@
3717                 { "mimetype.use-xattr",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
3718                 { "mimetype.assign",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },   /* 28 */
3719                 { "ssl.pemfile",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 29 */
3720 -               
3721 +
3722                 { "ssl.engine",                  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 30 */
3723 -               
3724 +
3725                 { "debug.log-file-not-found",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 31 */
3726                 { "debug.log-request-handling",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 32 */
3727                 { "debug.log-response-header",   NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 33 */
3728                 { "debug.log-request-header",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 34 */
3729 -               
3730 +
3731                 { "server.protocol-http11",      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 35 */
3732                 { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
3733                 { "debug.log-state-handling",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 37 */
3734                 { "ssl.ca-file",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 38 */
3735 -               
3736 +
3737                 { "server.errorlog-use-syslog",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 39 */
3738                 { "server.range-requests",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
3739                 { "server.stat-cache-engine",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 41 */
3740 @@ -80,7 +82,8 @@
3741                 { "server.network-backend",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 43 */
3742                 { "server.upload-dirs",          NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },   /* 44 */
3743                 { "server.core-files",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
3744 -               
3745 +               { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },    /* 46 */
3746 +
3747                 { "server.host",                 "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3748                 { "server.docroot",              "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3749                 { "server.virtual-root",         "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3750 @@ -90,11 +93,11 @@
3751                 { "server.groupid",              "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3752                 { "server.use-keep-alive",       "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3753                 { "server.force-lower-case-files",       "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3754 -               
3755 +
3756                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
3757         };
3758  
3759 -       
3760 +
3761         /* 0 */
3762         cv[0].destination = srv->srvconf.bindhost;
3763         cv[1].destination = srv->srvconf.errorlog_file;
3764 @@ -102,33 +105,33 @@
3765         cv[4].destination = srv->srvconf.username;
3766         cv[5].destination = srv->srvconf.groupname;
3767         cv[6].destination = &(srv->srvconf.port);
3768 -       
3769 +
3770         cv[9].destination = srv->srvconf.modules;
3771         cv[10].destination = srv->srvconf.event_handler;
3772         cv[11].destination = srv->srvconf.pid_file;
3773 -       
3774 +
3775         cv[13].destination = &(srv->srvconf.max_worker);
3776         cv[23].destination = &(srv->srvconf.max_fds);
3777         cv[36].destination = &(srv->srvconf.log_request_header_on_error);
3778         cv[37].destination = &(srv->srvconf.log_state_handling);
3779 -       
3780 +
3781         cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
3782 -       
3783 +
3784         stat_cache_string = buffer_init();
3785         cv[41].destination = stat_cache_string;
3786         cv[43].destination = srv->srvconf.network_backend;
3787         cv[44].destination = srv->srvconf.upload_tempdirs;
3788         cv[45].destination = &(srv->srvconf.enable_cores);
3789 -       
3790 +
3791         cv[42].destination = &(srv->srvconf.max_conns);
3792         cv[12].destination = &(srv->srvconf.max_request_size);
3793         srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
3794  
3795         assert(srv->config_storage);
3796 -       
3797 +
3798         for (i = 0; i < srv->config_context->used; i++) {
3799                 specific_config *s;
3800 -               
3801 +
3802                 s = calloc(1, sizeof(specific_config));
3803                 assert(s);
3804                 s->document_root = buffer_init();
3805 @@ -154,17 +157,18 @@
3806                 s->global_kbytes_per_second = 0;
3807                 s->global_bytes_per_second_cnt = 0;
3808                 s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
3809 -               
3810 +
3811                 cv[2].destination = s->errorfile_prefix;
3812 -               
3813 +
3814                 cv[7].destination = s->server_tag;
3815                 cv[8].destination = &(s->use_ipv6);
3816 -               
3817 -               
3818 +
3819 +
3820                 /* 13 max-worker */
3821                 cv[14].destination = s->document_root;
3822                 cv[15].destination = &(s->force_lowercase_filenames);
3823                 cv[16].destination = &(s->log_condition_handling);
3824 +               cv[46].destination = &(s->log_condition_cache_handling);
3825                 cv[17].destination = &(s->max_keep_alive_requests);
3826                 cv[18].destination = s->server_name;
3827                 cv[19].destination = &(s->max_keep_alive_idle);
3828 @@ -179,23 +183,23 @@
3829                 cv[28].destination = s->mimetypes;
3830                 cv[29].destination = s->ssl_pemfile;
3831                 cv[30].destination = &(s->is_ssl);
3832 -               
3833 +
3834                 cv[31].destination = &(s->log_file_not_found);
3835                 cv[32].destination = &(s->log_request_handling);
3836                 cv[33].destination = &(s->log_response_header);
3837                 cv[34].destination = &(s->log_request_header);
3838 -               
3839 +
3840                 cv[35].destination = &(s->allow_http11);
3841                 cv[38].destination = s->ssl_ca_file;
3842                 cv[40].destination = &(s->range_requests);
3843 -               
3844 +
3845                 srv->config_storage[i] = s;
3846 -       
3847 +
3848                 if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
3849                         break;
3850                 }
3851         }
3852 -       
3853 +
3854         if (buffer_is_empty(stat_cache_string)) {
3855                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
3856         } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
3857 @@ -205,22 +209,22 @@
3858         } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
3859                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
3860         } else {
3861 -               log_error_write(srv, __FILE__, __LINE__, "sb", 
3862 +               log_error_write(srv, __FILE__, __LINE__, "sb",
3863                                 "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string);
3864                 ret = HANDLER_ERROR;
3865         }
3866 -       
3867 +
3868         buffer_free(stat_cache_string);
3869 -       
3870 +
3871         return ret;
3872 -                                                                
3873 -}
3874  
3875 +}
3876  
3877 -#define PATCH(x) con->conf.x = s->x
3878 +#define PATCH(x) \
3879 +       con->conf.x = s->x
3880  int config_setup_connection(server *srv, connection *con) {
3881         specific_config *s = srv->config_storage[0];
3882 -       
3883 +
3884         PATCH(allow_http11);
3885         PATCH(mimetypes);
3886         PATCH(document_root);
3887 @@ -236,20 +240,21 @@
3888         PATCH(kbytes_per_second);
3889         PATCH(global_kbytes_per_second);
3890         PATCH(global_bytes_per_second_cnt);
3891 -       
3892 +
3893         con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
3894         buffer_copy_string_buffer(con->server_name, s->server_name);
3895 -       
3896 +
3897         PATCH(log_request_header);
3898         PATCH(log_response_header);
3899         PATCH(log_request_handling);
3900         PATCH(log_condition_handling);
3901 +       PATCH(log_condition_cache_handling);
3902         PATCH(log_file_not_found);
3903 -       
3904 +
3905         PATCH(range_requests);
3906         PATCH(force_lowercase_filenames);
3907         PATCH(is_ssl);
3908 -       
3909 +
3910         PATCH(ssl_pemfile);
3911         PATCH(ssl_ca_file);
3912         return 0;
3913 @@ -257,22 +262,22 @@
3914  
3915  int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
3916         size_t i, j;
3917 -       
3918 +
3919         /* skip the first, the global context */
3920         for (i = 1; i < srv->config_context->used; i++) {
3921                 data_config *dc = (data_config *)srv->config_context->data[i];
3922                 specific_config *s = srv->config_storage[i];
3923 -               
3924 +
3925                 /* not our stage */
3926                 if (comp != dc->comp) continue;
3927 -               
3928 +
3929                 /* condition didn't match */
3930                 if (!config_check_cond(srv, con, dc)) continue;
3931 -               
3932 +
3933                 /* merge config */
3934                 for (j = 0; j < dc->value->used; j++) {
3935                         data_unset *du = dc->value->data[j];
3936 -                       
3937 +
3938                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
3939                                 PATCH(document_root);
3940                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
3941 @@ -315,11 +320,13 @@
3942                                 PATCH(log_response_header);
3943                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
3944                                 PATCH(log_condition_handling);
3945 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-cache-handling"))) {
3946 +                               PATCH(log_condition_cache_handling);
3947                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
3948                                 PATCH(log_file_not_found);
3949                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
3950                                 PATCH(allow_http11);
3951 -                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {  
3952 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
3953                                 PATCH(force_lowercase_filenames);
3954                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
3955                                 PATCH(global_kbytes_per_second);
3956 @@ -328,7 +335,7 @@
3957                         }
3958                 }
3959         }
3960 -       
3961 +
3962         return 0;
3963  }
3964  #undef PATCH
3965 @@ -336,15 +343,15 @@
3966  typedef struct {
3967         int foo;
3968         int bar;
3969 -       
3970 +
3971         const buffer *source;
3972         const char *input;
3973         size_t offset;
3974         size_t size;
3975 -       
3976 +
3977         int line_pos;
3978         int line;
3979 -       
3980 +
3981         int in_key;
3982         int in_brace;
3983         int in_cond;
3984 @@ -362,7 +369,7 @@
3985         }
3986  
3987         if (0 != stream_open(&(t->s), t->file)) {
3988 -               log_error_write(srv, __FILE__, __LINE__, "sbss", 
3989 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
3990                                 "opening configfile ", t->file, "failed:", strerror(errno));
3991                 buffer_free(t->file);
3992                 return -1;
3993 @@ -373,7 +380,7 @@
3994         t->size = t->s.size;
3995         t->line = 1;
3996         t->line_pos = 1;
3997 -       
3998 +
3999         t->in_key = 1;
4000         t->in_brace = 0;
4001         t->in_cond = 0;
4002 @@ -401,7 +408,7 @@
4003  static int config_skip_comment(tokenizer_t *t) {
4004         int i;
4005         assert(t->input[t->offset] == '#');
4006 -       for (i = 1; t->input[t->offset + i] && 
4007 +       for (i = 1; t->input[t->offset + i] &&
4008              (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
4009              i++);
4010         t->offset += i;
4011 @@ -411,44 +418,44 @@
4012  static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
4013         int tid = 0;
4014         size_t i;
4015 -       
4016 +
4017         for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
4018                 char c = t->input[t->offset];
4019                 const char *start = NULL;
4020 -               
4021 +
4022                 switch (c) {
4023 -               case '=': 
4024 +               case '=':
4025                         if (t->in_brace) {
4026                                 if (t->input[t->offset + 1] == '>') {
4027                                         t->offset += 2;
4028 -                                       
4029 +
4030                                         buffer_copy_string(token, "=>");
4031 -                                       
4032 +
4033                                         tid = TK_ARRAY_ASSIGN;
4034                                 } else {
4035 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4036 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4037                                                         "source:", t->source,
4038 -                                                       "line:", t->line, "pos:", t->line_pos, 
4039 +                                                       "line:", t->line, "pos:", t->line_pos,
4040                                                         "use => for assignments in arrays");
4041                                         return -1;
4042                                 }
4043                         } else if (t->in_cond) {
4044                                 if (t->input[t->offset + 1] == '=') {
4045                                         t->offset += 2;
4046 -                                       
4047 +
4048                                         buffer_copy_string(token, "==");
4049 -                                       
4050 +
4051                                         tid = TK_EQ;
4052                                 } else if (t->input[t->offset + 1] == '~') {
4053                                         t->offset += 2;
4054 -                                       
4055 +
4056                                         buffer_copy_string(token, "=~");
4057 -                                       
4058 +
4059                                         tid = TK_MATCH;
4060                                 } else {
4061 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4062 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4063                                                         "source:", t->source,
4064 -                                                       "line:", t->line, "pos:", t->line_pos, 
4065 +                                                       "line:", t->line, "pos:", t->line_pos,
4066                                                         "only =~ and == are allowed in the condition");
4067                                         return -1;
4068                                 }
4069 @@ -456,51 +463,51 @@
4070                                 t->in_cond = 0;
4071                         } else if (t->in_key) {
4072                                 tid = TK_ASSIGN;
4073 -                               
4074 +
4075                                 buffer_copy_string_len(token, t->input + t->offset, 1);
4076 -                               
4077 +
4078                                 t->offset++;
4079                                 t->line_pos++;
4080                         } else {
4081 -                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4082 +                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4083                                                 "source:", t->source,
4084 -                                               "line:", t->line, "pos:", t->line_pos, 
4085 +                                               "line:", t->line, "pos:", t->line_pos,
4086                                                 "unexpected equal-sign: =");
4087                                 return -1;
4088                         }
4089 -                       
4090 +
4091                         break;
4092 -               case '!': 
4093 +               case '!':
4094                         if (t->in_cond) {
4095                                 if (t->input[t->offset + 1] == '=') {
4096                                         t->offset += 2;
4097 -                                       
4098 +
4099                                         buffer_copy_string(token, "!=");
4100 -                                       
4101 +
4102                                         tid = TK_NE;
4103                                 } else if (t->input[t->offset + 1] == '~') {
4104                                         t->offset += 2;
4105 -                                       
4106 +
4107                                         buffer_copy_string(token, "!~");
4108 -                                       
4109 +
4110                                         tid = TK_NOMATCH;
4111                                 } else {
4112 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4113 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4114                                                         "source:", t->source,
4115 -                                                       "line:", t->line, "pos:", t->line_pos, 
4116 +                                                       "line:", t->line, "pos:", t->line_pos,
4117                                                         "only !~ and != are allowed in the condition");
4118                                         return -1;
4119                                 }
4120                                 t->in_key = 1;
4121                                 t->in_cond = 0;
4122                         } else {
4123 -                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4124 +                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4125                                                 "source:", t->source,
4126 -                                               "line:", t->line, "pos:", t->line_pos, 
4127 +                                               "line:", t->line, "pos:", t->line_pos,
4128                                                 "unexpected exclamation-marks: !");
4129                                 return -1;
4130                         }
4131 -                       
4132 +
4133                         break;
4134                 case '\t':
4135                 case ' ':
4136 @@ -546,10 +553,10 @@
4137                 case ',':
4138                         if (t->in_brace > 0) {
4139                                 tid = TK_COMMA;
4140 -                               
4141 +
4142                                 buffer_copy_string(token, "(COMMA)");
4143                         }
4144 -                       
4145 +
4146                         t->offset++;
4147                         t->line_pos++;
4148                         break;
4149 @@ -557,70 +564,70 @@
4150                         /* search for the terminating " */
4151                         start = t->input + t->offset + 1;
4152                         buffer_copy_string(token, "");
4153 -                       
4154 +
4155                         for (i = 1; t->input[t->offset + i]; i++) {
4156                                 if (t->input[t->offset + i] == '\\' &&
4157                                     t->input[t->offset + i + 1] == '"') {
4158 -                                       
4159 +
4160                                         buffer_append_string_len(token, start, t->input + t->offset + i - start);
4161 -                                       
4162 +
4163                                         start = t->input + t->offset + i + 1;
4164 -                                       
4165 +
4166                                         /* skip the " */
4167                                         i++;
4168                                         continue;
4169                                 }
4170 -                               
4171 -                               
4172 +
4173 +
4174                                 if (t->input[t->offset + i] == '"') {
4175                                         tid = TK_STRING;
4176 -                               
4177 +
4178                                         buffer_append_string_len(token, start, t->input + t->offset + i - start);
4179 -                                       
4180 +
4181                                         break;
4182                                 }
4183                         }
4184  
4185                         if (t->input[t->offset + i] == '\0') {
4186                                 /* ERROR */
4187 -                               
4188 -                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4189 +
4190 +                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4191                                                 "source:", t->source,
4192 -                                               "line:", t->line, "pos:", t->line_pos, 
4193 +                                               "line:", t->line, "pos:", t->line_pos,
4194                                                 "missing closing quote");
4195 -                               
4196 +
4197                                 return -1;
4198                         }
4199 -                       
4200 +
4201                         t->offset += i + 1;
4202                         t->line_pos += i + 1;
4203 -                       
4204 +
4205                         break;
4206                 case '(':
4207                         t->offset++;
4208                         t->in_brace++;
4209 -                               
4210 +
4211                         tid = TK_LPARAN;
4212 -                               
4213 +
4214                         buffer_copy_string(token, "(");
4215                         break;
4216                 case ')':
4217                         t->offset++;
4218                         t->in_brace--;
4219 -                               
4220 +
4221                         tid = TK_RPARAN;
4222 -                               
4223 +
4224                         buffer_copy_string(token, ")");
4225                         break;
4226                 case '$':
4227                         t->offset++;
4228 -                               
4229 +
4230                         tid = TK_DOLLAR;
4231                         t->in_cond = 1;
4232                         t->in_key = 0;
4233 -                               
4234 +
4235                         buffer_copy_string(token, "$");
4236 -                       
4237 +
4238                         break;
4239  
4240                 case '+':
4241 @@ -637,96 +644,88 @@
4242  
4243                 case '{':
4244                         t->offset++;
4245 -                               
4246 +
4247                         tid = TK_LCURLY;
4248 -                               
4249 +
4250                         buffer_copy_string(token, "{");
4251 -                       
4252 +
4253                         break;
4254 -                       
4255 +
4256                 case '}':
4257                         t->offset++;
4258 -                               
4259 +
4260                         tid = TK_RCURLY;
4261 -                               
4262 +
4263                         buffer_copy_string(token, "}");
4264 -                       
4265 +
4266                         break;
4267  
4268                 case '[':
4269                         t->offset++;
4270 -                               
4271 +
4272                         tid = TK_LBRACKET;
4273 -                               
4274 +
4275                         buffer_copy_string(token, "[");
4276 -                       
4277 +
4278                         break;
4279 -                       
4280 +
4281                 case ']':
4282                         t->offset++;
4283 -                               
4284 +
4285                         tid = TK_RBRACKET;
4286 -                               
4287 +
4288                         buffer_copy_string(token, "]");
4289 -                       
4290 +
4291                         break;
4292                 case '#':
4293                         t->line_pos += config_skip_comment(t);
4294 -                       
4295 +
4296                         break;
4297                 default:
4298                         if (t->in_cond) {
4299 -                               for (i = 0; t->input[t->offset + i] && 
4300 +                               for (i = 0; t->input[t->offset + i] &&
4301                                      (isalpha((unsigned char)t->input[t->offset + i])
4302                                       ); i++);
4303 -                               
4304 +
4305                                 if (i && t->input[t->offset + i]) {
4306                                         tid = TK_SRVVARNAME;
4307                                         buffer_copy_string_len(token, t->input + t->offset, i);
4308 -                                       
4309 +
4310                                         t->offset += i;
4311                                         t->line_pos += i;
4312                                 } else {
4313                                         /* ERROR */
4314 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4315 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4316                                                         "source:", t->source,
4317 -                                                       "line:", t->line, "pos:", t->line_pos, 
4318 +                                                       "line:", t->line, "pos:", t->line_pos,
4319                                                         "invalid character in condition");
4320                                         return -1;
4321                                 }
4322                         } else if (isdigit((unsigned char)c)) {
4323                                 /* take all digits */
4324                                 for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]);  i++);
4325 -                               
4326 +
4327                                 /* was there it least a digit ? */
4328 -                               if (i && t->input[t->offset + i]) {
4329 +                               if (i) {
4330                                         tid = TK_INTEGER;
4331 -                                       
4332 +
4333                                         buffer_copy_string_len(token, t->input + t->offset, i);
4334 -                                       
4335 +
4336                                         t->offset += i;
4337                                         t->line_pos += i;
4338 -                               } else {
4339 -                                       /* ERROR */
4340 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4341 -                                                       "source:", t->source,
4342 -                                                       "line:", t->line, "pos:", t->line_pos, 
4343 -                                                       "unexpected EOF");
4344 -                                       
4345 -                                       return -1;
4346                                 }
4347                         } else {
4348                                 /* the key might consist of [-.0-9a-z] */
4349 -                               for (i = 0; t->input[t->offset + i] && 
4350 -                                    (isalnum((unsigned char)t->input[t->offset + i]) || 
4351 +                               for (i = 0; t->input[t->offset + i] &&
4352 +                                    (isalnum((unsigned char)t->input[t->offset + i]) ||
4353                                       t->input[t->offset + i] == '.' ||
4354                                       t->input[t->offset + i] == '_' || /* for env.* */
4355                                       t->input[t->offset + i] == '-'
4356                                       ); i++);
4357 -                               
4358 +
4359                                 if (i && t->input[t->offset + i]) {
4360                                         buffer_copy_string_len(token, t->input + t->offset, i);
4361 -                                       
4362 +
4363                                         if (strcmp(token->ptr, "include") == 0) {
4364                                                 tid = TK_INCLUDE;
4365                                         } else if (strcmp(token->ptr, "include_shell") == 0) {
4366 @@ -738,14 +737,14 @@
4367                                         } else {
4368                                                 tid = TK_LKEY;
4369                                         }
4370 -                                       
4371 +
4372                                         t->offset += i;
4373                                         t->line_pos += i;
4374                                 } else {
4375                                         /* ERROR */
4376 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4377 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4378                                                         "source:", t->source,
4379 -                                                       "line:", t->line, "pos:", t->line_pos, 
4380 +                                                       "line:", t->line, "pos:", t->line_pos,
4381                                                         "invalid character in variable name");
4382                                         return -1;
4383                                 }
4384 @@ -753,16 +752,16 @@
4385                         break;
4386                 }
4387         }
4388 -       
4389 +
4390         if (tid) {
4391                 *token_id = tid;
4392  #if 0
4393 -               log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd", 
4394 +               log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
4395                                 "source:", t->source,
4396                                 "line:", t->line, "pos:", t->line_pos,
4397                                 token, token->used - 1, tid);
4398  #endif
4399 -               
4400 +
4401                 return 1;
4402         } else if (t->offset < t->size) {
4403                 fprintf(stderr, "%s.%d: %d, %s\n",
4404 @@ -781,10 +780,11 @@
4405         pParser = configparserAlloc( malloc );
4406         lasttoken = buffer_init();
4407         token = buffer_init();
4408 +
4409         while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
4410                 buffer_copy_string_buffer(lasttoken, token);
4411                 configparser(pParser, token_id, token, context);
4412 -               
4413 +
4414                 token = buffer_init();
4415         }
4416         buffer_free(token);
4417 @@ -797,14 +797,14 @@
4418                 }
4419         }
4420         configparserFree(pParser, free);
4421 -       
4422 +
4423         if (ret == -1) {
4424 -               log_error_write(srv, __FILE__, __LINE__, "sb", 
4425 +               log_error_write(srv, __FILE__, __LINE__, "sb",
4426                                 "configfile parser failed:", lasttoken);
4427         } else if (context->ok == 0) {
4428 -               log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb", 
4429 +               log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
4430                                 "source:", t->source,
4431 -                               "line:", t->line, "pos:", t->line_pos, 
4432 +                               "line:", t->line, "pos:", t->line_pos,
4433                                 "parser failed somehow near here:", lasttoken);
4434                 ret = -1;
4435         }
4436 @@ -821,7 +821,7 @@
4437         t->offset = 0;
4438         t->line = 1;
4439         t->line_pos = 1;
4440 -       
4441 +
4442         t->in_key = 1;
4443         t->in_brace = 0;
4444         t->in_cond = 0;
4445 @@ -844,7 +844,7 @@
4446         }
4447  
4448         if (0 != stream_open(&s, filename)) {
4449 -               log_error_write(srv, __FILE__, __LINE__, "sbss", 
4450 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
4451                                 "opening configfile ", filename, "failed:", strerror(errno));
4452                 ret = -1;
4453         } else {
4454 @@ -866,7 +866,7 @@
4455         char oldpwd[PATH_MAX];
4456  
4457         if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
4458 -               log_error_write(srv, __FILE__, __LINE__, "s", 
4459 +               log_error_write(srv, __FILE__, __LINE__, "s",
4460                                 "cannot get cwd", strerror(errno));
4461                 return -1;
4462         }
4463 @@ -879,7 +879,7 @@
4464         }
4465  
4466         if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
4467 -               log_error_write(srv, __FILE__, __LINE__, "sbss", 
4468 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
4469                                 "opening", source, "failed:", strerror(errno));
4470                 ret = -1;
4471         } else {
4472 @@ -896,13 +896,12 @@
4473  static void context_init(server *srv, config_t *context) {
4474         context->srv = srv;
4475         context->ok = 1;
4476 -       context->configs_stack = array_init();
4477 -       context->configs_stack->is_weakref = 1;
4478 +       context->configs_stack = buffer_ptr_init(NULL);
4479         context->basedir = buffer_init();
4480  }
4481  
4482  static void context_free(config_t *context) {
4483 -       array_free(context->configs_stack);
4484 +       buffer_ptr_free(context->configs_stack);
4485         buffer_free(context->basedir);
4486  }
4487  
4488 @@ -918,18 +917,15 @@
4489         context_init(srv, &context);
4490         context.all_configs = srv->config_context;
4491  
4492 -       pos = strrchr(fn,
4493 -#ifdef __WIN32
4494 -                       '\\'
4495 -#else
4496 -                       '/'
4497 -#endif
4498 -                       );
4499 +    /* use the current dir as basedir for all other includes
4500 +    */
4501 +       pos = strrchr(fn, DIR_SEPERATOR);
4502 +
4503         if (pos) {
4504                 buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
4505                 fn = pos + 1;
4506         }
4507 -       
4508 +
4509         dc = data_config_init();
4510         buffer_copy_string(dc->key, "global");
4511  
4512 @@ -944,7 +940,7 @@
4513         dpid->value = getpid();
4514         buffer_copy_string(dpid->key, "var.PID");
4515         array_insert_unique(srv->config, (data_unset *)dpid);
4516 -       
4517 +
4518         dcwd = data_string_init();
4519         buffer_prepare_copy(dcwd->value, 1024);
4520         if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
4521 @@ -968,7 +964,7 @@
4522         } else {
4523                 return -1;
4524         }
4525 -       
4526 +
4527         if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
4528                 data_string *ds;
4529                 data_array *prepends;
4530 @@ -1026,22 +1022,23 @@
4531                 buffer_copy_string(modules->key, "server.modules");
4532                 array_insert_unique(srv->config, (data_unset *)modules);
4533         }
4534 -       
4535 +
4536  
4537         if (0 != config_insert(srv)) {
4538                 return -1;
4539         }
4540 -       
4541 +
4542         return 0;
4543  }
4544  
4545 +
4546  int config_set_defaults(server *srv) {
4547         size_t i;
4548         specific_config *s = srv->config_storage[0];
4549         struct stat st1, st2;
4550 -       
4551 -       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = 
4552 -       { 
4553 +
4554 +       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4555 +       {
4556                 /* - poll is most reliable
4557                  * - select works everywhere
4558                  * - linux-* are experimental
4559 @@ -1067,20 +1064,21 @@
4560  #endif
4561                 { FDEVENT_HANDLER_UNSET,          NULL }
4562         };
4563 -       
4564  
4565 -       if (buffer_is_empty(s->document_root)) {  
4566 -               log_error_write(srv, __FILE__, __LINE__, "s",  
4567 -                               "a default document-root has to be set");  
4568 -               
4569 -               return -1;  
4570 -       }  
4571 -       
4572 +
4573 +       if (buffer_is_empty(s->document_root)) {
4574 +               log_error_write(srv, __FILE__, __LINE__, "s",
4575 +                               "a default document-root has to be set");
4576 +
4577 +               return -1;
4578 +       }
4579 +
4580         if (buffer_is_empty(srv->srvconf.changeroot)) {
4581 -               if (-1 == stat(s->document_root->ptr, &st1)) {  
4582 -                       log_error_write(srv, __FILE__, __LINE__, "sb",  
4583 +        pathname_unix2local(s->document_root);
4584 +               if (-1 == stat(s->document_root->ptr, &st1)) {
4585 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
4586                                         "base-docroot doesn't exist:",
4587 -                                       s->document_root);  
4588 +                                       s->document_root, strerror(errno));
4589                         return -1;
4590                 }
4591  
4592 @@ -1088,18 +1086,18 @@
4593                 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
4594                 buffer_append_string_buffer(srv->tmp_buf, s->document_root);
4595  
4596 -               if (-1 == stat(srv->tmp_buf->ptr, &st1)) {  
4597 -                       log_error_write(srv, __FILE__, __LINE__, "sb",  
4598 +               if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
4599 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
4600                                         "base-docroot doesn't exist:",
4601 -                                       srv->tmp_buf);  
4602 +                                       srv->tmp_buf);
4603                         return -1;
4604                 }
4605 -               
4606 +
4607         }
4608 -       
4609 -       buffer_copy_string_buffer(srv->tmp_buf, s->document_root);  
4610  
4611 -       buffer_to_lower(srv->tmp_buf);  
4612 +       buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4613 +
4614 +       buffer_to_lower(srv->tmp_buf);
4615  
4616         if (0 == stat(srv->tmp_buf->ptr, &st1)) {
4617                 int is_lower = 0;
4618 @@ -1107,68 +1105,68 @@
4619                 is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
4620  
4621                 /* lower-case existed, check upper-case */
4622 -               buffer_copy_string_buffer(srv->tmp_buf, s->document_root);  
4623 +               buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4624  
4625 -               buffer_to_upper(srv->tmp_buf);  
4626 +               buffer_to_upper(srv->tmp_buf);
4627  
4628                 /* we have to handle the special case that upper and lower-casing results in the same filename
4629                  * as in server.document-root = "/" or "/12345/" */
4630  
4631                 if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
4632 -                       /* lower-casing and upper-casing didn't result in  
4633 -                        * an other filename, no need to stat(), 
4634 +                       /* lower-casing and upper-casing didn't result in
4635 +                        * an other filename, no need to stat(),
4636                          * just assume it is case-sensitive. */
4637  
4638                         s->force_lowercase_filenames = 0;
4639 -               } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {  
4640 +               } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
4641 +
4642 +                       /* upper case exists too, doesn't the FS handle this ? */
4643 +
4644 +                       /* upper and lower have the same inode -> case-insensitve FS */
4645 +
4646 +                       if (st1.st_ino == st2.st_ino) {
4647 +                               /* upper and lower have the same inode -> case-insensitve FS */
4648 +
4649 +                               s->force_lowercase_filenames = 1;
4650 +                       }
4651 +               }
4652 +       }
4653  
4654 -                       /* upper case exists too, doesn't the FS handle this ? */  
4655 -                       
4656 -                       /* upper and lower have the same inode -> case-insensitve FS */  
4657 -                       
4658 -                       if (st1.st_ino == st2.st_ino) {  
4659 -                               /* upper and lower have the same inode -> case-insensitve FS */  
4660 -                               
4661 -                               s->force_lowercase_filenames = 1;  
4662 -                       }  
4663 -               }  
4664 -       }  
4665 -       
4666         if (srv->srvconf.port == 0) {
4667                 srv->srvconf.port = s->is_ssl ? 443 : 80;
4668         }
4669 -       
4670 +
4671         if (srv->srvconf.event_handler->used == 0) {
4672                 /* choose a good default
4673 -                * 
4674 -                * the event_handler list is sorted by 'goodness' 
4675 +                *
4676 +                * the event_handler list is sorted by 'goodness'
4677                  * taking the first available should be the best solution
4678                  */
4679                 srv->event_handler = event_handlers[0].et;
4680 -               
4681 +
4682                 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4683 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
4684 +                       log_error_write(srv, __FILE__, __LINE__, "s",
4685                                         "sorry, there is no event handler for this system");
4686 -                       
4687 +
4688                         return -1;
4689                 }
4690         } else {
4691                 /*
4692                  * User override
4693                  */
4694 -               
4695 +
4696                 for (i = 0; event_handlers[i].name; i++) {
4697                         if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
4698                                 srv->event_handler = event_handlers[i].et;
4699                                 break;
4700                         }
4701                 }
4702 -               
4703 +
4704                 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4705 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
4706 -                                       "the selected event-handler in unknown or not supported:", 
4707 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
4708 +                                       "the selected event-handler in unknown or not supported:",
4709                                         srv->srvconf.event_handler );
4710 -                       
4711 +
4712                         return -1;
4713                 }
4714         }
4715 @@ -1176,19 +1174,19 @@
4716         if (s->is_ssl) {
4717                 if (buffer_is_empty(s->ssl_pemfile)) {
4718                         /* PEM file is require */
4719 -                       
4720 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
4721 +
4722 +                       log_error_write(srv, __FILE__, __LINE__, "s",
4723                                         "ssl.pemfile has to be set");
4724                         return -1;
4725                 }
4726 -               
4727 +
4728  #ifndef USE_OPENSSL
4729 -               log_error_write(srv, __FILE__, __LINE__, "s", 
4730 +               log_error_write(srv, __FILE__, __LINE__, "s",
4731                                 "ssl support is missing, recompile with --with-openssl");
4732 -               
4733 +
4734                 return -1;
4735  #endif
4736         }
4737 -       
4738 +
4739         return 0;
4740  }
4741 --- ../lighttpd-1.4.11/src/configfile.h 2005-08-23 17:36:12.000000000 +0300
4742 +++ lighttpd-1.4.12/src/configfile.h    2006-07-11 22:07:51.000000000 +0300
4743 @@ -9,7 +9,7 @@
4744         server *srv;
4745         int     ok;
4746         array  *all_configs;
4747 -       array  *configs_stack; /* to parse nested block */
4748 +       buffer_ptr  *configs_stack; /* to parse nested block */
4749         data_config *current; /* current started with { */
4750         buffer *basedir;
4751  } config_t;
4752 --- ../lighttpd-1.4.11/src/configparser.c       2006-02-01 19:51:15.000000000 +0200
4753 +++ lighttpd-1.4.12/src/configparser.c  2006-07-11 22:08:02.000000000 +0300
4754 @@ -24,52 +24,34 @@
4755      dc->parent = ctx->current;
4756      array_insert_unique(dc->parent->childs, (data_unset *)dc);
4757    }
4758 -  array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
4759 +  buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
4760    ctx->current = dc;
4761  }
4762  
4763  static data_config *configparser_pop(config_t *ctx) {
4764    data_config *old = ctx->current;
4765 -  ctx->current = (data_config *) array_pop(ctx->configs_stack);
4766 +  ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
4767    return old;
4768  }
4769  
4770  /* return a copied variable */
4771  static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
4772 -  if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
4773 -    char *env;
4774 -
4775 -    if (NULL != (env = getenv(key->ptr + 4))) {
4776 -      data_string *ds;
4777 -      ds = data_string_init();
4778 -      buffer_append_string(ds->value, env);
4779 -      return (data_unset *)ds;
4780 -    }
4781 -
4782 -    fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
4783 -    ctx->ok = 0;
4784 -
4785 -    return NULL;
4786 -  } else {
4787 -    data_unset *du;
4788 -    data_config *dc;
4789 +  data_unset *du;
4790 +  data_config *dc;
4791  
4792  #if 0
4793 -    fprintf(stderr, "get var %s\n", key->ptr);
4794 +  fprintf(stderr, "get var %s\n", key->ptr);
4795  #endif
4796 -    for (dc = ctx->current; dc; dc = dc->parent) {
4797 +  for (dc = ctx->current; dc; dc = dc->parent) {
4798  #if 0
4799 -      fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
4800 -      array_print(dc->value, 0);
4801 +    fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
4802 +    array_print(dc->value, 0);
4803  #endif
4804 -      if (NULL != (du = array_get_element(dc->value, key->ptr))) {
4805 -        return du->copy(du);
4806 -      }
4807 +    if (NULL != (du = array_get_element(dc->value, key->ptr))) {
4808 +      return du->copy(du);
4809      }
4810 -    fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
4811 -    ctx->ok = 0;
4812 -    return NULL;
4813    }
4814 +  return NULL;
4815  }
4816  
4817  /* op1 is to be eat/return by this function, op1->key is not cared
4818 @@ -124,14 +106,14 @@
4819  }
4820  
4821  
4822 -#line 128 "configparser.c"
4823 +#line 110 "configparser.c"
4824  /* Next is all token values, in a form suitable for use by makeheaders.
4825  ** This section will be null unless lemon is run with the -m switch.
4826  */
4827 -/* 
4828 +/*
4829  ** These constants (all generated automatically by the parser generator)
4830  ** specify the various kinds of tokens (terminals) that the parser
4831 -** understands. 
4832 +** understands.
4833  **
4834  ** Each symbol here is a terminal symbol in the grammar.
4835  */
4836 @@ -148,7 +130,7 @@
4837  **                       and nonterminals.  "int" is used otherwise.
4838  **    YYNOCODE           is a number of type YYCODETYPE which corresponds
4839  **                       to no legal terminal or nonterminal number.  This
4840 -**                       number is used to fill in empty slots of the hash 
4841 +**                       number is used to fill in empty slots of the hash
4842  **                       table.
4843  **    YYFALLBACK         If defined, this indicates that one or more tokens
4844  **                       have fall-back values which should be used if the
4845 @@ -157,7 +139,7 @@
4846  **                       and nonterminal numbers.  "unsigned char" is
4847  **                       used if there are fewer than 250 rules and
4848  **                       states combined.  "int" is used otherwise.
4849 -**    configparserTOKENTYPE     is the data type used for minor tokens given 
4850 +**    configparserTOKENTYPE     is the data type used for minor tokens given
4851  **                       directly to the parser from the tokenizer.
4852  **    YYMINORTYPE        is the data type used for all minor tokens.
4853  **                       This is typically a union of many types, one of
4854 @@ -192,8 +174,8 @@
4855  #define configparserARG_PDECL ,config_t *ctx
4856  #define configparserARG_FETCH config_t *ctx = yypParser->ctx
4857  #define configparserARG_STORE yypParser->ctx = ctx
4858 -#define YYNSTATE 62
4859 -#define YYNRULE 39
4860 +#define YYNSTATE 63
4861 +#define YYNRULE 40
4862  #define YYERRORSYMBOL 26
4863  #define YYERRSYMDT yy95
4864  #define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
4865 @@ -203,7 +185,7 @@
4866  /* Next are that tables used to determine what action to take based on the
4867  ** current state and lookahead token.  These tables are used to implement
4868  ** functions that take a state number and lookahead value and return an
4869 -** action integer.  
4870 +** action integer.
4871  **
4872  ** Suppose the action integer is N.  Then the action is determined as
4873  ** follows
4874 @@ -228,7 +210,7 @@
4875  ** If the index value yy_shift_ofst[S]+X is out of range or if the value
4876  ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
4877  ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
4878 -** and that yy_default[S] should be used instead.  
4879 +** and that yy_default[S] should be used instead.
4880  **
4881  ** The formula above is for computing the action when the lookahead is
4882  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
4883 @@ -248,67 +230,69 @@
4884  **  yy_default[]       Default action for each state.
4885  */
4886  static YYACTIONTYPE yy_action[] = {
4887 - /*     0 */     2,    3,    4,    5,   13,   14,   62,   15,    7,   44,
4888 - /*    10 */    20,   86,   16,   45,   28,   48,   40,   10,   39,   25,
4889 - /*    20 */    22,   49,   45,    8,   15,  102,    1,   20,   28,   18,
4890 - /*    30 */    57,   59,   19,   25,   22,   39,   19,   61,   98,   45,
4891 - /*    40 */    20,    6,   23,   24,   26,   28,   35,   57,   59,   12,
4892 - /*    50 */    25,   22,   28,   27,   36,   87,   29,   25,   22,   33,
4893 - /*    60 */    15,   30,   31,   20,   28,   38,    9,   17,   37,   25,
4894 - /*    70 */    22,   39,   42,   43,   10,   45,   11,   53,   54,   55,
4895 - /*    80 */    56,   28,   52,   57,   59,   34,   25,   22,   28,   27,
4896 - /*    90 */    32,   88,   41,   25,   22,   33,   28,   48,   46,   28,
4897 - /*   100 */    48,   25,   22,   58,   25,   22,   60,   21,   19,   47,
4898 - /*   110 */    51,   50,   25,   22,   88,   88,   93,
4899 + /*     0 */     2,    3,    4,    5,   13,   14,   63,   15,    7,   45,
4900 + /*    10 */    20,   88,   16,   46,   28,   49,   41,   10,   40,   25,
4901 + /*    20 */    22,   50,   46,    8,   15,  104,    1,   20,   28,   18,
4902 + /*    30 */    58,   60,    6,   25,   22,   40,   47,   62,   11,   46,
4903 + /*    40 */    20,    9,   23,   24,   26,   29,   89,   58,   60,   10,
4904 + /*    50 */    17,   38,   28,   27,   37,   19,   30,   25,   22,   34,
4905 + /*    60 */    15,  100,   20,   20,   23,   24,   26,   12,   19,   31,
4906 + /*    70 */    32,   40,   19,   44,   43,   46,   95,   35,   90,   89,
4907 + /*    80 */    28,   49,   42,   58,   60,   25,   22,   59,   28,   27,
4908 + /*    90 */    33,   48,   52,   25,   22,   34,   28,   49,   51,   28,
4909 + /*   100 */    36,   25,   22,   61,   25,   22,   89,   28,   39,   89,
4910 + /*   110 */    89,   89,   25,   22,   54,   55,   56,   57,   89,   28,
4911 + /*   120 */    53,   21,   89,   89,   25,   22,   25,   22,
4912  };
4913  static YYCODETYPE yy_lookahead[] = {
4914   /*     0 */    29,   30,   31,   32,   33,   34,    0,    1,   44,   38,
4915   /*    10 */     4,   15,   41,   16,   35,   36,   45,   46,   12,   40,
4916   /*    20 */    41,   42,   16,   15,    1,   27,   28,    4,   35,   36,
4917 - /*    30 */    24,   25,    5,   40,   41,   12,    5,   14,   11,   16,
4918 - /*    40 */     4,    1,    6,    7,    8,   35,   36,   24,   25,   28,
4919 - /*    50 */    40,   41,   35,   36,   37,   15,   39,   40,   41,   42,
4920 - /*    60 */     1,    9,   10,    4,   35,   36,   38,    2,    3,   40,
4921 - /*    70 */    41,   12,   28,   14,   46,   16,   13,   20,   21,   22,
4922 - /*    80 */    23,   35,   36,   24,   25,   11,   40,   41,   35,   36,
4923 - /*    90 */    37,   13,   13,   40,   41,   42,   35,   36,   17,   35,
4924 - /*   100 */    36,   40,   41,   42,   40,   41,   42,   35,    5,   18,
4925 - /*   110 */    43,   19,   40,   41,   47,   47,   13,
4926 + /*    30 */    24,   25,    1,   40,   41,   12,   17,   14,   13,   16,
4927 + /*    40 */     4,   38,    6,    7,    8,    9,   15,   24,   25,   46,
4928 + /*    50 */     2,    3,   35,   36,   37,    5,   39,   40,   41,   42,
4929 + /*    60 */     1,   11,    4,    4,    6,    7,    8,   28,    5,    9,
4930 + /*    70 */    10,   12,    5,   14,   28,   16,   13,   11,   13,   47,
4931 + /*    80 */    35,   36,   13,   24,   25,   40,   41,   42,   35,   36,
4932 + /*    90 */    37,   18,   43,   40,   41,   42,   35,   36,   19,   35,
4933 + /*   100 */    36,   40,   41,   42,   40,   41,   47,   35,   36,   47,
4934 + /*   110 */    47,   47,   40,   41,   20,   21,   22,   23,   47,   35,
4935 + /*   120 */    36,   35,   47,   47,   40,   41,   40,   41,
4936  };
4937  #define YY_SHIFT_USE_DFLT (-5)
4938  static signed char yy_shift_ofst[] = {
4939 - /*     0 */    -5,    6,   -5,   -5,   -5,   40,   -4,    8,   -3,   -5,
4940 - /*    10 */    63,   -5,   23,   -5,   -5,   -5,   65,   36,   31,   36,
4941 - /*    20 */    -5,   -5,   -5,   -5,   -5,   -5,   36,   27,   -5,   52,
4942 - /*    30 */    -5,   36,   -5,   74,   36,   31,   -5,   36,   31,   78,
4943 - /*    40 */    79,   -5,   59,   -5,   -5,   81,   91,   36,   31,   92,
4944 - /*    50 */    57,   36,  103,   -5,   -5,   -5,   -5,   36,   -5,   36,
4945 - /*    60 */    -5,   -5,
4946 + /*     0 */    -5,    6,   -5,   -5,   -5,   31,   -4,    8,   -3,   -5,
4947 + /*    10 */    25,   -5,   23,   -5,   -5,   -5,   48,   58,   67,   58,
4948 + /*    20 */    -5,   -5,   -5,   -5,   -5,   -5,   36,   50,   -5,   -5,
4949 + /*    30 */    60,   -5,   58,   -5,   66,   58,   67,   -5,   58,   67,
4950 + /*    40 */    65,   69,   -5,   59,   -5,   -5,   19,   73,   58,   67,
4951 + /*    50 */    79,   94,   58,   63,   -5,   -5,   -5,   -5,   58,   -5,
4952 + /*    60 */    58,   -5,   -5,
4953  };
4954  #define YY_REDUCE_USE_DFLT (-37)
4955  static signed char yy_reduce_ofst[] = {
4956 - /*     0 */    -2,  -29,  -37,  -37,  -37,  -36,  -37,  -37,   28,  -37,
4957 - /*    10 */   -37,   21,  -29,  -37,  -37,  -37,  -37,   -7,  -37,   72,
4958 + /*     0 */    -2,  -29,  -37,  -37,  -37,  -36,  -37,  -37,    3,  -37,
4959 + /*    10 */   -37,   39,  -29,  -37,  -37,  -37,  -37,   -7,  -37,   86,
4960   /*    20 */   -37,  -37,  -37,  -37,  -37,  -37,   17,  -37,  -37,  -37,
4961 - /*    30 */   -37,   53,  -37,  -37,   10,  -37,  -37,   29,  -37,  -37,
4962 - /*    40 */   -37,   44,  -29,  -37,  -37,  -37,  -37,  -21,  -37,  -37,
4963 - /*    50 */    67,   46,  -37,  -37,  -37,  -37,  -37,   61,  -37,   64,
4964 - /*    60 */   -37,  -37,
4965 + /*    30 */   -37,  -37,   53,  -37,  -37,   64,  -37,  -37,   72,  -37,
4966 + /*    40 */   -37,  -37,   46,  -29,  -37,  -37,  -37,  -37,  -21,  -37,
4967 + /*    50 */   -37,   49,   84,  -37,  -37,  -37,  -37,  -37,   45,  -37,
4968 + /*    60 */    61,  -37,  -37,
4969  };
4970  static YYACTIONTYPE yy_default[] = {
4971 - /*     0 */    64,  101,   63,   65,   66,  101,   67,  101,  101,   90,
4972 - /*    10 */   101,   64,  101,   68,   69,   70,  101,  101,   71,  101,
4973 - /*    20 */    73,   74,   76,   77,   78,   79,  101,   84,   75,  101,
4974 - /*    30 */    80,   82,   81,  101,  101,   85,   83,  101,   72,  101,
4975 - /*    40 */   101,   64,  101,   89,   91,  101,  101,  101,   98,  101,
4976 - /*    50 */   101,  101,  101,   94,   95,   96,   97,  101,   99,  101,
4977 - /*    60 */   100,   92,
4978 + /*     0 */    65,  103,   64,   66,   67,  103,   68,  103,  103,   92,
4979 + /*    10 */   103,   65,  103,   69,   70,   71,  103,  103,   72,  103,
4980 + /*    20 */    74,   75,   77,   78,   79,   80,  103,   86,   76,   81,
4981 + /*    30 */   103,   82,   84,   83,  103,  103,   87,   85,  103,   73,
4982 + /*    40 */   103,  103,   65,  103,   91,   93,  103,  103,  103,  100,
4983 + /*    50 */   103,  103,  103,  103,   96,   97,   98,   99,  103,  101,
4984 + /*    60 */   103,  102,   94,
4985  };
4986  #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
4987  
4988  /* The next table maps tokens into fallback tokens.  If a construct
4989  ** like the following:
4990 -** 
4991 +**
4992  **      %fallback ID X Y Z.
4993  **
4994  ** appears in the grammer, then ID becomes a fallback token for X, Y,
4995 @@ -359,10 +343,10 @@
4996  #endif /* NDEBUG */
4997  
4998  #ifndef NDEBUG
4999 -/* 
5000 +/*
5001  ** Turn parser tracing on by giving a stream to which to write the trace
5002  ** and a prompt to preface each trace message.  Tracing is turned off
5003 -** by making either argument NULL 
5004 +** by making either argument NULL
5005  **
5006  ** Inputs:
5007  ** <ul>
5008 @@ -387,7 +371,7 @@
5009  #ifndef NDEBUG
5010  /* For tracing shifts, the names of all terminals and nonterminals
5011  ** are required.  The following table supplies these names */
5012 -static const char *yyTokenName[] = { 
5013 +static const char *yyTokenName[] = {
5014    "$",             "EOL",           "ASSIGN",        "APPEND",      
5015    "LKEY",          "PLUS",          "STRING",        "INTEGER",     
5016    "LPARAN",        "RPARAN",        "COMMA",         "ARRAY_ASSIGN",
5017 @@ -425,27 +409,28 @@
5018   /*  15 */ "value ::= STRING",
5019   /*  16 */ "value ::= INTEGER",
5020   /*  17 */ "value ::= array",
5021 - /*  18 */ "array ::= LPARAN aelements RPARAN",
5022 - /*  19 */ "aelements ::= aelements COMMA aelement",
5023 - /*  20 */ "aelements ::= aelements COMMA",
5024 - /*  21 */ "aelements ::= aelement",
5025 - /*  22 */ "aelement ::= expression",
5026 - /*  23 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5027 - /*  24 */ "eols ::= EOL",
5028 - /*  25 */ "eols ::=",
5029 - /*  26 */ "globalstart ::= GLOBAL",
5030 - /*  27 */ "global ::= globalstart LCURLY metalines RCURLY",
5031 - /*  28 */ "condlines ::= condlines eols ELSE condline",
5032 - /*  29 */ "condlines ::= condline",
5033 - /*  30 */ "condline ::= context LCURLY metalines RCURLY",
5034 - /*  31 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5035 - /*  32 */ "cond ::= EQ",
5036 - /*  33 */ "cond ::= MATCH",
5037 - /*  34 */ "cond ::= NE",
5038 - /*  35 */ "cond ::= NOMATCH",
5039 - /*  36 */ "stringop ::= expression",
5040 - /*  37 */ "include ::= INCLUDE stringop",
5041 - /*  38 */ "include_shell ::= INCLUDE_SHELL stringop",
5042 + /*  18 */ "array ::= LPARAN RPARAN",
5043 + /*  19 */ "array ::= LPARAN aelements RPARAN",
5044 + /*  20 */ "aelements ::= aelements COMMA aelement",
5045 + /*  21 */ "aelements ::= aelements COMMA",
5046 + /*  22 */ "aelements ::= aelement",
5047 + /*  23 */ "aelement ::= expression",
5048 + /*  24 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5049 + /*  25 */ "eols ::= EOL",
5050 + /*  26 */ "eols ::=",
5051 + /*  27 */ "globalstart ::= GLOBAL",
5052 + /*  28 */ "global ::= globalstart LCURLY metalines RCURLY",
5053 + /*  29 */ "condlines ::= condlines eols ELSE condline",
5054 + /*  30 */ "condlines ::= condline",
5055 + /*  31 */ "condline ::= context LCURLY metalines RCURLY",
5056 + /*  32 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5057 + /*  33 */ "cond ::= EQ",
5058 + /*  34 */ "cond ::= MATCH",
5059 + /*  35 */ "cond ::= NE",
5060 + /*  36 */ "cond ::= NOMATCH",
5061 + /*  37 */ "stringop ::= expression",
5062 + /*  38 */ "include ::= INCLUDE stringop",
5063 + /*  39 */ "include_shell ::= INCLUDE_SHELL stringop",
5064  };
5065  #endif /* NDEBUG */
5066  
5067 @@ -465,7 +450,7 @@
5068  #endif
5069  }
5070  
5071 -/* 
5072 +/*
5073  ** This function allocates a new parser.
5074  ** The only argument is a pointer to a function which works like
5075  ** malloc.
5076 @@ -496,7 +481,7 @@
5077      /* Here is inserted the actions which take place when a
5078      ** terminal or non-terminal is destroyed.  This can happen
5079      ** when the symbol is popped from the stack during a
5080 -    ** reduce or during error processing or when a parser is 
5081 +    ** reduce or during error processing or when a parser is
5082      ** being destroyed before it is finished parsing.
5083      **
5084      ** Note: during a reduce, the only symbols destroyed are those
5085 @@ -528,44 +513,44 @@
5086      case 23:
5087      case 24:
5088      case 25:
5089 -#line 160 "./configparser.y"
5090 +#line 143 "./configparser.y"
5091  { buffer_free((yypminor->yy0)); }
5092 -#line 533 "configparser.c"
5093 +#line 518 "configparser.c"
5094        break;
5095      case 35:
5096 -#line 151 "./configparser.y"
5097 +#line 134 "./configparser.y"
5098  { (yypminor->yy41)->free((yypminor->yy41)); }
5099 -#line 538 "configparser.c"
5100 +#line 523 "configparser.c"
5101        break;
5102      case 36:
5103 -#line 152 "./configparser.y"
5104 +#line 135 "./configparser.y"
5105  { (yypminor->yy41)->free((yypminor->yy41)); }
5106 -#line 543 "configparser.c"
5107 +#line 528 "configparser.c"
5108        break;
5109      case 37:
5110 -#line 153 "./configparser.y"
5111 +#line 136 "./configparser.y"
5112  { (yypminor->yy41)->free((yypminor->yy41)); }
5113 -#line 548 "configparser.c"
5114 +#line 533 "configparser.c"
5115        break;
5116      case 39:
5117 -#line 154 "./configparser.y"
5118 +#line 137 "./configparser.y"
5119  { array_free((yypminor->yy40)); }
5120 -#line 553 "configparser.c"
5121 +#line 538 "configparser.c"
5122        break;
5123      case 40:
5124 -#line 155 "./configparser.y"
5125 +#line 138 "./configparser.y"
5126  { array_free((yypminor->yy40)); }
5127 -#line 558 "configparser.c"
5128 +#line 543 "configparser.c"
5129        break;
5130      case 41:
5131 -#line 156 "./configparser.y"
5132 +#line 139 "./configparser.y"
5133  { buffer_free((yypminor->yy43)); }
5134 -#line 563 "configparser.c"
5135 +#line 548 "configparser.c"
5136        break;
5137      case 42:
5138 -#line 157 "./configparser.y"
5139 +#line 140 "./configparser.y"
5140  { buffer_free((yypminor->yy43)); }
5141 -#line 568 "configparser.c"
5142 +#line 553 "configparser.c"
5143        break;
5144      default:  break;   /* If no destructor action specified: do nothing */
5145    }
5146 @@ -597,7 +582,7 @@
5147    return yymajor;
5148  }
5149  
5150 -/* 
5151 +/*
5152  ** Deallocate and destroy a parser.  Destructors are all called for
5153  ** all stack elements before shutting the parser down.
5154  **
5155 @@ -633,7 +618,7 @@
5156  ){
5157    int i;
5158    int stateno = pParser->yystack[pParser->yyidx].stateno;
5159
5160 +
5161    /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
5162    i = yy_shift_ofst[stateno];
5163    if( i==YY_SHIFT_USE_DFLT ){
5164 @@ -677,7 +662,7 @@
5165  ){
5166    int i;
5167    int stateno = pParser->yystack[pParser->yyidx].stateno;
5168
5169 +
5170    i = yy_reduce_ofst[stateno];
5171    if( i==YY_REDUCE_USE_DFLT ){
5172      return yy_default[stateno];
5173 @@ -759,6 +744,7 @@
5174    { 35, 1 },
5175    { 35, 1 },
5176    { 35, 1 },
5177 +  { 40, 2 },
5178    { 40, 3 },
5179    { 39, 3 },
5180    { 39, 2 },
5181 @@ -800,7 +786,7 @@
5182    configparserARG_FETCH;
5183    yymsp = &yypParser->yystack[yypParser->yyidx];
5184  #ifndef NDEBUG
5185 -  if( yyTraceFILE && yyruleno>=0 
5186 +  if( yyTraceFILE && yyruleno>=0
5187          && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
5188      fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
5189        yyRuleName[yyruleno]);
5190 @@ -832,9 +818,9 @@
5191          /* No destructor defined for global */
5192          break;
5193        case 5:
5194 -#line 134 "./configparser.y"
5195 +#line 116 "./configparser.y"
5196  { yymsp[-1].minor.yy78 = NULL; }
5197 -#line 837 "configparser.c"
5198 +#line 823 "configparser.c"
5199    yy_destructor(1,&yymsp[0].minor);
5200          break;
5201        case 6:
5202 @@ -847,10 +833,15 @@
5203    yy_destructor(1,&yymsp[0].minor);
5204          break;
5205        case 9:
5206 -#line 162 "./configparser.y"
5207 +#line 145 "./configparser.y"
5208  {
5209    buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5210 -  if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5211 +  if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5212 +    fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5213 +        ctx->current->context_ndx,
5214 +        ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5215 +    ctx->ok = 0;
5216 +  } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5217      array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5218      yymsp[0].minor.yy41 = NULL;
5219    } else {
5220 @@ -864,16 +855,21 @@
5221    buffer_free(yymsp[-2].minor.yy43);
5222    yymsp[-2].minor.yy43 = NULL;
5223  }
5224 -#line 867 "configparser.c"
5225 +#line 858 "configparser.c"
5226    yy_destructor(2,&yymsp[-1].minor);
5227          break;
5228        case 10:
5229 -#line 179 "./configparser.y"
5230 +#line 167 "./configparser.y"
5231  {
5232    array *vars = ctx->current->value;
5233    data_unset *du;
5234  
5235 -  if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5236 +  if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5237 +    fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5238 +        ctx->current->context_ndx,
5239 +        ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5240 +    ctx->ok = 0;
5241 +  } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5242      /* exists in current block */
5243      du = configparser_merge_data(du, yymsp[0].minor.yy41);
5244      if (NULL == du) {
5245 @@ -883,6 +879,7 @@
5246        buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5247        array_replace(vars, du);
5248      }
5249 +    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5250    } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) {
5251      du = configparser_merge_data(du, yymsp[0].minor.yy41);
5252      if (NULL == du) {
5253 @@ -892,22 +889,20 @@
5254        buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5255        array_insert_unique(ctx->current->value, du);
5256      }
5257 +    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5258    } else {
5259 -    fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n", 
5260 -            ctx->current->context_ndx,
5261 -            ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5262 -    ctx->ok = 0;
5263 +    buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5264 +    array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5265    }
5266    buffer_free(yymsp[-2].minor.yy43);
5267    yymsp[-2].minor.yy43 = NULL;
5268 -  yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5269    yymsp[0].minor.yy41 = NULL;
5270  }
5271 -#line 906 "configparser.c"
5272 +#line 901 "configparser.c"
5273    yy_destructor(3,&yymsp[-1].minor);
5274          break;
5275        case 11:
5276 -#line 214 "./configparser.y"
5277 +#line 206 "./configparser.y"
5278  {
5279    if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) {
5280      yygotominor.yy43 = buffer_init_string("var.");
5281 @@ -919,10 +914,10 @@
5282      yymsp[0].minor.yy0 = NULL;
5283    }
5284  }
5285 -#line 922 "configparser.c"
5286 +#line 917 "configparser.c"
5287          break;
5288        case 12:
5289 -#line 226 "./configparser.y"
5290 +#line 218 "./configparser.y"
5291  {
5292    yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41);
5293    if (NULL == yygotominor.yy41) {
5294 @@ -932,21 +927,38 @@
5295    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5296    yymsp[0].minor.yy41 = NULL;
5297  }
5298 -#line 935 "configparser.c"
5299 +#line 930 "configparser.c"
5300    yy_destructor(5,&yymsp[-1].minor);
5301          break;
5302        case 13:
5303 -#line 236 "./configparser.y"
5304 +#line 228 "./configparser.y"
5305  {
5306    yygotominor.yy41 = yymsp[0].minor.yy41;
5307    yymsp[0].minor.yy41 = NULL;
5308  }
5309 -#line 944 "configparser.c"
5310 +#line 939 "configparser.c"
5311          break;
5312        case 14:
5313 -#line 241 "./configparser.y"
5314 +#line 233 "./configparser.y"
5315  {
5316 -  yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43);
5317 +  if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5318 +    char *env;
5319 +
5320 +    if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) {
5321 +      data_string *ds;
5322 +      ds = data_string_init();
5323 +      buffer_append_string(ds->value, env);
5324 +      yygotominor.yy41 = (data_unset *)ds;
5325 +    }
5326 +    else {
5327 +      yygotominor.yy41 = NULL;
5328 +      fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4);
5329 +      ctx->ok = 0;
5330 +    }
5331 +  } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) {
5332 +    fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr);
5333 +    ctx->ok = 0;
5334 +  }
5335    if (!yygotominor.yy41) {
5336      /* make a dummy so it won't crash */
5337      yygotominor.yy41 = (data_unset *)data_string_init();
5338 @@ -954,50 +966,59 @@
5339    buffer_free(yymsp[0].minor.yy43);
5340    yymsp[0].minor.yy43 = NULL;
5341  }
5342 -#line 957 "configparser.c"
5343 +#line 969 "configparser.c"
5344          break;
5345        case 15:
5346 -#line 251 "./configparser.y"
5347 +#line 260 "./configparser.y"
5348  {
5349    yygotominor.yy41 = (data_unset *)data_string_init();
5350    buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
5351    buffer_free(yymsp[0].minor.yy0);
5352    yymsp[0].minor.yy0 = NULL;
5353  }
5354 -#line 967 "configparser.c"
5355 +#line 979 "configparser.c"
5356          break;
5357        case 16:
5358 -#line 258 "./configparser.y"
5359 +#line 267 "./configparser.y"
5360  {
5361    yygotominor.yy41 = (data_unset *)data_integer_init();
5362    ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
5363    buffer_free(yymsp[0].minor.yy0);
5364    yymsp[0].minor.yy0 = NULL;
5365  }
5366 -#line 977 "configparser.c"
5367 +#line 989 "configparser.c"
5368          break;
5369        case 17:
5370 -#line 264 "./configparser.y"
5371 +#line 273 "./configparser.y"
5372  {
5373    yygotominor.yy41 = (data_unset *)data_array_init();
5374    array_free(((data_array *)(yygotominor.yy41))->value);
5375    ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
5376    yymsp[0].minor.yy40 = NULL;
5377  }
5378 -#line 987 "configparser.c"
5379 +#line 999 "configparser.c"
5380          break;
5381        case 18:
5382 -#line 270 "./configparser.y"
5383 +#line 279 "./configparser.y"
5384 +{
5385 +  yygotominor.yy40 = array_init();
5386 +}
5387 +#line 1006 "configparser.c"
5388 +  yy_destructor(8,&yymsp[-1].minor);
5389 +  yy_destructor(9,&yymsp[0].minor);
5390 +        break;
5391 +      case 19:
5392 +#line 282 "./configparser.y"
5393  {
5394    yygotominor.yy40 = yymsp[-1].minor.yy40;
5395    yymsp[-1].minor.yy40 = NULL;
5396  }
5397 -#line 995 "configparser.c"
5398 +#line 1016 "configparser.c"
5399    yy_destructor(8,&yymsp[-2].minor);
5400    yy_destructor(9,&yymsp[0].minor);
5401          break;
5402 -      case 19:
5403 -#line 275 "./configparser.y"
5404 +      case 20:
5405 +#line 287 "./configparser.y"
5406  {
5407    if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
5408        NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
5409 @@ -1014,37 +1035,37 @@
5410    yygotominor.yy40 = yymsp[-2].minor.yy40;
5411    yymsp[-2].minor.yy40 = NULL;
5412  }
5413 -#line 1017 "configparser.c"
5414 +#line 1038 "configparser.c"
5415    yy_destructor(10,&yymsp[-1].minor);
5416          break;
5417 -      case 20:
5418 -#line 292 "./configparser.y"
5419 +      case 21:
5420 +#line 304 "./configparser.y"
5421  {
5422    yygotominor.yy40 = yymsp[-1].minor.yy40;
5423    yymsp[-1].minor.yy40 = NULL;
5424  }
5425 -#line 1026 "configparser.c"
5426 +#line 1047 "configparser.c"
5427    yy_destructor(10,&yymsp[0].minor);
5428          break;
5429 -      case 21:
5430 -#line 297 "./configparser.y"
5431 +      case 22:
5432 +#line 309 "./configparser.y"
5433  {
5434    yygotominor.yy40 = array_init();
5435    array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
5436    yymsp[0].minor.yy41 = NULL;
5437  }
5438 -#line 1036 "configparser.c"
5439 +#line 1057 "configparser.c"
5440          break;
5441 -      case 22:
5442 -#line 303 "./configparser.y"
5443 +      case 23:
5444 +#line 315 "./configparser.y"
5445  {
5446    yygotominor.yy41 = yymsp[0].minor.yy41;
5447    yymsp[0].minor.yy41 = NULL;
5448  }
5449 -#line 1044 "configparser.c"
5450 +#line 1065 "configparser.c"
5451          break;
5452 -      case 23:
5453 -#line 307 "./configparser.y"
5454 +      case 24:
5455 +#line 319 "./configparser.y"
5456  {
5457    buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5458    buffer_free(yymsp[-2].minor.yy43);
5459 @@ -1053,27 +1074,27 @@
5460    yygotominor.yy41 = yymsp[0].minor.yy41;
5461    yymsp[0].minor.yy41 = NULL;
5462  }
5463 -#line 1056 "configparser.c"
5464 +#line 1077 "configparser.c"
5465    yy_destructor(11,&yymsp[-1].minor);
5466          break;
5467 -      case 24:
5468 -  yy_destructor(1,&yymsp[0].minor);
5469 -        break;
5470        case 25:
5471 +  yy_destructor(1,&yymsp[0].minor);
5472          break;
5473        case 26:
5474 -#line 319 "./configparser.y"
5475 +        break;
5476 +      case 27:
5477 +#line 331 "./configparser.y"
5478  {
5479    data_config *dc;
5480    dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
5481    assert(dc);
5482    configparser_push(ctx, dc, 0);
5483  }
5484 -#line 1072 "configparser.c"
5485 +#line 1093 "configparser.c"
5486    yy_destructor(12,&yymsp[0].minor);
5487          break;
5488 -      case 27:
5489 -#line 326 "./configparser.y"
5490 +      case 28:
5491 +#line 338 "./configparser.y"
5492  {
5493    data_config *cur;
5494    
5495 @@ -1082,16 +1103,16 @@
5496  
5497    assert(cur && ctx->current);
5498  
5499 -  yygotominor.yy0 = cur;
5500 +  yygotominor.yy78 = cur;
5501  }
5502 -#line 1087 "configparser.c"
5503 +#line 1108 "configparser.c"
5504          /* No destructor defined for globalstart */
5505    yy_destructor(13,&yymsp[-2].minor);
5506          /* No destructor defined for metalines */
5507    yy_destructor(14,&yymsp[0].minor);
5508          break;
5509 -      case 28:
5510 -#line 337 "./configparser.y"
5511 +      case 29:
5512 +#line 349 "./configparser.y"
5513  {
5514    assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx);
5515    yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
5516 @@ -1100,20 +1121,20 @@
5517    yymsp[-3].minor.yy78 = NULL;
5518    yymsp[0].minor.yy78 = NULL;
5519  }
5520 -#line 1103 "configparser.c"
5521 +#line 1124 "configparser.c"
5522          /* No destructor defined for eols */
5523    yy_destructor(15,&yymsp[-1].minor);
5524          break;
5525 -      case 29:
5526 -#line 346 "./configparser.y"
5527 +      case 30:
5528 +#line 358 "./configparser.y"
5529  {
5530    yygotominor.yy78 = yymsp[0].minor.yy78;
5531    yymsp[0].minor.yy78 = NULL;
5532  }
5533 -#line 1113 "configparser.c"
5534 +#line 1134 "configparser.c"
5535          break;
5536 -      case 30:
5537 -#line 351 "./configparser.y"
5538 +      case 31:
5539 +#line 363 "./configparser.y"
5540  {
5541    data_config *cur;
5542    
5543 @@ -1124,14 +1145,14 @@
5544  
5545    yygotominor.yy78 = cur;
5546  }
5547 -#line 1127 "configparser.c"
5548 +#line 1148 "configparser.c"
5549          /* No destructor defined for context */
5550    yy_destructor(13,&yymsp[-2].minor);
5551          /* No destructor defined for metalines */
5552    yy_destructor(14,&yymsp[0].minor);
5553          break;
5554 -      case 31:
5555 -#line 362 "./configparser.y"
5556 +      case 32:
5557 +#line 374 "./configparser.y"
5558  {
5559    data_config *dc;
5560    buffer *b, *rvalue, *op;
5561 @@ -1266,45 +1287,45 @@
5562    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5563    yymsp[0].minor.yy41 = NULL;
5564  }
5565 -#line 1269 "configparser.c"
5566 +#line 1290 "configparser.c"
5567    yy_destructor(16,&yymsp[-6].minor);
5568    yy_destructor(18,&yymsp[-4].minor);
5569    yy_destructor(19,&yymsp[-2].minor);
5570          break;
5571 -      case 32:
5572 -#line 496 "./configparser.y"
5573 +      case 33:
5574 +#line 508 "./configparser.y"
5575  {
5576    yygotominor.yy27 = CONFIG_COND_EQ;
5577  }
5578 -#line 1279 "configparser.c"
5579 +#line 1300 "configparser.c"
5580    yy_destructor(20,&yymsp[0].minor);
5581          break;
5582 -      case 33:
5583 -#line 499 "./configparser.y"
5584 +      case 34:
5585 +#line 511 "./configparser.y"
5586  {
5587    yygotominor.yy27 = CONFIG_COND_MATCH;
5588  }
5589 -#line 1287 "configparser.c"
5590 +#line 1308 "configparser.c"
5591    yy_destructor(21,&yymsp[0].minor);
5592          break;
5593 -      case 34:
5594 -#line 502 "./configparser.y"
5595 +      case 35:
5596 +#line 514 "./configparser.y"
5597  {
5598    yygotominor.yy27 = CONFIG_COND_NE;
5599  }
5600 -#line 1295 "configparser.c"
5601 +#line 1316 "configparser.c"
5602    yy_destructor(22,&yymsp[0].minor);
5603          break;
5604 -      case 35:
5605 -#line 505 "./configparser.y"
5606 +      case 36:
5607 +#line 517 "./configparser.y"
5608  {
5609    yygotominor.yy27 = CONFIG_COND_NOMATCH;
5610  }
5611 -#line 1303 "configparser.c"
5612 +#line 1324 "configparser.c"
5613    yy_destructor(23,&yymsp[0].minor);
5614          break;
5615 -      case 36:
5616 -#line 509 "./configparser.y"
5617 +      case 37:
5618 +#line 521 "./configparser.y"
5619  {
5620    yygotominor.yy43 = NULL;
5621    if (ctx->ok) {
5622 @@ -1321,10 +1342,10 @@
5623    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5624    yymsp[0].minor.yy41 = NULL;
5625  }
5626 -#line 1324 "configparser.c"
5627 +#line 1345 "configparser.c"
5628          break;
5629 -      case 37:
5630 -#line 526 "./configparser.y"
5631 +      case 38:
5632 +#line 538 "./configparser.y"
5633  {
5634    if (ctx->ok) {
5635      if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5636 @@ -1334,11 +1355,11 @@
5637      yymsp[0].minor.yy43 = NULL;
5638    }
5639  }
5640 -#line 1337 "configparser.c"
5641 +#line 1358 "configparser.c"
5642    yy_destructor(24,&yymsp[-1].minor);
5643          break;
5644 -      case 38:
5645 -#line 536 "./configparser.y"
5646 +      case 39:
5647 +#line 548 "./configparser.y"
5648  {
5649    if (ctx->ok) {
5650      if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5651 @@ -1348,7 +1369,7 @@
5652      yymsp[0].minor.yy43 = NULL;
5653    }
5654  }
5655 -#line 1351 "configparser.c"
5656 +#line 1372 "configparser.c"
5657    yy_destructor(25,&yymsp[-1].minor);
5658          break;
5659    };
5660 @@ -1378,11 +1399,11 @@
5661    while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
5662    /* Here code is inserted which will be executed whenever the
5663    ** parser fails */
5664 -#line 125 "./configparser.y"
5665 +#line 107 "./configparser.y"
5666  
5667    ctx->ok = 0;
5668  
5669 -#line 1385 "configparser.c"
5670 +#line 1406 "configparser.c"
5671    configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
5672  }
5673  
5674 @@ -1489,7 +1510,7 @@
5675  #ifdef YYERRORSYMBOL
5676        /* A syntax error has occurred.
5677        ** The response to an error depends upon whether or not the
5678 -      ** grammar defines an error token "ERROR".  
5679 +      ** grammar defines an error token "ERROR".
5680        **
5681        ** This is what we do if the grammar does define ERROR:
5682        **
5683 --- ../lighttpd-1.4.11/src/configparser.y       2006-01-26 18:46:25.000000000 +0200
5684 +++ lighttpd-1.4.12/src/configparser.y  2006-07-11 22:07:53.000000000 +0300
5685 @@ -21,52 +21,34 @@
5686      dc->parent = ctx->current;
5687      array_insert_unique(dc->parent->childs, (data_unset *)dc);
5688    }
5689 -  array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
5690 +  buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
5691    ctx->current = dc;
5692  }
5693  
5694  static data_config *configparser_pop(config_t *ctx) {
5695    data_config *old = ctx->current;
5696 -  ctx->current = (data_config *) array_pop(ctx->configs_stack);
5697 +  ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
5698    return old;
5699  }
5700  
5701  /* return a copied variable */
5702  static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
5703 -  if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
5704 -    char *env;
5705 -
5706 -    if (NULL != (env = getenv(key->ptr + 4))) {
5707 -      data_string *ds;
5708 -      ds = data_string_init();
5709 -      buffer_append_string(ds->value, env);
5710 -      return (data_unset *)ds;
5711 -    }
5712 -
5713 -    fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
5714 -    ctx->ok = 0;
5715 -
5716 -    return NULL;
5717 -  } else {
5718 -    data_unset *du;
5719 -    data_config *dc;
5720 +  data_unset *du;
5721 +  data_config *dc;
5722  
5723  #if 0
5724 -    fprintf(stderr, "get var %s\n", key->ptr);
5725 +  fprintf(stderr, "get var %s\n", key->ptr);
5726  #endif
5727 -    for (dc = ctx->current; dc; dc = dc->parent) {
5728 +  for (dc = ctx->current; dc; dc = dc->parent) {
5729  #if 0
5730 -      fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5731 -      array_print(dc->value, 0);
5732 +    fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5733 +    array_print(dc->value, 0);
5734  #endif
5735 -      if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5736 -        return du->copy(du);
5737 -      }
5738 +    if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5739 +      return du->copy(du);
5740      }
5741 -    fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
5742 -    ctx->ok = 0;
5743 -    return NULL;
5744    }
5745 +  return NULL;
5746  }
5747  
5748  /* op1 is to be eat/return by this function, op1->key is not cared
5749 @@ -141,6 +123,7 @@
5750  %type       aelement               {data_unset *}
5751  %type       condline               {data_config *}
5752  %type       condlines              {data_config *}
5753 +%type       global                 {data_config *}
5754  %type       aelements              {array *}
5755  %type       array                  {array *}
5756  %type       key                    {buffer *}
5757 @@ -161,7 +144,12 @@
5758  
5759  varline ::= key(A) ASSIGN expression(B). {
5760    buffer_copy_string_buffer(B->key, A);
5761 -  if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
5762 +  if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
5763 +    fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5764 +        ctx->current->context_ndx,
5765 +        ctx->current->key->ptr, A->ptr);
5766 +    ctx->ok = 0;
5767 +  } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
5768      array_insert_unique(ctx->current->value, B);
5769      B = NULL;
5770    } else {
5771 @@ -180,7 +168,12 @@
5772    array *vars = ctx->current->value;
5773    data_unset *du;
5774  
5775 -  if (NULL != (du = array_get_element(vars, A->ptr))) {
5776 +  if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
5777 +    fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5778 +        ctx->current->context_ndx,
5779 +        ctx->current->key->ptr, A->ptr);
5780 +    ctx->ok = 0;
5781 +  } else if (NULL != (du = array_get_element(vars, A->ptr))) {
5782      /* exists in current block */
5783      du = configparser_merge_data(du, B);
5784      if (NULL == du) {
5785 @@ -190,6 +183,7 @@
5786        buffer_copy_string_buffer(du->key, A);
5787        array_replace(vars, du);
5788      }
5789 +    B->free(B);
5790    } else if (NULL != (du = configparser_get_variable(ctx, A))) {
5791      du = configparser_merge_data(du, B);
5792      if (NULL == du) {
5793 @@ -199,15 +193,13 @@
5794        buffer_copy_string_buffer(du->key, A);
5795        array_insert_unique(ctx->current->value, du);
5796      }
5797 +    B->free(B);
5798    } else {
5799 -    fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n", 
5800 -            ctx->current->context_ndx,
5801 -            ctx->current->key->ptr, A->ptr);
5802 -    ctx->ok = 0;
5803 +    buffer_copy_string_buffer(B->key, A);
5804 +    array_insert_unique(ctx->current->value, B);
5805    }
5806    buffer_free(A);
5807    A = NULL;
5808 -  B->free(B);
5809    B = NULL;
5810  }
5811  
5812 @@ -239,7 +231,24 @@
5813  }
5814  
5815  value(A) ::= key(B). {
5816 -  A = configparser_get_variable(ctx, B);
5817 +  if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
5818 +    char *env;
5819 +
5820 +    if (NULL != (env = getenv(B->ptr + 4))) {
5821 +      data_string *ds;
5822 +      ds = data_string_init();
5823 +      buffer_append_string(ds->value, env);
5824 +      A = (data_unset *)ds;
5825 +    }
5826 +    else {
5827 +      A = NULL;
5828 +      fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
5829 +      ctx->ok = 0;
5830 +    }
5831 +  } else if (NULL == (A = configparser_get_variable(ctx, B))) {
5832 +    fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
5833 +    ctx->ok = 0;
5834 +  }
5835    if (!A) {
5836      /* make a dummy so it won't crash */
5837      A = (data_unset *)data_string_init();
5838 @@ -267,6 +276,9 @@
5839    ((data_array *)(A))->value = B;
5840    B = NULL;
5841  }
5842 +array(A) ::= LPARAN RPARAN. {
5843 +  A = array_init();
5844 +}
5845  array(A) ::= LPARAN aelements(B) RPARAN. {
5846    A = B;
5847    B = NULL;
5848 --- ../lighttpd-1.4.11/src/connections-glue.c   2005-09-12 10:04:23.000000000 +0300
5849 +++ lighttpd-1.4.12/src/connections-glue.c      2006-07-11 22:07:51.000000000 +0300
5850 @@ -13,7 +13,7 @@
5851         case CON_STATE_REQUEST_END: return "req-end";
5852         case CON_STATE_RESPONSE_START: return "resp-start";
5853         case CON_STATE_RESPONSE_END: return "resp-end";
5854 -       default: return "(unknown)";    
5855 +       default: return "(unknown)";
5856         }
5857  }
5858  
5859 @@ -30,15 +30,15 @@
5860         case CON_STATE_REQUEST_END: return "Q";
5861         case CON_STATE_RESPONSE_START: return "s";
5862         case CON_STATE_RESPONSE_END: return "S";
5863 -       default: return "x";    
5864 +       default: return "x";
5865         }
5866  }
5867  
5868  int connection_set_state(server *srv, connection *con, connection_state_t state) {
5869         UNUSED(srv);
5870 -       
5871 +
5872         con->state = state;
5873 -       
5874 +
5875         return 0;
5876  }
5877  
5878 --- ../lighttpd-1.4.11/src/connections.c        2006-03-05 22:14:53.000000000 +0200
5879 +++ lighttpd-1.4.12/src/connections.c   2006-07-15 22:43:21.000000000 +0300
5880 @@ -2,7 +2,6 @@
5881  
5882  #include <stdlib.h>
5883  #include <stdio.h>
5884 -#include <unistd.h>
5885  #include <errno.h>
5886  #include <string.h>
5887  #include <fcntl.h>
5888 @@ -26,8 +25,8 @@
5889  #include "inet_ntop_cache.h"
5890  
5891  #ifdef USE_OPENSSL
5892 -# include <openssl/ssl.h> 
5893 -# include <openssl/err.h> 
5894 +# include <openssl/ssl.h>
5895 +# include <openssl/err.h>
5896  #endif
5897  
5898  #ifdef HAVE_SYS_FILIO_H
5899 @@ -35,15 +34,16 @@
5900  #endif
5901  
5902  #include "sys-socket.h"
5903 +#include "sys-files.h"
5904  
5905  typedef struct {
5906 -               PLUGIN_DATA;
5907 +       PLUGIN_DATA;
5908  } plugin_data;
5909  
5910  static connection *connections_get_new_connection(server *srv) {
5911         connections *conns = srv->conns;
5912         size_t i;
5913 -       
5914 +
5915         if (conns->size == 0) {
5916                 conns->size = 128;
5917                 conns->ptr = NULL;
5918 @@ -54,21 +54,21 @@
5919         } else if (conns->size == conns->used) {
5920                 conns->size += 128;
5921                 conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
5922 -               
5923 +
5924                 for (i = conns->used; i < conns->size; i++) {
5925                         conns->ptr[i] = connection_init(srv);
5926                 }
5927         }
5928  
5929         connection_reset(srv, conns->ptr[conns->used]);
5930 -#if 0  
5931 +#if 0
5932         fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
5933         for (i = 0; i < conns->used + 1; i++) {
5934                 fprintf(stderr, "%d ", conns->ptr[i]->fd);
5935         }
5936         fprintf(stderr, "\n");
5937 -#endif 
5938 -       
5939 +#endif
5940 +
5941         conns->ptr[conns->used]->ndx = conns->used;
5942         return conns->ptr[conns->used++];
5943  }
5944 @@ -77,26 +77,26 @@
5945         size_t i;
5946         connections *conns = srv->conns;
5947         connection *temp;
5948 -       
5949 +
5950         if (con == NULL) return -1;
5951 -       
5952 +
5953         if (-1 == con->ndx) return -1;
5954 -       
5955 +
5956         i = con->ndx;
5957 -       
5958 +
5959         /* not last element */
5960 -       
5961 +
5962         if (i != conns->used - 1) {
5963                 temp = conns->ptr[i];
5964                 conns->ptr[i] = conns->ptr[conns->used - 1];
5965                 conns->ptr[conns->used - 1] = temp;
5966 -               
5967 +
5968                 conns->ptr[i]->ndx = i;
5969                 conns->ptr[conns->used - 1]->ndx = -1;
5970         }
5971 -       
5972 +
5973         conns->used--;
5974 -       
5975 +
5976         con->ndx = -1;
5977  #if 0
5978         fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
5979 @@ -104,25 +104,23 @@
5980                 fprintf(stderr, "%d ", conns->ptr[i]->fd);
5981         }
5982         fprintf(stderr, "\n");
5983 -#endif 
5984 +#endif
5985         return 0;
5986  }
5987  
5988  int connection_close(server *srv, connection *con) {
5989  #ifdef USE_OPENSSL
5990         server_socket *srv_sock = con->srv_socket;
5991 -#endif
5992 -       
5993 -#ifdef USE_OPENSSL
5994 +
5995         if (srv_sock->is_ssl) {
5996                 if (con->ssl) SSL_free(con->ssl);
5997                 con->ssl = NULL;
5998         }
5999  #endif
6000 -       
6001 +
6002         fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
6003         fdevent_unregister(srv->ev, con->fd);
6004 -#ifdef __WIN32
6005 +#ifdef _WIN32
6006         if (closesocket(con->fd)) {
6007                 log_error_write(srv, __FILE__, __LINE__, "sds",
6008                                 "(warning) close:", con->fd, strerror(errno));
6009 @@ -133,207 +131,96 @@
6010                                 "(warning) close:", con->fd, strerror(errno));
6011         }
6012  #endif
6013 -       
6014 +
6015         srv->cur_fds--;
6016  #if 0
6017         log_error_write(srv, __FILE__, __LINE__, "sd",
6018                         "closed()", con->fd);
6019  #endif
6020 -       
6021 +
6022         connection_del(srv, con);
6023         connection_set_state(srv, con, CON_STATE_CONNECT);
6024 -       
6025 +
6026         return 0;
6027  }
6028  
6029  #if 0
6030  static void dump_packet(const unsigned char *data, size_t len) {
6031         size_t i, j;
6032 -       
6033 +
6034         if (len == 0) return;
6035 -       
6036 +
6037         for (i = 0; i < len; i++) {
6038                 if (i % 16 == 0) fprintf(stderr, "  ");
6039 -               
6040 +
6041                 fprintf(stderr, "%02x ", data[i]);
6042 -               
6043 +
6044                 if ((i + 1) % 16 == 0) {
6045                         fprintf(stderr, "  ");
6046                         for (j = 0; j <= i % 16; j++) {
6047                                 unsigned char c;
6048 -                               
6049 +
6050                                 if (i-15+j >= len) break;
6051 -                               
6052 +
6053                                 c = data[i-15+j];
6054 -                               
6055 +
6056                                 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6057                         }
6058 -                       
6059 +
6060                         fprintf(stderr, "\n");
6061                 }
6062         }
6063 -       
6064 +
6065         if (len % 16 != 0) {
6066                 for (j = i % 16; j < 16; j++) {
6067                         fprintf(stderr, "   ");
6068                 }
6069 -               
6070 +
6071                 fprintf(stderr, "  ");
6072                 for (j = i & ~0xf; j < len; j++) {
6073                         unsigned char c;
6074 -                       
6075 +
6076                         c = data[j];
6077                         fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6078                 }
6079                 fprintf(stderr, "\n");
6080         }
6081  }
6082 -#endif 
6083 -
6084 -static int connection_handle_read(server *srv, connection *con) {
6085 -       int len;
6086 -       buffer *b;
6087 -       int toread;
6088 -#ifdef USE_OPENSSL
6089 -       server_socket *srv_sock = con->srv_socket;
6090  #endif
6091  
6092 -       b = chunkqueue_get_append_buffer(con->read_queue);
6093 -       buffer_prepare_copy(b, 4096);
6094 +static network_status_t connection_handle_read(server *srv, connection *con) {
6095 +       off_t oldlen, newlen;
6096  
6097 -#ifdef USE_OPENSSL
6098 -       if (srv_sock->is_ssl) {
6099 -               len = SSL_read(con->ssl, b->ptr, b->size - 1);
6100 -       } else {
6101 -               if (ioctl(con->fd, FIONREAD, &toread)) {
6102 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
6103 -                                       "unexpected end-of-file:",
6104 -                                       con->fd);
6105 -                       return -1;
6106 -               }
6107 -               buffer_prepare_copy(b, toread);
6108 +       oldlen = chunkqueue_length(con->read_queue);
6109  
6110 -               len = read(con->fd, b->ptr, b->size - 1);
6111 -       }
6112 -#elif defined(__WIN32)
6113 -       len = recv(con->fd, b->ptr, b->size - 1, 0);
6114 -#else
6115 -       if (ioctl(con->fd, FIONREAD, &toread)) {
6116 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
6117 -                               "unexpected end-of-file:",
6118 -                               con->fd);
6119 -               return -1;
6120 -       }
6121 -       buffer_prepare_copy(b, toread);
6122 -
6123 -       len = read(con->fd, b->ptr, b->size - 1);
6124 -#endif
6125 -       
6126 -       if (len < 0) {
6127 +       switch(network_read_chunkqueue(srv, con, con->read_queue)) {
6128 +       case NETWORK_STATUS_SUCCESS:
6129 +               break;
6130 +       case NETWORK_STATUS_WAIT_FOR_EVENT:
6131 +               con->is_readable = 0;
6132 +               return NETWORK_STATUS_WAIT_FOR_EVENT;
6133 +       case NETWORK_STATUS_INTERRUPTED:
6134 +               con->is_readable = 1;
6135 +               return NETWORK_STATUS_WAIT_FOR_EVENT;
6136 +       case NETWORK_STATUS_CONNECTION_CLOSE:
6137 +               /* pipelining */
6138 +               con->is_readable = 0;
6139 +               return NETWORK_STATUS_CONNECTION_CLOSE;
6140 +       case NETWORK_STATUS_FATAL_ERROR:
6141                 con->is_readable = 0;
6142 -               
6143 -#ifdef USE_OPENSSL
6144 -               if (srv_sock->is_ssl) {
6145 -                       int r, ssl_err;
6146 -                       
6147 -                       switch ((r = SSL_get_error(con->ssl, len))) {
6148 -                       case SSL_ERROR_WANT_READ:
6149 -                               return 0;
6150 -                       case SSL_ERROR_SYSCALL:
6151 -                               /**
6152 -                                * man SSL_get_error()
6153 -                                * 
6154 -                                * SSL_ERROR_SYSCALL
6155 -                                *   Some I/O error occurred.  The OpenSSL error queue may contain more 
6156 -                                *   information on the error.  If the error queue is empty (i.e.
6157 -                                *   ERR_get_error() returns 0), ret can be used to find out more about 
6158 -                                *   the error: If ret == 0, an EOF was observed that violates the
6159 -                                *   protocol.  If ret == -1, the underlying BIO reported an I/O error 
6160 -                                *   (for socket I/O on Unix systems, consult errno for details).
6161 -                                *
6162 -                                */
6163 -                               while((ssl_err = ERR_get_error())) {
6164 -                                       /* get all errors from the error-queue */
6165 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", 
6166 -                                                       r, ERR_error_string(ssl_err, NULL));
6167 -                               }
6168  
6169 -                               switch(errno) {
6170 -                               default:
6171 -                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 
6172 -                                                       len, r, errno,
6173 -                                                       strerror(errno));
6174 -                                       break;
6175 -                               }
6176 -                               
6177 -                               break;
6178 -                       case SSL_ERROR_ZERO_RETURN:
6179 -                               /* clean shutdown on the remote side */
6180 -                               
6181 -                               if (r == 0) {
6182 -                                       /* FIXME: later */
6183 -                               }
6184 -                               
6185 -                               /* fall thourgh */
6186 -                       default:
6187 -                               while((ssl_err = ERR_get_error())) {
6188 -                                       /* get all errors from the error-queue */
6189 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", 
6190 -                                                       r, ERR_error_string(ssl_err, NULL));
6191 -                               }
6192 -                               break;
6193 -                       }
6194 -               } else {
6195 -                       if (errno == EAGAIN) return 0;
6196 -                       if (errno == EINTR) {
6197 -                               /* we have been interrupted before we could read */
6198 -                               con->is_readable = 1;
6199 -                               return 0;
6200 -                       }
6201 -               
6202 -                       if (errno != ECONNRESET) {
6203 -                               /* expected for keep-alive */
6204 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6205 -                       }
6206 -               }
6207 -#else
6208 -               if (errno == EAGAIN) return 0;
6209 -               if (errno == EINTR) {
6210 -                       /* we have been interrupted before we could read */
6211 -                       con->is_readable = 1;
6212 -                       return 0;
6213 -               }
6214 -               
6215 -               if (errno != ECONNRESET) {
6216 -                       /* expected for keep-alive */
6217 -                       log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6218 -               }
6219 -#endif
6220                 connection_set_state(srv, con, CON_STATE_ERROR);
6221 -               
6222 -               return -1;
6223 -       } else if (len == 0) {
6224 -               con->is_readable = 0;
6225 -               /* the other end close the connection -> KEEP-ALIVE */
6226 +               return NETWORK_STATUS_FATAL_ERROR;
6227 +       default:
6228 +               SEGFAULT();
6229 +               break;
6230 +       }
6231  
6232 -               /* pipelining */
6233 +       newlen = chunkqueue_length(con->read_queue);
6234  
6235 -               return -2;
6236 -       } else if ((size_t)len < b->size - 1) {
6237 -               /* we got less then expected, wait for the next fd-event */
6238 -               
6239 -               con->is_readable = 0;
6240 -       }
6241 -       
6242 -       b->used = len;
6243 -       b->ptr[b->used++] = '\0';
6244 -       
6245 -       con->bytes_read += len;
6246 -#if 0
6247 -       dump_packet(b->ptr, len);
6248 -#endif
6249 -       
6250 -       return 0;
6251 +       con->bytes_read += (newlen - oldlen);
6252 +
6253 +       return NETWORK_STATUS_SUCCESS;
6254  }
6255  
6256  static int connection_handle_write_prepare(server *srv, connection *con) {
6257 @@ -343,6 +230,7 @@
6258                 case HTTP_METHOD_GET:
6259                 case HTTP_METHOD_POST:
6260                 case HTTP_METHOD_HEAD:
6261 +                       /* webdav */
6262                 case HTTP_METHOD_PUT:
6263                 case HTTP_METHOD_MKCOL:
6264                 case HTTP_METHOD_DELETE:
6265 @@ -350,12 +238,14 @@
6266                 case HTTP_METHOD_MOVE:
6267                 case HTTP_METHOD_PROPFIND:
6268                 case HTTP_METHOD_PROPPATCH:
6269 +               case HTTP_METHOD_LOCK:
6270 +               case HTTP_METHOD_UNLOCK:
6271                         break;
6272                 case HTTP_METHOD_OPTIONS:
6273                         /*
6274                          * 400 is coming from the request-parser BEFORE uri.path is set
6275 -                        * 403 is from the response handler when noone else catched it 
6276 -                        * 
6277 +                        * 403 is from the response handler when noone else catched it
6278 +                        *
6279                          * */
6280                         if (con->uri.path->used &&
6281                             con->uri.path->ptr[0] != '*') {
6282 @@ -381,55 +271,58 @@
6283                         break;
6284                 }
6285         }
6286 -       
6287 +
6288         if (con->http_status == 0) {
6289                 con->http_status = 403;
6290         }
6291 -       
6292 +
6293         switch(con->http_status) {
6294         case 400: /* class: header + custom body */
6295         case 401:
6296         case 403:
6297         case 404:
6298         case 408:
6299 +       case 409:
6300 +       case 410:
6301         case 411:
6302         case 416:
6303         case 423:
6304         case 500:
6305         case 501:
6306         case 503:
6307 -       case 505: 
6308 +       case 505:
6309 +       case 509:
6310                 if (con->mode != DIRECT) break;
6311 -               
6312 +
6313                 con->file_finished = 0;
6314 -               
6315 +
6316                 buffer_reset(con->physical.path);
6317 -                               
6318 +
6319                 /* try to send static errorfile */
6320                 if (!buffer_is_empty(con->conf.errorfile_prefix)) {
6321                         stat_cache_entry *sce = NULL;
6322 -                       
6323 +
6324                         buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
6325                         buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
6326 -                       
6327 +
6328                         if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
6329                                 con->file_finished = 1;
6330 -                               
6331 +
6332                                 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
6333                                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
6334                         }
6335                 }
6336 -               
6337 -               if (!con->file_finished) {                      
6338 +
6339 +               if (!con->file_finished) {
6340                         buffer *b;
6341 -                       
6342 +
6343                         buffer_reset(con->physical.path);
6344 -                       
6345 +
6346                         con->file_finished = 1;
6347                         b = chunkqueue_get_append_buffer(con->write_queue);
6348 -                               
6349 +
6350                         /* build default error-page */
6351 -                       buffer_copy_string(b, 
6352 +                       buffer_copy_string(b,
6353                                            "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
6354                                            "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
6355                                            "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
6356 @@ -439,7 +332,7 @@
6357                         buffer_append_long(b, con->http_status);
6358                         buffer_append_string(b, " - ");
6359                         buffer_append_string(b, get_http_status_name(con->http_status));
6360 -                       
6361 +
6362                         buffer_append_string(b,
6363                                              "</title>\n"
6364                                              " </head>\n"
6365 @@ -448,12 +341,12 @@
6366                         buffer_append_long(b, con->http_status);
6367                         buffer_append_string(b, " - ");
6368                         buffer_append_string(b, get_http_status_name(con->http_status));
6369 -                       
6370 -                       buffer_append_string(b,"</h1>\n" 
6371 +
6372 +                       buffer_append_string(b,"</h1>\n"
6373                                              " </body>\n"
6374                                              "</html>\n"
6375                                              );
6376 -                       
6377 +
6378                         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
6379                 }
6380                 /* fall through */
6381 @@ -463,10 +356,10 @@
6382         case 301:
6383         case 302:
6384                 break;
6385 -               
6386 +
6387         case 206: /* write_queue is already prepared */
6388                 con->file_finished = 1;
6389 -               
6390 +
6391                 break;
6392         case 205: /* class: header only */
6393         case 304:
6394 @@ -474,19 +367,19 @@
6395                 /* disable chunked encoding again as we have no body */
6396                 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
6397                 chunkqueue_reset(con->write_queue);
6398 -               
6399 +
6400                 con->file_finished = 1;
6401                 break;
6402         }
6403 -       
6404 +
6405  
6406         if (con->file_finished) {
6407 -               /* we have all the content and chunked encoding is not used, set a content-length */ 
6408 -               
6409 -               if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) && 
6410 +               /* we have all the content and chunked encoding is not used, set a content-length */
6411 +
6412 +               if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6413                     (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
6414                         buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
6415 -               
6416 +
6417                         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
6418                 }
6419         } else {
6420 @@ -495,74 +388,77 @@
6421                     ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
6422                         con->keep_alive = 0;
6423                 }
6424 -               
6425 +
6426                 if (0 == (con->parsed_response & HTTP_CONNECTION)) {
6427                         /* (f)cgi did'nt send Connection: header
6428 -                        *                          
6429 +                        *
6430                          * shall we ?
6431                          */
6432                         if (((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) &&
6433                             (con->parsed_response & HTTP_CONTENT_LENGTH) == 0) {
6434                                 /* without content_length, no keep-alive */
6435 -                               
6436 +
6437                                 con->keep_alive = 0;
6438                         }
6439                 } else {
6440                         /* a subrequest disable keep-alive although the client wanted it */
6441                         if (con->keep_alive && !con->response.keep_alive) {
6442                                 con->keep_alive = 0;
6443 -                               
6444 +
6445                                 /* FIXME: we have to drop the Connection: Header from the subrequest */
6446                         }
6447                 }
6448         }
6449 -       
6450 +
6451         if (con->request.http_method == HTTP_METHOD_HEAD) {
6452                 chunkqueue_reset(con->write_queue);
6453         }
6454  
6455         http_response_write_header(srv, con);
6456 -               
6457 +
6458         return 0;
6459  }
6460  
6461  static int connection_handle_write(server *srv, connection *con) {
6462         switch(network_write_chunkqueue(srv, con, con->write_queue)) {
6463 -       case 0:
6464 +       case NETWORK_STATUS_SUCCESS:
6465                 if (con->file_finished) {
6466                         connection_set_state(srv, con, CON_STATE_RESPONSE_END);
6467                         joblist_append(srv, con);
6468                 }
6469                 break;
6470 -       case -1: /* error on our side */
6471 +       case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
6472                 log_error_write(srv, __FILE__, __LINE__, "sd",
6473                                 "connection closed: write failed on fd", con->fd);
6474                 connection_set_state(srv, con, CON_STATE_ERROR);
6475                 joblist_append(srv, con);
6476                 break;
6477 -       case -2: /* remote close */
6478 +       case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
6479                 connection_set_state(srv, con, CON_STATE_ERROR);
6480                 joblist_append(srv, con);
6481                 break;
6482 -       case 1:
6483 +       case NETWORK_STATUS_WAIT_FOR_EVENT:
6484                 con->is_writable = 0;
6485 -               
6486 +
6487                 /* not finished yet -> WRITE */
6488                 break;
6489 +       case NETWORK_STATUS_INTERRUPTED:
6490 +               con->is_writable = 1;
6491 +               break;
6492 +       case NETWORK_STATUS_UNSET:
6493 +               break;
6494         }
6495 -       
6496 +
6497         return 0;
6498  }
6499  
6500 -
6501 -
6502  connection *connection_init(server *srv) {
6503         connection *con;
6504 -       
6505 +
6506         UNUSED(srv);
6507  
6508         con = calloc(1, sizeof(*con));
6509 -               
6510 +
6511         con->fd = 0;
6512         con->ndx = -1;
6513         con->fde_ndx = -1;
6514 @@ -573,32 +469,32 @@
6515  
6516  #define CLEAN(x) \
6517         con->x = buffer_init();
6518 -       
6519 +
6520         CLEAN(request.uri);
6521         CLEAN(request.request_line);
6522         CLEAN(request.request);
6523         CLEAN(request.pathinfo);
6524 -       
6525 +
6526         CLEAN(request.orig_uri);
6527 -       
6528 +
6529         CLEAN(uri.scheme);
6530         CLEAN(uri.authority);
6531         CLEAN(uri.path);
6532         CLEAN(uri.path_raw);
6533         CLEAN(uri.query);
6534 -       
6535 +
6536         CLEAN(physical.doc_root);
6537         CLEAN(physical.path);
6538         CLEAN(physical.basedir);
6539         CLEAN(physical.rel_path);
6540         CLEAN(physical.etag);
6541         CLEAN(parse_request);
6542 -       
6543 +
6544         CLEAN(authed_user);
6545         CLEAN(server_name);
6546         CLEAN(error_handler);
6547         CLEAN(dst_addr_buf);
6548 -       
6549 +
6550  #undef CLEAN
6551         con->write_queue = chunkqueue_init();
6552         con->read_queue = chunkqueue_init();
6553 @@ -608,26 +504,26 @@
6554         con->request.headers      = array_init();
6555         con->response.headers     = array_init();
6556         con->environment     = array_init();
6557 -       
6558 +
6559         /* init plugin specific connection structures */
6560 -       
6561 +
6562         con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
6563 -       
6564 +
6565         con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
6566         config_setup_connection(srv, con);
6567 -       
6568 +
6569         return con;
6570  }
6571  
6572  void connections_free(server *srv) {
6573         connections *conns = srv->conns;
6574 -       size_t i;       
6575 -       
6576 +       size_t i;
6577 +
6578         for (i = 0; i < conns->size; i++) {
6579                 connection *con = conns->ptr[i];
6580 -               
6581 +
6582                 connection_reset(srv, con);
6583 -               
6584 +
6585                 chunkqueue_free(con->write_queue);
6586                 chunkqueue_free(con->read_queue);
6587                 chunkqueue_free(con->request_content_queue);
6588 @@ -637,27 +533,27 @@
6589  
6590  #define CLEAN(x) \
6591         buffer_free(con->x);
6592 -               
6593 +
6594                 CLEAN(request.uri);
6595                 CLEAN(request.request_line);
6596                 CLEAN(request.request);
6597                 CLEAN(request.pathinfo);
6598 -               
6599 +
6600                 CLEAN(request.orig_uri);
6601 -               
6602 +
6603                 CLEAN(uri.scheme);
6604                 CLEAN(uri.authority);
6605                 CLEAN(uri.path);
6606                 CLEAN(uri.path_raw);
6607                 CLEAN(uri.query);
6608 -               
6609 +
6610                 CLEAN(physical.doc_root);
6611                 CLEAN(physical.path);
6612                 CLEAN(physical.basedir);
6613                 CLEAN(physical.etag);
6614                 CLEAN(physical.rel_path);
6615                 CLEAN(parse_request);
6616 -               
6617 +
6618                 CLEAN(authed_user);
6619                 CLEAN(server_name);
6620                 CLEAN(error_handler);
6621 @@ -665,97 +561,97 @@
6622  #undef CLEAN
6623                 free(con->plugin_ctx);
6624                 free(con->cond_cache);
6625 -               
6626 +
6627                 free(con);
6628         }
6629 -       
6630 +
6631         free(conns->ptr);
6632  }
6633  
6634  
6635  int connection_reset(server *srv, connection *con) {
6636         size_t i;
6637 -       
6638 +
6639         plugins_call_connection_reset(srv, con);
6640 -       
6641 +
6642         con->is_readable = 1;
6643         con->is_writable = 1;
6644         con->http_status = 0;
6645         con->file_finished = 0;
6646         con->file_started = 0;
6647         con->got_response = 0;
6648 -       
6649 +
6650         con->parsed_response = 0;
6651 -       
6652 +
6653         con->bytes_written = 0;
6654         con->bytes_written_cur_second = 0;
6655         con->bytes_read = 0;
6656         con->bytes_header = 0;
6657         con->loops_per_request = 0;
6658 -       
6659 +
6660         con->request.http_method = HTTP_METHOD_UNSET;
6661         con->request.http_version = HTTP_VERSION_UNSET;
6662 -       
6663 +
6664         con->request.http_if_modified_since = NULL;
6665         con->request.http_if_none_match = NULL;
6666 -       
6667 +
6668         con->response.keep_alive = 0;
6669         con->response.content_length = -1;
6670         con->response.transfer_encoding = 0;
6671 -       
6672 +
6673         con->mode = DIRECT;
6674 -       
6675 +
6676  #define CLEAN(x) \
6677         if (con->x) buffer_reset(con->x);
6678 -       
6679 +
6680         CLEAN(request.uri);
6681         CLEAN(request.request_line);
6682         CLEAN(request.pathinfo);
6683         CLEAN(request.request);
6684 -       
6685 +
6686         CLEAN(request.orig_uri);
6687 -       
6688 +
6689         CLEAN(uri.scheme);
6690         CLEAN(uri.authority);
6691         CLEAN(uri.path);
6692         CLEAN(uri.path_raw);
6693         CLEAN(uri.query);
6694 -       
6695 +
6696         CLEAN(physical.doc_root);
6697         CLEAN(physical.path);
6698         CLEAN(physical.basedir);
6699         CLEAN(physical.rel_path);
6700         CLEAN(physical.etag);
6701 -       
6702 +
6703         CLEAN(parse_request);
6704 -       
6705 +
6706         CLEAN(authed_user);
6707         CLEAN(server_name);
6708         CLEAN(error_handler);
6709 -#undef CLEAN   
6710 -       
6711 +#undef CLEAN
6712 +
6713  #define CLEAN(x) \
6714 -       if (con->x) con->x->used = 0;   
6715 -       
6716 +       if (con->x) con->x->used = 0;
6717 +
6718  #undef CLEAN
6719 -       
6720 +
6721  #define CLEAN(x) \
6722                 con->request.x = NULL;
6723 -       
6724 +
6725         CLEAN(http_host);
6726         CLEAN(http_range);
6727         CLEAN(http_content_type);
6728  #undef CLEAN
6729         con->request.content_length = 0;
6730 -       
6731 +
6732         array_reset(con->request.headers);
6733         array_reset(con->response.headers);
6734         array_reset(con->environment);
6735 -       
6736 +
6737         chunkqueue_reset(con->write_queue);
6738         chunkqueue_reset(con->request_content_queue);
6739  
6740 -       /* the plugins should cleanup themself */       
6741 +       /* the plugins should cleanup themself */
6742         for (i = 0; i < srv->plugins.used; i++) {
6743                 plugin *p = ((plugin **)(srv->plugins.ptr))[i];
6744                 plugin_data *pd = p->data;
6745 @@ -768,7 +664,7 @@
6746  
6747                 con->plugin_ctx[pd->id] = NULL;
6748         }
6749 -       
6750 +
6751  #if COND_RESULT_UNSET
6752         for (i = srv->config_context->used - 1; i >= 0; i --) {
6753                 con->cond_cache[i].result = COND_RESULT_UNSET;
6754 @@ -777,56 +673,56 @@
6755  #else
6756         memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
6757  #endif
6758 -       
6759 +
6760         con->header_len = 0;
6761         con->in_error_handler = 0;
6762 -       
6763 +
6764         config_setup_connection(srv, con);
6765 -       
6766 +
6767         return 0;
6768  }
6769  
6770  /**
6771 - * 
6772 - * search for \r\n\r\n 
6773 - * 
6774 + *
6775 + * search for \r\n\r\n
6776 + *
6777   * this is a special 32bit version which is using a sliding window for
6778 - * the comparisions 
6779 - * 
6780 + * the comparisions
6781 + *
6782   * how it works:
6783 - * 
6784 + *
6785   * b:      'abcdefg'
6786   * rnrn:   'cdef'
6787 - * 
6788 + *
6789   * cmpbuf: abcd != cdef
6790   * cmpbuf: bcde != cdef
6791   * cmpbuf: cdef == cdef -> return &c
6792 - * 
6793 - * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to 
6794 + *
6795 + * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
6796   * maintain cmpbuf and rnrn
6797 - * 
6798 + *
6799   */
6800  
6801  char *buffer_search_rnrn(buffer *b) {
6802         uint32_t cmpbuf, rnrn;
6803         char *cp;
6804         size_t i;
6805 -       
6806 +
6807         if (b->used < 4) return NULL;
6808 -       
6809 +
6810         rnrn = ('\r' << 24) | ('\n' << 16) |
6811                 ('\r' << 8) | ('\n' << 0);
6812 -       
6813 +
6814         cmpbuf = (b->ptr[0] << 24) | (b->ptr[1] << 16) |
6815                 (b->ptr[2] << 8) | (b->ptr[3] << 0);
6816 -               
6817 +
6818         cp = b->ptr + 4;
6819         for (i = 0; i < b->used - 4; i++) {
6820                 if (cmpbuf == rnrn) return cp - 4;
6821 -                       
6822 +
6823                 cmpbuf = (cmpbuf << 8 | *(cp++)) & 0xffffffff;
6824         }
6825 -       
6826 +
6827         return NULL;
6828  }
6829  /**
6830 @@ -840,22 +736,25 @@
6831         chunk *c;
6832         chunkqueue *cq = con->read_queue;
6833         chunkqueue *dst_cq = con->request_content_queue;
6834 -       
6835 +
6836         if (con->is_readable) {
6837                 con->read_idle_ts = srv->cur_ts;
6838 -       
6839 +
6840                 switch(connection_handle_read(srv, con)) {
6841 -               case -1:
6842 +               case NETWORK_STATUS_FATAL_ERROR:
6843                         return -1;
6844 -               case -2:
6845 +               case NETWORK_STATUS_CONNECTION_CLOSE:
6846                         /* remote side closed the connection
6847                          * if we still have content, handle it, if not leave here */
6848  
6849                         if (cq->first == cq->last &&
6850 -                           cq->first->mem->used == 0) {
6851 +                           (NULL == cq->first ||
6852 +                           cq->first->mem->used == 0)) {
6853  
6854                                 /* conn-closed, leave here */
6855                                 connection_set_state(srv, con, CON_STATE_ERROR);
6856 +
6857 +                               return 0;
6858                         }
6859                 default:
6860                         break;
6861 @@ -891,14 +790,14 @@
6862                         /* the last node was empty */
6863                         if (c->next == NULL) {
6864                                 cq->last = c;
6865 -                       } 
6866 +                       }
6867  
6868                         c = c->next;
6869                 } else {
6870                         c = c->next;
6871                 }
6872         }
6873 -       
6874 +
6875         /* nothing to handle */
6876         if (cq->first == NULL) return 0;
6877  
6878 @@ -906,25 +805,26 @@
6879         case CON_STATE_READ:
6880                 /* prepare con->request.request */
6881                 c = cq->first;
6882 -               
6883 +
6884                 /* check if we need the full package */
6885                 if (con->request.request->used == 0) {
6886                         buffer b;
6887 -                       
6888 +
6889                         b.ptr = c->mem->ptr + c->offset;
6890                         b.used = c->mem->used - c->offset;
6891 -                       
6892 +
6893                         if (NULL != (h_term = buffer_search_rnrn(&b))) {
6894                                 /* \r\n\r\n found
6895                                  * - copy everything incl. the terminator to request.request
6896                                  */
6897 -                               
6898 -                               buffer_copy_string_len(con->request.request, 
6899 -                                                      b.ptr, 
6900 +
6901 +                               buffer_copy_string_len(con->request.request,
6902 +                                                      b.ptr,
6903                                                        h_term - b.ptr + 4);
6904 -                               
6905 +
6906                                 /* the buffer has been read up to the terminator */
6907                                 c->offset += h_term - b.ptr + 4;
6908 +
6909                         } else {
6910                                 /* not found, copy everything */
6911                                 buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
6912 @@ -932,14 +832,14 @@
6913                         }
6914                 } else {
6915                         /* have to take care of overlapping header terminators */
6916 -                       
6917 +
6918                         size_t l = con->request.request->used - 2;
6919                         char *s  = con->request.request->ptr;
6920                         buffer b;
6921 -                       
6922 +
6923                         b.ptr = c->mem->ptr + c->offset;
6924                         b.used = c->mem->used - c->offset;
6925 -                       
6926 +
6927                         if (con->request.request->used - 1 > 3 &&
6928                             c->mem->used > 1 &&
6929                             s[l-2] == '\r' &&
6930 @@ -948,7 +848,7 @@
6931                             c->mem->ptr[0] == '\n') {
6932                                 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
6933                                 c->offset += 1;
6934 -                               
6935 +
6936                                 h_term = con->request.request->ptr;
6937                         } else if (con->request.request->used - 1 > 2 &&
6938                                    c->mem->used > 2 &&
6939 @@ -958,7 +858,7 @@
6940                                    c->mem->ptr[1] == '\n') {
6941                                 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
6942                                 c->offset += 2;
6943 -                               
6944 +
6945                                 h_term = con->request.request->ptr;
6946                         } else if (con->request.request->used - 1 > 1 &&
6947                                    c->mem->used > 3 &&
6948 @@ -968,17 +868,17 @@
6949                                    c->mem->ptr[2] == '\n') {
6950                                 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3);
6951                                 c->offset += 3;
6952 -                               
6953 +
6954                                 h_term = con->request.request->ptr;
6955                         } else if (NULL != (h_term = buffer_search_string_len(&b, "\r\n\r\n", 4))) {
6956                                 /* \r\n\r\n found
6957                                  * - copy everything incl. the terminator to request.request
6958                                  */
6959 -                               
6960 -                               buffer_append_string_len(con->request.request, 
6961 -                                                      c->mem->ptr + c->offset, 
6962 +
6963 +                               buffer_append_string_len(con->request.request,
6964 +                                                      c->mem->ptr + c->offset,
6965                                                        c->offset + h_term - b.ptr + 4);
6966 -                               
6967 +
6968                                 /* the buffer has been read up to the terminator */
6969                                 c->offset += h_term - b.ptr + 4;
6970                         } else {
6971 @@ -999,16 +899,16 @@
6972                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
6973                 }
6974                 break;
6975 -       case CON_STATE_READ_POST: 
6976 +       case CON_STATE_READ_POST:
6977                 for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
6978                         off_t weWant, weHave, toRead;
6979 -                       
6980 +
6981                         weWant = con->request.content_length - dst_cq->bytes_in;
6982 -                       
6983 +
6984                         assert(c->mem->used);
6985 -                       
6986 +
6987                         weHave = c->mem->used - c->offset - 1;
6988 -                               
6989 +
6990                         toRead = weHave > weWant ? weWant : weHave;
6991  
6992                         /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
6993 @@ -1017,13 +917,13 @@
6994                                 /* copy everything to max 1Mb sized tempfiles */
6995  
6996                                 /*
6997 -                                * if the last chunk is 
6998 +                                * if the last chunk is
6999                                  * - smaller than 1Mb (size < 1Mb)
7000                                  * - not read yet (offset == 0)
7001                                  * -> append to it
7002                                  * otherwise
7003 -                                * -> create a new chunk 
7004 -                                * 
7005 +                                * -> create a new chunk
7006 +                                *
7007                                  * */
7008  
7009                                 if (dst_cq->last &&
7010 @@ -1056,14 +956,14 @@
7011                                 /* we have a chunk, let's write to it */
7012  
7013                                 if (dst_c->file.fd == -1) {
7014 -                                       /* we don't have file to write to, 
7015 +                                       /* we don't have file to write to,
7016                                          * EACCES might be one reason.
7017                                          *
7018                                          * Instead of sending 500 we send 413 and say the request is too large
7019                                          *  */
7020  
7021                                         log_error_write(srv, __FILE__, __LINE__, "sbs",
7022 -                                                       "denying upload as opening to temp-file for upload failed:", 
7023 +                                                       "denying upload as opening to temp-file for upload failed:",
7024                                                         dst_c->file.name, strerror(errno));
7025  
7026                                         con->http_status = 413; /* Request-Entity too large */
7027 @@ -1074,15 +974,15 @@
7028                                 }
7029  
7030                                 if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
7031 -                                       /* write failed for some reason ... disk full ? */ 
7032 +                                       /* write failed for some reason ... disk full ? */
7033                                         log_error_write(srv, __FILE__, __LINE__, "sbs",
7034 -                                                       "denying upload as writing to file failed:", 
7035 +                                                       "denying upload as writing to file failed:",
7036                                                         dst_c->file.name, strerror(errno));
7037 -                                       
7038 +
7039                                         con->http_status = 413; /* Request-Entity too large */
7040                                         con->keep_alive = 0;
7041                                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7042 -                               
7043 +
7044                                         close(dst_c->file.fd);
7045                                         dst_c->file.fd = -1;
7046  
7047 @@ -1090,7 +990,7 @@
7048                                 }
7049  
7050                                 dst_c->file.length += toRead;
7051 -                                       
7052 +
7053                                 if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
7054                                         /* we read everything, close the chunk */
7055                                         close(dst_c->file.fd);
7056 @@ -1102,7 +1002,7 @@
7057                                 b = chunkqueue_get_append_buffer(dst_cq);
7058                                 buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
7059                         }
7060 -                       
7061 +
7062                         c->offset += toRead;
7063                         dst_cq->bytes_in += toRead;
7064                 }
7065 @@ -1111,7 +1011,7 @@
7066                 if (dst_cq->bytes_in == (off_t)con->request.content_length) {
7067                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7068                 }
7069 -                       
7070 +
7071                 break;
7072         }
7073  
7074 @@ -1123,9 +1023,9 @@
7075  handler_t connection_handle_fdevent(void *s, void *context, int revents) {
7076         server     *srv = (server *)s;
7077         connection *con = context;
7078 -       
7079 +
7080         joblist_append(srv, con);
7081 -       
7082 +
7083         if (revents & FDEVENT_IN) {
7084                 con->is_readable = 1;
7085  #if 0
7086 @@ -1136,19 +1036,19 @@
7087                 con->is_writable = 1;
7088                 /* we don't need the event twice */
7089         }
7090 -       
7091 -       
7092 +
7093 +
7094         if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
7095                 /* looks like an error */
7096 -                                               
7097 +
7098                 /* FIXME: revents = 0x19 still means that we should read from the queue */
7099                 if (revents & FDEVENT_HUP) {
7100                         if (con->state == CON_STATE_CLOSE) {
7101                                 con->close_timeout_ts = 0;
7102                         } else {
7103                                 /* sigio reports the wrong event here
7104 -                                * 
7105 -                                * there was no HUP at all 
7106 +                                *
7107 +                                * there was no HUP at all
7108                                  */
7109  #ifdef USE_LINUX_SIGIO
7110                                 if (srv->ev->in_sigio == 1) {
7111 @@ -1160,32 +1060,39 @@
7112  #else
7113                                 connection_set_state(srv, con, CON_STATE_ERROR);
7114  #endif
7115 -                               
7116 +
7117                         }
7118                 } else if (revents & FDEVENT_ERR) {
7119  #ifndef USE_LINUX_SIGIO
7120                         log_error_write(srv, __FILE__, __LINE__, "sd",
7121                                         "connection closed: poll() -> ERR", con->fd);
7122 -#endif 
7123 +#endif
7124                         connection_set_state(srv, con, CON_STATE_ERROR);
7125                 } else {
7126                         log_error_write(srv, __FILE__, __LINE__, "sd",
7127                                         "connection closed: poll() -> ???", revents);
7128 -               } 
7129 +               }
7130         }
7131 -       
7132 +
7133         if (con->state == CON_STATE_READ ||
7134             con->state == CON_STATE_READ_POST) {
7135                 connection_handle_read_state(srv, con);
7136 +               /**
7137 +                * if SSL_read() is not readin in the full packet we won't get
7138 +                * a fdevent as the low-level has already fetched everything.
7139 +                *
7140 +                * we have to call the state-engine to read the rest of the packet
7141 +                */
7142 +               if (con->is_readable) joblist_append(srv, con);
7143         }
7144 -       
7145 +
7146         if (con->state == CON_STATE_WRITE &&
7147             !chunkqueue_is_empty(con->write_queue) &&
7148             con->is_writable) {
7149 -               
7150 +
7151                 if (-1 == connection_handle_write(srv, con)) {
7152                         connection_set_state(srv, con, CON_STATE_ERROR);
7153 -                       
7154 +
7155                         log_error_write(srv, __FILE__, __LINE__, "ds",
7156                                         con->fd,
7157                                         "handle write failed.");
7158 @@ -1193,30 +1100,30 @@
7159                         con->write_request_ts = srv->cur_ts;
7160                 }
7161         }
7162 -       
7163 +
7164         if (con->state == CON_STATE_CLOSE) {
7165                 /* flush the read buffers */
7166                 int b;
7167 -               
7168 +
7169                 if (ioctl(con->fd, FIONREAD, &b)) {
7170                         log_error_write(srv, __FILE__, __LINE__, "ss",
7171                                         "ioctl() failed", strerror(errno));
7172                 }
7173 -               
7174 +
7175                 if (b > 0) {
7176                         char buf[1024];
7177                         log_error_write(srv, __FILE__, __LINE__, "sdd",
7178                                         "CLOSE-read()", con->fd, b);
7179 -                       
7180 +
7181                         /* */
7182                         read(con->fd, buf, sizeof(buf));
7183                 } else {
7184                         /* nothing to read */
7185 -                       
7186 +
7187                         con->close_timeout_ts = 0;
7188                 }
7189         }
7190 -       
7191 +
7192         return HANDLER_FINISHED;
7193  }
7194  
7195 @@ -1229,63 +1136,68 @@
7196         sock_addr cnt_addr;
7197         socklen_t cnt_len;
7198         /* accept it and register the fd */
7199 -       
7200 +
7201         cnt_len = sizeof(cnt_addr);
7202  
7203         if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
7204 +#ifdef _WIN32
7205 +               errno = WSAGetLastError();
7206 +#endif
7207                 if ((errno != EAGAIN) &&
7208 +                   (errno != EWOULDBLOCK) &&
7209                     (errno != EINTR)) {
7210 -                       log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
7211 +                       log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), srv_socket->fd);
7212                 }
7213                 return NULL;
7214         } else {
7215                 connection *con;
7216 -               
7217 +
7218                 srv->cur_fds++;
7219 -               
7220 +
7221                 /* ok, we have the connection, register it */
7222  #if 0
7223                 log_error_write(srv, __FILE__, __LINE__, "sd",
7224                                 "appected()", cnt);
7225  #endif
7226                 srv->con_opened++;
7227 -               
7228 +
7229                 con = connections_get_new_connection(srv);
7230 -               
7231                 con->fd = cnt;
7232                 con->fde_ndx = -1;
7233 -#if 0          
7234 +#if 0
7235                 gettimeofday(&(con->start_tv), NULL);
7236 -#endif         
7237 +#endif
7238                 fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
7239 -               
7240 +
7241                 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7242 -               
7243 +
7244                 con->connection_start = srv->cur_ts;
7245                 con->dst_addr = cnt_addr;
7246                 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
7247                 con->srv_socket = srv_socket;
7248 -               
7249 +
7250                 if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
7251                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
7252 +                       connection_close(srv, con);
7253                         return NULL;
7254                 }
7255  #ifdef USE_OPENSSL
7256                 /* connect FD to SSL */
7257                 if (srv_socket->is_ssl) {
7258                         if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
7259 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
7260 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7261                                                 ERR_error_string(ERR_get_error(), NULL));
7262 -                               
7263 +                               connection_close(srv, con);
7264                                 return NULL;
7265                         }
7266 -                       
7267 +
7268                         SSL_set_accept_state(con->ssl);
7269                         con->conf.is_ssl=1;
7270 -                       
7271 +
7272                         if (1 != (SSL_set_fd(con->ssl, cnt))) {
7273 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
7274 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7275                                                 ERR_error_string(ERR_get_error(), NULL));
7276 +                               connection_close(srv, con);
7277                                 return NULL;
7278                         }
7279                 }
7280 @@ -1300,10 +1212,10 @@
7281  #ifdef USE_OPENSSL
7282         server_socket *srv_sock = con->srv_socket;
7283  #endif
7284 -       
7285 +
7286         if (srv->srvconf.log_state_handling) {
7287 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
7288 -                               "state at start", 
7289 +               log_error_write(srv, __FILE__, __LINE__, "sds",
7290 +                               "state at start",
7291                                 con->fd,
7292                                 connection_get_state(con->state));
7293         }
7294 @@ -1311,91 +1223,91 @@
7295         while (done == 0) {
7296                 size_t ostate = con->state;
7297                 int b;
7298 -               
7299 +
7300                 switch (con->state) {
7301                 case CON_STATE_REQUEST_START: /* transient */
7302                         if (srv->srvconf.log_state_handling) {
7303 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7304 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7305                                                 "state for fd", con->fd, connection_get_state(con->state));
7306                         }
7307 -                       
7308 +
7309                         con->request_start = srv->cur_ts;
7310                         con->read_idle_ts = srv->cur_ts;
7311 -                       
7312 +
7313                         con->request_count++;
7314                         con->loops_per_request = 0;
7315 -                       
7316 +
7317                         connection_set_state(srv, con, CON_STATE_READ);
7318 -                       
7319 +
7320                         break;
7321                 case CON_STATE_REQUEST_END: /* transient */
7322                         if (srv->srvconf.log_state_handling) {
7323 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7324 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7325                                                 "state for fd", con->fd, connection_get_state(con->state));
7326                         }
7327 -                       
7328 +
7329                         if (http_request_parse(srv, con)) {
7330                                 /* we have to read some data from the POST request */
7331 -                               
7332 +
7333                                 connection_set_state(srv, con, CON_STATE_READ_POST);
7334  
7335                                 break;
7336                         }
7337 -                       
7338 +
7339                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7340 -                       
7341 +
7342                         break;
7343                 case CON_STATE_HANDLE_REQUEST:
7344 -                       /* 
7345 +                       /*
7346                          * the request is parsed
7347 -                        * 
7348 +                        *
7349                          * decided what to do with the request
7350 -                        * - 
7351 -                        * 
7352 -                        * 
7353 +                        * -
7354 +                        *
7355 +                        *
7356                          */
7357 -                       
7358 +
7359                         if (srv->srvconf.log_state_handling) {
7360 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7361 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7362                                                 "state for fd", con->fd, connection_get_state(con->state));
7363                         }
7364 -                       
7365 +
7366                         switch (r = http_response_prepare(srv, con)) {
7367                         case HANDLER_FINISHED:
7368                                 if (con->http_status == 404 ||
7369                                     con->http_status == 403) {
7370                                         /* 404 error-handler */
7371 -                                       
7372 -                                       if (con->in_error_handler == 0 && 
7373 +
7374 +                                       if (con->in_error_handler == 0 &&
7375                                             (!buffer_is_empty(con->conf.error_handler) ||
7376                                              !buffer_is_empty(con->error_handler))) {
7377                                                 /* call error-handler */
7378 -                                               
7379 +
7380                                                 con->error_handler_saved_status = con->http_status;
7381                                                 con->http_status = 0;
7382 -                                               
7383 +
7384                                                 if (buffer_is_empty(con->error_handler)) {
7385                                                         buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
7386                                                 } else {
7387                                                         buffer_copy_string_buffer(con->request.uri, con->error_handler);
7388                                                 }
7389                                                 buffer_reset(con->physical.path);
7390 -                                               
7391 +
7392                                                 con->in_error_handler = 1;
7393 -                                               
7394 +
7395                                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7396 -                                               
7397 +
7398                                                 done = -1;
7399                                                 break;
7400                                         } else if (con->in_error_handler) {
7401                                                 /* error-handler is a 404 */
7402 -                                               
7403 +
7404                                                 /* continue as normal, status is the same */
7405 -                                               log_error_write(srv, __FILE__, __LINE__, "sb", 
7406 +                                               log_error_write(srv, __FILE__, __LINE__, "sb",
7407                                                                 "Warning: Either the error-handler returned status 404 or the error-handler itself was not found:", con->request.uri);
7408 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
7409 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
7410                                                                 "returning the original status", con->error_handler_saved_status);
7411 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
7412 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
7413                                                                 "If this is a rails app: check your production.log");
7414                                                 con->http_status = con->error_handler_saved_status;
7415                                         }
7416 @@ -1403,26 +1315,26 @@
7417                                         /* error-handler is back and has generated content */
7418                                         /* if Status: was set, take it otherwise use 200 */
7419                                 }
7420 -                               
7421 +
7422                                 if (con->http_status == 0) con->http_status = 200;
7423 -                               
7424 +
7425                                 /* we have something to send, go on */
7426                                 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
7427                                 break;
7428                         case HANDLER_WAIT_FOR_FD:
7429                                 srv->want_fds++;
7430 -                               
7431 +
7432                                 fdwaitqueue_append(srv, con);
7433 -                               
7434 +
7435                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7436 -                               
7437 +
7438                                 break;
7439                         case HANDLER_COMEBACK:
7440                                 done = -1;
7441                         case HANDLER_WAIT_FOR_EVENT:
7442                                 /* come back here */
7443                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7444 -                               
7445 +
7446                                 break;
7447                         case HANDLER_ERROR:
7448                                 /* something went wrong */
7449 @@ -1432,44 +1344,44 @@
7450                                 log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
7451                                 break;
7452                         }
7453 -                       
7454 +
7455                         break;
7456                 case CON_STATE_RESPONSE_START:
7457 -                       /* 
7458 +                       /*
7459                          * the decision is done
7460                          * - create the HTTP-Response-Header
7461 -                        * 
7462 +                        *
7463                          */
7464 -                       
7465 +
7466                         if (srv->srvconf.log_state_handling) {
7467 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7468 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7469                                                 "state for fd", con->fd, connection_get_state(con->state));
7470                         }
7471 -                       
7472 +
7473                         if (-1 == connection_handle_write_prepare(srv, con)) {
7474                                 connection_set_state(srv, con, CON_STATE_ERROR);
7475 -                               
7476 +
7477                                 break;
7478                         }
7479 -                       
7480 +
7481                         connection_set_state(srv, con, CON_STATE_WRITE);
7482                         break;
7483                 case CON_STATE_RESPONSE_END: /* transient */
7484                         /* log the request */
7485 -                       
7486 +
7487                         if (srv->srvconf.log_state_handling) {
7488 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7489 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7490                                                 "state for fd", con->fd, connection_get_state(con->state));
7491                         }
7492 -                       
7493 +
7494                         plugins_call_handle_request_done(srv, con);
7495 -                       
7496 +
7497                         srv->con_written++;
7498 -                       
7499 +
7500                         if (con->keep_alive) {
7501                                 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7502 -                               
7503 -#if 0                                  
7504 +
7505 +#if 0
7506                                 con->request_start = srv->cur_ts;
7507                                 con->read_idle_ts = srv->cur_ts;
7508  #endif
7509 @@ -1482,7 +1394,7 @@
7510                                         log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
7511                                         break;
7512                                 }
7513 -                               
7514 +
7515  #ifdef USE_OPENSSL
7516                                 if (srv_sock->is_ssl) {
7517                                         switch (SSL_shutdown(con->ssl)) {
7518 @@ -1490,44 +1402,44 @@
7519                                                 /* done */
7520                                                 break;
7521                                         case 0:
7522 -                                               /* wait for fd-event 
7523 -                                                * 
7524 +                                               /* wait for fd-event
7525 +                                                *
7526                                                  * FIXME: wait for fdevent and call SSL_shutdown again
7527 -                                                * 
7528 +                                                *
7529                                                  */
7530 -                                               
7531 +
7532                                                 break;
7533                                         default:
7534 -                                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
7535 +                                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7536                                                                 ERR_error_string(ERR_get_error(), NULL));
7537                                         }
7538                                 }
7539  #endif
7540                                 connection_close(srv, con);
7541 -                               
7542 +
7543                                 srv->con_closed++;
7544                         }
7545 -                       
7546 +
7547                         connection_reset(srv, con);
7548 -                       
7549 +
7550                         break;
7551                 case CON_STATE_CONNECT:
7552                         if (srv->srvconf.log_state_handling) {
7553 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7554 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7555                                                 "state for fd", con->fd, connection_get_state(con->state));
7556                         }
7557 -                       
7558 +
7559                         chunkqueue_reset(con->read_queue);
7560 -                       
7561 +
7562                         con->request_count = 0;
7563 -                       
7564 +
7565                         break;
7566                 case CON_STATE_CLOSE:
7567                         if (srv->srvconf.log_state_handling) {
7568 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7569 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7570                                                 "state for fd", con->fd, connection_get_state(con->state));
7571                         }
7572 -                       
7573 +
7574                         if (con->keep_alive) {
7575                                 if (ioctl(con->fd, FIONREAD, &b)) {
7576                                         log_error_write(srv, __FILE__, __LINE__, "ss",
7577 @@ -1537,43 +1449,43 @@
7578                                         char buf[1024];
7579                                         log_error_write(srv, __FILE__, __LINE__, "sdd",
7580                                                         "CLOSE-read()", con->fd, b);
7581 -                                       
7582 +
7583                                         /* */
7584                                         read(con->fd, buf, sizeof(buf));
7585                                 } else {
7586                                         /* nothing to read */
7587 -                                       
7588 +
7589                                         con->close_timeout_ts = 0;
7590                                 }
7591                         } else {
7592                                 con->close_timeout_ts = 0;
7593                         }
7594 -                       
7595 +
7596                         if (srv->cur_ts - con->close_timeout_ts > 1) {
7597                                 connection_close(srv, con);
7598 -                               
7599 +
7600                                 if (srv->srvconf.log_state_handling) {
7601 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
7602 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
7603                                                         "connection closed for fd", con->fd);
7604                                 }
7605                         }
7606 -                       
7607 +
7608                         break;
7609                 case CON_STATE_READ_POST:
7610                 case CON_STATE_READ:
7611                         if (srv->srvconf.log_state_handling) {
7612 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7613 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7614                                                 "state for fd", con->fd, connection_get_state(con->state));
7615                         }
7616 -                       
7617 +
7618                         connection_handle_read_state(srv, con);
7619                         break;
7620                 case CON_STATE_WRITE:
7621                         if (srv->srvconf.log_state_handling) {
7622 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7623 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7624                                                 "state for fd", con->fd, connection_get_state(con->state));
7625                         }
7626 -                       
7627 +
7628                         /* only try to write if we have something in the queue */
7629                         if (!chunkqueue_is_empty(con->write_queue)) {
7630  #if 0
7631 @@ -1593,10 +1505,10 @@
7632                                         con->write_request_ts = srv->cur_ts;
7633                                 }
7634                         }
7635 -                       
7636 +
7637                         break;
7638                 case CON_STATE_ERROR: /* transient */
7639 -                       
7640 +
7641                         /* even if the connection was drop we still have to write it to the access log */
7642                         if (con->http_status) {
7643                                 plugins_call_handle_request_done(srv, con);
7644 @@ -1612,19 +1524,19 @@
7645                                         SSL_shutdown(con->ssl);
7646                                         break;
7647                                 default:
7648 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", 
7649 -                                                       SSL_get_error(con->ssl, ret), 
7650 +                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
7651 +                                                       SSL_get_error(con->ssl, ret),
7652                                                         ERR_error_string(ERR_get_error(), NULL));
7653                                         return -1;
7654                                 }
7655                         }
7656  #endif
7657 -                       
7658 +
7659                         switch(con->mode) {
7660                         case DIRECT:
7661  #if 0
7662 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
7663 -                                               "emergency exit: direct", 
7664 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
7665 +                                               "emergency exit: direct",
7666                                                 con->fd);
7667  #endif
7668                                 break;
7669 @@ -1639,35 +1551,35 @@
7670                                 }
7671                                 break;
7672                         }
7673 -                       
7674 +
7675                         connection_reset(srv, con);
7676 -                       
7677 +
7678                         /* close the connection */
7679                         if ((con->keep_alive == 1) &&
7680                             (0 == shutdown(con->fd, SHUT_WR))) {
7681                                 con->close_timeout_ts = srv->cur_ts;
7682                                 connection_set_state(srv, con, CON_STATE_CLOSE);
7683 -                               
7684 +
7685                                 if (srv->srvconf.log_state_handling) {
7686 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
7687 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
7688                                                         "shutdown for fd", con->fd);
7689                                 }
7690                         } else {
7691                                 connection_close(srv, con);
7692                         }
7693 -                       
7694 +
7695                         con->keep_alive = 0;
7696 -                       
7697 +
7698                         srv->con_closed++;
7699 -                       
7700 +
7701                         break;
7702                 default:
7703 -                       log_error_write(srv, __FILE__, __LINE__, "sdd", 
7704 +                       log_error_write(srv, __FILE__, __LINE__, "sdd",
7705                                         "unknown state:", con->fd, con->state);
7706 -                       
7707 +
7708                         break;
7709                 }
7710 -               
7711 +
7712                 if (done == -1) {
7713                         done = 0;
7714                 } else if (ostate == con->state) {
7715 @@ -1676,12 +1588,12 @@
7716         }
7717  
7718         if (srv->srvconf.log_state_handling) {
7719 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
7720 -                               "state at exit:", 
7721 +               log_error_write(srv, __FILE__, __LINE__, "sds",
7722 +                               "state at exit:",
7723                                 con->fd,
7724                                 connection_get_state(con->state));
7725         }
7726 -       
7727 +
7728         switch(con->state) {
7729         case CON_STATE_READ_POST:
7730         case CON_STATE_READ:
7731 @@ -1689,11 +1601,11 @@
7732                 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
7733                 break;
7734         case CON_STATE_WRITE:
7735 -               /* request write-fdevent only if we really need it 
7736 +               /* request write-fdevent only if we really need it
7737                  * - if we have data to write
7738 -                * - if the socket is not writable yet 
7739 +                * - if the socket is not writable yet
7740                  */
7741 -               if (!chunkqueue_is_empty(con->write_queue) && 
7742 +               if (!chunkqueue_is_empty(con->write_queue) &&
7743                     (con->is_writable == 0) &&
7744                     (con->traffic_limit_reached == 0)) {
7745                         fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
7746 --- ../lighttpd-1.4.11/src/crc32.h      2005-09-30 20:18:59.000000000 +0300
7747 +++ lighttpd-1.4.12/src/crc32.h 2006-07-11 22:07:53.000000000 +0300
7748 @@ -6,6 +6,7 @@
7749  #endif
7750  
7751  #include <sys/types.h>
7752 +#include <stdlib.h>
7753  
7754  #if defined HAVE_STDINT_H
7755  #include <stdint.h>
7756 @@ -13,6 +14,10 @@
7757  #include <inttypes.h>
7758  #endif
7759  
7760 +#ifdef _WIN32
7761 +#define uint32_t unsigned __int32
7762 +#endif
7763 +
7764  uint32_t generate_crc32c(char *string, size_t length);
7765  
7766  #endif
7767 --- ../lighttpd-1.4.11/src/data_array.c 2005-08-23 17:36:12.000000000 +0300
7768 +++ lighttpd-1.4.12/src/data_array.c    2006-07-11 22:07:52.000000000 +0300
7769 @@ -17,16 +17,16 @@
7770  
7771  static void data_array_free(data_unset *d) {
7772         data_array *ds = (data_array *)d;
7773 -       
7774 +
7775         buffer_free(ds->key);
7776         array_free(ds->value);
7777 -       
7778 +
7779         free(d);
7780  }
7781  
7782  static void data_array_reset(data_unset *d) {
7783         data_array *ds = (data_array *)d;
7784 -       
7785 +
7786         /* reused array elements */
7787         buffer_reset(ds->key);
7788         array_reset(ds->value);
7789 @@ -36,7 +36,7 @@
7790         UNUSED(dst);
7791  
7792         src->free(src);
7793 -       
7794 +
7795         return 0;
7796  }
7797  
7798 @@ -48,18 +48,18 @@
7799  
7800  data_array *data_array_init(void) {
7801         data_array *ds;
7802 -       
7803 +
7804         ds = calloc(1, sizeof(*ds));
7805 -       
7806 +
7807         ds->key = buffer_init();
7808         ds->value = array_init();
7809 -       
7810 +
7811         ds->copy = data_array_copy;
7812         ds->free = data_array_free;
7813         ds->reset = data_array_reset;
7814         ds->insert_dup = data_array_insert_dup;
7815         ds->print = data_array_print;
7816         ds->type = TYPE_ARRAY;
7817 -       
7818 +
7819         return ds;
7820  }
7821 --- ../lighttpd-1.4.11/src/data_config.c        2005-08-17 12:53:19.000000000 +0300
7822 +++ lighttpd-1.4.12/src/data_config.c   2006-07-11 22:07:51.000000000 +0300
7823 @@ -17,26 +17,26 @@
7824  
7825  static void data_config_free(data_unset *d) {
7826         data_config *ds = (data_config *)d;
7827 -       
7828 +
7829         buffer_free(ds->key);
7830         buffer_free(ds->op);
7831         buffer_free(ds->comp_key);
7832 -       
7833 +
7834         array_free(ds->value);
7835         array_free(ds->childs);
7836 -       
7837 +
7838         if (ds->string) buffer_free(ds->string);
7839  #ifdef HAVE_PCRE_H
7840         if (ds->regex) pcre_free(ds->regex);
7841         if (ds->regex_study) pcre_free(ds->regex_study);
7842  #endif
7843 -       
7844 +
7845         free(d);
7846  }
7847  
7848  static void data_config_reset(data_unset *d) {
7849         data_config *ds = (data_config *)d;
7850 -       
7851 +
7852         /* reused array elements */
7853         buffer_reset(ds->key);
7854         buffer_reset(ds->comp_key);
7855 @@ -45,9 +45,9 @@
7856  
7857  static int data_config_insert_dup(data_unset *dst, data_unset *src) {
7858         UNUSED(dst);
7859 -       
7860 +
7861         src->free(src);
7862 -       
7863 +
7864         return 0;
7865  }
7866  
7867 @@ -56,7 +56,7 @@
7868         array *a = (array *)ds->value;
7869         size_t i;
7870         size_t maxlen;
7871 -       
7872 +
7873         if (0 == ds->context_ndx) {
7874                 fprintf(stderr, "config {\n");
7875         }
7876 @@ -117,22 +117,22 @@
7877  
7878  data_config *data_config_init(void) {
7879         data_config *ds;
7880 -       
7881 +
7882         ds = calloc(1, sizeof(*ds));
7883 -       
7884 +
7885         ds->key = buffer_init();
7886         ds->op = buffer_init();
7887         ds->comp_key = buffer_init();
7888         ds->value = array_init();
7889         ds->childs = array_init();
7890         ds->childs->is_weakref = 1;
7891 -       
7892 +
7893         ds->copy = data_config_copy;
7894         ds->free = data_config_free;
7895         ds->reset = data_config_reset;
7896         ds->insert_dup = data_config_insert_dup;
7897         ds->print = data_config_print;
7898         ds->type = TYPE_CONFIG;
7899 -       
7900 +
7901         return ds;
7902  }
7903 --- ../lighttpd-1.4.11/src/data_count.c 2005-08-23 17:36:12.000000000 +0300
7904 +++ lighttpd-1.4.12/src/data_count.c    2006-07-11 22:07:51.000000000 +0300
7905 @@ -16,53 +16,53 @@
7906  
7907  static void data_count_free(data_unset *d) {
7908         data_count *ds = (data_count *)d;
7909 -       
7910 +
7911         buffer_free(ds->key);
7912 -       
7913 +
7914         free(d);
7915  }
7916  
7917  static void data_count_reset(data_unset *d) {
7918         data_count *ds = (data_count *)d;
7919 -       
7920 +
7921         buffer_reset(ds->key);
7922 -       
7923 +
7924         ds->count = 0;
7925  }
7926  
7927  static int data_count_insert_dup(data_unset *dst, data_unset *src) {
7928         data_count *ds_dst = (data_count *)dst;
7929         data_count *ds_src = (data_count *)src;
7930 -       
7931 +
7932         ds_dst->count += ds_src->count;
7933 -       
7934 +
7935         src->free(src);
7936 -       
7937 +
7938         return 0;
7939  }
7940  
7941  static void data_count_print(const data_unset *d, int depth) {
7942         data_count *ds = (data_count *)d;
7943         UNUSED(depth);
7944 -       
7945 +
7946         fprintf(stderr, "count(%d)", ds->count);
7947  }
7948  
7949  
7950  data_count *data_count_init(void) {
7951         data_count *ds;
7952 -       
7953 +
7954         ds = calloc(1, sizeof(*ds));
7955 -       
7956 +
7957         ds->key = buffer_init();
7958         ds->count = 1;
7959 -       
7960 +
7961         ds->copy = data_count_copy;
7962         ds->free = data_count_free;
7963         ds->reset = data_count_reset;
7964         ds->insert_dup = data_count_insert_dup;
7965         ds->print = data_count_print;
7966         ds->type = TYPE_COUNT;
7967 -       
7968 +
7969         return ds;
7970  }
7971 --- ../lighttpd-1.4.11/src/data_fastcgi.c       2005-08-23 17:36:12.000000000 +0300
7972 +++ lighttpd-1.4.12/src/data_fastcgi.c  2006-07-11 22:07:53.000000000 +0300
7973 @@ -17,53 +17,53 @@
7974  
7975  static void data_fastcgi_free(data_unset *d) {
7976         data_fastcgi *ds = (data_fastcgi *)d;
7977 -       
7978 +
7979         buffer_free(ds->key);
7980         buffer_free(ds->host);
7981 -       
7982 +
7983         free(d);
7984  }
7985  
7986  static void data_fastcgi_reset(data_unset *d) {
7987         data_fastcgi *ds = (data_fastcgi *)d;
7988 -       
7989 +
7990         buffer_reset(ds->key);
7991         buffer_reset(ds->host);
7992 -       
7993 +
7994  }
7995  
7996  static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
7997         UNUSED(dst);
7998  
7999         src->free(src);
8000 -       
8001 +
8002         return 0;
8003  }
8004  
8005  static void data_fastcgi_print(const data_unset *d, int depth) {
8006         data_fastcgi *ds = (data_fastcgi *)d;
8007         UNUSED(depth);
8008 -       
8009 +
8010         fprintf(stderr, "fastcgi(%s)", ds->host->ptr);
8011  }
8012  
8013  
8014  data_fastcgi *data_fastcgi_init(void) {
8015         data_fastcgi *ds;
8016 -       
8017 +
8018         ds = calloc(1, sizeof(*ds));
8019 -       
8020 +
8021         ds->key = buffer_init();
8022         ds->host = buffer_init();
8023         ds->port = 0;
8024         ds->is_disabled = 0;
8025 -       
8026 +
8027         ds->copy = data_fastcgi_copy;
8028         ds->free = data_fastcgi_free;
8029         ds->reset = data_fastcgi_reset;
8030         ds->insert_dup = data_fastcgi_insert_dup;
8031         ds->print = data_fastcgi_print;
8032         ds->type = TYPE_FASTCGI;
8033 -       
8034 +
8035         return ds;
8036  }
8037 --- ../lighttpd-1.4.11/src/data_integer.c       2005-08-23 17:36:12.000000000 +0300
8038 +++ lighttpd-1.4.12/src/data_integer.c  2006-07-11 22:07:51.000000000 +0300
8039 @@ -16,15 +16,15 @@
8040  
8041  static void data_integer_free(data_unset *d) {
8042         data_integer *ds = (data_integer *)d;
8043 -       
8044 +
8045         buffer_free(ds->key);
8046 -       
8047 +
8048         free(d);
8049  }
8050  
8051  static void data_integer_reset(data_unset *d) {
8052         data_integer *ds = (data_integer *)d;
8053 -       
8054 +
8055         /* reused integer elements */
8056         buffer_reset(ds->key);
8057         ds->value = 0;
8058 @@ -32,9 +32,9 @@
8059  
8060  static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
8061         UNUSED(dst);
8062 -       
8063 +
8064         src->free(src);
8065 -       
8066 +
8067         return 0;
8068  }
8069  
8070 @@ -48,18 +48,18 @@
8071  
8072  data_integer *data_integer_init(void) {
8073         data_integer *ds;
8074 -       
8075 +
8076         ds = calloc(1, sizeof(*ds));
8077 -       
8078 +
8079         ds->key = buffer_init();
8080         ds->value = 0;
8081 -       
8082 +
8083         ds->copy = data_integer_copy;
8084         ds->free = data_integer_free;
8085         ds->reset = data_integer_reset;
8086         ds->insert_dup = data_integer_insert_dup;
8087         ds->print = data_integer_print;
8088         ds->type = TYPE_INTEGER;
8089 -       
8090 +
8091         return ds;
8092  }
8093 --- ../lighttpd-1.4.11/src/data_string.c        2005-08-23 17:36:12.000000000 +0300
8094 +++ lighttpd-1.4.12/src/data_string.c   2006-07-11 22:07:53.000000000 +0300
8095 @@ -17,16 +17,16 @@
8096  
8097  static void data_string_free(data_unset *d) {
8098         data_string *ds = (data_string *)d;
8099 -       
8100 +
8101         buffer_free(ds->key);
8102         buffer_free(ds->value);
8103 -       
8104 +
8105         free(d);
8106  }
8107  
8108  static void data_string_reset(data_unset *d) {
8109         data_string *ds = (data_string *)d;
8110 -       
8111 +
8112         /* reused array elements */
8113         buffer_reset(ds->key);
8114         buffer_reset(ds->value);
8115 @@ -35,23 +35,23 @@
8116  static int data_string_insert_dup(data_unset *dst, data_unset *src) {
8117         data_string *ds_dst = (data_string *)dst;
8118         data_string *ds_src = (data_string *)src;
8119 -       
8120 +
8121         if (ds_dst->value->used) {
8122                 buffer_append_string(ds_dst->value, ", ");
8123                 buffer_append_string_buffer(ds_dst->value, ds_src->value);
8124         } else {
8125                 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8126         }
8127 -       
8128 +
8129         src->free(src);
8130 -       
8131 +
8132         return 0;
8133  }
8134  
8135  static int data_response_insert_dup(data_unset *dst, data_unset *src) {
8136         data_string *ds_dst = (data_string *)dst;
8137         data_string *ds_src = (data_string *)src;
8138 -       
8139 +
8140         if (ds_dst->value->used) {
8141                 buffer_append_string(ds_dst->value, "\r\n");
8142                 buffer_append_string_buffer(ds_dst->value, ds_dst->key);
8143 @@ -60,9 +60,9 @@
8144         } else {
8145                 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8146         }
8147 -       
8148 +
8149         src->free(src);
8150 -       
8151 +
8152         return 0;
8153  }
8154  
8155 @@ -77,28 +77,28 @@
8156  
8157  data_string *data_string_init(void) {
8158         data_string *ds;
8159 -       
8160 +
8161         ds = calloc(1, sizeof(*ds));
8162         assert(ds);
8163 -       
8164 +
8165         ds->key = buffer_init();
8166         ds->value = buffer_init();
8167 -       
8168 +
8169         ds->copy = data_string_copy;
8170         ds->free = data_string_free;
8171         ds->reset = data_string_reset;
8172         ds->insert_dup = data_string_insert_dup;
8173         ds->print = data_string_print;
8174         ds->type = TYPE_STRING;
8175 -       
8176 +
8177         return ds;
8178  }
8179  
8180  data_string *data_response_init(void) {
8181         data_string *ds;
8182 -       
8183 +
8184         ds = data_string_init();
8185         ds->insert_dup = data_response_insert_dup;
8186 -       
8187 +
8188         return ds;
8189  }
8190 --- ../lighttpd-1.4.11/src/etag.c       2005-08-11 01:26:40.000000000 +0300
8191 +++ lighttpd-1.4.12/src/etag.c  2006-07-11 22:07:51.000000000 +0300
8192 @@ -14,19 +14,19 @@
8193         buffer_append_off_t(etag, st->st_size);
8194         buffer_append_string_len(etag, CONST_STR_LEN("-"));
8195         buffer_append_long(etag, st->st_mtime);
8196 -       
8197 +
8198         return 0;
8199  }
8200  
8201  int etag_mutate(buffer *mut, buffer *etag) {
8202         size_t h, i;
8203 -       
8204 +
8205         for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
8206 -       
8207 +
8208         buffer_reset(mut);
8209         buffer_copy_string_len(mut, CONST_STR_LEN("\""));
8210         buffer_append_long(mut, h);
8211         buffer_append_string_len(mut, CONST_STR_LEN("\""));
8212 -       
8213 +
8214         return 0;
8215  }
8216 --- ../lighttpd-1.4.11/src/etag.h       2005-08-11 01:26:40.000000000 +0300
8217 +++ lighttpd-1.4.12/src/etag.h  2006-07-11 22:07:51.000000000 +0300
8218 @@ -3,13 +3,12 @@
8219  
8220  #include <sys/types.h>
8221  #include <sys/stat.h>
8222 -#include <unistd.h>
8223  
8224  #include "buffer.h"
8225  
8226  int etag_is_equal(buffer *etag, const char *matches);
8227  int etag_create(buffer *etag, struct stat *st);
8228  int etag_mutate(buffer *mut, buffer *etag);
8229 -       
8230 +
8231  
8232  #endif
8233 --- ../lighttpd-1.4.11/src/fastcgi.h    2005-08-11 01:26:40.000000000 +0300
8234 +++ lighttpd-1.4.12/src/fastcgi.h       2006-07-11 22:07:51.000000000 +0300
8235 @@ -1,4 +1,4 @@
8236 -/* 
8237 +/*
8238   * fastcgi.h --
8239   *
8240   *     Defines for the FastCGI protocol.
8241 @@ -123,7 +123,7 @@
8242  
8243  
8244  typedef struct {
8245 -    unsigned char type;    
8246 +    unsigned char type;
8247      unsigned char reserved[7];
8248  } FCGI_UnknownTypeBody;
8249  
8250 --- ../lighttpd-1.4.11/src/fdevent.c    2005-11-15 10:51:05.000000000 +0200
8251 +++ lighttpd-1.4.12/src/fdevent.c       2006-07-11 22:07:53.000000000 +0300
8252 @@ -2,7 +2,6 @@
8253  
8254  #include "settings.h"
8255  
8256 -#include <unistd.h>
8257  #include <stdlib.h>
8258  #include <string.h>
8259  #include <errno.h>
8260 @@ -12,59 +11,61 @@
8261  #include "fdevent.h"
8262  #include "buffer.h"
8263  
8264 +#include "sys-socket.h"
8265 +
8266  fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
8267         fdevents *ev;
8268 -       
8269 +
8270         ev = calloc(1, sizeof(*ev));
8271         ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
8272         ev->maxfds = maxfds;
8273 -       
8274 +
8275         switch(type) {
8276         case FDEVENT_HANDLER_POLL:
8277                 if (0 != fdevent_poll_init(ev)) {
8278 -                       fprintf(stderr, "%s.%d: event-handler poll failed\n", 
8279 +                       fprintf(stderr, "%s.%d: event-handler poll failed\n",
8280                                 __FILE__, __LINE__);
8281 -                       
8282 +
8283                         return NULL;
8284                 }
8285                 break;
8286         case FDEVENT_HANDLER_SELECT:
8287                 if (0 != fdevent_select_init(ev)) {
8288 -                       fprintf(stderr, "%s.%d: event-handler select failed\n", 
8289 +                       fprintf(stderr, "%s.%d: event-handler select failed\n",
8290                                 __FILE__, __LINE__);
8291                         return NULL;
8292                 }
8293                 break;
8294         case FDEVENT_HANDLER_LINUX_RTSIG:
8295                 if (0 != fdevent_linux_rtsig_init(ev)) {
8296 -                       fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8297 +                       fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8298                                 __FILE__, __LINE__);
8299                         return NULL;
8300                 }
8301                 break;
8302         case FDEVENT_HANDLER_LINUX_SYSEPOLL:
8303                 if (0 != fdevent_linux_sysepoll_init(ev)) {
8304 -                       fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8305 +                       fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8306                                 __FILE__, __LINE__);
8307                         return NULL;
8308                 }
8309                 break;
8310         case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
8311                 if (0 != fdevent_solaris_devpoll_init(ev)) {
8312 -                       fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8313 +                       fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8314                                 __FILE__, __LINE__);
8315                         return NULL;
8316                 }
8317                 break;
8318         case FDEVENT_HANDLER_FREEBSD_KQUEUE:
8319                 if (0 != fdevent_freebsd_kqueue_init(ev)) {
8320 -                       fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8321 +                       fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8322                                 __FILE__, __LINE__);
8323                         return NULL;
8324                 }
8325                 break;
8326         default:
8327 -               fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n", 
8328 +               fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
8329                         __FILE__, __LINE__);
8330                 return NULL;
8331         }
8332 @@ -75,26 +76,26 @@
8333  void fdevent_free(fdevents *ev) {
8334         size_t i;
8335         if (!ev) return;
8336 -       
8337 +
8338         if (ev->free) ev->free(ev);
8339 -       
8340 +
8341         for (i = 0; i < ev->maxfds; i++) {
8342                 if (ev->fdarray[i]) free(ev->fdarray[i]);
8343         }
8344 -       
8345 +
8346         free(ev->fdarray);
8347         free(ev);
8348  }
8349  
8350  int fdevent_reset(fdevents *ev) {
8351         if (ev->reset) return ev->reset(ev);
8352 -       
8353 +
8354         return 0;
8355  }
8356  
8357  fdnode *fdnode_init() {
8358         fdnode *fdn;
8359 -       
8360 +
8361         fdn = calloc(1, sizeof(*fdn));
8362         fdn->fd = -1;
8363         return fdn;
8364 @@ -106,12 +107,12 @@
8365  
8366  int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
8367         fdnode *fdn;
8368 -       
8369 +
8370         fdn = fdnode_init();
8371         fdn->handler = handler;
8372         fdn->fd      = fd;
8373         fdn->ctx     = ctx;
8374 -       
8375 +
8376         ev->fdarray[fd] = fdn;
8377  
8378         return 0;
8379 @@ -121,31 +122,31 @@
8380         fdnode *fdn;
8381          if (!ev) return 0;
8382         fdn = ev->fdarray[fd];
8383 -       
8384 +
8385         fdnode_free(fdn);
8386 -       
8387 +
8388         ev->fdarray[fd] = NULL;
8389 -       
8390 +
8391         return 0;
8392  }
8393  
8394  int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
8395         int fde = fde_ndx ? *fde_ndx : -1;
8396 -       
8397 +
8398         if (ev->event_del) fde = ev->event_del(ev, fde, fd);
8399 -       
8400 +
8401         if (fde_ndx) *fde_ndx = fde;
8402 -       
8403 +
8404         return 0;
8405  }
8406  
8407  int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
8408         int fde = fde_ndx ? *fde_ndx : -1;
8409 -       
8410 +
8411         if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
8412 -       
8413 +
8414         if (fde_ndx) *fde_ndx = fde;
8415 -       
8416 +
8417         return 0;
8418  }
8419  
8420 @@ -156,38 +157,43 @@
8421  
8422  int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
8423         if (ev->event_get_revent == NULL) SEGFAULT();
8424 -       
8425 +
8426         return ev->event_get_revent(ev, ndx);
8427  }
8428  
8429  int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
8430         if (ev->event_get_fd == NULL) SEGFAULT();
8431 -       
8432 +
8433         return ev->event_get_fd(ev, ndx);
8434  }
8435  
8436  fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
8437         if (ev->fdarray[fd] == NULL) SEGFAULT();
8438         if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8439 -       
8440 +
8441         return ev->fdarray[fd]->handler;
8442  }
8443  
8444  void * fdevent_get_context(fdevents *ev, int fd) {
8445         if (ev->fdarray[fd] == NULL) SEGFAULT();
8446         if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8447 -       
8448 +
8449         return ev->fdarray[fd]->ctx;
8450  }
8451  
8452  int fdevent_fcntl_set(fdevents *ev, int fd) {
8453 +#ifdef _WIN32
8454 +    int i = 1;
8455 +#endif
8456  #ifdef FD_CLOEXEC
8457         /* close fd on exec (cgi) */
8458         fcntl(fd, F_SETFD, FD_CLOEXEC);
8459  #endif
8460         if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
8461 -#ifdef O_NONBLOCK      
8462 +#ifdef O_NONBLOCK
8463         return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
8464 +#elif defined _WIN32
8465 +    return ioctlsocket(fd, FIONBIO, &i);
8466  #else
8467         return 0;
8468  #endif
8469 @@ -196,7 +202,7 @@
8470  
8471  int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
8472         if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
8473 -       
8474 +
8475         return -1;
8476  }
8477  
8478 --- ../lighttpd-1.4.11/src/fdevent.h    2005-09-27 11:26:33.000000000 +0300
8479 +++ lighttpd-1.4.12/src/fdevent.h       2006-07-11 22:07:51.000000000 +0300
8480 @@ -17,13 +17,13 @@
8481  # include <sys/epoll.h>
8482  #endif
8483  
8484 -/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes 
8485 +/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
8486   * under /usr/include/sys/ */
8487  #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
8488  # define USE_POLL
8489  # ifdef HAVE_POLL_H
8490  #  include <poll.h>
8491 -# else 
8492 +# else
8493  #  include <sys/poll.h>
8494  # endif
8495  # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
8496 @@ -31,9 +31,11 @@
8497  #  include <signal.h>
8498  # endif
8499  #endif
8500 -
8501 +#ifdef _WIN32
8502 +# define HAVE_SELECT
8503 +#endif
8504  #if defined HAVE_SELECT
8505 -# ifdef __WIN32
8506 +# ifdef _WIN32
8507  #  include <winsock2.h>
8508  # endif
8509  # define USE_SELECT
8510 @@ -67,14 +69,14 @@
8511  #define FDEVENT_HUP    BV(4)
8512  #define FDEVENT_NVAL   BV(5)
8513  
8514 -typedef enum { FD_EVENT_TYPE_UNSET = -1, 
8515 -               FD_EVENT_TYPE_CONNECTION, 
8516 -               FD_EVENT_TYPE_FCGI_CONNECTION, 
8517 -               FD_EVENT_TYPE_DIRWATCH, 
8518 -               FD_EVENT_TYPE_CGI_CONNECTION 
8519 +typedef enum { FD_EVENT_TYPE_UNSET = -1,
8520 +               FD_EVENT_TYPE_CONNECTION,
8521 +               FD_EVENT_TYPE_FCGI_CONNECTION,
8522 +               FD_EVENT_TYPE_DIRWATCH,
8523 +               FD_EVENT_TYPE_CGI_CONNECTION
8524  } fd_event_t;
8525  
8526 -typedef enum { FDEVENT_HANDLER_UNSET, 
8527 +typedef enum { FDEVENT_HANDLER_UNSET,
8528                 FDEVENT_HANDLER_SELECT,
8529                 FDEVENT_HANDLER_POLL,
8530                 FDEVENT_HANDLER_LINUX_RTSIG,
8531 @@ -86,7 +88,7 @@
8532  
8533  /**
8534   * a mapping from fd to connection structure
8535 - * 
8536 + *
8537   */
8538  typedef struct {
8539         int fd;                  /**< the fd */
8540 @@ -98,41 +100,41 @@
8541  
8542  typedef struct {
8543         fd_conn *ptr;
8544 -       
8545 +
8546         size_t size;
8547         size_t used;
8548  } fd_conn_buffer;
8549  
8550  /**
8551   * array of unused fd's
8552 - * 
8553 + *
8554   */
8555  
8556  typedef struct _fdnode {
8557         fdevent_handler handler;
8558         void *ctx;
8559         int fd;
8560 -       
8561 +
8562         struct _fdnode *prev, *next;
8563  } fdnode;
8564  
8565  typedef struct {
8566         int *ptr;
8567 -       
8568 +
8569         size_t used;
8570         size_t size;
8571  } buffer_int;
8572  
8573  /**
8574   * fd-event handler for select(), poll() and rt-signals on Linux 2.4
8575 - * 
8576 + *
8577   */
8578  typedef struct fdevents {
8579         fdevent_handler_t type;
8580 -       
8581 +
8582         fdnode **fdarray;
8583         size_t maxfds;
8584 -       
8585 +
8586  #ifdef USE_LINUX_SIGIO
8587         int in_sigio;
8588         int signum;
8589 @@ -146,21 +148,21 @@
8590  #endif
8591  #ifdef USE_POLL
8592         struct pollfd *pollfds;
8593 -       
8594 +
8595         size_t size;
8596         size_t used;
8597 -       
8598 +
8599         buffer_int unused;
8600  #endif
8601  #ifdef USE_SELECT
8602         fd_set select_read;
8603         fd_set select_write;
8604         fd_set select_error;
8605 -       
8606 +
8607         fd_set select_set_read;
8608         fd_set select_set_write;
8609         fd_set select_set_error;
8610 -       
8611 +
8612         int select_max_fd;
8613  #endif
8614  #ifdef USE_SOLARIS_DEVPOLL
8615 @@ -177,16 +179,16 @@
8616  #endif
8617         int (*reset)(struct fdevents *ev);
8618         void (*free)(struct fdevents *ev);
8619 -       
8620 +
8621         int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events);
8622         int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
8623         int (*event_get_revent)(struct fdevents *ev, size_t ndx);
8624         int (*event_get_fd)(struct fdevents *ev, size_t ndx);
8625 -       
8626 +
8627         int (*event_next_fdndx)(struct fdevents *ev, int ndx);
8628 -       
8629 +
8630         int (*poll)(struct fdevents *ev, int timeout_ms);
8631 -       
8632 +
8633         int (*fcntl_set)(struct fdevents *ev, int fd);
8634  } fdevents;
8635  
8636 --- ../lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c     2005-09-01 10:46:24.000000000 +0300
8637 +++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c        2006-07-11 22:07:51.000000000 +0300
8638 @@ -1,6 +1,5 @@
8639  #include <sys/types.h>
8640  
8641 -#include <unistd.h>
8642  #include <stdlib.h>
8643  #include <stdio.h>
8644  #include <string.h>
8645 @@ -48,7 +47,7 @@
8646  
8647                 return -1;
8648         }
8649 -       
8650 +
8651         return -1;
8652  }
8653  
8654 @@ -65,7 +64,7 @@
8655  
8656         ts.tv_sec  = 0;
8657         ts.tv_nsec = 0;
8658 -       
8659 +
8660         ret = kevent(ev->kq_fd,
8661                      &kev, 1,
8662                      NULL, 0,
8663 @@ -77,7 +76,7 @@
8664  
8665                 return -1;
8666         }
8667 -       
8668 +
8669         if (filter == EVFILT_READ) {
8670                 bitset_set_bit(ev->kq_bevents, fd);
8671         } else {
8672 @@ -124,7 +123,7 @@
8673         } else if (e == EVFILT_WRITE) {
8674                 events |= FDEVENT_OUT;
8675         }
8676 -       
8677 +
8678         e = ev->kq_results[ndx].flags;
8679  
8680         if (e & EV_EOF) {
8681 @@ -152,10 +151,10 @@
8682         if (-1 == (ev->kq_fd = kqueue())) {
8683                 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8684                         __FILE__, __LINE__, strerror(errno));
8685 -               
8686 +
8687                 return -1;
8688         }
8689 -       
8690 +
8691         return 0;
8692  }
8693  
8694 @@ -186,7 +185,7 @@
8695         if (-1 == (ev->kq_fd = kqueue())) {
8696                 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8697                         __FILE__, __LINE__, strerror(errno));
8698 -               
8699 +
8700                 return -1;
8701         }
8702  
8703 --- ../lighttpd-1.4.11/src/fdevent_linux_rtsig.c        2005-11-21 19:56:11.000000000 +0200
8704 +++ lighttpd-1.4.12/src/fdevent_linux_rtsig.c   2006-07-15 22:43:21.000000000 +0300
8705 @@ -1,6 +1,5 @@
8706  #include <sys/types.h>
8707  
8708 -#include <unistd.h>
8709  #include <stdlib.h>
8710  #include <stdio.h>
8711  #include <string.h>
8712 @@ -14,6 +13,7 @@
8713  #include "fdevent.h"
8714  #include "settings.h"
8715  #include "buffer.h"
8716 +#include "sys-process.h"
8717  
8718  #ifdef USE_LINUX_SIGIO
8719  static void fdevent_linux_rtsig_free(fdevents *ev) {
8720 @@ -26,19 +26,19 @@
8721  
8722  static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) {
8723         if (fde_ndx < 0) return -1;
8724 -       
8725 +
8726         if ((size_t)fde_ndx >= ev->used) {
8727                 fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used);
8728                 SEGFAULT();
8729         }
8730 -       
8731 +
8732         if (ev->pollfds[fde_ndx].fd == fd) {
8733                 size_t k = fde_ndx;
8734 -               
8735 +
8736                 ev->pollfds[k].fd = -1;
8737  
8738                 bitset_clear_bit(ev->sigbset, fd);
8739 -               
8740 +
8741                 if (ev->unused.size == 0) {
8742                         ev->unused.size = 16;
8743                         ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
8744 @@ -46,29 +46,29 @@
8745                         ev->unused.size += 16;
8746                         ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
8747                 }
8748 -               
8749 +
8750                 ev->unused.ptr[ev->unused.used++] = k;
8751         } else {
8752                 fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd);
8753 -               
8754 +
8755                 SEGFAULT();
8756         }
8757 -       
8758 +
8759         return -1;
8760  }
8761  
8762  #if 0
8763  static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
8764         size_t j;
8765 -       
8766 +
8767         if (ev->used == 0) return 0;
8768         if (ev->unused.used != 0) return 0;
8769 -       
8770 +
8771         for (j = ev->used - 1; j + 1 > 0; j--) {
8772                 if (ev->pollfds[j].fd == -1) ev->used--;
8773         }
8774 -       
8775 -       
8776 +
8777 +
8778         return 0;
8779  }
8780  #endif
8781 @@ -78,21 +78,21 @@
8782         if (fde_ndx != -1) {
8783                 if (ev->pollfds[fde_ndx].fd == fd) {
8784                         ev->pollfds[fde_ndx].events = events;
8785 -                       
8786 +
8787                         return fde_ndx;
8788                 }
8789                 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
8790                 SEGFAULT();
8791         }
8792 -       
8793 +
8794         if (ev->unused.used > 0) {
8795                 int k = ev->unused.ptr[--ev->unused.used];
8796 -               
8797 +
8798                 ev->pollfds[k].fd = fd;
8799                 ev->pollfds[k].events = events;
8800  
8801                 bitset_set_bit(ev->sigbset, fd);
8802 -               
8803 +
8804                 return k;
8805         } else {
8806                 if (ev->size == 0) {
8807 @@ -102,12 +102,12 @@
8808                         ev->size += 16;
8809                         ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
8810                 }
8811 -               
8812 +
8813                 ev->pollfds[ev->used].fd = fd;
8814                 ev->pollfds[ev->used].events = events;
8815  
8816                 bitset_set_bit(ev->sigbset, fd);
8817 -       
8818 +
8819                 return ev->used++;
8820         }
8821  }
8822 @@ -115,20 +115,20 @@
8823  static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
8824         struct timespec ts;
8825         int r;
8826 -       
8827 +
8828  #if 0
8829         fdevent_linux_rtsig_event_compress(ev);
8830  #endif
8831 -       
8832 +
8833         ev->in_sigio = 1;
8834 -               
8835 +
8836         ts.tv_sec =  timeout_ms / 1000;
8837         ts.tv_nsec = (timeout_ms % 1000) * 1000000;
8838         r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
8839 -               
8840 -       if (r == -1) { 
8841 +
8842 +       if (r == -1) {
8843                 if (errno == EAGAIN) return 0;
8844 -               return r; 
8845 +               return r;
8846         } else if (r == SIGIO) {
8847                 struct sigaction act;
8848  
8849 @@ -140,7 +140,7 @@
8850                 /* re-enable the signal queue */
8851                 act.sa_handler = SIG_DFL;
8852                 sigaction(ev->signum, &act, NULL);
8853 -               
8854 +
8855                 ev->in_sigio = 0;
8856                 r = poll(ev->pollfds, ev->used, timeout_ms);
8857  
8858 @@ -162,12 +162,12 @@
8859                 if (ev->siginfo.si_band == POLLERR) {
8860                         fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno));
8861                 }
8862 -#  endif               
8863 +#  endif
8864                 if (ndx != 0) {
8865                         fprintf(stderr, "+\n");
8866                         return 0;
8867                 }
8868 -               
8869 +
8870                 return ev->siginfo.si_band & 0x3f;
8871         } else {
8872                 if (ndx >= ev->used) {
8873 @@ -188,13 +188,13 @@
8874  
8875  static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
8876         static pid_t pid = 0;
8877 -       
8878 +
8879         if (pid == 0) pid = getpid();
8880 -       
8881 +
8882         if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
8883 -       
8884 +
8885         if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
8886 -       
8887 +
8888         return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
8889  }
8890  
8891 @@ -205,12 +205,12 @@
8892                 return -1;
8893         } else {
8894                 size_t i;
8895 -               
8896 +
8897                 i = (ndx < 0) ? 0 : ndx + 1;
8898                 for (; i < ev->used; i++) {
8899                         if (ev->pollfds[i].revents) break;
8900                 }
8901 -               
8902 +
8903                 return i;
8904         }
8905  }
8906 @@ -219,34 +219,34 @@
8907         ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
8908  #define SET(x) \
8909         ev->x = fdevent_linux_rtsig_##x;
8910 -       
8911 +
8912         SET(free);
8913         SET(poll);
8914 -       
8915 +
8916         SET(event_del);
8917         SET(event_add);
8918 -       
8919 +
8920         SET(event_next_fdndx);
8921         SET(fcntl_set);
8922         SET(event_get_fd);
8923         SET(event_get_revent);
8924 -       
8925 +
8926         ev->signum = SIGRTMIN + 1;
8927 -       
8928 +
8929         sigemptyset(&(ev->sigset));
8930         sigaddset(&(ev->sigset), ev->signum);
8931         sigaddset(&(ev->sigset), SIGIO);
8932         if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) {
8933                 fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8934                         __FILE__, __LINE__, strerror(errno));
8935 -               
8936 +
8937                 return -1;
8938         }
8939 -       
8940 +
8941         ev->in_sigio = 1;
8942  
8943         ev->sigbset = bitset_init(ev->maxfds);
8944 -       
8945 +
8946         return 0;
8947  }
8948  #else
8949 --- ../lighttpd-1.4.11/src/fdevent_linux_sysepoll.c     2005-09-30 20:29:27.000000000 +0300
8950 +++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c        2006-07-11 22:07:53.000000000 +0300
8951 @@ -1,6 +1,5 @@
8952  #include <sys/types.h>
8953  
8954 -#include <unistd.h>
8955  #include <stdlib.h>
8956  #include <stdio.h>
8957  #include <string.h>
8958 @@ -12,6 +11,8 @@
8959  #include "settings.h"
8960  #include "buffer.h"
8961  
8962 +#include "sys-files.h"
8963 +
8964  #ifdef USE_LINUX_EPOLL
8965  static void fdevent_linux_sysepoll_free(fdevents *ev) {
8966         close(ev->epoll_fd);
8967 @@ -20,36 +21,36 @@
8968  
8969  static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
8970         struct epoll_event ep;
8971 -       
8972 +
8973         if (fde_ndx < 0) return -1;
8974 -       
8975 +
8976         memset(&ep, 0, sizeof(ep));
8977 -       
8978 +
8979         ep.data.fd = fd;
8980         ep.data.ptr = NULL;
8981 -       
8982 +
8983         if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
8984                 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
8985 -               
8986 +
8987                 SEGFAULT();
8988 -               
8989 +
8990                 return 0;
8991         }
8992 -       
8993 -       
8994 +
8995 +
8996         return -1;
8997  }
8998  
8999  static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9000         struct epoll_event ep;
9001         int add = 0;
9002 -       
9003 +
9004         if (fde_ndx == -1) add = 1;
9005 -       
9006 +
9007         memset(&ep, 0, sizeof(ep));
9008 -       
9009 +
9010         ep.events = 0;
9011 -       
9012 +
9013         if (events & FDEVENT_IN)  ep.events |= EPOLLIN;
9014         if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
9015  
9016 @@ -60,20 +61,20 @@
9017          * sent.
9018          *
9019          */
9020 -       
9021 +
9022         ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
9023 -       
9024 +
9025         ep.data.ptr = NULL;
9026         ep.data.fd = fd;
9027 -       
9028 +
9029         if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
9030                 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9031 -               
9032 +
9033                 SEGFAULT();
9034 -               
9035 +
9036                 return 0;
9037         }
9038 -       
9039 +
9040         return fd;
9041  }
9042  
9043 @@ -83,14 +84,14 @@
9044  
9045  static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
9046         int events = 0, e;
9047 -       
9048 +
9049         e = ev->epoll_events[ndx].events;
9050         if (e & EPOLLIN) events |= FDEVENT_IN;
9051         if (e & EPOLLOUT) events |= FDEVENT_OUT;
9052         if (e & EPOLLERR) events |= FDEVENT_ERR;
9053         if (e & EPOLLHUP) events |= FDEVENT_HUP;
9054         if (e & EPOLLPRI) events |= FDEVENT_PRI;
9055 -       
9056 +
9057         return e;
9058  }
9059  
9060 @@ -98,17 +99,17 @@
9061  # if 0
9062         fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
9063  # endif
9064 -       
9065 +
9066         return ev->epoll_events[ndx].data.fd;
9067  }
9068  
9069  static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
9070         size_t i;
9071 -       
9072 +
9073         UNUSED(ev);
9074  
9075         i = (ndx < 0) ? 0 : ndx + 1;
9076 -       
9077 +
9078         return i;
9079  }
9080  
9081 @@ -116,17 +117,17 @@
9082         ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
9083  #define SET(x) \
9084         ev->x = fdevent_linux_sysepoll_##x;
9085 -       
9086 +
9087         SET(free);
9088         SET(poll);
9089 -       
9090 +
9091         SET(event_del);
9092         SET(event_add);
9093 -       
9094 +
9095         SET(event_next_fdndx);
9096         SET(event_get_fd);
9097         SET(event_get_revent);
9098 -       
9099 +
9100         if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
9101                 fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9102                         __FILE__, __LINE__, strerror(errno));
9103 @@ -154,7 +155,7 @@
9104  
9105         fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9106                 __FILE__, __LINE__);
9107 -       
9108 +
9109         return -1;
9110  }
9111  #endif
9112 --- ../lighttpd-1.4.11/src/fdevent_poll.c       2005-11-18 13:59:16.000000000 +0200
9113 +++ lighttpd-1.4.12/src/fdevent_poll.c  2006-07-11 22:07:53.000000000 +0300
9114 @@ -1,6 +1,5 @@
9115  #include <sys/types.h>
9116  
9117 -#include <unistd.h>
9118  #include <stdlib.h>
9119  #include <stdio.h>
9120  #include <string.h>
9121 @@ -20,19 +19,19 @@
9122  
9123  static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
9124         if (fde_ndx < 0) return -1;
9125 -       
9126 +
9127         if ((size_t)fde_ndx >= ev->used) {
9128                 fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used);
9129                 SEGFAULT();
9130         }
9131 -       
9132 +
9133         if (ev->pollfds[fde_ndx].fd == fd) {
9134                 size_t k = fde_ndx;
9135 -               
9136 +
9137                 ev->pollfds[k].fd = -1;
9138                 /* ev->pollfds[k].events = 0; */
9139                 /* ev->pollfds[k].revents = 0; */
9140 -               
9141 +
9142                 if (ev->unused.size == 0) {
9143                         ev->unused.size = 16;
9144                         ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9145 @@ -40,47 +39,47 @@
9146                         ev->unused.size += 16;
9147                         ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9148                 }
9149 -               
9150 +
9151                 ev->unused.ptr[ev->unused.used++] = k;
9152         } else {
9153                 SEGFAULT();
9154         }
9155 -       
9156 +
9157         return -1;
9158  }
9159  
9160  #if 0
9161  static int fdevent_poll_event_compress(fdevents *ev) {
9162         size_t j;
9163 -       
9164 +
9165         if (ev->used == 0) return 0;
9166         if (ev->unused.used != 0) return 0;
9167 -       
9168 +
9169         for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
9170 -       
9171 +
9172         return 0;
9173  }
9174  #endif
9175  
9176  static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9177         /* known index */
9178 -       
9179 +
9180         if (fde_ndx != -1) {
9181                 if (ev->pollfds[fde_ndx].fd == fd) {
9182                         ev->pollfds[fde_ndx].events = events;
9183 -                       
9184 +
9185                         return fde_ndx;
9186                 }
9187                 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9188                 SEGFAULT();
9189         }
9190 -       
9191 +
9192         if (ev->unused.used > 0) {
9193                 int k = ev->unused.ptr[--ev->unused.used];
9194 -               
9195 +
9196                 ev->pollfds[k].fd = fd;
9197                 ev->pollfds[k].events = events;
9198 -               
9199 +
9200                 return k;
9201         } else {
9202                 if (ev->size == 0) {
9203 @@ -90,10 +89,10 @@
9204                         ev->size += 16;
9205                         ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9206                 }
9207 -               
9208 +
9209                 ev->pollfds[ev->used].fd = fd;
9210                 ev->pollfds[ev->used].events = events;
9211 -               
9212 +
9213                 return ev->used++;
9214         }
9215  }
9216 @@ -109,12 +108,12 @@
9217         int r, poll_r;
9218         if (ndx >= ev->used) {
9219                 fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used);
9220 -               
9221 +
9222                 SEGFAULT();
9223 -               
9224 +
9225                 return 0;
9226         }
9227 -       
9228 +
9229         if (ev->pollfds[ndx].revents & POLLNVAL) {
9230                 /* should never happen */
9231                 SEGFAULT();
9232 @@ -131,7 +130,7 @@
9233         if (poll_r & POLLHUP) r |= FDEVENT_HUP;
9234         if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
9235         if (poll_r & POLLPRI) r |= FDEVENT_PRI;
9236 -       
9237 +
9238         return ev->pollfds[ndx].revents;
9239  }
9240  
9241 @@ -141,12 +140,12 @@
9242  
9243  static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
9244         size_t i;
9245 -       
9246 +
9247         i = (ndx < 0) ? 0 : ndx + 1;
9248         for (; i < ev->used; i++) {
9249                 if (ev->pollfds[i].revents) break;
9250         }
9251 -       
9252 +
9253         return i;
9254  }
9255  
9256 @@ -154,17 +153,17 @@
9257         ev->type = FDEVENT_HANDLER_POLL;
9258  #define SET(x) \
9259         ev->x = fdevent_poll_##x;
9260 -       
9261 +
9262         SET(free);
9263         SET(poll);
9264 -       
9265 +
9266         SET(event_del);
9267         SET(event_add);
9268 -       
9269 +
9270         SET(event_next_fdndx);
9271         SET(event_get_fd);
9272         SET(event_get_revent);
9273 -       
9274 +
9275         return 0;
9276  }
9277  
9278 --- ../lighttpd-1.4.11/src/fdevent_select.c     2005-08-31 11:12:46.000000000 +0300
9279 +++ lighttpd-1.4.12/src/fdevent_select.c        2006-07-11 22:07:53.000000000 +0300
9280 @@ -1,18 +1,19 @@
9281 -#include <sys/time.h>
9282  #include <sys/types.h>
9283  
9284 -#include <unistd.h>
9285  #include <stdlib.h>
9286  #include <string.h>
9287  #include <errno.h>
9288  #include <signal.h>
9289  #include <fcntl.h>
9290  #include <assert.h>
9291 +#include <stdio.h>
9292  
9293  #include "fdevent.h"
9294  #include "settings.h"
9295  #include "buffer.h"
9296  
9297 +#include "sys-socket.h"
9298 +
9299  #ifdef USE_SELECT
9300  
9301  static int fdevent_select_reset(fdevents *ev) {
9302 @@ -38,7 +39,9 @@
9303         UNUSED(fde_ndx);
9304  
9305         /* we should be protected by max-fds, but you never know */
9306 +#ifndef _WIN32
9307         assert(fd < FD_SETSIZE);
9308 +#endif
9309  
9310         if (events & FDEVENT_IN) {
9311                 FD_SET(fd, &(ev->select_set_read));
9312 @@ -49,28 +52,28 @@
9313                 FD_SET(fd, &(ev->select_set_write));
9314         }
9315         FD_SET(fd, &(ev->select_set_error));
9316 -       
9317 +
9318         if (fd > ev->select_max_fd) ev->select_max_fd = fd;
9319 -       
9320 +
9321         return fd;
9322  }
9323  
9324  static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
9325         struct timeval tv;
9326 -       
9327 +
9328         tv.tv_sec =  timeout_ms / 1000;
9329         tv.tv_usec = (timeout_ms % 1000) * 1000;
9330 -       
9331 +
9332         ev->select_read = ev->select_set_read;
9333         ev->select_write = ev->select_set_write;
9334         ev->select_error = ev->select_set_error;
9335 -       
9336 +
9337         return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
9338  }
9339  
9340  static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
9341         int revents = 0;
9342 -       
9343 +
9344         if (FD_ISSET(ndx, &(ev->select_read))) {
9345                 revents |= FDEVENT_IN;
9346         }
9347 @@ -80,7 +83,7 @@
9348         if (FD_ISSET(ndx, &(ev->select_error))) {
9349                 revents |= FDEVENT_ERR;
9350         }
9351 -       
9352 +
9353         return revents;
9354  }
9355  
9356 @@ -92,15 +95,15 @@
9357  
9358  static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
9359         int i;
9360 -       
9361 +
9362         i = (ndx < 0) ? 0 : ndx + 1;
9363 -       
9364 +
9365         for (; i < ev->select_max_fd + 1; i++) {
9366                 if (FD_ISSET(i, &(ev->select_read))) break;
9367                 if (FD_ISSET(i, &(ev->select_write))) break;
9368                 if (FD_ISSET(i, &(ev->select_error))) break;
9369         }
9370 -       
9371 +
9372         return i;
9373  }
9374  
9375 @@ -108,17 +111,17 @@
9376         ev->type = FDEVENT_HANDLER_SELECT;
9377  #define SET(x) \
9378         ev->x = fdevent_select_##x;
9379 -       
9380 +
9381         SET(reset);
9382         SET(poll);
9383 -       
9384 +
9385         SET(event_del);
9386         SET(event_add);
9387 -       
9388 +
9389         SET(event_next_fdndx);
9390         SET(event_get_fd);
9391         SET(event_get_revent);
9392 -       
9393 +
9394         return 0;
9395  }
9396  
9397 --- ../lighttpd-1.4.11/src/fdevent_solaris_devpoll.c    2005-09-01 10:45:26.000000000 +0300
9398 +++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c       2006-07-11 22:07:51.000000000 +0300
9399 @@ -1,6 +1,5 @@
9400  #include <sys/types.h>
9401  
9402 -#include <unistd.h>
9403  #include <stdlib.h>
9404  #include <stdio.h>
9405  #include <string.h>
9406 @@ -23,55 +22,55 @@
9407  
9408  static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9409         struct pollfd pfd;
9410 -               
9411 +
9412         if (fde_ndx < 0) return -1;
9413 -       
9414 +
9415         pfd.fd = fd;
9416         pfd.events = POLLREMOVE;
9417         pfd.revents = 0;
9418 -       
9419 +
9420         if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9421 -               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", 
9422 -                       __FILE__, __LINE__, 
9423 +               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9424 +                       __FILE__, __LINE__,
9425                         fd, strerror(errno));
9426 -               
9427 +
9428                 return -1;
9429         }
9430 -       
9431 +
9432         return -1;
9433  }
9434  
9435  static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9436         struct pollfd pfd;
9437         int add = 0;
9438 -               
9439 +
9440         if (fde_ndx == -1) add = 1;
9441 -       
9442 +
9443         pfd.fd = fd;
9444         pfd.events = events;
9445         pfd.revents = 0;
9446 -       
9447 +
9448         if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9449 -               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", 
9450 -                       __FILE__, __LINE__, 
9451 +               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9452 +                       __FILE__, __LINE__,
9453                         fd, strerror(errno));
9454 -               
9455 +
9456                 return -1;
9457         }
9458 -       
9459 +
9460         return fd;
9461  }
9462  
9463  static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
9464         struct dvpoll dopoll;
9465         int ret;
9466 -       
9467 +
9468         dopoll.dp_timeout = timeout_ms;
9469         dopoll.dp_nfds = ev->maxfds;
9470         dopoll.dp_fds = ev->devpollfds;
9471 -       
9472 +
9473         ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
9474 -       
9475 +
9476         return ret;
9477  }
9478  
9479 @@ -85,11 +84,11 @@
9480  
9481  static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
9482         size_t i;
9483 -       
9484 +
9485         UNUSED(ev);
9486  
9487         i = (last_ndx < 0) ? 0 : last_ndx + 1;
9488 -       
9489 +
9490         return i;
9491  }
9492  
9493 @@ -117,20 +116,20 @@
9494         ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
9495  #define SET(x) \
9496         ev->x = fdevent_solaris_devpoll_##x;
9497 -       
9498 +
9499         SET(free);
9500         SET(poll);
9501         SET(reset);
9502 -       
9503 +
9504         SET(event_del);
9505         SET(event_add);
9506 -       
9507 +
9508         SET(event_next_fdndx);
9509         SET(event_get_fd);
9510         SET(event_get_revent);
9511 -       
9512 +
9513         ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
9514 -       
9515 +
9516         if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
9517                 fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9518                         __FILE__, __LINE__, strerror(errno));
9519 @@ -152,7 +151,7 @@
9520  
9521         fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9522                         __FILE__, __LINE__);
9523 -       
9524 +
9525         return -1;
9526  }
9527  #endif
9528 --- ../lighttpd-1.4.11/src/http-header-glue.c   2006-02-08 15:31:36.000000000 +0200
9529 +++ lighttpd-1.4.12/src/http-header-glue.c      2006-07-11 22:07:53.000000000 +0300
9530 @@ -45,20 +45,20 @@
9531  #   ifdef HAVE_STRUCT_SOCKADDR_STORAGE
9532  static size_t get_sa_len(const struct sockaddr *addr) {
9533         switch (addr->sa_family) {
9534 -               
9535 +
9536  #    ifdef AF_INET
9537         case AF_INET:
9538                 return (sizeof (struct sockaddr_in));
9539  #    endif
9540 -               
9541 +
9542  #    ifdef AF_INET6
9543         case AF_INET6:
9544                 return (sizeof (struct sockaddr_in6));
9545  #    endif
9546 -               
9547 +
9548         default:
9549                 return (sizeof (struct sockaddr));
9550 -               
9551 +
9552         }
9553  }
9554  #    define SA_LEN(addr)   (get_sa_len(addr))
9555 @@ -74,7 +74,7 @@
9556  
9557  int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9558         data_string *ds;
9559 -       
9560 +
9561         UNUSED(srv);
9562  
9563         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
9564 @@ -82,32 +82,32 @@
9565         }
9566         buffer_copy_string_len(ds->key, key, keylen);
9567         buffer_copy_string_len(ds->value, value, vallen);
9568 -       
9569 +
9570         array_insert_unique(con->response.headers, (data_unset *)ds);
9571 -       
9572 +
9573         return 0;
9574  }
9575  
9576  int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9577         data_string *ds;
9578 -       
9579 +
9580         UNUSED(srv);
9581  
9582         /* if there already is a key by this name overwrite the value */
9583         if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
9584                 buffer_copy_string(ds->value, value);
9585 -               
9586 +
9587                 return 0;
9588         }
9589 -       
9590 +
9591         return response_header_insert(srv, con, key, keylen, value, vallen);
9592  }
9593  
9594  int http_response_redirect_to_directory(server *srv, connection *con) {
9595         buffer *o;
9596 -       
9597 +
9598         o = buffer_init();
9599 -       
9600 +
9601         if (con->conf.is_ssl) {
9602                 buffer_copy_string(o, "https://");
9603         } else {
9604 @@ -123,36 +123,36 @@
9605  #endif
9606                 sock_addr our_addr;
9607                 socklen_t our_addr_len;
9608 -               
9609 +
9610                 our_addr_len = sizeof(our_addr);
9611 -               
9612 +
9613                 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
9614                         con->http_status = 500;
9615 -                       
9616 +
9617                         log_error_write(srv, __FILE__, __LINE__, "ss",
9618                                         "can't get sockname", strerror(errno));
9619 -                       
9620 +
9621                         buffer_free(o);
9622                         return 0;
9623                 }
9624 -               
9625 -               
9626 +
9627 +
9628                 /* Lookup name: secondly try to get hostname for bind address */
9629                 switch(our_addr.plain.sa_family) {
9630  #ifdef HAVE_IPV6
9631                 case AF_INET6:
9632 -                       if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6), 
9633 -                                            SA_LEN((const struct sockaddr *)&our_addr.ipv6), 
9634 +                       if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
9635 +                                            SA_LEN((const struct sockaddr *)&our_addr.ipv6),
9636                                              hbuf, sizeof(hbuf), NULL, 0, 0)) {
9637 -                               
9638 +
9639                                 char dst[INET6_ADDRSTRLEN];
9640 -                               
9641 +
9642                                 log_error_write(srv, __FILE__, __LINE__,
9643                                                 "SSSS", "NOTICE: getnameinfo failed: ",
9644                                                 strerror(errno), ", using ip-address instead");
9645 -                               
9646 -                               buffer_append_string(o, 
9647 -                                                    inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr, 
9648 +
9649 +                               buffer_append_string(o,
9650 +                                                    inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
9651                                                                dst, sizeof(dst)));
9652                         } else {
9653                                 buffer_append_string(o, hbuf);
9654 @@ -164,7 +164,7 @@
9655                                 log_error_write(srv, __FILE__, __LINE__,
9656                                                 "SdSS", "NOTICE: gethostbyaddr failed: ",
9657                                                 h_errno, ", using ip-address instead");
9658 -                               
9659 +
9660                                 buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
9661                         } else {
9662                                 buffer_append_string(o, he->h_name);
9663 @@ -173,12 +173,12 @@
9664                 default:
9665                         log_error_write(srv, __FILE__, __LINE__,
9666                                         "S", "ERROR: unsupported address-type");
9667 -                       
9668 +
9669                         buffer_free(o);
9670                         return -1;
9671                 }
9672 -               
9673 -               if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) || 
9674 +
9675 +               if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
9676                       (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
9677                         buffer_append_string(o, ":");
9678                         buffer_append_long(o, srv->srvconf.port);
9679 @@ -190,41 +190,41 @@
9680                 buffer_append_string(o, "?");
9681                 buffer_append_string_buffer(o, con->uri.query);
9682         }
9683 -       
9684 +
9685         response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
9686 -       
9687 +
9688         con->http_status = 301;
9689         con->file_finished = 1;
9690 -       
9691 +
9692         buffer_free(o);
9693 -       
9694 +
9695         return 0;
9696  }
9697  
9698  buffer * strftime_cache_get(server *srv, time_t last_mod) {
9699         struct tm *tm;
9700         size_t i;
9701 -               
9702 +
9703         for (i = 0; i < FILE_CACHE_MAX; i++) {
9704                 /* found cache-entry */
9705                 if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;
9706 -                               
9707 +
9708                 /* found empty slot */
9709                 if (srv->mtime_cache[i].mtime == 0) break;
9710         }
9711 -       
9712 +
9713         if (i == FILE_CACHE_MAX) {
9714                 i = 0;
9715         }
9716 -               
9717 +
9718         srv->mtime_cache[i].mtime = last_mod;
9719         buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
9720         tm = gmtime(&(srv->mtime_cache[i].mtime));
9721 -       srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr, 
9722 +       srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
9723                                                  srv->mtime_cache[i].str->size - 1,
9724                                                  "%a, %d %b %Y %H:%M:%S GMT", tm);
9725         srv->mtime_cache[i].str->used++;
9726 -       
9727 +
9728         return srv->mtime_cache[i].str;
9729  }
9730  
9731 @@ -239,56 +239,60 @@
9732          *    request. That is, if no entity tags match, then the server MUST NOT
9733          *    return a 304 (Not Modified) response.
9734          */
9735 -       
9736 +
9737         /* last-modified handling */
9738         if (con->request.http_if_none_match) {
9739                 if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) {
9740 -                       if (con->request.http_method == HTTP_METHOD_GET || 
9741 +                       if (con->request.http_method == HTTP_METHOD_GET ||
9742                             con->request.http_method == HTTP_METHOD_HEAD) {
9743 -                               
9744 +
9745                                 /* check if etag + last-modified */
9746                                 if (con->request.http_if_modified_since) {
9747                                         size_t used_len;
9748                                         char *semicolon;
9749 -                                       
9750 +
9751                                         if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
9752                                                 used_len = strlen(con->request.http_if_modified_since);
9753                                         } else {
9754                                                 used_len = semicolon - con->request.http_if_modified_since;
9755                                         }
9756 -                                       
9757 +
9758                                         if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
9759                                                 con->http_status = 304;
9760                                                 return HANDLER_FINISHED;
9761                                         } else {
9762 +#ifdef HAVE_STRPTIME
9763                                                 char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
9764 +                                               time_t t_header, t_file;
9765 +                                               struct tm tm;
9766  
9767 -                                               /* convert to timestamp */
9768 -                                               if (used_len < sizeof(buf)) {
9769 -                                                       time_t t_header, t_file;
9770 -                                                       struct tm tm;
9771 -                                                       
9772 -                                                       strncpy(buf, con->request.http_if_modified_since, used_len);
9773 -                                                       buf[used_len] = '\0';
9774 -                                                       
9775 -                                                       strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9776 -                                                       t_header = mktime(&tm);
9777 -                                                       
9778 -                                                       strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9779 -                                                       t_file = mktime(&tm);
9780 -
9781 -                                                       if (t_file > t_header) {
9782 -                                                               con->http_status = 304;
9783 -                                                               return HANDLER_FINISHED;
9784 -                                                       }
9785 -                                               } else {
9786 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssdd", 
9787 -                                                                       "DEBUG: Last-Modified check failed as the received timestamp was too long:", 
9788 +                                               /* check if we can safely copy the string */
9789 +                                               if (used_len >= sizeof(buf)) {
9790 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssdd",
9791 +                                                                       "DEBUG: Last-Modified check failed as the received timestamp was too long:",
9792                                                                         con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
9793 -                                                       
9794 +
9795                                                         con->http_status = 412;
9796                                                         return HANDLER_FINISHED;
9797                                                 }
9798 +
9799 +
9800 +                                               strncpy(buf, con->request.http_if_modified_since, used_len);
9801 +                                               buf[used_len] = '\0';
9802 +
9803 +                                               strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9804 +                                               t_header = mktime(&tm);
9805 +
9806 +                                               strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9807 +                                               t_file = mktime(&tm);
9808 +
9809 +                                               if (t_file > t_header) return HANDLER_GO_ON;
9810 +
9811 +                                               con->http_status = 304;
9812 +                                               return HANDLER_FINISHED;
9813 +#else
9814 +                        return HANDLER_GO_ON;
9815 +#endif
9816                                         }
9817                                 } else {
9818                                         con->http_status = 304;
9819 @@ -302,16 +306,41 @@
9820         } else if (con->request.http_if_modified_since) {
9821                 size_t used_len;
9822                 char *semicolon;
9823 -               
9824 +
9825                 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
9826                         used_len = strlen(con->request.http_if_modified_since);
9827                 } else {
9828                         used_len = semicolon - con->request.http_if_modified_since;
9829                 }
9830 -               
9831 +
9832                 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
9833                         con->http_status = 304;
9834                         return HANDLER_FINISHED;
9835 +               } else {
9836 +#ifdef HAVE_STRPTIME
9837 +                       char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
9838 +                       time_t t_header, t_file;
9839 +                       struct tm tm;
9840 +
9841 +                       /* convert to timestamp */
9842 +                       if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
9843 +
9844 +                       strncpy(buf, con->request.http_if_modified_since, used_len);
9845 +                       buf[used_len] = '\0';
9846 +
9847 +                       strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9848 +                       t_header = mktime(&tm);
9849 +
9850 +                       strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9851 +                       t_file = mktime(&tm);
9852 +
9853 +                       if (t_file > t_header) return HANDLER_GO_ON;
9854 +
9855 +                       con->http_status = 304;
9856 +                       return HANDLER_FINISHED;
9857 +#else
9858 +            return HANDLER_GO_ON;
9859 +#endif
9860                 }
9861         }
9862  
9863 --- ../lighttpd-1.4.11/src/http_auth.c  2006-02-01 13:02:52.000000000 +0200
9864 +++ lighttpd-1.4.12/src/http_auth.c     2006-07-11 22:07:53.000000000 +0300
9865 @@ -22,7 +22,6 @@
9866  #include <string.h>
9867  #include <time.h>
9868  #include <errno.h>
9869 -#include <unistd.h>
9870  #include <ctype.h>
9871  
9872  #include "server.h"
9873 @@ -31,23 +30,14 @@
9874  #include "http_auth_digest.h"
9875  #include "stream.h"
9876  
9877 +#include "sys-strings.h"
9878 +
9879  #ifdef USE_OPENSSL
9880  # include <openssl/md5.h>
9881  #else
9882  # include "md5.h"
9883  #endif
9884  
9885 -
9886 -#ifdef USE_PAM
9887 -#include <security/pam_appl.h>
9888 -#include <security/pam_misc.h>
9889 -
9890 -static struct pam_conv conv = {
9891 -       misc_conv,
9892 -               NULL
9893 -};
9894 -#endif
9895 -
9896  handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
9897  
9898  static const char base64_pad = '=';
9899 @@ -75,25 +65,25 @@
9900         unsigned char *result;
9901         int ch, j = 0, k;
9902         size_t i;
9903 -       
9904 +
9905         size_t in_len = strlen(in);
9906 -       
9907 +
9908         buffer_prepare_copy(out, in_len);
9909 -       
9910 +
9911         result = (unsigned char *)out->ptr;
9912 -       
9913 +
9914         ch = in[0];
9915         /* run through the whole string, converting as we go */
9916         for (i = 0; i < in_len; i++) {
9917                 ch = in[i];
9918 -               
9919 +
9920                 if (ch == '\0') break;
9921 -               
9922 +
9923                 if (ch == base64_pad) break;
9924 -               
9925 +
9926                 ch = base64_reverse_table[ch];
9927                 if (ch < 0) continue;
9928 -               
9929 +
9930                 switch(i % 4) {
9931                 case 0:
9932                         result[j] = ch << 2;
9933 @@ -125,168 +115,168 @@
9934                 }
9935         }
9936         result[k] = '\0';
9937 -       
9938 +
9939         out->used = k;
9940 -       
9941 +
9942         return result;
9943  }
9944  
9945  static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
9946         int ret = -1;
9947 -       
9948 +
9949         if (!username->used|| !realm->used) return -1;
9950 -       
9951 +
9952         if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
9953                 stream f;
9954                 char * f_line;
9955 -               
9956 +
9957                 if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
9958 -               
9959 +
9960                 if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) {
9961                         log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno));
9962 -                       
9963 +
9964                         return -1;
9965                 }
9966 -               
9967 +
9968                 f_line = f.start;
9969 -               
9970 +
9971                 while (f_line - f.start != f.size) {
9972                         char *f_user, *f_pwd, *e, *f_realm;
9973                         size_t u_len, pwd_len, r_len;
9974 -                       
9975 +
9976                         f_user = f_line;
9977 -                       
9978 -                       /* 
9979 +
9980 +                       /*
9981                          * htdigest format
9982 -                        * 
9983 -                        * user:realm:md5(user:realm:password) 
9984 +                        *
9985 +                        * user:realm:md5(user:realm:password)
9986                          */
9987 -                       
9988 +
9989                         if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
9990 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
9991 -                                               "parsed error in", p->conf.auth_htdigest_userfile, 
9992 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
9993 +                                               "parsed error in", p->conf.auth_htdigest_userfile,
9994                                                 "expected 'username:realm:hashed password'");
9995 -                               
9996 +
9997                                 stream_close(&f);
9998 -                               
9999 +
10000                                 return -1;
10001                         }
10002 -                       
10003 +
10004                         if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) {
10005 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
10006 -                                               "parsed error in", p->conf.auth_plain_userfile, 
10007 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
10008 +                                               "parsed error in", p->conf.auth_plain_userfile,
10009                                                 "expected 'username:realm:hashed password'");
10010 -                               
10011 +
10012                                 stream_close(&f);
10013 -                               
10014 +
10015                                 return -1;
10016                         }
10017 -                       
10018 +
10019                         /* get pointers to the fields */
10020 -                       u_len = f_realm - f_user; 
10021 +                       u_len = f_realm - f_user;
10022                         f_realm++;
10023                         r_len = f_pwd - f_realm;
10024                         f_pwd++;
10025 -                       
10026 +
10027                         if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10028                                 pwd_len = e - f_pwd;
10029                         } else {
10030                                 pwd_len = f.size - (f_pwd - f.start);
10031                         }
10032 -                       
10033 +
10034                         if (username->used - 1 == u_len &&
10035                             (realm->used - 1 == r_len) &&
10036                             (0 == strncmp(username->ptr, f_user, u_len)) &&
10037                             (0 == strncmp(realm->ptr, f_realm, r_len))) {
10038                                 /* found */
10039 -                               
10040 +
10041                                 buffer_copy_string_len(password, f_pwd, pwd_len);
10042 -                               
10043 +
10044                                 ret = 0;
10045                                 break;
10046                         }
10047 -                       
10048 +
10049                         /* EOL */
10050                         if (!e) break;
10051 -                       
10052 +
10053                         f_line = e + 1;
10054                 }
10055 -               
10056 +
10057                 stream_close(&f);
10058         } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
10059                    p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10060                 stream f;
10061                 char * f_line;
10062                 buffer *auth_fn;
10063 -               
10064 +
10065                 auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
10066 -               
10067 +
10068                 if (buffer_is_empty(auth_fn)) return -1;
10069 -               
10070 +
10071                 if (0 != stream_open(&f, auth_fn)) {
10072 -                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
10073 +                       log_error_write(srv, __FILE__, __LINE__, "sbss",
10074                                         "opening plain-userfile", auth_fn, "failed:", strerror(errno));
10075 -                       
10076 +
10077                         return -1;
10078                 }
10079 -               
10080 +
10081                 f_line = f.start;
10082 -               
10083 +
10084                 while (f_line - f.start != f.size) {
10085                         char *f_user, *f_pwd, *e;
10086                         size_t u_len, pwd_len;
10087 -                       
10088 +
10089                         f_user = f_line;
10090 -                       
10091 -                       /* 
10092 +
10093 +                       /*
10094                          * htpasswd format
10095 -                        * 
10096 +                        *
10097                          * user:crypted passwd
10098                          */
10099 -                       
10100 +
10101                         if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10102 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
10103 -                                               "parsed error in", auth_fn, 
10104 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
10105 +                                               "parsed error in", auth_fn,
10106                                                 "expected 'username:hashed password'");
10107 -                               
10108 +
10109                                 stream_close(&f);
10110 -                               
10111 +
10112                                 return -1;
10113                         }
10114 -                       
10115 +
10116                         /* get pointers to the fields */
10117 -                       u_len = f_pwd - f_user; 
10118 +                       u_len = f_pwd - f_user;
10119                         f_pwd++;
10120 -                       
10121 +
10122                         if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10123                                 pwd_len = e - f_pwd;
10124                         } else {
10125                                 pwd_len = f.size - (f_pwd - f.start);
10126                         }
10127 -                       
10128 +
10129                         if (username->used - 1 == u_len &&
10130                             (0 == strncmp(username->ptr, f_user, u_len))) {
10131                                 /* found */
10132 -                               
10133 +
10134                                 buffer_copy_string_len(password, f_pwd, pwd_len);
10135 -                               
10136 +
10137                                 ret = 0;
10138                                 break;
10139                         }
10140 -                       
10141 +
10142                         /* EOL */
10143                         if (!e) break;
10144 -                       
10145 +
10146                         f_line = e + 1;
10147                 }
10148 -               
10149 +
10150                 stream_close(&f);
10151         } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10152                 ret = 0;
10153         } else {
10154                 return -1;
10155         }
10156 -       
10157 +
10158         return ret;
10159  }
10160  
10161 @@ -296,7 +286,7 @@
10162         int username_len;
10163         data_string *require;
10164         array *req;
10165 -       
10166 +
10167         UNUSED(group);
10168         UNUSED(host);
10169  
10170 @@ -304,12 +294,12 @@
10171         /* search auth-directives for path */
10172         for (i = 0; i < p->conf.auth_require->used; i++) {
10173                 if (p->conf.auth_require->data[i]->key->used == 0) continue;
10174 -               
10175 +
10176                 if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
10177                         break;
10178                 }
10179         }
10180 -       
10181 +
10182         if (i == p->conf.auth_require->used) {
10183                 return -1;
10184         }
10185 @@ -317,72 +307,72 @@
10186         req = ((data_array *)(p->conf.auth_require->data[i]))->value;
10187  
10188         require = (data_string *)array_get_element(req, "require");
10189 -       
10190 +
10191         /* if we get here, the user we got a authed user */
10192         if (0 == strcmp(require->value->ptr, "valid-user")) {
10193                 return 0;
10194         }
10195 -       
10196 +
10197         /* user=name1|group=name3|host=name4 */
10198 -       
10199 +
10200         /* seperate the string by | */
10201  #if 0
10202         log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
10203 -#endif 
10204 -       
10205 +#endif
10206 +
10207         username_len = username ? strlen(username) : 0;
10208 -       
10209 +
10210         r = rules = require->value->ptr;
10211 -       
10212 +
10213         while (1) {
10214                 const char *eq;
10215                 const char *k, *v, *e;
10216                 int k_len, v_len, r_len;
10217 -               
10218 +
10219                 e = strchr(r, '|');
10220 -               
10221 +
10222                 if (e) {
10223                         r_len = e - r;
10224                 } else {
10225                         r_len = strlen(rules) - (r - rules);
10226                 }
10227 -               
10228 +
10229                 /* from r to r + r_len is a rule */
10230 -               
10231 +
10232                 if (0 == strncmp(r, "valid-user", r_len)) {
10233 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
10234 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
10235                                         "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules",
10236                                         require->value);
10237                         return -1;
10238                 }
10239 -               
10240 +
10241                 /* search for = in the rules */
10242                 if (NULL == (eq = strchr(r, '='))) {
10243 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
10244 -                                       "parsing the 'require' section in 'auth.require' failed: a = is missing", 
10245 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
10246 +                                       "parsing the 'require' section in 'auth.require' failed: a = is missing",
10247                                         require->value);
10248                         return -1;
10249                 }
10250 -               
10251 +
10252                 /* = out of range */
10253                 if (eq > r + r_len) {
10254 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
10255 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
10256                                         "parsing the 'require' section in 'auth.require' failed: = out of range",
10257                                         require->value);
10258 -                       
10259 +
10260                         return -1;
10261                 }
10262 -               
10263 +
10264                 /* the part before the = is user|group|host */
10265 -               
10266 +
10267                 k = r;
10268                 k_len = eq - r;
10269                 v = eq + 1;
10270                 v_len = r_len - k_len - 1;
10271 -               
10272 +
10273                 if (k_len == 4) {
10274                         if (0 == strncmp(k, "user", k_len)) {
10275 -                               if (username && 
10276 +                               if (username &&
10277                                     username_len == v_len &&
10278                                     0 == strncmp(username, v, v_len)) {
10279                                         return 0;
10280 @@ -404,19 +394,19 @@
10281                         log_error_write(srv, __FILE__, __LINE__, "s", "unknown  key");
10282                         return -1;
10283                 }
10284 -               
10285 +
10286                 if (!e) break;
10287                 r = e + 1;
10288         }
10289 -       
10290 +
10291         log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
10292 -       
10293 +
10294         return -1;
10295  }
10296  
10297  /**
10298 - * 
10299 - * 
10300 + *
10301 + *
10302   * @param password password-string from the auth-backend
10303   * @param pw       password-string from the client
10304   */
10305 @@ -426,16 +416,16 @@
10306         UNUSED(req);
10307  
10308         if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10309 -               /* 
10310 +               /*
10311                  * htdigest format
10312 -                * 
10313 -                * user:realm:md5(user:realm:password) 
10314 +                *
10315 +                * user:realm:md5(user:realm:password)
10316                  */
10317 -               
10318 +
10319                 MD5_CTX Md5Ctx;
10320                 HASH HA1;
10321                 char a1[256];
10322 -               
10323 +
10324                 MD5_Init(&Md5Ctx);
10325                 MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1);
10326                 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10327 @@ -443,24 +433,24 @@
10328                 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10329                 MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
10330                 MD5_Final(HA1, &Md5Ctx);
10331 -               
10332 +
10333                 CvtHex(HA1, a1);
10334 -               
10335 +
10336                 if (0 == strcmp(password->ptr, a1)) {
10337                         return 0;
10338                 }
10339 -       } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) { 
10340 -#ifdef HAVE_CRYPT      
10341 +       } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
10342 +#ifdef HAVE_CRYPT
10343                 char salt[32];
10344                 char *crypted;
10345                 size_t salt_len = 0;
10346 -               /* 
10347 +               /*
10348                  * htpasswd format
10349 -                * 
10350 +                *
10351                  * user:crypted password
10352                  */
10353  
10354 -               /* 
10355 +               /*
10356                  *  Algorithm      Salt
10357                  *  CRYPT_STD_DES   2-character (Default)
10358                  *  CRYPT_EXT_DES   9-character
10359 @@ -478,7 +468,7 @@
10360                         salt_len = 2;
10361                 } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
10362                         char *dollar = NULL;
10363 -               
10364 +
10365                         if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
10366                                 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10367                                 return -1;
10368 @@ -495,7 +485,7 @@
10369                 strncpy(salt, password->ptr, salt_len);
10370  
10371                 salt[salt_len] = '\0';
10372 -               
10373 +
10374                 crypted = crypt(pw, salt);
10375  
10376                 if (0 == strcmp(password->ptr, crypted)) {
10377 @@ -503,40 +493,13 @@
10378                 } else {
10379                         fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10380                 }
10381 -       
10382 -#endif 
10383 -       } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) { 
10384 +
10385 +#endif
10386 +       } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10387                 if (0 == strcmp(password->ptr, pw)) {
10388                         return 0;
10389                 }
10390 -       } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) { 
10391 -#ifdef USE_PAM
10392 -               pam_handle_t *pamh=NULL;
10393 -               int retval;
10394 -               
10395 -               retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
10396 -               
10397 -               if (retval == PAM_SUCCESS)
10398 -                       retval = pam_authenticate(pamh, 0);    /* is user really user? */
10399 -               
10400 -               if (retval == PAM_SUCCESS)
10401 -                       retval = pam_acct_mgmt(pamh, 0);       /* permitted access? */
10402 -               
10403 -               /* This is where we have been authorized or not. */
10404 -               
10405 -               if (pam_end(pamh,retval) != PAM_SUCCESS) {     /* close Linux-PAM */
10406 -                       pamh = NULL;
10407 -                       log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
10408 -               }
10409 -               
10410 -               if (retval == PAM_SUCCESS) {
10411 -                       log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
10412 -                       return 0;
10413 -               } else {
10414 -                       log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
10415 -               }
10416 -#endif
10417 -       } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { 
10418 +       } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10419  #ifdef USE_LDAP
10420                 LDAP *ldap;
10421                 LDAPMessage *lm, *first;
10422 @@ -544,45 +507,45 @@
10423                 int ret;
10424                 char *attrs[] = { LDAP_NO_ATTRS, NULL };
10425                 size_t i;
10426 -               
10427 +
10428                 /* for now we stay synchronous */
10429 -               
10430 -               /* 
10431 +
10432 +               /*
10433                  * 1. connect anonymously (done in plugin init)
10434                  * 2. get DN for uid = username
10435                  * 3. auth against ldap server
10436                  * 4. (optional) check a field
10437                  * 5. disconnect
10438 -                * 
10439 +                *
10440                  */
10441 -               
10442 +
10443                 /* check username
10444 -                * 
10445 +                *
10446                  * we have to protect us againt username which modifies out filter in
10447                  * a unpleasant way
10448                  */
10449 -               
10450 +
10451                 for (i = 0; i < username->used - 1; i++) {
10452                         char c = username->ptr[i];
10453 -                       
10454 +
10455                         if (!isalpha(c) &&
10456                             !isdigit(c)) {
10457 -                               
10458 -                               log_error_write(srv, __FILE__, __LINE__, "sbd", 
10459 +
10460 +                               log_error_write(srv, __FILE__, __LINE__, "sbd",
10461                                         "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
10462 -                               
10463 +
10464                                 return -1;
10465                         }
10466                 }
10467 -               
10468 -               
10469 -               
10470 +
10471 +
10472 +
10473                 /* build filter */
10474                 buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
10475                 buffer_append_string_buffer(p->ldap_filter, username);
10476                 buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post);
10477 -               
10478 -               
10479 +
10480 +
10481                 /* 2. */
10482                 if (p->conf.ldap == NULL ||
10483                     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))) {
10484 @@ -590,71 +553,71 @@
10485                                 return -1;
10486                         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))) {
10487  
10488 -                       log_error_write(srv, __FILE__, __LINE__, "sssb", 
10489 +                       log_error_write(srv, __FILE__, __LINE__, "sssb",
10490                                         "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
10491 -                       
10492 +
10493                         return -1;
10494                         }
10495                 }
10496 -               
10497 +
10498                 if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
10499                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10500 -                       
10501 +
10502                         ldap_msgfree(lm);
10503 -                       
10504 +
10505                         return -1;
10506                 }
10507 -               
10508 +
10509                 if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
10510                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10511 -                       
10512 +
10513                         ldap_msgfree(lm);
10514 -                       
10515 +
10516                         return -1;
10517                 }
10518 -               
10519 +
10520                 ldap_msgfree(lm);
10521 -               
10522 -               
10523 +
10524 +
10525                 /* 3. */
10526                 if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) {
10527                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
10528                         return -1;
10529                 }
10530 -               
10531 +
10532                 ret = LDAP_VERSION3;
10533                 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
10534                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10535 -                       
10536 +
10537                         ldap_unbind_s(ldap);
10538 -                       
10539 +
10540                         return -1;
10541                 }
10542 -               
10543 +
10544                 if (p->conf.auth_ldap_starttls == 1) {
10545                         if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL,  NULL))) {
10546                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
10547 -               
10548 +
10549                                 ldap_unbind_s(ldap);
10550 -                               
10551 +
10552                                 return -1;
10553                         }
10554                 }
10555  
10556 -               
10557 +
10558                 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
10559                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10560 -                       
10561 +
10562                         ldap_unbind_s(ldap);
10563 -                       
10564 +
10565                         return -1;
10566                 }
10567 -               
10568 +
10569                 /* 5. */
10570                 ldap_unbind_s(ldap);
10571 -               
10572 +
10573                 /* everything worked, good, access granted */
10574 -               
10575 +
10576                 return 0;
10577  #endif
10578         }
10579 @@ -664,65 +627,65 @@
10580  int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
10581         buffer *username, *password;
10582         char *pw;
10583 -       
10584 +
10585         data_string *realm;
10586 -       
10587 +
10588         realm = (data_string *)array_get_element(req, "realm");
10589 -       
10590 +
10591         username = buffer_init();
10592         password = buffer_init();
10593 -       
10594 +
10595         base64_decode(username, realm_str);
10596 -       
10597 +
10598         /* r2 == user:password */
10599         if (NULL == (pw = strchr(username->ptr, ':'))) {
10600                 buffer_free(username);
10601 -               
10602 +
10603                 log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
10604 -               
10605 +
10606                 return 0;
10607         }
10608 -       
10609 +
10610         *pw++ = '\0';
10611 -       
10612 +
10613         username->used = pw - username->ptr;
10614 -       
10615 +
10616         /* copy password to r1 */
10617         if (http_auth_get_password(srv, p, username, realm->value, password)) {
10618                 buffer_free(username);
10619                 buffer_free(password);
10620 -               
10621 +
10622                 log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed");
10623 -               
10624 +
10625                 return 0;
10626         }
10627 -       
10628 +
10629         /* password doesn't match */
10630         if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
10631                 log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
10632 -               
10633 +
10634                 buffer_free(username);
10635                 buffer_free(password);
10636 -               
10637 +
10638                 return 0;
10639         }
10640 -       
10641 +
10642         /* value is our allow-rules */
10643         if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
10644                 buffer_free(username);
10645                 buffer_free(password);
10646 -               
10647 +
10648                 log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
10649 -               
10650 +
10651                 return 0;
10652         }
10653 -       
10654 +
10655         /* remember the username */
10656         buffer_copy_string_buffer(p->auth_user, username);
10657 -       
10658 +
10659         buffer_free(username);
10660         buffer_free(password);
10661 -       
10662 +
10663         return 1;
10664  }
10665  
10666 @@ -735,7 +698,7 @@
10667  int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
10668         char a1[256];
10669         char a2[256];
10670 -       
10671 +
10672         char *username;
10673         char *realm;
10674         char *nonce;
10675 @@ -745,18 +708,18 @@
10676         char *cnonce;
10677         char *nc;
10678         char *respons;
10679 -       
10680 +
10681         char *e, *c;
10682         const char *m = NULL;
10683         int i;
10684         buffer *password, *b, *username_buf, *realm_buf;
10685 -       
10686 +
10687         MD5_CTX Md5Ctx;
10688         HASH HA1;
10689         HASH HA2;
10690         HASH RespHash;
10691         HASHHEX HA2Hex;
10692 -       
10693 +
10694  
10695         /* init pointers */
10696  #define S(x) \
10697 @@ -771,11 +734,11 @@
10698                 { S("cnonce=") },
10699                 { S("nc=") },
10700                 { S("response=") },
10701 -               
10702 +
10703                 { NULL, 0, NULL }
10704         };
10705  #undef S
10706 -       
10707 +
10708         dkv[0].ptr = &username;
10709         dkv[1].ptr = &realm;
10710         dkv[2].ptr = &nonce;
10711 @@ -786,24 +749,24 @@
10712         dkv[7].ptr = &nc;
10713         dkv[8].ptr = &respons;
10714         dkv[9].ptr = NULL;
10715 -       
10716 +
10717         UNUSED(req);
10718 -       
10719 +
10720         for (i = 0; dkv[i].key; i++) {
10721                 *(dkv[i].ptr) = NULL;
10722         }
10723 -       
10724 -       
10725 +
10726 +
10727         if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST &&
10728             p->conf.auth_backend != AUTH_BACKEND_PLAIN) {
10729 -               log_error_write(srv, __FILE__, __LINE__, "s", 
10730 +               log_error_write(srv, __FILE__, __LINE__, "s",
10731                                 "digest: unsupported backend (only htdigest or plain)");
10732 -               
10733 +
10734                 return -1;
10735         }
10736 -       
10737 +
10738         b = buffer_init_string(realm_str);
10739 -       
10740 +
10741         /* parse credentials from client */
10742         for (c = b->ptr; *c; c++) {
10743                 /* skip whitespaces */
10744 @@ -812,18 +775,18 @@
10745  
10746                 for (i = 0; dkv[i].key; i++) {
10747                         if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) {
10748 -                               if ((c[dkv[i].key_len] == '"') && 
10749 +                               if ((c[dkv[i].key_len] == '"') &&
10750                                     (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) {
10751                                         /* value with "..." */
10752                                         *(dkv[i].ptr) = c + dkv[i].key_len + 1;
10753                                         c = e;
10754 -       
10755 +
10756                                         *e = '\0';
10757                                 } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) {
10758                                         /* value without "...", terminated by ',' */
10759                                         *(dkv[i].ptr) = c + dkv[i].key_len;
10760                                         c = e;
10761 -                                       
10762 +
10763                                         *e = '\0';
10764                                 } else {
10765                                         /* value without "...", terminated by EOL */
10766 @@ -833,7 +796,7 @@
10767                         }
10768                 }
10769         }
10770 -       
10771 +
10772         if (p->conf.auth_debug > 1) {
10773                 log_error_write(srv, __FILE__, __LINE__, "ss", "username", username);
10774                 log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm);
10775 @@ -845,22 +808,22 @@
10776                 log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc);
10777                 log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons);
10778         }
10779 -       
10780 +
10781         /* check if everything is transmitted */
10782 -       if (!username || 
10783 +       if (!username ||
10784             !realm ||
10785             !nonce ||
10786             !uri ||
10787             (qop && (!nc || !cnonce)) ||
10788             !respons ) {
10789                 /* missing field */
10790 -               
10791 -               log_error_write(srv, __FILE__, __LINE__, "s", 
10792 +
10793 +               log_error_write(srv, __FILE__, __LINE__, "s",
10794                                 "digest: missing field");
10795                 return -1;
10796         }
10797  
10798 -       m = get_http_method_name(con->request.http_method);     
10799 +       m = get_http_method_name(con->request.http_method);
10800  
10801         /* password-string == HA1 */
10802         password = buffer_init();
10803 @@ -873,10 +836,10 @@
10804                 buffer_free(realm_buf);
10805                 return 0;
10806         }
10807 -       
10808 +
10809         buffer_free(username_buf);
10810         buffer_free(realm_buf);
10811 -       
10812 +
10813         if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10814                 /* generate password from plain-text */
10815                 MD5_Init(&Md5Ctx);
10816 @@ -890,16 +853,16 @@
10817                 /* HA1 */
10818                 /* transform the 32-byte-hex-md5 to a 16-byte-md5 */
10819                 for (i = 0; i < HASHLEN; i++) {
10820 -                       HA1[i] = hex2int(password->ptr[i*2]) << 4; 
10821 -                       HA1[i] |= hex2int(password->ptr[i*2+1]); 
10822 +                       HA1[i] = hex2int(password->ptr[i*2]) << 4;
10823 +                       HA1[i] |= hex2int(password->ptr[i*2+1]);
10824                 }
10825         } else {
10826                 /* we already check that above */
10827                 SEGFAULT();
10828         }
10829 -       
10830 +
10831         buffer_free(password);
10832 -       
10833 +
10834         if (algorithm &&
10835             strcasecmp(algorithm, "md5-sess") == 0) {
10836                 MD5_Init(&Md5Ctx);
10837 @@ -910,9 +873,9 @@
10838                 MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
10839                 MD5_Final(HA1, &Md5Ctx);
10840         }
10841 -       
10842 +
10843         CvtHex(HA1, a1);
10844 -       
10845 +
10846         /* calculate H(A2) */
10847         MD5_Init(&Md5Ctx);
10848         MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
10849 @@ -924,7 +887,7 @@
10850         }
10851         MD5_Final(HA2, &Md5Ctx);
10852         CvtHex(HA2, HA2Hex);
10853 -       
10854 +
10855         /* calculate response */
10856         MD5_Init(&Md5Ctx);
10857         MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN);
10858 @@ -942,39 +905,39 @@
10859         MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN);
10860         MD5_Final(RespHash, &Md5Ctx);
10861         CvtHex(RespHash, a2);
10862 -       
10863 +
10864         if (0 != strcmp(a2, respons)) {
10865                 /* digest not ok */
10866 -               
10867 +
10868                 if (p->conf.auth_debug) {
10869 -                       log_error_write(srv, __FILE__, __LINE__, "sss", 
10870 +                       log_error_write(srv, __FILE__, __LINE__, "sss",
10871                                 "digest: digest mismatch", a2, respons);
10872                 }
10873 -               
10874 -               log_error_write(srv, __FILE__, __LINE__, "sss", 
10875 +
10876 +               log_error_write(srv, __FILE__, __LINE__, "sss",
10877                                 "digest: auth failed for", username, "wrong password");
10878 -               
10879 +
10880                 buffer_free(b);
10881                 return 0;
10882         }
10883 -       
10884 +
10885         /* value is our allow-rules */
10886         if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
10887                 buffer_free(b);
10888 -               
10889 -               log_error_write(srv, __FILE__, __LINE__, "s", 
10890 +
10891 +               log_error_write(srv, __FILE__, __LINE__, "s",
10892                                 "digest: rules did match");
10893 -               
10894 +
10895                 return 0;
10896         }
10897 -       
10898 +
10899         /* remember the username */
10900         buffer_copy_string(p->auth_user, username);
10901 -       
10902 +
10903         buffer_free(b);
10904 -       
10905 +
10906         if (p->conf.auth_debug) {
10907 -               log_error_write(srv, __FILE__, __LINE__, "s", 
10908 +               log_error_write(srv, __FILE__, __LINE__, "s",
10909                                 "digest: auth ok");
10910         }
10911         return 1;
10912 @@ -985,23 +948,23 @@
10913         HASH h;
10914         MD5_CTX Md5Ctx;
10915         char hh[32];
10916 -       
10917 +
10918         UNUSED(p);
10919  
10920         /* generate shared-secret */
10921         MD5_Init(&Md5Ctx);
10922         MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
10923         MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
10924 -       
10925 +
10926         /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
10927         ltostr(hh, srv->cur_ts);
10928         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
10929         ltostr(hh, rand());
10930         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
10931 -       
10932 +
10933         MD5_Final(h, &Md5Ctx);
10934 -       
10935 +
10936         CvtHex(h, out);
10937 -       
10938 +
10939         return 0;
10940  }
10941 --- ../lighttpd-1.4.11/src/http_auth.h  2005-08-14 17:12:31.000000000 +0300
10942 +++ lighttpd-1.4.12/src/http_auth.h     2006-07-11 22:07:53.000000000 +0300
10943 @@ -9,22 +9,26 @@
10944  # include <ldap.h>
10945  #endif
10946  
10947 -typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN, 
10948 -               AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD, 
10949 -               AUTH_BACKEND_HTDIGEST, AUTH_BACKEND_PAM } auth_backend_t;
10950 +typedef enum {
10951 +       AUTH_BACKEND_UNSET,
10952 +       AUTH_BACKEND_PLAIN,
10953 +       AUTH_BACKEND_LDAP,
10954 +       AUTH_BACKEND_HTPASSWD,
10955 +       AUTH_BACKEND_HTDIGEST
10956 +} auth_backend_t;
10957  
10958  typedef struct {
10959         /* auth */
10960         array  *auth_require;
10961 -       
10962 +
10963         buffer *auth_plain_groupfile;
10964         buffer *auth_plain_userfile;
10965 -       
10966 +
10967         buffer *auth_htdigest_userfile;
10968         buffer *auth_htpasswd_userfile;
10969 -       
10970 +
10971         buffer *auth_backend_conf;
10972 -       
10973 +
10974         buffer *auth_ldap_hostname;
10975         buffer *auth_ldap_basedn;
10976         buffer *auth_ldap_binddn;
10977 @@ -32,15 +36,15 @@
10978         buffer *auth_ldap_filter;
10979         buffer *auth_ldap_cafile;
10980         unsigned short auth_ldap_starttls;
10981 -       
10982 +
10983         unsigned short auth_debug;
10984 -       
10985 +
10986         /* generated */
10987         auth_backend_t auth_backend;
10988 -       
10989 +
10990  #ifdef USE_LDAP
10991         LDAP *ldap;
10992 -       
10993 +
10994         buffer *ldap_filter_pre;
10995         buffer *ldap_filter_post;
10996  #endif
10997 @@ -49,15 +53,15 @@
10998  typedef struct {
10999         PLUGIN_DATA;
11000         buffer *tmp_buf;
11001 -       
11002 +
11003         buffer *auth_user;
11004  
11005  #ifdef USE_LDAP
11006         buffer *ldap_filter;
11007  #endif
11008 -       
11009 +
11010         mod_auth_plugin_config **config_storage;
11011 -       
11012 +
11013         mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
11014  } mod_auth_plugin_data;
11015  
11016 --- ../lighttpd-1.4.11/src/http_auth_digest.h   2006-01-05 00:54:01.000000000 +0200
11017 +++ lighttpd-1.4.12/src/http_auth_digest.h      2006-07-11 22:07:53.000000000 +0300
11018 @@ -12,7 +12,7 @@
11019  #ifdef USE_OPENSSL
11020  #define IN const
11021  #else
11022 -#define IN 
11023 +#define IN
11024  #endif
11025  #define OUT
11026  
11027 --- ../lighttpd-1.4.11/src/http_chunk.c 2005-08-11 01:26:50.000000000 +0300
11028 +++ lighttpd-1.4.12/src/http_chunk.c    2006-07-11 22:07:53.000000000 +0300
11029 @@ -1,7 +1,7 @@
11030  /**
11031   * the HTTP chunk-API
11032 - * 
11033 - * 
11034 + *
11035 + *
11036   */
11037  
11038  #include <sys/types.h>
11039 @@ -9,7 +9,6 @@
11040  
11041  #include <stdlib.h>
11042  #include <fcntl.h>
11043 -#include <unistd.h>
11044  
11045  #include <stdio.h>
11046  #include <errno.h>
11047 @@ -23,19 +22,19 @@
11048  static int http_chunk_append_len(server *srv, connection *con, size_t len) {
11049         size_t i, olen = len, j;
11050         buffer *b;
11051 -       
11052 +
11053         b = srv->tmp_chunk_len;
11054 -       
11055 +
11056         if (len == 0) {
11057                 buffer_copy_string(b, "0");
11058         } else {
11059                 for (i = 0; i < 8 && len; i++) {
11060                         len >>= 4;
11061                 }
11062 -               
11063 +
11064                 /* i is the number of hex digits we have */
11065                 buffer_prepare_copy(b, i + 1);
11066 -               
11067 +
11068                 for (j = i-1, len = olen; j+1 > 0; j--) {
11069                         b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
11070                         len >>= 4;
11071 @@ -43,61 +42,61 @@
11072                 b->used = i;
11073                 b->ptr[b->used++] = '\0';
11074         }
11075 -               
11076 +
11077         buffer_append_string(b, "\r\n");
11078         chunkqueue_append_buffer(con->write_queue, b);
11079 -       
11080 +
11081         return 0;
11082  }
11083  
11084  
11085  int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
11086         chunkqueue *cq;
11087 -       
11088 +
11089         if (!con) return -1;
11090 -       
11091 +
11092         cq = con->write_queue;
11093 -       
11094 +
11095         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11096                 http_chunk_append_len(srv, con, len);
11097         }
11098 -       
11099 +
11100         chunkqueue_append_file(cq, fn, offset, len);
11101 -       
11102 +
11103         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
11104                 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11105         }
11106 -       
11107 +
11108         return 0;
11109  }
11110  
11111  int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
11112         chunkqueue *cq;
11113 -       
11114 +
11115         if (!con) return -1;
11116 -       
11117 +
11118         cq = con->write_queue;
11119 -       
11120 +
11121         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11122                 http_chunk_append_len(srv, con, mem->used - 1);
11123         }
11124 -       
11125 +
11126         chunkqueue_append_buffer(cq, mem);
11127 -       
11128 +
11129         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
11130                 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11131         }
11132 -       
11133 +
11134         return 0;
11135  }
11136  
11137  int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
11138         chunkqueue *cq;
11139 -       
11140 +
11141         if (!con) return -1;
11142 -       
11143 +
11144         cq = con->write_queue;
11145 -       
11146 +
11147         if (len == 0) {
11148                 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11149                         http_chunk_append_len(srv, con, 0);
11150 @@ -107,17 +106,17 @@
11151                 }
11152                 return 0;
11153         }
11154 -       
11155 +
11156         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11157                 http_chunk_append_len(srv, con, len - 1);
11158         }
11159 -       
11160 +
11161         chunkqueue_append_mem(cq, mem, len);
11162 -       
11163 +
11164         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11165                 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11166         }
11167 -       
11168 +
11169         return 0;
11170  }
11171  
11172 @@ -125,9 +124,9 @@
11173  off_t http_chunkqueue_length(server *srv, connection *con) {
11174         if (!con) {
11175                 log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
11176 -               
11177 +
11178                 return 0;
11179         }
11180 -       
11181 +
11182         return chunkqueue_length(con->write_queue);
11183  }
11184 --- ../lighttpd-1.4.11/src/http_resp.c  1970-01-01 03:00:00.000000000 +0300
11185 +++ lighttpd-1.4.12/src/http_resp.c     2006-07-15 22:43:21.000000000 +0300
11186 @@ -0,0 +1,274 @@
11187 +#include <string.h>
11188 +#include <stdlib.h>
11189 +#include <stdio.h>
11190 +#include <assert.h>
11191 +
11192 +#include "http_resp.h"
11193 +#include "http_resp_parser.h"
11194 +
11195 +/* declare prototypes for the parser */
11196 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t));
11197 +void http_resp_parserFree(void *p,  void (*freeProc)(void*));
11198 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt);
11199 +void http_resp_parser(void *, int, buffer *, http_resp_ctx_t *);
11200 +
11201 +typedef struct {
11202 +       chunkqueue *cq;
11203 +
11204 +       chunk *c; /* current chunk in the chunkqueue */
11205 +       size_t offset; /* current offset in current chunk */
11206 +
11207 +       chunk *lookup_c;
11208 +       size_t lookup_offset;
11209 +
11210 +       int is_key;
11211 +       int is_statusline;
11212 +} http_resp_tokenizer_t;
11213 +
11214 +http_resp *http_response_init(void) {
11215 +       http_resp *resp = calloc(1, sizeof(*resp));
11216 +
11217 +       resp->reason = buffer_init();
11218 +       resp->headers = array_init();
11219 +
11220 +       return resp;
11221 +}
11222 +
11223 +void http_response_reset(http_resp *resp) {
11224 +       if (!resp) return;
11225 +
11226 +       buffer_reset(resp->reason);
11227 +       array_reset(resp->headers);
11228 +
11229 +}
11230 +
11231 +void http_response_free(http_resp *resp) {
11232 +       if (!resp) return;
11233 +
11234 +       buffer_free(resp->reason);
11235 +       array_free(resp->headers);
11236 +
11237 +       free(resp);
11238 +}
11239 +
11240 +static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11241 +       if (t->offset == t->c->mem->used - 1) {
11242 +               /* end of chunk, open next chunk */
11243 +
11244 +               if (!t->c->next) return -1;
11245 +
11246 +               t->c = t->c->next;
11247 +               t->offset = 0;
11248 +       }
11249 +
11250 +       *c = t->c->mem->ptr[t->offset++];
11251 +
11252 +       t->lookup_offset = t->offset;
11253 +       t->lookup_c = t->c;
11254 +
11255 +#if 0
11256 +       fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
11257 +#endif
11258 +
11259 +       return 0;
11260 +}
11261 +
11262 +static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11263 +       if (t->lookup_offset == t->lookup_c->mem->used - 1) {
11264 +               /* end of chunk, open next chunk */
11265 +
11266 +               if (!t->lookup_c->next) return -1;
11267 +
11268 +               t->lookup_c = t->lookup_c->next;
11269 +               t->lookup_offset = 0;
11270 +       }
11271 +
11272 +       *c = t->lookup_c->mem->ptr[t->lookup_offset++];
11273 +#if 0
11274 +       fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
11275 +#endif
11276 +
11277 +       return 0;
11278 +}
11279 +
11280 +
11281 +static int http_resp_tokenizer(
11282 +       http_resp_tokenizer_t *t,
11283 +       int *token_id,
11284 +       buffer *token
11285 +) {
11286 +       unsigned char c;
11287 +       int tid = 0;
11288 +
11289 +       /* push the token to the parser */
11290 +
11291 +       while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
11292 +               switch (c) {
11293 +               case ':':
11294 +                       tid = TK_COLON;
11295 +
11296 +                       t->is_key = 0;
11297 +
11298 +                       break;
11299 +               case ' ':
11300 +               case '\t':
11301 +                       /* ignore WS */
11302 +
11303 +                       break;
11304 +               case '\r':
11305 +                       if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11306 +
11307 +                       if (c == '\n') {
11308 +                               tid = TK_CRLF;
11309 +
11310 +                               t->c = t->lookup_c;
11311 +                               t->offset = t->lookup_offset;
11312 +
11313 +                               t->is_statusline = 0;
11314 +                               t->is_key = 1;
11315 +                       } else {
11316 +                               fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__);
11317 +                               return -1;
11318 +                       }
11319 +                       break;
11320 +               case '\n':
11321 +                       tid = TK_CRLF;
11322 +
11323 +                       t->is_statusline = 0;
11324 +                       t->is_key = 1;
11325 +
11326 +                       break;
11327 +               default:
11328 +                       while (c >= 32 && c != 127 && c != 255) {
11329 +                               if (t->is_statusline) {
11330 +                                       if (c == ':') { t->is_statusline = 0; break; } /* this is not a status line by a real header */
11331 +                                       if (c == 32) break; /* the space is a splitter in the statusline */
11332 +                               } else {
11333 +                                       if (t->is_key) {
11334 +                                               if (c == ':') break; /* the : is the splitter between key and value */
11335 +                                       }
11336 +                               }
11337 +                               if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11338 +                       }
11339 +
11340 +                       if (t->c == t->lookup_c &&
11341 +                               t->offset == t->lookup_offset + 1) {
11342 +
11343 +                               fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__);
11344 +                               return -1;
11345 +                       }
11346 +
11347 +                       tid = TK_STRING;
11348 +
11349 +                       /* the lookup points to the first invalid char */
11350 +                       t->lookup_offset--;
11351 +
11352 +                       /* no overlapping string */
11353 +                       if (t->c == t->lookup_c) {
11354 +                               buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
11355 +                       } else {
11356 +                               /* first chunk */
11357 +                               buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
11358 +
11359 +                               /* chunks in the middle */
11360 +                               for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
11361 +                                       buffer_append_string_buffer(token, t->c->mem);
11362 +                                       t->offset = t->c->mem->used - 1;
11363 +                               }
11364 +
11365 +                               /* last chunk */
11366 +                               buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
11367 +                       }
11368 +
11369 +                       t->offset = t->lookup_offset;
11370 +
11371 +                       break;
11372 +               }
11373 +       }
11374 +
11375 +       if (tid) {
11376 +               *token_id = tid;
11377 +
11378 +               return 1;
11379 +       }
11380 +
11381 +       return -1;
11382 +}
11383 +
11384 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
11385 +       http_resp_tokenizer_t t;
11386 +       void *pParser = NULL;
11387 +       int token_id = 0;
11388 +       buffer *token = NULL;
11389 +       http_resp_ctx_t context;
11390 +       parse_status_t ret = PARSE_UNSET;
11391 +       int last_token_id = 0;
11392 +
11393 +       t.cq = cq;
11394 +       t.c = cq->first;
11395 +       t.offset = t.c->offset;
11396 +       t.is_key = 0;
11397 +       t.is_statusline = 1;
11398 +
11399 +       context.ok = 1;
11400 +       context.errmsg = buffer_init();
11401 +       context.resp = resp;
11402 +
11403 +       pParser = http_resp_parserAlloc( malloc );
11404 +       token = buffer_init();
11405 +#if 0
11406 +       http_resp_parserTrace(stderr, "http-response: "); 
11407 +#endif
11408 +
11409 +       while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) {
11410 +               http_resp_parser(pParser, token_id, token, &context);
11411 +
11412 +               token = buffer_init();
11413 +
11414 +               /* CRLF CRLF ... the header end sequence */
11415 +               if (last_token_id == TK_CRLF &&
11416 +                   token_id == TK_CRLF) break;
11417 +
11418 +               last_token_id = token_id;
11419 +       }
11420 +
11421 +       /* oops, the parser failed */
11422 +       if (context.ok == 0) {
11423 +               ret = PARSE_ERROR;
11424 +
11425 +               fprintf(stderr, "%s.%d: parsing failed at: ...%20s\r\n",
11426 +                       __FILE__, __LINE__, t.c->mem->ptr + t.offset);
11427 +       }
11428 +
11429 +       http_resp_parser(pParser, 0, token, &context);
11430 +       http_resp_parserFree(pParser, free );
11431 +
11432 +       if (context.ok == 0) {
11433 +               /* we are missing the some tokens */
11434 +
11435 +               if (!buffer_is_empty(context.errmsg)) {
11436 +                       fprintf(stderr, "%s.%d: hmm, %20s\r\n",
11437 +                               __FILE__, __LINE__, context.errmsg->ptr);
11438 +               }
11439 +
11440 +               if (ret == PARSE_UNSET) {
11441 +                       ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR;
11442 +               }
11443 +       } else {
11444 +               chunk *c;
11445 +
11446 +               for (c = cq->first; c != t.c; c = c->next) {
11447 +                       c->offset = c->mem->used - 1;
11448 +               }
11449 +
11450 +               c->offset = t.offset;
11451 +
11452 +               ret = PARSE_SUCCESS;
11453 +       }
11454 +
11455 +       buffer_free(token);
11456 +       buffer_free(context.errmsg);
11457 +
11458 +       return ret;
11459 +}
11460 +
11461 --- ../lighttpd-1.4.11/src/http_resp.h  1970-01-01 03:00:00.000000000 +0300
11462 +++ lighttpd-1.4.12/src/http_resp.h     2006-07-11 22:07:53.000000000 +0300
11463 @@ -0,0 +1,34 @@
11464 +#ifndef _HTTP_RESP_H_
11465 +#define _HTTP_RESP_H_
11466 +
11467 +#include "array.h"
11468 +#include "chunk.h"
11469 +
11470 +typedef enum {
11471 +    PARSE_UNSET,
11472 +    PARSE_SUCCESS,
11473 +    PARSE_ERROR,
11474 +    PARSE_NEED_MORE
11475 +} parse_status_t;
11476 +
11477 +typedef struct {
11478 +    int protocol;   /* http/1.0, http/1.1 */
11479 +    int status;     /* e.g. 200 */
11480 +    buffer *reason; /* e.g. Ok */
11481 +    array *headers;
11482 +} http_resp;
11483 +
11484 +typedef struct {
11485 +       int     ok;
11486 +    buffer *errmsg;
11487 +
11488 +    http_resp *resp;
11489 +} http_resp_ctx_t;
11490 +
11491 +http_resp *http_response_init(void);
11492 +void http_response_free(http_resp *resp);
11493 +void http_response_reset(http_resp *resp);
11494 +
11495 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
11496 +
11497 +#endif
11498 --- ../lighttpd-1.4.11/src/http_resp_parser.c   1970-01-01 03:00:00.000000000 +0300
11499 +++ lighttpd-1.4.12/src/http_resp_parser.c      2006-07-15 22:44:07.000000000 +0300
11500 @@ -0,0 +1,895 @@
11501 +/* Driver template for the LEMON parser generator.
11502 +** The author disclaims copyright to this source code.
11503 +*/
11504 +/* First off, code is include which follows the "include" declaration
11505 +** in the input file. */
11506 +#include <stdio.h>
11507 +#line 6 "./http_resp_parser.y"
11508 +
11509 +#include <assert.h>
11510 +#include <string.h>
11511 +#include "http_resp.h"
11512 +#include "keyvalue.h"
11513 +#include "array.h"
11514 +
11515 +#line 16 "http_resp_parser.c"
11516 +/* Next is all token values, in a form suitable for use by makeheaders.
11517 +** This section will be null unless lemon is run with the -m switch.
11518 +*/
11519 +/*
11520 +** These constants (all generated automatically by the parser generator)
11521 +** specify the various kinds of tokens (terminals) that the parser
11522 +** understands.
11523 +**
11524 +** Each symbol here is a terminal symbol in the grammar.
11525 +*/
11526 +/* Make sure the INTERFACE macro is defined.
11527 +*/
11528 +#ifndef INTERFACE
11529 +# define INTERFACE 1
11530 +#endif
11531 +/* The next thing included is series of defines which control
11532 +** various aspects of the generated parser.
11533 +**    YYCODETYPE         is the data type used for storing terminal
11534 +**                       and nonterminal numbers.  "unsigned char" is
11535 +**                       used if there are fewer than 250 terminals
11536 +**                       and nonterminals.  "int" is used otherwise.
11537 +**    YYNOCODE           is a number of type YYCODETYPE which corresponds
11538 +**                       to no legal terminal or nonterminal number.  This
11539 +**                       number is used to fill in empty slots of the hash
11540 +**                       table.
11541 +**    YYFALLBACK         If defined, this indicates that one or more tokens
11542 +**                       have fall-back values which should be used if the
11543 +**                       original value of the token will not parse.
11544 +**    YYACTIONTYPE       is the data type used for storing terminal
11545 +**                       and nonterminal numbers.  "unsigned char" is
11546 +**                       used if there are fewer than 250 rules and
11547 +**                       states combined.  "int" is used otherwise.
11548 +**    http_resp_parserTOKENTYPE     is the data type used for minor tokens given
11549 +**                       directly to the parser from the tokenizer.
11550 +**    YYMINORTYPE        is the data type used for all minor tokens.
11551 +**                       This is typically a union of many types, one of
11552 +**                       which is http_resp_parserTOKENTYPE.  The entry in the union
11553 +**                       for base tokens is called "yy0".
11554 +**    YYSTACKDEPTH       is the maximum depth of the parser's stack.
11555 +**    http_resp_parserARG_SDECL     A static variable declaration for the %extra_argument
11556 +**    http_resp_parserARG_PDECL     A parameter declaration for the %extra_argument
11557 +**    http_resp_parserARG_STORE     Code to store %extra_argument into yypParser
11558 +**    http_resp_parserARG_FETCH     Code to extract %extra_argument from yypParser
11559 +**    YYNSTATE           the combined number of states.
11560 +**    YYNRULE            the number of rules in the grammar
11561 +**    YYERRORSYMBOL      is the code number of the error symbol.  If not
11562 +**                       defined, then do no error processing.
11563 +*/
11564 +/* \ 1 */
11565 +#define YYCODETYPE unsigned char
11566 +#define YYNOCODE 12
11567 +#define YYACTIONTYPE unsigned char
11568 +#define http_resp_parserTOKENTYPE buffer *
11569 +typedef union {
11570 +  http_resp_parserTOKENTYPE yy0;
11571 +  http_resp * yy2;
11572 +  data_string * yy9;
11573 +  array * yy12;
11574 +  int yy20;
11575 +  int yy23;
11576 +} YYMINORTYPE;
11577 +#define YYSTACKDEPTH 100
11578 +#define http_resp_parserARG_SDECL http_resp_ctx_t *ctx;
11579 +#define http_resp_parserARG_PDECL ,http_resp_ctx_t *ctx
11580 +#define http_resp_parserARG_FETCH http_resp_ctx_t *ctx = yypParser->ctx
11581 +#define http_resp_parserARG_STORE yypParser->ctx = ctx
11582 +#define YYNSTATE 19
11583 +#define YYNRULE 9
11584 +#define YYERRORSYMBOL 4
11585 +#define YYERRSYMDT yy23
11586 +#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
11587 +#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
11588 +#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)
11589 +
11590 +/* Next are that tables used to determine what action to take based on the
11591 +** current state and lookahead token.  These tables are used to implement
11592 +** functions that take a state number and lookahead value and return an
11593 +** action integer.
11594 +**
11595 +** Suppose the action integer is N.  Then the action is determined as
11596 +** follows
11597 +**
11598 +**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead
11599 +**                                      token onto the stack and goto state N.
11600 +**
11601 +**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE.
11602 +**
11603 +**   N == YYNSTATE+YYNRULE              A syntax error has occurred.
11604 +**
11605 +**   N == YYNSTATE+YYNRULE+1            The parser accepts its input.
11606 +**
11607 +**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused
11608 +**                                      slots in the yy_action[] table.
11609 +**
11610 +** The action table is constructed as a single large table named yy_action[].
11611 +** Given state S and lookahead X, the action is computed as
11612 +**
11613 +**      yy_action[ yy_shift_ofst[S] + X ]
11614 +**
11615 +** If the index value yy_shift_ofst[S]+X is out of range or if the value
11616 +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
11617 +** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
11618 +** and that yy_default[S] should be used instead.
11619 +**
11620 +** The formula above is for computing the action when the lookahead is
11621 +** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
11622 +** a reduce action) then the yy_reduce_ofst[] array is used in place of
11623 +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
11624 +** YY_SHIFT_USE_DFLT.
11625 +**
11626 +** The following are the tables generated in this section:
11627 +**
11628 +**  yy_action[]        A single table containing all actions.
11629 +**  yy_lookahead[]     A table containing the lookahead for each entry in
11630 +**                     yy_action.  Used to detect hash collisions.
11631 +**  yy_shift_ofst[]    For each state, the offset into yy_action for
11632 +**                     shifting terminals.
11633 +**  yy_reduce_ofst[]   For each state, the offset into yy_action for
11634 +**                     shifting non-terminals after a reduce.
11635 +**  yy_default[]       Default action for each state.
11636 +*/
11637 +static YYACTIONTYPE yy_action[] = {
11638 + /*     0 */     8,   29,   18,    1,   14,    2,    4,   11,   15,   12,
11639 + /*    10 */    14,   13,    4,   21,    5,   19,    3,    5,    6,    7,
11640 + /*    20 */     9,   17,   16,    4,   20,   22,   22,   10,
11641 +};
11642 +static YYCODETYPE yy_lookahead[] = {
11643 + /*     0 */     5,    6,    2,    8,    9,    1,    2,    1,    2,    8,
11644 + /*    10 */     9,    1,    2,    2,    3,    0,    9,    3,    2,    1,
11645 + /*    20 */     7,    2,    2,    2,    0,    2,   11,   10,
11646 +};
11647 +#define YY_SHIFT_USE_DFLT (-1)
11648 +static signed char yy_shift_ofst[] = {
11649 + /*     0 */     0,    4,   15,   -1,   14,   16,   18,   -1,   19,   20,
11650 + /*    10 */     6,   21,   10,   24,   -1,   -1,   -1,   23,   11,
11651 +};
11652 +#define YY_REDUCE_USE_DFLT (-6)
11653 +static signed char yy_reduce_ofst[] = {
11654 + /*     0 */    -5,    7,   -6,   -6,   -6,   -6,   -6,   -6,   13,   17,
11655 + /*    10 */    -6,    1,    7,   -6,   -6,   -6,   -6,   -6,   -6,
11656 +};
11657 +static YYACTIONTYPE yy_default[] = {
11658 + /*     0 */    28,   28,   28,   25,   28,   28,   28,   27,   28,   28,
11659 + /*    10 */    28,   28,   28,   28,   26,   24,   23,   28,   28,
11660 +};
11661 +#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
11662 +
11663 +/* The next table maps tokens into fallback tokens.  If a construct
11664 +** like the following:
11665 +**
11666 +**      %fallback ID X Y Z.
11667 +**
11668 +** appears in the grammer, then ID becomes a fallback token for X, Y,
11669 +** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
11670 +** but it does not parse, the type of the token is changed to ID and
11671 +** the parse is retried before an error is thrown.
11672 +*/
11673 +#ifdef YYFALLBACK
11674 +static const YYCODETYPE yyFallback[] = {
11675 +};
11676 +#endif /* YYFALLBACK */
11677 +
11678 +/* The following structure represents a single element of the
11679 +** parser's stack.  Information stored includes:
11680 +**
11681 +**   +  The state number for the parser at this level of the stack.
11682 +**
11683 +**   +  The value of the token stored at this level of the stack.
11684 +**      (In other words, the "major" token.)
11685 +**
11686 +**   +  The semantic value stored at this level of the stack.  This is
11687 +**      the information used by the action routines in the grammar.
11688 +**      It is sometimes called the "minor" token.
11689 +*/
11690 +struct yyStackEntry {
11691 +  int stateno;       /* The state-number */
11692 +  int major;         /* The major token value.  This is the code
11693 +                     ** number for the token at this stack level */
11694 +  YYMINORTYPE minor; /* The user-supplied minor token value.  This
11695 +                     ** is the value of the token  */
11696 +};
11697 +typedef struct yyStackEntry yyStackEntry;
11698 +
11699 +/* The state of the parser is completely contained in an instance of
11700 +** the following structure */
11701 +struct yyParser {
11702 +  int yyidx;                    /* Index of top element in stack */
11703 +  int yyerrcnt;                 /* Shifts left before out of the error */
11704 +  http_resp_parserARG_SDECL                /* A place to hold %extra_argument */
11705 +  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
11706 +};
11707 +typedef struct yyParser yyParser;
11708 +
11709 +#ifndef NDEBUG
11710 +#include <stdio.h>
11711 +static FILE *yyTraceFILE = 0;
11712 +static char *yyTracePrompt = 0;
11713 +#endif /* NDEBUG */
11714 +
11715 +#ifndef NDEBUG
11716 +/*
11717 +** Turn parser tracing on by giving a stream to which to write the trace
11718 +** and a prompt to preface each trace message.  Tracing is turned off
11719 +** by making either argument NULL
11720 +**
11721 +** Inputs:
11722 +** <ul>
11723 +** <li> A FILE* to which trace output should be written.
11724 +**      If NULL, then tracing is turned off.
11725 +** <li> A prefix string written at the beginning of every
11726 +**      line of trace output.  If NULL, then tracing is
11727 +**      turned off.
11728 +** </ul>
11729 +**
11730 +** Outputs:
11731 +** None.
11732 +*/
11733 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt){
11734 +  yyTraceFILE = TraceFILE;
11735 +  yyTracePrompt = zTracePrompt;
11736 +  if( yyTraceFILE==0 ) yyTracePrompt = 0;
11737 +  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
11738 +}
11739 +#endif /* NDEBUG */
11740 +
11741 +#ifndef NDEBUG
11742 +/* For tracing shifts, the names of all terminals and nonterminals
11743 +** are required.  The following table supplies these names */
11744 +static const char *yyTokenName[] = {
11745 +  "$",             "CRLF",          "STRING",        "COLON",       
11746 +  "error",         "protocol",      "response_hdr",  "number",      
11747 +  "headers",       "header",        "reason",      
11748 +};
11749 +#endif /* NDEBUG */
11750 +
11751 +#ifndef NDEBUG
11752 +/* For tracing reduce actions, the names of all rules are required.
11753 +*/
11754 +static const char *yyRuleName[] = {
11755 + /*   0 */ "response_hdr ::= headers CRLF",
11756 + /*   1 */ "response_hdr ::= protocol number reason CRLF headers CRLF",
11757 + /*   2 */ "protocol ::= STRING",
11758 + /*   3 */ "number ::= STRING",
11759 + /*   4 */ "reason ::= STRING",
11760 + /*   5 */ "reason ::= reason STRING",
11761 + /*   6 */ "headers ::= headers header",
11762 + /*   7 */ "headers ::= header",
11763 + /*   8 */ "header ::= STRING COLON STRING CRLF",
11764 +};
11765 +#endif /* NDEBUG */
11766 +
11767 +/*
11768 +** This function returns the symbolic name associated with a token
11769 +** value.
11770 +*/
11771 +const char *http_resp_parserTokenName(int tokenType){
11772 +#ifndef NDEBUG
11773 +  if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
11774 +    return yyTokenName[tokenType];
11775 +  }else{
11776 +    return "Unknown";
11777 +  }
11778 +#else
11779 +  return "";
11780 +#endif
11781 +}
11782 +
11783 +/*
11784 +** This function allocates a new parser.
11785 +** The only argument is a pointer to a function which works like
11786 +** malloc.
11787 +**
11788 +** Inputs:
11789 +** A pointer to the function used to allocate memory.
11790 +**
11791 +** Outputs:
11792 +** A pointer to a parser.  This pointer is used in subsequent calls
11793 +** to http_resp_parser and http_resp_parserFree.
11794 +*/
11795 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t)){
11796 +  yyParser *pParser;
11797 +  pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
11798 +  if( pParser ){
11799 +    pParser->yyidx = -1;
11800 +  }
11801 +  return pParser;
11802 +}
11803 +
11804 +/* The following function deletes the value associated with a
11805 +** symbol.  The symbol can be either a terminal or nonterminal.
11806 +** "yymajor" is the symbol code, and "yypminor" is a pointer to
11807 +** the value.
11808 +*/
11809 +static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
11810 +  switch( yymajor ){
11811 +    /* Here is inserted the actions which take place when a
11812 +    ** terminal or non-terminal is destroyed.  This can happen
11813 +    ** when the symbol is popped from the stack during a
11814 +    ** reduce or during error processing or when a parser is
11815 +    ** being destroyed before it is finished parsing.
11816 +    **
11817 +    ** Note: during a reduce, the only symbols destroyed are those
11818 +    ** which appear on the RHS of the rule, but which are not used
11819 +    ** inside the C code.
11820 +    */
11821 +    case 1:
11822 +    case 2:
11823 +    case 3:
11824 +#line 23 "./http_resp_parser.y"
11825 +{ buffer_free((yypminor->yy0)); }
11826 +#line 326 "http_resp_parser.c"
11827 +      break;
11828 +    default:  break;   /* If no destructor action specified: do nothing */
11829 +  }
11830 +}
11831 +
11832 +/*
11833 +** Pop the parser's stack once.
11834 +**
11835 +** If there is a destructor routine associated with the token which
11836 +** is popped from the stack, then call it.
11837 +**
11838 +** Return the major token number for the symbol popped.
11839 +*/
11840 +static int yy_pop_parser_stack(yyParser *pParser){
11841 +  YYCODETYPE yymajor;
11842 +  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
11843 +
11844 +  if( pParser->yyidx<0 ) return 0;
11845 +#ifndef NDEBUG
11846 +  if( yyTraceFILE && pParser->yyidx>=0 ){
11847 +    fprintf(yyTraceFILE,"%sPopping %s\n",
11848 +      yyTracePrompt,
11849 +      yyTokenName[yytos->major]);
11850 +  }
11851 +#endif
11852 +  yymajor = yytos->major;
11853 +  yy_destructor( yymajor, &yytos->minor);
11854 +  pParser->yyidx--;
11855 +  return yymajor;
11856 +}
11857 +
11858 +/*
11859 +** Deallocate and destroy a parser.  Destructors are all called for
11860 +** all stack elements before shutting the parser down.
11861 +**
11862 +** Inputs:
11863 +** <ul>
11864 +** <li>  A pointer to the parser.  This should be a pointer
11865 +**       obtained from http_resp_parserAlloc.
11866 +** <li>  A pointer to a function used to reclaim memory obtained
11867 +**       from malloc.
11868 +** </ul>
11869 +*/
11870 +void http_resp_parserFree(
11871 +  void *p,                    /* The parser to be deleted */
11872 +  void (*freeProc)(void*)     /* Function used to reclaim memory */
11873 +){
11874 +  yyParser *pParser = (yyParser*)p;
11875 +  if( pParser==0 ) return;
11876 +  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
11877 +  (*freeProc)((void*)pParser);
11878 +}
11879 +
11880 +/*
11881 +** Find the appropriate action for a parser given the terminal
11882 +** look-ahead token iLookAhead.
11883 +**
11884 +** If the look-ahead token is YYNOCODE, then check to see if the action is
11885 +** independent of the look-ahead.  If it is, return the action, otherwise
11886 +** return YY_NO_ACTION.
11887 +*/
11888 +static int yy_find_shift_action(
11889 +  yyParser *pParser,        /* The parser */
11890 +  int iLookAhead            /* The look-ahead token */
11891 +){
11892 +  int i;
11893 +  int stateno = pParser->yystack[pParser->yyidx].stateno;
11894 +
11895 +  /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
11896 +  i = yy_shift_ofst[stateno];
11897 +  if( i==YY_SHIFT_USE_DFLT ){
11898 +    return yy_default[stateno];
11899 +  }
11900 +  if( iLookAhead==YYNOCODE ){
11901 +    return YY_NO_ACTION;
11902 +  }
11903 +  i += iLookAhead;
11904 +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
11905 +#ifdef YYFALLBACK
11906 +    int iFallback;            /* Fallback token */
11907 +    if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
11908 +           && (iFallback = yyFallback[iLookAhead])!=0 ){
11909 +#ifndef NDEBUG
11910 +      if( yyTraceFILE ){
11911 +        fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
11912 +           yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
11913 +      }
11914 +#endif
11915 +      return yy_find_shift_action(pParser, iFallback);
11916 +    }
11917 +#endif
11918 +    return yy_default[stateno];
11919 +  }else{
11920 +    return yy_action[i];
11921 +  }
11922 +}
11923 +
11924 +/*
11925 +** Find the appropriate action for a parser given the non-terminal
11926 +** look-ahead token iLookAhead.
11927 +**
11928 +** If the look-ahead token is YYNOCODE, then check to see if the action is
11929 +** independent of the look-ahead.  If it is, return the action, otherwise
11930 +** return YY_NO_ACTION.
11931 +*/
11932 +static int yy_find_reduce_action(
11933 +  yyParser *pParser,        /* The parser */
11934 +  int iLookAhead            /* The look-ahead token */
11935 +){
11936 +  int i;
11937 +  int stateno = pParser->yystack[pParser->yyidx].stateno;
11938 +
11939 +  i = yy_reduce_ofst[stateno];
11940 +  if( i==YY_REDUCE_USE_DFLT ){
11941 +    return yy_default[stateno];
11942 +  }
11943 +  if( iLookAhead==YYNOCODE ){
11944 +    return YY_NO_ACTION;
11945 +  }
11946 +  i += iLookAhead;
11947 +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
11948 +    return yy_default[stateno];
11949 +  }else{
11950 +    return yy_action[i];
11951 +  }
11952 +}
11953 +
11954 +/*
11955 +** Perform a shift action.
11956 +*/
11957 +static void yy_shift(
11958 +  yyParser *yypParser,          /* The parser to be shifted */
11959 +  int yyNewState,               /* The new state to shift in */
11960 +  int yyMajor,                  /* The major token to shift in */
11961 +  YYMINORTYPE *yypMinor         /* Pointer ot the minor token to shift in */
11962 +){
11963 +  yyStackEntry *yytos;
11964 +  yypParser->yyidx++;
11965 +  if( yypParser->yyidx>=YYSTACKDEPTH ){
11966 +     http_resp_parserARG_FETCH;
11967 +     yypParser->yyidx--;
11968 +#ifndef NDEBUG
11969 +     if( yyTraceFILE ){
11970 +       fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
11971 +     }
11972 +#endif
11973 +     while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
11974 +     /* Here code is inserted which will execute if the parser
11975 +     ** stack every overflows */
11976 +     http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument var */
11977 +     return;
11978 +  }
11979 +  yytos = &yypParser->yystack[yypParser->yyidx];
11980 +  yytos->stateno = yyNewState;
11981 +  yytos->major = yyMajor;
11982 +  yytos->minor = *yypMinor;
11983 +#ifndef NDEBUG
11984 +  if( yyTraceFILE && yypParser->yyidx>0 ){
11985 +    int i;
11986 +    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
11987 +    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
11988 +    for(i=1; i<=yypParser->yyidx; i++)
11989 +      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
11990 +    fprintf(yyTraceFILE,"\n");
11991 +  }
11992 +#endif
11993 +}
11994 +
11995 +/* The following table contains information about every rule that
11996 +** is used during the reduce.
11997 +*/
11998 +static struct {
11999 +  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
12000 +  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
12001 +} yyRuleInfo[] = {
12002 +  { 6, 2 },
12003 +  { 6, 6 },
12004 +  { 5, 1 },
12005 +  { 7, 1 },
12006 +  { 10, 1 },
12007 +  { 10, 2 },
12008 +  { 8, 2 },
12009 +  { 8, 1 },
12010 +  { 9, 4 },
12011 +};
12012 +
12013 +static void yy_accept(yyParser*);  /* Forward Declaration */
12014 +
12015 +/*
12016 +** Perform a reduce action and the shift that must immediately
12017 +** follow the reduce.
12018 +*/
12019 +static void yy_reduce(
12020 +  yyParser *yypParser,         /* The parser */
12021 +  int yyruleno                 /* Number of the rule by which to reduce */
12022 +){
12023 +  int yygoto;                     /* The next state */
12024 +  int yyact;                      /* The next action */
12025 +  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */
12026 +  yyStackEntry *yymsp;            /* The top of the parser's stack */
12027 +  int yysize;                     /* Amount to pop the stack */
12028 +  http_resp_parserARG_FETCH;
12029 +  yymsp = &yypParser->yystack[yypParser->yyidx];
12030 +#ifndef NDEBUG
12031 +  if( yyTraceFILE && yyruleno>=0
12032 +        && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
12033 +    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
12034 +      yyRuleName[yyruleno]);
12035 +  }
12036 +#endif /* NDEBUG */
12037 +
12038 +  switch( yyruleno ){
12039 +  /* Beginning here are the reduction cases.  A typical example
12040 +  ** follows:
12041 +  **   case 0:
12042 +  **  #line <lineno> <grammarfile>
12043 +  **     { ... }           // User supplied code
12044 +  **  #line <lineno> <thisfile>
12045 +  **     break;
12046 +  */
12047 +      case 0:
12048 +#line 26 "./http_resp_parser.y"
12049 +{
12050 +    http_resp *resp = ctx->resp;
12051 +    data_string *ds;
12052
12053 +    resp->protocol = HTTP_VERSION_UNSET;
12054 +
12055 +    buffer_copy_string(resp->reason, ""); /* no reason */
12056 +    array_free(resp->headers);
12057 +    resp->headers = yymsp[-1].minor.yy12;
12058 +
12059 +    if (NULL == (ds = (data_string *)array_get_element(yymsp[-1].minor.yy12, "Status"))) { 
12060 +        resp->status = 0;
12061 +    } else {
12062 +        char *err;
12063 +        resp->status = strtol(ds->value->ptr, &err, 10);
12064 +   
12065 +        if (*err != '\0' && *err != ' ') {
12066 +            buffer_copy_string(ctx->errmsg, "expected a number: ");
12067 +            buffer_append_string_buffer(ctx->errmsg, ds->value);
12068 +            buffer_append_string(ctx->errmsg, err);
12069 +        
12070 +            ctx->ok = 0;
12071 +        }
12072 +    }
12073 +
12074 +    yymsp[-1].minor.yy12 = NULL;
12075 +}
12076 +#line 576 "http_resp_parser.c"
12077 +  yy_destructor(1,&yymsp[0].minor);
12078 +        break;
12079 +      case 1:
12080 +#line 54 "./http_resp_parser.y"
12081 +{
12082 +    http_resp *resp = ctx->resp;
12083 +    
12084 +    resp->status = yymsp[-4].minor.yy20;
12085 +    resp->protocol = yymsp[-5].minor.yy20;
12086 +    buffer_copy_string_buffer(resp->reason, yymsp[-3].minor.yy0);
12087 +    
12088 +    array_free(resp->headers);
12089 +    
12090 +    resp->headers = yymsp[-1].minor.yy12;
12091 +    
12092 +    yymsp[-1].minor.yy12 = NULL;
12093 +}
12094 +#line 594 "http_resp_parser.c"
12095 +  yy_destructor(1,&yymsp[-2].minor);
12096 +  yy_destructor(1,&yymsp[0].minor);
12097 +        break;
12098 +      case 2:
12099 +#line 68 "./http_resp_parser.y"
12100 +{
12101 +    if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.0"))) {
12102 +        yygotominor.yy20 = HTTP_VERSION_1_0;
12103 +    } else if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.1"))) {
12104 +        yygotominor.yy20 = HTTP_VERSION_1_1;
12105 +    } else {
12106 +        buffer_copy_string(ctx->errmsg, "unknown protocol: ");
12107 +        buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12108 +        
12109 +        ctx->ok = 0;
12110 +    }
12111 +}
12112 +#line 612 "http_resp_parser.c"
12113 +        break;
12114 +      case 3:
12115 +#line 81 "./http_resp_parser.y"
12116 +{
12117 +    char *err;
12118 +    yygotominor.yy20 = strtol(yymsp[0].minor.yy0->ptr, &err, 10);
12119 +    
12120 +    if (*err != '\0') {
12121 +        buffer_copy_string(ctx->errmsg, "expected a number: ");
12122 +        buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12123 +        
12124 +        ctx->ok = 0;
12125 +    }
12126 +}
12127 +#line 627 "http_resp_parser.c"
12128 +        break;
12129 +      case 4:
12130 +#line 93 "./http_resp_parser.y"
12131 +{
12132 +    yygotominor.yy0 = yymsp[0].minor.yy0;
12133 +    yymsp[0].minor.yy0 = NULL;
12134 +}
12135 +#line 635 "http_resp_parser.c"
12136 +        break;
12137 +      case 5:
12138 +#line 98 "./http_resp_parser.y"
12139 +{
12140 +    yygotominor.yy0 = yymsp[-1].minor.yy0;
12141 +    
12142 +    buffer_append_string(yygotominor.yy0, " ");
12143 +    buffer_append_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12144 +    
12145 +    yymsp[-1].minor.yy0 = NULL;
12146 +}
12147 +#line 647 "http_resp_parser.c"
12148 +        break;
12149 +      case 6:
12150 +#line 107 "./http_resp_parser.y"
12151 +{
12152 +    yygotominor.yy12 = yymsp[-1].minor.yy12;
12153 +    
12154 +    array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12155 +    
12156 +    yymsp[-1].minor.yy12 = NULL;
12157 +}
12158 +#line 658 "http_resp_parser.c"
12159 +        break;
12160 +      case 7:
12161 +#line 115 "./http_resp_parser.y"
12162 +{
12163 +    yygotominor.yy12 = array_init();
12164 +
12165 +    array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12166 +}
12167 +#line 667 "http_resp_parser.c"
12168 +        break;
12169 +      case 8:
12170 +#line 120 "./http_resp_parser.y"
12171 +{
12172 +    yygotominor.yy9 = data_string_init();
12173 +    
12174 +    buffer_copy_string_buffer(yygotominor.yy9->key, yymsp[-3].minor.yy0);
12175 +    buffer_copy_string_buffer(yygotominor.yy9->value, yymsp[-1].minor.yy0);    
12176 +}
12177 +#line 677 "http_resp_parser.c"
12178 +  yy_destructor(3,&yymsp[-2].minor);
12179 +  yy_destructor(1,&yymsp[0].minor);
12180 +        break;
12181 +  };
12182 +  yygoto = yyRuleInfo[yyruleno].lhs;
12183 +  yysize = yyRuleInfo[yyruleno].nrhs;
12184 +  yypParser->yyidx -= yysize;
12185 +  yyact = yy_find_reduce_action(yypParser,yygoto);
12186 +  if( yyact < YYNSTATE ){
12187 +    yy_shift(yypParser,yyact,yygoto,&yygotominor);
12188 +  }else if( yyact == YYNSTATE + YYNRULE + 1 ){
12189 +    yy_accept(yypParser);
12190 +  }
12191 +}
12192 +
12193 +/*
12194 +** The following code executes when the parse fails
12195 +*/
12196 +static void yy_parse_failed(
12197 +  yyParser *yypParser           /* The parser */
12198 +){
12199 +  http_resp_parserARG_FETCH;
12200 +#ifndef NDEBUG
12201 +  if( yyTraceFILE ){
12202 +    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
12203 +  }
12204 +#endif
12205 +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12206 +  /* Here code is inserted which will be executed whenever the
12207 +  ** parser fails */
12208 +#line 14 "./http_resp_parser.y"
12209 +
12210 +  ctx->ok = 0;
12211 +
12212 +#line 712 "http_resp_parser.c"
12213 +  http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12214 +}
12215 +
12216 +/*
12217 +** The following code executes when a syntax error first occurs.
12218 +*/
12219 +static void yy_syntax_error(
12220 +  yyParser *yypParser,           /* The parser */
12221 +  int yymajor,                   /* The major type of the error token */
12222 +  YYMINORTYPE yyminor            /* The minor type of the error token */
12223 +){
12224 +  http_resp_parserARG_FETCH;
12225 +#define TOKEN (yyminor.yy0)
12226 +  http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12227 +}
12228 +
12229 +/*
12230 +** The following is executed when the parser accepts
12231 +*/
12232 +static void yy_accept(
12233 +  yyParser *yypParser           /* The parser */
12234 +){
12235 +  http_resp_parserARG_FETCH;
12236 +#ifndef NDEBUG
12237 +  if( yyTraceFILE ){
12238 +    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
12239 +  }
12240 +#endif
12241 +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12242 +  /* Here code is inserted which will be executed whenever the
12243 +  ** parser accepts */
12244 +  http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12245 +}
12246 +
12247 +/* The main parser program.
12248 +** The first argument is a pointer to a structure obtained from
12249 +** "http_resp_parserAlloc" which describes the current state of the parser.
12250 +** The second argument is the major token number.  The third is
12251 +** the minor token.  The fourth optional argument is whatever the
12252 +** user wants (and specified in the grammar) and is available for
12253 +** use by the action routines.
12254 +**
12255 +** Inputs:
12256 +** <ul>
12257 +** <li> A pointer to the parser (an opaque structure.)
12258 +** <li> The major token number.
12259 +** <li> The minor token number.
12260 +** <li> An option argument of a grammar-specified type.
12261 +** </ul>
12262 +**
12263 +** Outputs:
12264 +** None.
12265 +*/
12266 +void http_resp_parser(
12267 +  void *yyp,                   /* The parser */
12268 +  int yymajor,                 /* The major token code number */
12269 +  http_resp_parserTOKENTYPE yyminor       /* The value for the token */
12270 +  http_resp_parserARG_PDECL               /* Optional %extra_argument parameter */
12271 +){
12272 +  YYMINORTYPE yyminorunion;
12273 +  int yyact;            /* The parser action. */
12274 +  int yyendofinput;     /* True if we are at the end of input */
12275 +  int yyerrorhit = 0;   /* True if yymajor has invoked an error */
12276 +  yyParser *yypParser;  /* The parser */
12277 +
12278 +  /* (re)initialize the parser, if necessary */
12279 +  yypParser = (yyParser*)yyp;
12280 +  if( yypParser->yyidx<0 ){
12281 +    if( yymajor==0 ) return;
12282 +    yypParser->yyidx = 0;
12283 +    yypParser->yyerrcnt = -1;
12284 +    yypParser->yystack[0].stateno = 0;
12285 +    yypParser->yystack[0].major = 0;
12286 +  }
12287 +  yyminorunion.yy0 = yyminor;
12288 +  yyendofinput = (yymajor==0);
12289 +  http_resp_parserARG_STORE;
12290 +
12291 +#ifndef NDEBUG
12292 +  if( yyTraceFILE ){
12293 +    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
12294 +  }
12295 +#endif
12296 +
12297 +  do{
12298 +    yyact = yy_find_shift_action(yypParser,yymajor);
12299 +    if( yyact<YYNSTATE ){
12300 +      yy_shift(yypParser,yyact,yymajor,&yyminorunion);
12301 +      yypParser->yyerrcnt--;
12302 +      if( yyendofinput && yypParser->yyidx>=0 ){
12303 +        yymajor = 0;
12304 +      }else{
12305 +        yymajor = YYNOCODE;
12306 +      }
12307 +    }else if( yyact < YYNSTATE + YYNRULE ){
12308 +      yy_reduce(yypParser,yyact-YYNSTATE);
12309 +    }else if( yyact == YY_ERROR_ACTION ){
12310 +      int yymx;
12311 +#ifndef NDEBUG
12312 +      if( yyTraceFILE ){
12313 +        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
12314 +      }
12315 +#endif
12316 +#ifdef YYERRORSYMBOL
12317 +      /* A syntax error has occurred.
12318 +      ** The response to an error depends upon whether or not the
12319 +      ** grammar defines an error token "ERROR".
12320 +      **
12321 +      ** This is what we do if the grammar does define ERROR:
12322 +      **
12323 +      **  * Call the %syntax_error function.
12324 +      **
12325 +      **  * Begin popping the stack until we enter a state where
12326 +      **    it is legal to shift the error symbol, then shift
12327 +      **    the error symbol.
12328 +      **
12329 +      **  * Set the error count to three.
12330 +      **
12331 +      **  * Begin accepting and shifting new tokens.  No new error
12332 +      **    processing will occur until three tokens have been
12333 +      **    shifted successfully.
12334 +      **
12335 +      */
12336 +      if( yypParser->yyerrcnt<0 ){
12337 +        yy_syntax_error(yypParser,yymajor,yyminorunion);
12338 +      }
12339 +      yymx = yypParser->yystack[yypParser->yyidx].major;
12340 +      if( yymx==YYERRORSYMBOL || yyerrorhit ){
12341 +#ifndef NDEBUG
12342 +        if( yyTraceFILE ){
12343 +          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
12344 +             yyTracePrompt,yyTokenName[yymajor]);
12345 +        }
12346 +#endif
12347 +        yy_destructor(yymajor,&yyminorunion);
12348 +        yymajor = YYNOCODE;
12349 +      }else{
12350 +         while(
12351 +          yypParser->yyidx >= 0 &&
12352 +          yymx != YYERRORSYMBOL &&
12353 +          (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
12354 +        ){
12355 +          yy_pop_parser_stack(yypParser);
12356 +        }
12357 +        if( yypParser->yyidx < 0 || yymajor==0 ){
12358 +          yy_destructor(yymajor,&yyminorunion);
12359 +          yy_parse_failed(yypParser);
12360 +          yymajor = YYNOCODE;
12361 +        }else if( yymx!=YYERRORSYMBOL ){
12362 +          YYMINORTYPE u2;
12363 +          u2.YYERRSYMDT = 0;
12364 +          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
12365 +        }
12366 +      }
12367 +      yypParser->yyerrcnt = 3;
12368 +      yyerrorhit = 1;
12369 +#else  /* YYERRORSYMBOL is not defined */
12370 +      /* This is what we do if the grammar does not define ERROR:
12371 +      **
12372 +      **  * Report an error message, and throw away the input token.
12373 +      **
12374 +      **  * If the input token is $, then fail the parse.
12375 +      **
12376 +      ** As before, subsequent error messages are suppressed until
12377 +      ** three input tokens have been successfully shifted.
12378 +      */
12379 +      if( yypParser->yyerrcnt<=0 ){
12380 +        yy_syntax_error(yypParser,yymajor,yyminorunion);
12381 +      }
12382 +      yypParser->yyerrcnt = 3;
12383 +      yy_destructor(yymajor,&yyminorunion);
12384 +      if( yyendofinput ){
12385 +        yy_parse_failed(yypParser);
12386 +      }
12387 +      yymajor = YYNOCODE;
12388 +#endif
12389 +    }else{
12390 +      yy_accept(yypParser);
12391 +      yymajor = YYNOCODE;
12392 +    }
12393 +  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
12394 +  return;
12395 +}
12396 --- ../lighttpd-1.4.11/src/inet_ntop_cache.c    2005-08-11 01:26:38.000000000 +0300
12397 +++ lighttpd-1.4.12/src/inet_ntop_cache.c       2006-07-11 22:07:52.000000000 +0300
12398 @@ -8,7 +8,7 @@
12399  #include "sys-socket.h"
12400  
12401  const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
12402 -#ifdef HAVE_IPV6       
12403 +#ifdef HAVE_IPV6
12404         size_t ndx = 0, i;
12405         for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
12406                 if (srv->inet_ntop_cache[i].ts != 0) {
12407 @@ -20,31 +20,31 @@
12408                                    srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
12409                                 /* IPv4 found in cache */
12410                                 break;
12411 -                               
12412 +
12413                         }
12414                 }
12415         }
12416 -       
12417 +
12418         if (i == INET_NTOP_CACHE_MAX) {
12419                 /* not found in cache */
12420 -               
12421 +
12422                 i = ndx;
12423 -               inet_ntop(addr->plain.sa_family, 
12424 -                         addr->plain.sa_family == AF_INET6 ? 
12425 +               inet_ntop(addr->plain.sa_family,
12426 +                         addr->plain.sa_family == AF_INET6 ?
12427                           (const void *) &(addr->ipv6.sin6_addr) :
12428                           (const void *) &(addr->ipv4.sin_addr),
12429                           srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
12430 -               
12431 +
12432                 srv->inet_ntop_cache[i].ts = srv->cur_ts;
12433                 srv->inet_ntop_cache[i].family = addr->plain.sa_family;
12434 -               
12435 +
12436                 if (srv->inet_ntop_cache[i].family == AF_INET) {
12437                         srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
12438                 } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
12439                         memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
12440                 }
12441         }
12442 -       
12443 +
12444         return srv->inet_ntop_cache[i].b2;
12445  #else
12446         UNUSED(srv);
12447 --- ../lighttpd-1.4.11/src/joblist.c    2005-08-11 01:26:41.000000000 +0300
12448 +++ lighttpd-1.4.12/src/joblist.c       2006-07-11 22:07:51.000000000 +0300
12449 @@ -7,7 +7,7 @@
12450  
12451  int joblist_append(server *srv, connection *con) {
12452         if (con->in_joblist) return 0;
12453 -       
12454 +
12455         if (srv->joblist->size == 0) {
12456                 srv->joblist->size  = 16;
12457                 srv->joblist->ptr   = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
12458 @@ -15,15 +15,15 @@
12459                 srv->joblist->size += 16;
12460                 srv->joblist->ptr   = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
12461         }
12462 -       
12463 +
12464         srv->joblist->ptr[srv->joblist->used++] = con;
12465 -       
12466 +
12467         return 0;
12468  }
12469  
12470  void joblist_free(server *srv, connections *joblist) {
12471         UNUSED(srv);
12472 -               
12473 +
12474         free(joblist->ptr);
12475         free(joblist);
12476  }
12477 @@ -31,14 +31,14 @@
12478  connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
12479         connection *con;
12480         UNUSED(srv);
12481 -               
12482 -       
12483 +
12484 +
12485         if (fdwaitqueue->used == 0) return NULL;
12486 -       
12487 +
12488         con = fdwaitqueue->ptr[0];
12489 -       
12490 +
12491         memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
12492 -       
12493 +
12494         return con;
12495  }
12496  
12497 @@ -50,9 +50,9 @@
12498                 srv->fdwaitqueue->size += 16;
12499                 srv->fdwaitqueue->ptr   = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
12500         }
12501 -       
12502 +
12503         srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
12504 -       
12505 +
12506         return 0;
12507  }
12508  
12509 --- ../lighttpd-1.4.11/src/keyvalue.c   2006-03-02 16:08:06.000000000 +0200
12510 +++ lighttpd-1.4.12/src/keyvalue.c      2006-07-11 22:07:51.000000000 +0300
12511 @@ -87,7 +87,8 @@
12512         { 504, "Gateway Timeout" },
12513         { 505, "HTTP Version Not Supported" },
12514         { 507, "Insufficient Storage" }, /* WebDAV */
12515 -       
12516 +       { 509, "Bandwidth Limit exceeded" },
12517 +
12518         { -1, NULL }
12519  };
12520  
12521 @@ -102,12 +103,12 @@
12522         { 501, "501.html" },
12523         { 503, "503.html" },
12524         { 505, "505.html" },
12525 -       
12526 +
12527         { -1, NULL }
12528  };
12529  
12530  
12531 -const char *keyvalue_get_value(keyvalue *kv, int k) { 
12532 +const char *keyvalue_get_value(keyvalue *kv, int k) {
12533         int i;
12534         for (i = 0; kv[i].value; i++) {
12535                 if (kv[i].key == k) return kv[i].value;
12536 @@ -115,7 +116,7 @@
12537         return NULL;
12538  }
12539  
12540 -int keyvalue_get_key(keyvalue *kv, const char *s) { 
12541 +int keyvalue_get_key(keyvalue *kv, const char *s) {
12542         int i;
12543         for (i = 0; kv[i].value; i++) {
12544                 if (0 == strcmp(kv[i].value, s)) return kv[i].key;
12545 @@ -125,9 +126,9 @@
12546  
12547  keyvalue_buffer *keyvalue_buffer_init(void) {
12548         keyvalue_buffer *kvb;
12549 -       
12550 +
12551         kvb = calloc(1, sizeof(*kvb));
12552 -       
12553 +
12554         return kvb;
12555  }
12556  
12557 @@ -135,49 +136,49 @@
12558         size_t i;
12559         if (kvb->size == 0) {
12560                 kvb->size = 4;
12561 -               
12562 +
12563                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12564 -               
12565 +
12566                 for(i = 0; i < kvb->size; i++) {
12567                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12568                 }
12569         } else if (kvb->used == kvb->size) {
12570                 kvb->size += 4;
12571 -               
12572 +
12573                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12574 -               
12575 +
12576                 for(i = kvb->used; i < kvb->size; i++) {
12577                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12578                 }
12579         }
12580 -       
12581 +
12582         kvb->kv[kvb->used]->key = key;
12583         kvb->kv[kvb->used]->value = strdup(value);
12584 -       
12585 +
12586         kvb->used++;
12587 -       
12588 +
12589         return 0;
12590  }
12591  
12592  void keyvalue_buffer_free(keyvalue_buffer *kvb) {
12593         size_t i;
12594 -       
12595 +
12596         for (i = 0; i < kvb->size; i++) {
12597                 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12598                 free(kvb->kv[i]);
12599         }
12600 -       
12601 +
12602         if (kvb->kv) free(kvb->kv);
12603 -       
12604 +
12605         free(kvb);
12606  }
12607  
12608  
12609  s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
12610         s_keyvalue_buffer *kvb;
12611 -       
12612 +
12613         kvb = calloc(1, sizeof(*kvb));
12614 -       
12615 +
12616         return kvb;
12617  }
12618  
12619 @@ -186,50 +187,50 @@
12620         if (kvb->size == 0) {
12621                 kvb->size = 4;
12622                 kvb->used = 0;
12623 -               
12624 +
12625                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12626 -               
12627 +
12628                 for(i = 0; i < kvb->size; i++) {
12629                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12630                 }
12631         } else if (kvb->used == kvb->size) {
12632                 kvb->size += 4;
12633 -               
12634 +
12635                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12636 -               
12637 +
12638                 for(i = kvb->used; i < kvb->size; i++) {
12639                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12640                 }
12641         }
12642 -       
12643 +
12644         kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
12645         kvb->kv[kvb->used]->value = strdup(value);
12646 -       
12647 +
12648         kvb->used++;
12649 -       
12650 +
12651         return 0;
12652  }
12653  
12654  void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
12655         size_t i;
12656 -       
12657 +
12658         for (i = 0; i < kvb->size; i++) {
12659                 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12660                 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12661                 free(kvb->kv[i]);
12662         }
12663 -       
12664 +
12665         if (kvb->kv) free(kvb->kv);
12666 -       
12667 +
12668         free(kvb);
12669  }
12670  
12671  
12672  httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
12673         httpauth_keyvalue_buffer *kvb;
12674 -       
12675 +
12676         kvb = calloc(1, sizeof(*kvb));
12677 -       
12678 +
12679         return kvb;
12680  }
12681  
12682 @@ -237,42 +238,42 @@
12683         size_t i;
12684         if (kvb->size == 0) {
12685                 kvb->size = 4;
12686 -               
12687 +
12688                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12689 -               
12690 +
12691                 for(i = 0; i < kvb->size; i++) {
12692                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12693                 }
12694         } else if (kvb->used == kvb->size) {
12695                 kvb->size += 4;
12696 -               
12697 +
12698                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12699 -               
12700 +
12701                 for(i = kvb->used; i < kvb->size; i++) {
12702                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12703                 }
12704         }
12705 -       
12706 +
12707         kvb->kv[kvb->used]->key = strdup(key);
12708         kvb->kv[kvb->used]->realm = strdup(realm);
12709         kvb->kv[kvb->used]->type = type;
12710 -       
12711 +
12712         kvb->used++;
12713 -       
12714 +
12715         return 0;
12716  }
12717  
12718  void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
12719         size_t i;
12720 -       
12721 +
12722         for (i = 0; i < kvb->size; i++) {
12723                 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12724                 if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
12725                 free(kvb->kv[i]);
12726         }
12727 -       
12728 +
12729         if (kvb->kv) free(kvb->kv);
12730 -       
12731 +
12732         free(kvb);
12733  }
12734  
12735 @@ -306,9 +307,9 @@
12736  
12737  pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
12738         pcre_keyvalue_buffer *kvb;
12739 -       
12740 +
12741         kvb = calloc(1, sizeof(*kvb));
12742 -       
12743 +
12744         return kvb;
12745  }
12746  
12747 @@ -319,46 +320,46 @@
12748         int erroff;
12749         pcre_keyvalue *kv;
12750  #endif
12751 -       
12752 +
12753         if (!key) return -1;
12754  
12755  #ifdef HAVE_PCRE_H
12756         if (kvb->size == 0) {
12757                 kvb->size = 4;
12758                 kvb->used = 0;
12759 -               
12760 +
12761                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12762 -               
12763 +
12764                 for(i = 0; i < kvb->size; i++) {
12765                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12766                 }
12767         } else if (kvb->used == kvb->size) {
12768                 kvb->size += 4;
12769 -               
12770 +
12771                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12772 -               
12773 +
12774                 for(i = kvb->used; i < kvb->size; i++) {
12775                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12776                 }
12777         }
12778 -       
12779 +
12780         kv = kvb->kv[kvb->used];
12781         if (NULL == (kv->key = pcre_compile(key,
12782                                           0, &errptr, &erroff, NULL))) {
12783 -               
12784 +
12785                 fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
12786                 return -1;
12787         }
12788  
12789 -       if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&  
12790 +       if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
12791                         errptr != NULL) {
12792                 return -1;
12793         }
12794 -       
12795 +
12796         kv->value = buffer_init_string(value);
12797 -       
12798 +
12799         kvb->used++;
12800 -       
12801 +
12802         return 0;
12803  #else
12804         UNUSED(kvb);
12805 @@ -380,9 +381,9 @@
12806                 if (kv->value) buffer_free(kv->value);
12807                 free(kv);
12808         }
12809 -       
12810 +
12811         if (kvb->kv) free(kvb->kv);
12812  #endif
12813 -       
12814 +
12815         free(kvb);
12816  }
12817 --- ../lighttpd-1.4.11/src/keyvalue.h   2006-03-02 16:08:06.000000000 +0200
12818 +++ lighttpd-1.4.12/src/keyvalue.h      2006-07-11 22:07:52.000000000 +0300
12819 @@ -9,19 +9,19 @@
12820  # include <pcre.h>
12821  #endif
12822  
12823 -typedef enum { 
12824 -       HTTP_METHOD_UNSET = -1, 
12825 -       HTTP_METHOD_GET, 
12826 -       HTTP_METHOD_POST, 
12827 -       HTTP_METHOD_HEAD, 
12828 -       HTTP_METHOD_OPTIONS, 
12829 +typedef enum {
12830 +       HTTP_METHOD_UNSET = -1,
12831 +       HTTP_METHOD_GET,
12832 +       HTTP_METHOD_POST,
12833 +       HTTP_METHOD_HEAD,
12834 +       HTTP_METHOD_OPTIONS,
12835         HTTP_METHOD_PROPFIND,  /* WebDAV */
12836 -       HTTP_METHOD_MKCOL, 
12837 -       HTTP_METHOD_PUT, 
12838 -       HTTP_METHOD_DELETE, 
12839 -       HTTP_METHOD_COPY, 
12840 -       HTTP_METHOD_MOVE, 
12841 -       HTTP_METHOD_PROPPATCH, 
12842 +       HTTP_METHOD_MKCOL,
12843 +       HTTP_METHOD_PUT,
12844 +       HTTP_METHOD_DELETE,
12845 +       HTTP_METHOD_COPY,
12846 +       HTTP_METHOD_MOVE,
12847 +       HTTP_METHOD_PROPPATCH,
12848         HTTP_METHOD_REPORT, /* DeltaV */
12849         HTTP_METHOD_CHECKOUT,
12850         HTTP_METHOD_CHECKIN,
12851 @@ -39,13 +39,13 @@
12852  
12853  typedef struct {
12854         int key;
12855 -       
12856 +
12857         char *value;
12858  } keyvalue;
12859  
12860  typedef struct {
12861         char *key;
12862 -       
12863 +
12864         char *value;
12865  } s_keyvalue;
12866  
12867 @@ -54,7 +54,7 @@
12868         pcre *key;
12869         pcre_extra *key_extra;
12870  #endif
12871 -       
12872 +
12873         buffer *value;
12874  } pcre_keyvalue;
12875  
12876 @@ -62,7 +62,7 @@
12877  
12878  typedef struct {
12879         char *key;
12880 -       
12881 +
12882         char *realm;
12883         httpauth_type type;
12884  } httpauth_keyvalue;
12885 --- ../lighttpd-1.4.11/src/lemon.c      2005-09-01 00:21:34.000000000 +0300
12886 +++ lighttpd-1.4.12/src/lemon.c 2006-07-11 22:07:51.000000000 +0300
12887 @@ -579,7 +579,7 @@
12888  */
12889  
12890  /* Find a precedence symbol of every rule in the grammar.
12891 -** 
12892 +**
12893  ** Those rules which have a precedence symbol coded in the input
12894  ** grammar using the "[symbol]" construct will already have the
12895  ** rp->precsym field filled.  Other rules take as their precedence
12896 @@ -869,7 +869,7 @@
12897        cfp->status = INCOMPLETE;
12898      }
12899    }
12900 -  
12901 +
12902    do{
12903      progress = 0;
12904      for(i=0; i<lemp->nstate; i++){
12905 @@ -900,7 +900,7 @@
12906    struct symbol *sp;
12907    struct rule *rp;
12908  
12909 -  /* Add all of the reduce actions 
12910 +  /* Add all of the reduce actions
12911    ** A reduce action is added for each element of the followset of
12912    ** a configuration which has its dot at the extreme right.
12913    */
12914 @@ -1017,7 +1017,7 @@
12915        apx->type = RD_RESOLVED;
12916      }
12917    }else{
12918 -    assert( 
12919 +    assert(
12920        apx->type==SH_RESOLVED ||
12921        apx->type==RD_RESOLVED ||
12922        apx->type==CONFLICT ||
12923 @@ -1350,7 +1350,7 @@
12924    OptInit(argv,options,stderr);
12925    if( version ){
12926       printf("Lemon version 1.0\n");
12927 -     exit(0); 
12928 +     exit(0);
12929    }
12930    if( OptNArgs() < 1 ){
12931      fprintf(stderr,"Exactly one filename argument is required.\n");
12932 @@ -2031,7 +2031,7 @@
12933      case IN_RHS:
12934        if( x[0]=='.' ){
12935          struct rule *rp;
12936 -        rp = (struct rule *)malloc( sizeof(struct rule) + 
12937 +        rp = (struct rule *)malloc( sizeof(struct rule) +
12938               sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
12939          if( rp==0 ){
12940            ErrorMsg(psp->filename,psp->tokenlineno,
12941 @@ -2546,7 +2546,7 @@
12942    return fp;
12943  }
12944  
12945 -/* Duplicate the input file without comments and without actions 
12946 +/* Duplicate the input file without comments and without actions
12947  ** on rules */
12948  void Reprint(lemp)
12949  struct lemon *lemp;
12950 @@ -2822,7 +2822,7 @@
12951  PRIVATE FILE *tplt_open(lemp)
12952  struct lemon *lemp;
12953  {
12954 -  
12955 +
12956    char buf[1000];
12957    FILE *in;
12958    char *tpltname;
12959 @@ -2930,7 +2930,7 @@
12960    return ret;
12961  }
12962  
12963 -/* 
12964 +/*
12965  ** Generate code which executes when the rule "rp" is reduced.  Write
12966  ** the code to "out".  Make sure lineno stays up-to-date.
12967  */
12968 @@ -3384,7 +3384,7 @@
12969  
12970    /* Output the yy_shift_ofst[] table */
12971    fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
12972 -  fprintf(out, "static %s yy_shift_ofst[] = {\n", 
12973 +  fprintf(out, "static %s yy_shift_ofst[] = {\n",
12974            minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
12975    n = lemp->nstate;
12976    for(i=j=0; i<n; i++){
12977 @@ -3405,7 +3405,7 @@
12978  
12979    /* Output the yy_reduce_ofst[] table */
12980    fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
12981 -  fprintf(out, "static %s yy_reduce_ofst[] = {\n", 
12982 +  fprintf(out, "static %s yy_reduce_ofst[] = {\n",
12983            minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
12984    n = lemp->nstate;
12985    for(i=j=0; i<n; i++){
12986 @@ -3480,7 +3480,7 @@
12987    tplt_xfer(lemp->name,in,out,&lineno);
12988  
12989    /* Generate code which executes every time a symbol is popped from
12990 -  ** the stack while processing errors or while destroying the parser. 
12991 +  ** the stack while processing errors or while destroying the parser.
12992    ** (In other words, generate the %destructor actions)
12993    */
12994    if( lemp->tokendest ){
12995 @@ -3522,7 +3522,7 @@
12996    tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
12997    tplt_xfer(lemp->name,in,out,&lineno);
12998  
12999 -  /* Generate the table of rule information 
13000 +  /* Generate the table of rule information
13001    **
13002    ** Note: This code depends on the fact that rules are number
13003    ** sequentually beginning with 0.
13004 @@ -3589,7 +3589,7 @@
13005      for(i=1; i<lemp->nterminal; i++){
13006        fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
13007      }
13008 -    fclose(out);  
13009 +    fclose(out);
13010    }
13011    return;
13012  }
13013 @@ -3630,7 +3630,7 @@
13014          rbest = rp;
13015        }
13016      }
13017
13018 +
13019      /* Do not make a default if the number of rules to default
13020      ** is not at least 2 */
13021      if( nbest<2 ) continue;
13022 @@ -3781,7 +3781,7 @@
13023    if( x1a ){
13024      x1a->size = 1024;
13025      x1a->count = 0;
13026 -    x1a->tbl = (x1node*)malloc( 
13027 +    x1a->tbl = (x1node*)malloc(
13028        (sizeof(x1node) + sizeof(x1node*))*1024 );
13029      if( x1a->tbl==0 ){
13030        free(x1a);
13031 @@ -3943,7 +3943,7 @@
13032    if( x2a ){
13033      x2a->size = 128;
13034      x2a->count = 0;
13035 -    x2a->tbl = (x2node*)malloc( 
13036 +    x2a->tbl = (x2node*)malloc(
13037        (sizeof(x2node) + sizeof(x2node*))*128 );
13038      if( x2a->tbl==0 ){
13039        free(x2a);
13040 @@ -4149,7 +4149,7 @@
13041    if( x3a ){
13042      x3a->size = 128;
13043      x3a->count = 0;
13044 -    x3a->tbl = (x3node*)malloc( 
13045 +    x3a->tbl = (x3node*)malloc(
13046        (sizeof(x3node) + sizeof(x3node*))*128 );
13047      if( x3a->tbl==0 ){
13048        free(x3a);
13049 @@ -4295,7 +4295,7 @@
13050    if( x4a ){
13051      x4a->size = 64;
13052      x4a->count = 0;
13053 -    x4a->tbl = (x4node*)malloc( 
13054 +    x4a->tbl = (x4node*)malloc(
13055        (sizeof(x4node) + sizeof(x4node*))*64 );
13056      if( x4a->tbl==0 ){
13057        free(x4a);
13058 --- ../lighttpd-1.4.11/src/lempar.c     2005-08-11 01:26:40.000000000 +0300
13059 +++ lighttpd-1.4.12/src/lempar.c        2006-07-11 22:07:51.000000000 +0300
13060 @@ -8,10 +8,10 @@
13061  /* Next is all token values, in a form suitable for use by makeheaders.
13062  ** This section will be null unless lemon is run with the -m switch.
13063  */
13064 -/* 
13065 +/*
13066  ** These constants (all generated automatically by the parser generator)
13067  ** specify the various kinds of tokens (terminals) that the parser
13068 -** understands. 
13069 +** understands.
13070  **
13071  ** Each symbol here is a terminal symbol in the grammar.
13072  */
13073 @@ -29,7 +29,7 @@
13074  **                       and nonterminals.  "int" is used otherwise.
13075  **    YYNOCODE           is a number of type YYCODETYPE which corresponds
13076  **                       to no legal terminal or nonterminal number.  This
13077 -**                       number is used to fill in empty slots of the hash 
13078 +**                       number is used to fill in empty slots of the hash
13079  **                       table.
13080  **    YYFALLBACK         If defined, this indicates that one or more tokens
13081  **                       have fall-back values which should be used if the
13082 @@ -38,7 +38,7 @@
13083  **                       and nonterminal numbers.  "unsigned char" is
13084  **                       used if there are fewer than 250 rules and
13085  **                       states combined.  "int" is used otherwise.
13086 -**    ParseTOKENTYPE     is the data type used for minor tokens given 
13087 +**    ParseTOKENTYPE     is the data type used for minor tokens given
13088  **                       directly to the parser from the tokenizer.
13089  **    YYMINORTYPE        is the data type used for all minor tokens.
13090  **                       This is typically a union of many types, one of
13091 @@ -62,7 +62,7 @@
13092  /* Next are that tables used to determine what action to take based on the
13093  ** current state and lookahead token.  These tables are used to implement
13094  ** functions that take a state number and lookahead value and return an
13095 -** action integer.  
13096 +** action integer.
13097  **
13098  ** Suppose the action integer is N.  Then the action is determined as
13099  ** follows
13100 @@ -87,7 +87,7 @@
13101  ** If the index value yy_shift_ofst[S]+X is out of range or if the value
13102  ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
13103  ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
13104 -** and that yy_default[S] should be used instead.  
13105 +** and that yy_default[S] should be used instead.
13106  **
13107  ** The formula above is for computing the action when the lookahead is
13108  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
13109 @@ -111,7 +111,7 @@
13110  
13111  /* The next table maps tokens into fallback tokens.  If a construct
13112  ** like the following:
13113 -** 
13114 +**
13115  **      %fallback ID X Y Z.
13116  **
13117  ** appears in the grammer, then ID becomes a fallback token for X, Y,
13118 @@ -163,10 +163,10 @@
13119  #endif /* NDEBUG */
13120  
13121  #ifndef NDEBUG
13122 -/* 
13123 +/*
13124  ** Turn parser tracing on by giving a stream to which to write the trace
13125  ** and a prompt to preface each trace message.  Tracing is turned off
13126 -** by making either argument NULL 
13127 +** by making either argument NULL
13128  **
13129  ** Inputs:
13130  ** <ul>
13131 @@ -191,7 +191,7 @@
13132  #ifndef NDEBUG
13133  /* For tracing shifts, the names of all terminals and nonterminals
13134  ** are required.  The following table supplies these names */
13135 -static const char *yyTokenName[] = { 
13136 +static const char *yyTokenName[] = {
13137  %%
13138  };
13139  #endif /* NDEBUG */
13140 @@ -220,7 +220,7 @@
13141  #endif
13142  }
13143  
13144 -/* 
13145 +/*
13146  ** This function allocates a new parser.
13147  ** The only argument is a pointer to a function which works like
13148  ** malloc.
13149 @@ -251,7 +251,7 @@
13150      /* Here is inserted the actions which take place when a
13151      ** terminal or non-terminal is destroyed.  This can happen
13152      ** when the symbol is popped from the stack during a
13153 -    ** reduce or during error processing or when a parser is 
13154 +    ** reduce or during error processing or when a parser is
13155      ** being destroyed before it is finished parsing.
13156      **
13157      ** Note: during a reduce, the only symbols destroyed are those
13158 @@ -289,7 +289,7 @@
13159    return yymajor;
13160  }
13161  
13162 -/* 
13163 +/*
13164  ** Deallocate and destroy a parser.  Destructors are all called for
13165  ** all stack elements before shutting the parser down.
13166  **
13167 @@ -325,7 +325,7 @@
13168  ){
13169    int i;
13170    int stateno = pParser->yystack[pParser->yyidx].stateno;
13171
13172 +
13173    /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
13174    i = yy_shift_ofst[stateno];
13175    if( i==YY_SHIFT_USE_DFLT ){
13176 @@ -369,7 +369,7 @@
13177  ){
13178    int i;
13179    int stateno = pParser->yystack[pParser->yyidx].stateno;
13180
13181 +
13182    i = yy_reduce_ofst[stateno];
13183    if( i==YY_REDUCE_USE_DFLT ){
13184      return yy_default[stateno];
13185 @@ -455,7 +455,7 @@
13186    ParseARG_FETCH;
13187    yymsp = &yypParser->yystack[yypParser->yyidx];
13188  #ifndef NDEBUG
13189 -  if( yyTraceFILE && yyruleno>=0 
13190 +  if( yyTraceFILE && yyruleno>=0
13191          && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
13192      fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
13193        yyRuleName[yyruleno]);
13194 @@ -608,7 +608,7 @@
13195  #ifdef YYERRORSYMBOL
13196        /* A syntax error has occurred.
13197        ** The response to an error depends upon whether or not the
13198 -      ** grammar defines an error token "ERROR".  
13199 +      ** grammar defines an error token "ERROR".
13200        **
13201        ** This is what we do if the grammar does define ERROR:
13202        **
13203 --- ../lighttpd-1.4.11/src/log.c        2005-11-07 15:01:35.000000000 +0200
13204 +++ lighttpd-1.4.12/src/log.c   2006-07-15 22:43:21.000000000 +0300
13205 @@ -5,7 +5,6 @@
13206  #include <errno.h>
13207  #include <fcntl.h>
13208  #include <time.h>
13209 -#include <unistd.h>
13210  #include <string.h>
13211  #include <stdlib.h>
13212  
13213 @@ -16,6 +15,10 @@
13214  #include "config.h"
13215  #endif
13216  
13217 +#ifdef _WIN32
13218 +#undef HAVE_SYSLOG_H
13219 +#endif
13220 +
13221  #ifdef HAVE_SYSLOG_H
13222  #include <syslog.h>
13223  #endif
13224 @@ -23,6 +26,8 @@
13225  #include "log.h"
13226  #include "array.h"
13227  
13228 +#include "sys-files.h"
13229 +
13230  #ifdef HAVE_VALGRIND_VALGRIND_H
13231  #include <valgrind/valgrind.h>
13232  #endif
13233 @@ -31,38 +36,38 @@
13234  # define O_LARGEFILE 0
13235  #endif
13236  
13237 -/** 
13238 +/**
13239   * open the errorlog
13240 - * 
13241 + *
13242   * we have 3 possibilities:
13243   * - stderr (default)
13244 - * - syslog 
13245 + * - syslog
13246   * - logfile
13247 - * 
13248 + *
13249   * if the open failed, report to the user and die
13250 - * 
13251 + *
13252   */
13253  
13254  int log_error_open(server *srv) {
13255         int fd;
13256         int close_stderr = 1;
13257 -       
13258 +
13259  #ifdef HAVE_SYSLOG_H
13260         /* perhaps someone wants to use syslog() */
13261         openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
13262  #endif
13263         srv->errorlog_mode = ERRORLOG_STDERR;
13264 -       
13265 +
13266         if (srv->srvconf.errorlog_use_syslog) {
13267                 srv->errorlog_mode = ERRORLOG_SYSLOG;
13268         } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
13269                 const char *logfile = srv->srvconf.errorlog_file->ptr;
13270 -               
13271 +
13272                 if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13273 -                       log_error_write(srv, __FILE__, __LINE__, "SSSS", 
13274 +                       log_error_write(srv, __FILE__, __LINE__, "SSSS",
13275                                         "opening errorlog '", logfile,
13276                                         "' failed: ", strerror(errno));
13277 -                       
13278 +
13279                         return -1;
13280                 }
13281  #ifdef FD_CLOEXEC
13282 @@ -71,15 +76,15 @@
13283  #endif
13284                 srv->errorlog_mode = ERRORLOG_FILE;
13285         }
13286 -       
13287 +
13288         log_error_write(srv, __FILE__, __LINE__, "s", "server started");
13289 -       
13290 +
13291  #ifdef HAVE_VALGRIND_VALGRIND_H
13292         /* don't close stderr for debugging purposes if run in valgrind */
13293         if (RUNNING_ON_VALGRIND) close_stderr = 0;
13294  #endif
13295         if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
13296 -       
13297 +
13298         /* move stderr to /dev/null */
13299         if (close_stderr &&
13300             -1 != (fd = open("/dev/null", O_WRONLY))) {
13301 @@ -90,33 +95,33 @@
13302         return 0;
13303  }
13304  
13305 -/** 
13306 +/**
13307   * open the errorlog
13308 - * 
13309 + *
13310   * if the open failed, report to the user and die
13311   * if no filename is given, use syslog instead
13312 - * 
13313 + *
13314   */
13315  
13316  int log_error_cycle(server *srv) {
13317         /* only cycle if we are not in syslog-mode */
13318 -       
13319 +
13320         if (srv->errorlog_mode == ERRORLOG_FILE) {
13321                 const char *logfile = srv->srvconf.errorlog_file->ptr;
13322                 /* already check of opening time */
13323 -               
13324 +
13325                 int new_fd;
13326 -               
13327 +
13328                 if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13329                         /* write to old log */
13330 -                       log_error_write(srv, __FILE__, __LINE__, "SSSSS", 
13331 +                       log_error_write(srv, __FILE__, __LINE__, "SSSSS",
13332                                         "cycling errorlog '", logfile,
13333                                         "' failed: ", strerror(errno),
13334                                         ", falling back to syslog()");
13335 -                       
13336 +
13337                         close(srv->errorlog_fd);
13338                         srv->errorlog_fd = -1;
13339 -#ifdef HAVE_SYSLOG_H   
13340 +#ifdef HAVE_SYSLOG_H
13341                         srv->errorlog_mode = ERRORLOG_SYSLOG;
13342  #endif
13343                 } else {
13344 @@ -125,15 +130,15 @@
13345                         srv->errorlog_fd = new_fd;
13346                 }
13347         }
13348 -       
13349 +
13350         log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
13351 -       
13352 +
13353         return 0;
13354  }
13355  
13356  int log_error_close(server *srv) {
13357         log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
13358 -       
13359 +
13360         switch(srv->errorlog_mode) {
13361         case ERRORLOG_FILE:
13362                 close(srv->errorlog_fd);
13363 @@ -146,13 +151,13 @@
13364         case ERRORLOG_STDERR:
13365                 break;
13366         }
13367 -       
13368 +
13369         return 0;
13370  }
13371  
13372  int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
13373         va_list ap;
13374 -       
13375 +
13376         switch(srv->errorlog_mode) {
13377         case ERRORLOG_FILE:
13378         case ERRORLOG_STDERR:
13379 @@ -161,7 +166,7 @@
13380                         buffer_prepare_copy(srv->ts_debug_str, 255);
13381                         strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
13382                         srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
13383 -                       
13384 +
13385                         srv->last_generated_debug_ts = srv->cur_ts;
13386                 }
13387  
13388 @@ -173,19 +178,19 @@
13389                 BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
13390                 break;
13391         }
13392 -       
13393 +
13394         buffer_append_string(srv->errorlog_buf, filename);
13395         BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ".");
13396         buffer_append_long(srv->errorlog_buf, line);
13397         BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") ");
13398 -       
13399 -       
13400 +
13401 +
13402         for(va_start(ap, fmt); *fmt; fmt++) {
13403                 int d;
13404                 char *s;
13405                 buffer *b;
13406                 off_t o;
13407 -               
13408 +
13409                 switch(*fmt) {
13410                 case 's':           /* string */
13411                         s = va_arg(ap, char *);
13412 @@ -227,7 +232,7 @@
13413                         break;
13414                 case '(':
13415                 case ')':
13416 -               case '<':       
13417 +               case '<':
13418                 case '>':
13419                 case ',':
13420                 case ' ':
13421 @@ -236,7 +241,7 @@
13422                 }
13423         }
13424         va_end(ap);
13425 -       
13426 +
13427         switch(srv->errorlog_mode) {
13428         case ERRORLOG_FILE:
13429                 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13430 @@ -246,11 +251,13 @@
13431                 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13432                 write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
13433                 break;
13434 +#ifdef HAVE_SYSLOG_H
13435         case ERRORLOG_SYSLOG:
13436                 syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
13437                 break;
13438 +#endif
13439         }
13440 -       
13441 +
13442         return 0;
13443  }
13444  
13445 --- ../lighttpd-1.4.11/src/log.h        2005-08-11 01:26:36.000000000 +0300
13446 +++ lighttpd-1.4.12/src/log.h   2006-07-11 22:07:53.000000000 +0300
13447 @@ -9,5 +9,5 @@
13448  int log_error_close(server *srv);
13449  int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
13450  int log_error_cycle(server *srv);
13451 -       
13452 +
13453  #endif
13454 --- ../lighttpd-1.4.11/src/md5.h        2005-11-17 16:20:40.000000000 +0200
13455 +++ lighttpd-1.4.12/src/md5.h   2006-07-11 22:07:53.000000000 +0300
13456 @@ -30,9 +30,15 @@
13457  # include <inttypes.h>
13458  #endif
13459  
13460 +#ifdef _WIN32
13461 +#define UINT4 unsigned __int32
13462 +#define UINT2 unsigned __int16
13463 +#define POINTER unsigned char *
13464 +#else
13465  #define UINT4 uint32_t
13466  #define UINT2 uint16_t
13467  #define POINTER unsigned char *
13468 +#endif
13469  
13470  /* MD5 context. */
13471  typedef struct {
13472 --- ../lighttpd-1.4.11/src/mod_access.c 2006-01-14 19:44:54.000000000 +0200
13473 +++ lighttpd-1.4.12/src/mod_access.c    2006-07-11 22:07:53.000000000 +0300
13474 @@ -8,126 +8,125 @@
13475  
13476  #include "plugin.h"
13477  
13478 +#include "sys-strings.h"
13479 +
13480  typedef struct {
13481         array *access_deny;
13482  } plugin_config;
13483  
13484  typedef struct {
13485         PLUGIN_DATA;
13486 -       
13487 +
13488         plugin_config **config_storage;
13489 -       
13490 -       plugin_config conf; 
13491 +
13492 +       plugin_config conf;
13493  } plugin_data;
13494  
13495  INIT_FUNC(mod_access_init) {
13496         plugin_data *p;
13497 -       
13498 +
13499         p = calloc(1, sizeof(*p));
13500 -       
13501 +
13502         return p;
13503  }
13504  
13505  FREE_FUNC(mod_access_free) {
13506         plugin_data *p = p_d;
13507 -       
13508 +
13509         UNUSED(srv);
13510  
13511         if (!p) return HANDLER_GO_ON;
13512 -       
13513 +
13514         if (p->config_storage) {
13515                 size_t i;
13516                 for (i = 0; i < srv->config_context->used; i++) {
13517                         plugin_config *s = p->config_storage[i];
13518 -                       
13519 +
13520                         array_free(s->access_deny);
13521 -                       
13522 +
13523                         free(s);
13524                 }
13525                 free(p->config_storage);
13526         }
13527 -       
13528 +
13529         free(p);
13530 -       
13531 +
13532         return HANDLER_GO_ON;
13533  }
13534  
13535  SETDEFAULTS_FUNC(mod_access_set_defaults) {
13536         plugin_data *p = p_d;
13537         size_t i = 0;
13538 -       
13539 -       config_values_t cv[] = { 
13540 +
13541 +       config_values_t cv[] = {
13542                 { "url.access-deny",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
13543                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
13544         };
13545 -       
13546 +
13547         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
13548 -       
13549 +
13550         for (i = 0; i < srv->config_context->used; i++) {
13551                 plugin_config *s;
13552 -               
13553 +
13554                 s = calloc(1, sizeof(plugin_config));
13555                 s->access_deny    = array_init();
13556 -               
13557 +
13558                 cv[0].destination = s->access_deny;
13559 -               
13560 +
13561                 p->config_storage[i] = s;
13562 -       
13563 +
13564                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
13565                         return HANDLER_ERROR;
13566                 }
13567         }
13568 -       
13569 +
13570         return HANDLER_GO_ON;
13571  }
13572  
13573 -#define PATCH(x) \
13574 -       p->conf.x = s->x;
13575  static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
13576         size_t i, j;
13577         plugin_config *s = p->config_storage[0];
13578  
13579 -       PATCH(access_deny);
13580 -       
13581 +       PATCH_OPTION(access_deny);
13582 +
13583         /* skip the first, the global context */
13584         for (i = 1; i < srv->config_context->used; i++) {
13585                 data_config *dc = (data_config *)srv->config_context->data[i];
13586                 s = p->config_storage[i];
13587 -               
13588 +
13589                 /* condition didn't match */
13590                 if (!config_check_cond(srv, con, dc)) continue;
13591 -               
13592 +
13593                 /* merge config */
13594                 for (j = 0; j < dc->value->used; j++) {
13595                         data_unset *du = dc->value->data[j];
13596 -                       
13597 +
13598                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
13599 -                               PATCH(access_deny);
13600 +                               PATCH_OPTION(access_deny);
13601                         }
13602                 }
13603         }
13604 -       
13605 +
13606         return 0;
13607  }
13608 -#undef PATCH
13609  
13610  URIHANDLER_FUNC(mod_access_uri_handler) {
13611         plugin_data *p = p_d;
13612         int s_len;
13613         size_t k;
13614 -       
13615 +
13616         if (con->uri.path->used == 0) return HANDLER_GO_ON;
13617 -       
13618 +
13619         mod_access_patch_connection(srv, con, p);
13620 -       
13621 +
13622         s_len = con->uri.path->used - 1;
13623 -       
13624 +
13625         for (k = 0; k < p->conf.access_deny->used; k++) {
13626                 data_string *ds = (data_string *)p->conf.access_deny->data[k];
13627                 int ct_len = ds->value->used - 1;
13628 -               
13629 +
13630                 if (ct_len > s_len) continue;
13631 -               
13632 +
13633                 if (ds->value->used == 0) continue;
13634  
13635                 /* if we have a case-insensitive FS we have to lower-case the URI here too */
13636 @@ -135,18 +134,18 @@
13637                 if (con->conf.force_lowercase_filenames) {
13638                         if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13639                                 con->http_status = 403;
13640 -                       
13641 +
13642                                 return HANDLER_FINISHED;
13643                         }
13644                 } else {
13645                         if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13646                                 con->http_status = 403;
13647 -                       
13648 +
13649                                 return HANDLER_FINISHED;
13650                         }
13651                 }
13652         }
13653 -       
13654 +
13655         /* not found */
13656         return HANDLER_GO_ON;
13657  }
13658 @@ -155,13 +154,13 @@
13659  int mod_access_plugin_init(plugin *p) {
13660         p->version     = LIGHTTPD_VERSION_ID;
13661         p->name        = buffer_init_string("access");
13662 -       
13663 +
13664         p->init        = mod_access_init;
13665         p->set_defaults = mod_access_set_defaults;
13666         p->handle_uri_clean  = mod_access_uri_handler;
13667         p->cleanup     = mod_access_free;
13668 -       
13669 +
13670         p->data        = NULL;
13671 -       
13672 +
13673         return 0;
13674  }
13675 --- ../lighttpd-1.4.11/src/mod_accesslog.c      2006-01-31 14:01:43.000000000 +0200
13676 +++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-11 22:07:53.000000000 +0300
13677 @@ -6,8 +6,7 @@
13678  #include <ctype.h>
13679  #include <stdlib.h>
13680  #include <string.h>
13681 -#include <fcntl.h>
13682 -#include <unistd.h>
13683 +#include <fcntl.h> /* only the defines on windows */
13684  #include <errno.h>
13685  #include <time.h>
13686  
13687 @@ -22,6 +21,7 @@
13688  #include "inet_ntop_cache.h"
13689  
13690  #include "sys-socket.h"
13691 +#include "sys-files.h"
13692  
13693  #ifdef HAVE_SYSLOG_H
13694  # include <syslog.h>
13695 @@ -29,7 +29,7 @@
13696  
13697  typedef struct {
13698         char key;
13699 -       enum { 
13700 +       enum {
13701                 FORMAT_UNSET,
13702                         FORMAT_UNSUPPORTED,
13703                         FORMAT_PERCENT,
13704 @@ -41,7 +41,7 @@
13705                         FORMAT_STATUS,
13706                         FORMAT_BYTES_OUT_NO_HEADER,
13707                         FORMAT_HEADER,
13708 -                       
13709 +
13710                         FORMAT_REMOTE_ADDR,
13711                         FORMAT_LOCAL_ADDR,
13712                         FORMAT_COOKIE,
13713 @@ -59,20 +59,20 @@
13714                         FORMAT_CONNECTION_STATUS,
13715                         FORMAT_BYTES_IN,
13716                         FORMAT_BYTES_OUT,
13717 -                       
13718 +
13719                         FORMAT_RESPONSE_HEADER
13720         } type;
13721  } format_mapping;
13722  
13723  /**
13724 - * 
13725 - * 
13726 + *
13727 + *
13728   * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
13729 - * 
13730 + *
13731   */
13732  
13733 -const format_mapping fmap[] = 
13734 -{ 
13735 +const format_mapping fmap[] =
13736 +{
13737         { '%', FORMAT_PERCENT },
13738         { 'h', FORMAT_REMOTE_HOST },
13739         { 'l', FORMAT_REMOTE_IDENT },
13740 @@ -82,7 +82,7 @@
13741         { 's', FORMAT_STATUS },
13742         { 'b', FORMAT_BYTES_OUT_NO_HEADER },
13743         { 'i', FORMAT_HEADER },
13744 -       
13745 +
13746         { 'a', FORMAT_REMOTE_ADDR },
13747         { 'A', FORMAT_LOCAL_ADDR },
13748         { 'B', FORMAT_BYTES_OUT_NO_HEADER },
13749 @@ -103,23 +103,23 @@
13750         { 'X', FORMAT_CONNECTION_STATUS },
13751         { 'I', FORMAT_BYTES_IN },
13752         { 'O', FORMAT_BYTES_OUT },
13753 -       
13754 +
13755         { 'o', FORMAT_RESPONSE_HEADER },
13756 -       
13757 +
13758         { '\0', FORMAT_UNSET }
13759  };
13760  
13761  
13762  typedef struct {
13763         enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
13764 -       
13765 +
13766         buffer *string;
13767         int field;
13768  } format_field;
13769  
13770  typedef struct {
13771         format_field **ptr;
13772 -       
13773 +
13774         size_t used;
13775         size_t size;
13776  } format_fields;
13777 @@ -128,39 +128,39 @@
13778         buffer *access_logfile;
13779         buffer *format;
13780         unsigned short use_syslog;
13781 -       
13782 -       
13783 +
13784 +
13785         int    log_access_fd;
13786         time_t last_generated_accesslog_ts;
13787         time_t *last_generated_accesslog_ts_ptr;
13788 -       
13789 -       
13790 +
13791 +
13792         buffer *access_logbuffer;
13793         buffer *ts_accesslog_str;
13794 -       
13795 +
13796         format_fields *parsed_format;
13797  } plugin_config;
13798  
13799  typedef struct {
13800         PLUGIN_DATA;
13801 -       
13802 +
13803         plugin_config **config_storage;
13804 -       plugin_config conf; 
13805 +       plugin_config conf;
13806  } plugin_data;
13807  
13808  INIT_FUNC(mod_accesslog_init) {
13809         plugin_data *p;
13810 -       
13811 +
13812         p = calloc(1, sizeof(*p));
13813 -       
13814 +
13815         return p;
13816  }
13817  
13818  int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
13819         size_t i, j, k = 0, start = 0;
13820 -       
13821 +
13822         for (i = 0; i < format->used - 1; i++) {
13823 -               
13824 +
13825                 switch(format->ptr[i]) {
13826                 case '%':
13827                         if (start != i) {
13828 @@ -173,19 +173,19 @@
13829                                         fields->size += 16;
13830                                         fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
13831                                 }
13832 -                               
13833 +
13834                                 fields->ptr[fields->used] = malloc(sizeof(format_fields));
13835                                 fields->ptr[fields->used]->type = FIELD_STRING;
13836                                 fields->ptr[fields->used]->string = buffer_init();
13837 -                               
13838 +
13839                                 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
13840 -                               
13841 +
13842                                 fields->used++;
13843                         }
13844 -                       
13845 -                       
13846 +
13847 +
13848                         /* we need a new field */
13849 -                       
13850 +
13851                         if (fields->size == 0) {
13852                                 fields->size = 16;
13853                                 fields->used = 0;
13854 @@ -194,43 +194,43 @@
13855                                 fields->size += 16;
13856                                 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
13857                         }
13858 -                       
13859 +
13860                         /* search for the terminating command */
13861                         switch (format->ptr[i+1]) {
13862                         case '>':
13863                         case '<':
13864                                 /* only for s */
13865 -                               
13866 +
13867                                 for (j = 0; fmap[j].key != '\0'; j++) {
13868                                         if (fmap[j].key != format->ptr[i+2]) continue;
13869 -                                       
13870 +
13871                                         /* found key */
13872 -                                               
13873 +
13874                                         fields->ptr[fields->used] = malloc(sizeof(format_fields));
13875                                         fields->ptr[fields->used]->type = FIELD_FORMAT;
13876                                         fields->ptr[fields->used]->field = fmap[j].type;
13877                                         fields->ptr[fields->used]->string = NULL;
13878 -                                       
13879 +
13880                                         fields->used++;
13881 -                                       
13882 +
13883                                         break;
13884                                 }
13885 -                               
13886 +
13887                                 if (fmap[j].key == '\0') {
13888                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13889                                         return -1;
13890                                 }
13891 -                               
13892 +
13893                                 start = i + 3;
13894 -                               
13895 +
13896                                 break;
13897                         case '{':
13898                                 /* go forward to } */
13899 -                               
13900 +
13901                                 for (k = i+2; k < format->used - 1; k++) {
13902                                         if (format->ptr[k] == '}') break;
13903                                 }
13904 -                               
13905 +
13906                                 if (k == format->used - 1) {
13907                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13908                                         return -1;
13909 @@ -239,62 +239,62 @@
13910                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13911                                         return -1;
13912                                 }
13913 -                               
13914 +
13915                                 for (j = 0; fmap[j].key != '\0'; j++) {
13916                                         if (fmap[j].key != format->ptr[k+1]) continue;
13917 -                                       
13918 +
13919                                         /* found key */
13920 -                                               
13921 +
13922                                         fields->ptr[fields->used] = malloc(sizeof(format_fields));
13923                                         fields->ptr[fields->used]->type = FIELD_FORMAT;
13924                                         fields->ptr[fields->used]->field = fmap[j].type;
13925                                         fields->ptr[fields->used]->string = buffer_init();
13926 -                                       
13927 +
13928                                         buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
13929 -                                       
13930 +
13931                                         fields->used++;
13932 -                                       
13933 +
13934                                         break;
13935                                 }
13936 -                               
13937 +
13938                                 if (fmap[j].key == '\0') {
13939                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13940                                         return -1;
13941                                 }
13942 -                               
13943 +
13944                                 start = k + 2;
13945 -                               
13946 +
13947                                 break;
13948                         default:
13949                                 for (j = 0; fmap[j].key != '\0'; j++) {
13950                                         if (fmap[j].key != format->ptr[i+1]) continue;
13951 -                                       
13952 +
13953                                         /* found key */
13954 -                                               
13955 +
13956                                         fields->ptr[fields->used] = malloc(sizeof(format_fields));
13957                                         fields->ptr[fields->used]->type = FIELD_FORMAT;
13958                                         fields->ptr[fields->used]->field = fmap[j].type;
13959                                         fields->ptr[fields->used]->string = NULL;
13960 -                                       
13961 +
13962                                         fields->used++;
13963 -                                       
13964 +
13965                                         break;
13966                                 }
13967 -                               
13968 +
13969                                 if (fmap[j].key == '\0') {
13970                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13971                                         return -1;
13972                                 }
13973 -                               
13974 +
13975                                 start = i + 2;
13976 -                               
13977 +
13978                                 break;
13979                         }
13980 -                       
13981 +
13982                         break;
13983                 }
13984         }
13985 -       
13986 +
13987         if (start < i) {
13988                 /* copy the string */
13989                 if (fields->size == 0) {
13990 @@ -305,32 +305,32 @@
13991                         fields->size += 16;
13992                         fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
13993                 }
13994 -               
13995 +
13996                 fields->ptr[fields->used] = malloc(sizeof(format_fields));
13997                 fields->ptr[fields->used]->type = FIELD_STRING;
13998                 fields->ptr[fields->used]->string = buffer_init();
13999 -               
14000 +
14001                 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14002 -               
14003 +
14004                 fields->used++;
14005         }
14006 -       
14007 +
14008         return 0;
14009  }
14010  
14011  FREE_FUNC(mod_accesslog_free) {
14012         plugin_data *p = p_d;
14013         size_t i;
14014 -       
14015 +
14016         if (!p) return HANDLER_GO_ON;
14017 -       
14018 +
14019         if (p->config_storage) {
14020 -               
14021 +
14022                 for (i = 0; i < srv->config_context->used; i++) {
14023                         plugin_config *s = p->config_storage[i];
14024  
14025                         if (!s) continue;
14026 -                       
14027 +
14028                         if (s->access_logbuffer->used) {
14029                                 if (s->use_syslog) {
14030  # ifdef HAVE_SYSLOG_H
14031 @@ -342,14 +342,14 @@
14032                                         write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14033                                 }
14034                         }
14035 -                       
14036 +
14037                         if (s->log_access_fd != -1) close(s->log_access_fd);
14038 -                       
14039 +
14040                         buffer_free(s->ts_accesslog_str);
14041                         buffer_free(s->access_logbuffer);
14042                         buffer_free(s->format);
14043                         buffer_free(s->access_logfile);
14044 -                       
14045 +
14046                         if (s->parsed_format) {
14047                                 size_t j;
14048                                 for (j = 0; j < s->parsed_format->used; j++) {
14049 @@ -359,36 +359,36 @@
14050                                 free(s->parsed_format->ptr);
14051                                 free(s->parsed_format);
14052                         }
14053 -                       
14054 +
14055                         free(s);
14056                 }
14057 -       
14058 +
14059                 free(p->config_storage);
14060         }
14061 -       
14062 +
14063         free(p);
14064 -       
14065 +
14066         return HANDLER_GO_ON;
14067  }
14068  
14069  SETDEFAULTS_FUNC(log_access_open) {
14070         plugin_data *p = p_d;
14071         size_t i = 0;
14072 -       
14073 -       config_values_t cv[] = { 
14074 +
14075 +       config_values_t cv[] = {
14076                 { "accesslog.filename",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14077                 { "accesslog.use-syslog",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
14078                 { "accesslog.format",               NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14079                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14080         };
14081 -       
14082 +
14083         if (!p) return HANDLER_ERROR;
14084 -       
14085 +
14086         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14087 -       
14088 +
14089         for (i = 0; i < srv->config_context->used; i++) {
14090                 plugin_config *s;
14091 -               
14092 +
14093                 s = calloc(1, sizeof(plugin_config));
14094                 s->access_logfile = buffer_init();
14095                 s->format = buffer_init();
14096 @@ -397,44 +397,44 @@
14097                 s->log_access_fd = -1;
14098                 s->last_generated_accesslog_ts = 0;
14099                 s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
14100 -               
14101 -       
14102 +
14103 +
14104                 cv[0].destination = s->access_logfile;
14105                 cv[1].destination = &(s->use_syslog);
14106                 cv[2].destination = s->format;
14107 -       
14108 +
14109                 p->config_storage[i] = s;
14110 -               
14111 +
14112                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14113                         return HANDLER_ERROR;
14114                 }
14115 -               
14116 +
14117                 if (i == 0 && buffer_is_empty(s->format)) {
14118                         /* set a default logfile string */
14119 -                       
14120 +
14121                         buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
14122                 }
14123 -               
14124 +
14125                 /* parse */
14126 -               
14127 +
14128                 if (s->format->used) {
14129                         s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
14130 -                       
14131 +
14132                         if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
14133  
14134 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
14135 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
14136                                                 "parsing accesslog-definition failed:", s->format);
14137  
14138                                 return HANDLER_ERROR;
14139                         }
14140  #if 0
14141 -                       /* debugging */                 
14142 +                       /* debugging */
14143                         for (j = 0; j < s->parsed_format->used; j++) {
14144                                 switch (s->parsed_format->ptr[j]->type) {
14145                                 case FIELD_FORMAT:
14146 -                                       log_error_write(srv, __FILE__, __LINE__, "ssds", 
14147 +                                       log_error_write(srv, __FILE__, __LINE__, "ssds",
14148                                                         "config:", "format", s->parsed_format->ptr[j]->field,
14149 -                                                       s->parsed_format->ptr[j]->string ? 
14150 +                                                       s->parsed_format->ptr[j]->string ?
14151                                                         s->parsed_format->ptr[j]->string->ptr : "" );
14152                                         break;
14153                                 case FIELD_STRING:
14154 @@ -446,52 +446,52 @@
14155                         }
14156  #endif
14157                 }
14158 -               
14159 +
14160                 if (s->use_syslog) {
14161                         /* ignore the next checks */
14162                         continue;
14163                 }
14164 -               
14165 +
14166                 if (buffer_is_empty(s->access_logfile)) continue;
14167 -               
14168 +
14169                 if (s->access_logfile->ptr[0] == '|') {
14170  #ifdef HAVE_FORK
14171                         /* create write pipe and spawn process */
14172 -                       
14173 +
14174                         int to_log_fds[2];
14175                         pid_t pid;
14176 -                       
14177 +
14178                         if (pipe(to_log_fds)) {
14179                                 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
14180                                 return HANDLER_ERROR;
14181                         }
14182 -                       
14183 +
14184                         /* fork, execve */
14185                         switch (pid = fork()) {
14186 -                       case 0: 
14187 +                       case 0:
14188                                 /* child */
14189 -                               
14190 +
14191                                 close(STDIN_FILENO);
14192                                 dup2(to_log_fds[0], STDIN_FILENO);
14193                                 close(to_log_fds[0]);
14194                                 /* not needed */
14195                                 close(to_log_fds[1]);
14196 -                               
14197 +
14198                                 /* we don't need the client socket */
14199                                 for (i = 3; i < 256; i++) {
14200                                         close(i);
14201                                 }
14202 -                               
14203 -                               /* exec the log-process (skip the | ) 
14204 -                                * 
14205 +
14206 +                               /* exec the log-process (skip the | )
14207 +                                *
14208                                  */
14209 -                               
14210 +
14211                                 execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
14212  
14213 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
14214 -                                               "spawning log-process failed: ", strerror(errno), 
14215 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
14216 +                                               "spawning log-process failed: ", strerror(errno),
14217                                                 s->access_logfile->ptr + 1);
14218 -                               
14219 +
14220                                 exit(-1);
14221                                 break;
14222                         case -1:
14223 @@ -500,27 +500,28 @@
14224                                 break;
14225                         default:
14226                                 close(to_log_fds[0]);
14227 -                               
14228 +
14229                                 s->log_access_fd = to_log_fds[1];
14230 -                               
14231 +
14232                                 break;
14233                         }
14234  #else
14235                         return -1;
14236  #endif
14237 -               } else if (-1 == (s->log_access_fd = 
14238 +               } else if (-1 == (s->log_access_fd =
14239                                   open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14240 -                       
14241 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", 
14242 -                                       "opening access-log failed:", 
14243 +
14244 +                       log_error_write(srv, __FILE__, __LINE__, "ssb",
14245 +                                       "opening access-log failed:",
14246                                         strerror(errno), s->access_logfile);
14247 -                       
14248 +
14249                         return HANDLER_ERROR;
14250                 }
14251 +#ifndef _WIN32
14252                 fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
14253 -       
14254 +#endif
14255         }
14256 -       
14257 +
14258         return HANDLER_GO_ON;
14259  }
14260  
14261 @@ -529,7 +530,7 @@
14262         size_t i;
14263  
14264         if (!p->config_storage) return HANDLER_GO_ON;
14265 -               
14266 +
14267         for (i = 0; i < srv->config_context->used; i++) {
14268                 plugin_config *s = p->config_storage[i];
14269  
14270 @@ -544,90 +545,87 @@
14271                         } else if (s->log_access_fd != -1) {
14272                                 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14273                         }
14274 -                       
14275 +
14276                         buffer_reset(s->access_logbuffer);
14277                 }
14278 -               
14279 +
14280                 if (s->use_syslog == 0 &&
14281                     !buffer_is_empty(s->access_logfile) &&
14282                     s->access_logfile->ptr[0] != '|') {
14283 -                       
14284 +
14285                         close(s->log_access_fd);
14286 -                       
14287 -                       if (-1 == (s->log_access_fd = 
14288 +
14289 +                       if (-1 == (s->log_access_fd =
14290                                    open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14291 -                               
14292 +
14293                                 log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
14294 -                               
14295 +
14296                                 return HANDLER_ERROR;
14297                         }
14298                 }
14299         }
14300 -       
14301 +
14302         return HANDLER_GO_ON;
14303  }
14304  
14305 -#define PATCH(x) \
14306 -       p->conf.x = s->x;
14307  static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
14308         size_t i, j;
14309         plugin_config *s = p->config_storage[0];
14310 -       
14311 -       PATCH(access_logfile);
14312 -       PATCH(format);
14313 -       PATCH(log_access_fd);
14314 -       PATCH(last_generated_accesslog_ts_ptr);
14315 -       PATCH(access_logbuffer);
14316 -       PATCH(ts_accesslog_str);
14317 -       PATCH(parsed_format);
14318 -       PATCH(use_syslog);
14319 -       
14320 +
14321 +       PATCH_OPTION(access_logfile);
14322 +       PATCH_OPTION(format);
14323 +       PATCH_OPTION(log_access_fd);
14324 +       PATCH_OPTION(last_generated_accesslog_ts_ptr);
14325 +       PATCH_OPTION(access_logbuffer);
14326 +       PATCH_OPTION(ts_accesslog_str);
14327 +       PATCH_OPTION(parsed_format);
14328 +       PATCH_OPTION(use_syslog);
14329 +
14330         /* skip the first, the global context */
14331         for (i = 1; i < srv->config_context->used; i++) {
14332                 data_config *dc = (data_config *)srv->config_context->data[i];
14333                 s = p->config_storage[i];
14334 -               
14335 +
14336                 /* condition didn't match */
14337                 if (!config_check_cond(srv, con, dc)) continue;
14338 -               
14339 +
14340                 /* merge config */
14341                 for (j = 0; j < dc->value->used; j++) {
14342                         data_unset *du = dc->value->data[j];
14343 -                       
14344 +
14345                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
14346 -                               PATCH(access_logfile);
14347 -                               PATCH(log_access_fd);
14348 -                               PATCH(last_generated_accesslog_ts_ptr);
14349 -                               PATCH(access_logbuffer);
14350 -                               PATCH(ts_accesslog_str);
14351 +                               PATCH_OPTION(access_logfile);
14352 +                               PATCH_OPTION(log_access_fd);
14353 +                               PATCH_OPTION(last_generated_accesslog_ts_ptr);
14354 +                               PATCH_OPTION(access_logbuffer);
14355 +                               PATCH_OPTION(ts_accesslog_str);
14356                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
14357 -                               PATCH(format);
14358 -                               PATCH(parsed_format);
14359 +                               PATCH_OPTION(format);
14360 +                               PATCH_OPTION(parsed_format);
14361                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
14362 -                               PATCH(use_syslog);
14363 +                               PATCH_OPTION(use_syslog);
14364                         }
14365                 }
14366         }
14367 -       
14368 +
14369         return 0;
14370  }
14371 -#undef PATCH
14372  
14373  REQUESTDONE_FUNC(log_access_write) {
14374         plugin_data *p = p_d;
14375         buffer *b;
14376         size_t j;
14377 -       
14378 +
14379         int newts = 0;
14380         data_string *ds;
14381 -       
14382 +
14383         mod_accesslog_patch_connection(srv, con, p);
14384 -       
14385 +
14386         b = p->conf.access_logbuffer;
14387         if (b->used == 0) {
14388                 buffer_copy_string(b, "");
14389         }
14390 -       
14391 +
14392         for (j = 0; j < p->conf.parsed_format->used; j++) {
14393                 switch(p->conf.parsed_format->ptr[j]->type) {
14394                 case FIELD_STRING:
14395 @@ -636,14 +634,14 @@
14396                 case FIELD_FORMAT:
14397                         switch(p->conf.parsed_format->ptr[j]->field) {
14398                         case FORMAT_TIMESTAMP:
14399 -                               
14400 +
14401                                 /* cache the generated timestamp */
14402                                 if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
14403                                         struct tm tm;
14404  #if defined(HAVE_STRUCT_TM_GMTOFF)
14405                                         long scd, hrs, min;
14406  #endif
14407 -               
14408 +
14409                                         buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
14410  #if defined(HAVE_STRUCT_TM_GMTOFF)
14411  # ifdef HAVE_LOCALTIME_R
14412 @@ -653,17 +651,17 @@
14413                                         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)));
14414  # endif
14415                                         p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14416 -                                       
14417 +
14418                                         buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
14419 -                                       
14420 +
14421                                         scd = abs(tm.tm_gmtoff);
14422                                         hrs = scd / 3600;
14423                                         min = (scd % 3600) / 60;
14424 -                                       
14425 +
14426                                         /* hours */
14427                                         if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14428                                         buffer_append_long(p->conf.ts_accesslog_str, hrs);
14429 -                                       
14430 +
14431                                         if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14432                                         buffer_append_long(p->conf.ts_accesslog_str, min);
14433                                         BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]");
14434 @@ -676,20 +674,20 @@
14435  #endif
14436                                         p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14437  #endif
14438 -                                       
14439 +
14440                                         *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
14441                                         newts = 1;
14442                                 }
14443 -                               
14444 +
14445                                 buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
14446 -                               
14447 +
14448                                 break;
14449                         case FORMAT_REMOTE_HOST:
14450 -       
14451 +
14452                                 /* handle inet_ntop cache */
14453 -       
14454 +
14455                                 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
14456 -                               
14457 +
14458                                 break;
14459                         case FORMAT_REMOTE_IDENT:
14460                                 /* ident */
14461 @@ -710,10 +708,10 @@
14462                         case FORMAT_STATUS:
14463                                 buffer_append_long(b, con->http_status);
14464                                 break;
14465 -       
14466 +
14467                         case FORMAT_BYTES_OUT_NO_HEADER:
14468                                 if (con->bytes_written > 0) {
14469 -                                       buffer_append_off_t(b, 
14470 +                                       buffer_append_off_t(b,
14471                                                             con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
14472                                 } else {
14473                                         BUFFER_APPEND_STRING_CONST(b, "-");
14474 @@ -772,7 +770,7 @@
14475                                 }
14476                                 break;
14477                         case FORMAT_REQUEST_PROTOCOL:
14478 -                               buffer_append_string(b, 
14479 +                               buffer_append_string(b,
14480                                                      con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
14481                                 break;
14482                         case FORMAT_REQUEST_METHOD:
14483 @@ -801,7 +799,7 @@
14484                                  { 'D', FORMAT_TIME_USED_MS },
14485                                  { 'e', FORMAT_ENV },
14486                                  */
14487 -                               
14488 +
14489                                 break;
14490                         }
14491                         break;
14492 @@ -809,7 +807,7 @@
14493                         break;
14494                 }
14495         }
14496 -       
14497 +
14498         BUFFER_APPEND_STRING_CONST(b, "\n");
14499  
14500         if (p->conf.use_syslog ||  /* syslog doesn't cache */
14501 @@ -828,7 +826,7 @@
14502                 }
14503                 buffer_reset(b);
14504         }
14505 -       
14506 +
14507         return HANDLER_GO_ON;
14508  }
14509  
14510 @@ -836,15 +834,15 @@
14511  int mod_accesslog_plugin_init(plugin *p) {
14512         p->version     = LIGHTTPD_VERSION_ID;
14513         p->name        = buffer_init_string("accesslog");
14514 -       
14515 +
14516         p->init        = mod_accesslog_init;
14517         p->set_defaults= log_access_open;
14518         p->cleanup     = mod_accesslog_free;
14519 -       
14520 +
14521         p->handle_request_done  = log_access_write;
14522         p->handle_sighup        = log_access_cycle;
14523 -       
14524 +
14525         p->data        = NULL;
14526 -       
14527 +
14528         return 0;
14529  }
14530 --- ../lighttpd-1.4.11/src/mod_alias.c  2006-03-01 23:18:51.000000000 +0200
14531 +++ lighttpd-1.4.12/src/mod_alias.c     2006-07-11 22:07:51.000000000 +0300
14532 @@ -8,6 +8,7 @@
14533  #include "buffer.h"
14534  
14535  #include "plugin.h"
14536 +#include "sys-strings.h"
14537  
14538  /* plugin config for all request/connections */
14539  typedef struct {
14540 @@ -16,44 +17,44 @@
14541  
14542  typedef struct {
14543         PLUGIN_DATA;
14544 -       
14545 +
14546         plugin_config **config_storage;
14547 -       
14548 -       plugin_config conf; 
14549 +
14550 +       plugin_config conf;
14551  } plugin_data;
14552  
14553  /* init the plugin data */
14554  INIT_FUNC(mod_alias_init) {
14555         plugin_data *p;
14556 -       
14557 +
14558         p = calloc(1, sizeof(*p));
14559 -       
14560 -       
14561 -       
14562 +
14563 +
14564 +
14565         return p;
14566  }
14567  
14568  /* detroy the plugin data */
14569  FREE_FUNC(mod_alias_free) {
14570         plugin_data *p = p_d;
14571 -       
14572 +
14573         if (!p) return HANDLER_GO_ON;
14574 -       
14575 +
14576         if (p->config_storage) {
14577                 size_t i;
14578 -               
14579 +
14580                 for (i = 0; i < srv->config_context->used; i++) {
14581                         plugin_config *s = p->config_storage[i];
14582 -                       
14583 +
14584                         array_free(s->alias);
14585 -                       
14586 +
14587                         free(s);
14588                 }
14589                 free(p->config_storage);
14590         }
14591 -       
14592 +
14593         free(p);
14594 -       
14595 +
14596         return HANDLER_GO_ON;
14597  }
14598  
14599 @@ -62,25 +63,25 @@
14600  SETDEFAULTS_FUNC(mod_alias_set_defaults) {
14601         plugin_data *p = p_d;
14602         size_t i = 0;
14603 -       
14604 -       config_values_t cv[] = { 
14605 +
14606 +       config_values_t cv[] = {
14607                 { "alias.url",                  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
14608                 { NULL,                         NULL, T_CONFIG_UNSET,  T_CONFIG_SCOPE_UNSET }
14609         };
14610 -       
14611 +
14612         if (!p) return HANDLER_ERROR;
14613 -       
14614 +
14615         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14616 -       
14617 +
14618         for (i = 0; i < srv->config_context->used; i++) {
14619                 plugin_config *s;
14620 -               
14621 +
14622                 s = calloc(1, sizeof(plugin_config));
14623 -               s->alias = array_init();        
14624 +               s->alias = array_init();
14625                 cv[0].destination = s->alias;
14626 -               
14627 +
14628                 p->config_storage[i] = s;
14629 -               
14630 +
14631                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14632                         return HANDLER_ERROR;
14633                 }
14634 @@ -110,76 +111,73 @@
14635                         }
14636                 }
14637         }
14638 -       
14639 +
14640         return HANDLER_GO_ON;
14641  }
14642  
14643 -#define PATCH(x) \
14644 -       p->conf.x = s->x;
14645  static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
14646         size_t i, j;
14647         plugin_config *s = p->config_storage[0];
14648 -       
14649 -       PATCH(alias);
14650 -       
14651 +
14652 +       PATCH_OPTION(alias);
14653 +
14654         /* skip the first, the global context */
14655         for (i = 1; i < srv->config_context->used; i++) {
14656                 data_config *dc = (data_config *)srv->config_context->data[i];
14657                 s = p->config_storage[i];
14658 -               
14659 +
14660                 /* condition didn't match */
14661                 if (!config_check_cond(srv, con, dc)) continue;
14662 -               
14663 +
14664                 /* merge config */
14665                 for (j = 0; j < dc->value->used; j++) {
14666                         data_unset *du = dc->value->data[j];
14667 -                       
14668 +
14669                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
14670 -                               PATCH(alias);
14671 +                               PATCH_OPTION(alias);
14672                         }
14673                 }
14674         }
14675 -       
14676 +
14677         return 0;
14678  }
14679 -#undef PATCH
14680  
14681  PHYSICALPATH_FUNC(mod_alias_physical_handler) {
14682         plugin_data *p = p_d;
14683         int uri_len, basedir_len;
14684         char *uri_ptr;
14685         size_t k;
14686 -       
14687 +
14688         if (con->physical.path->used == 0) return HANDLER_GO_ON;
14689 -       
14690 +
14691         mod_alias_patch_connection(srv, con, p);
14692 -       
14693 +
14694         /* not to include the tailing slash */
14695         basedir_len = (con->physical.basedir->used - 1) - 1;
14696         uri_len = con->physical.path->used - 1 - basedir_len;
14697         uri_ptr = con->physical.path->ptr + basedir_len;
14698 -       
14699 +
14700         for (k = 0; k < p->conf.alias->used; k++) {
14701                 data_string *ds = (data_string *)p->conf.alias->data[k];
14702                 int alias_len = ds->key->used - 1;
14703 -               
14704 +
14705                 if (alias_len > uri_len) continue;
14706                 if (ds->key->used == 0) continue;
14707 -               
14708 +
14709                 if (0 == (con->conf.force_lowercase_filenames ?
14710                                         strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
14711                                         strncmp(uri_ptr, ds->key->ptr, alias_len))) {
14712                         /* matched */
14713 -                       
14714 +
14715                         buffer_copy_string_buffer(con->physical.basedir, ds->value);
14716                         buffer_copy_string_buffer(srv->tmp_buf, ds->value);
14717                         buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
14718                         buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
14719 -                       
14720 +
14721                         return HANDLER_GO_ON;
14722                 }
14723         }
14724 -       
14725 +
14726         /* not found */
14727         return HANDLER_GO_ON;
14728  }
14729 @@ -189,13 +187,13 @@
14730  int mod_alias_plugin_init(plugin *p) {
14731         p->version     = LIGHTTPD_VERSION_ID;
14732         p->name        = buffer_init_string("alias");
14733 -       
14734 +
14735         p->init           = mod_alias_init;
14736         p->handle_physical= mod_alias_physical_handler;
14737         p->set_defaults   = mod_alias_set_defaults;
14738         p->cleanup        = mod_alias_free;
14739 -       
14740 +
14741         p->data        = NULL;
14742 -       
14743 +
14744         return 0;
14745  }
14746 --- ../lighttpd-1.4.11/src/mod_auth.c   2006-02-15 20:01:31.000000000 +0200
14747 +++ lighttpd-1.4.12/src/mod_auth.c      2006-07-11 22:07:53.000000000 +0300
14748 @@ -5,168 +5,167 @@
14749  #include <string.h>
14750  #include <errno.h>
14751  #include <fcntl.h>
14752 -#include <unistd.h>
14753  
14754  #include "plugin.h"
14755  #include "http_auth.h"
14756  #include "log.h"
14757  #include "response.h"
14758  
14759 +#include "sys-strings.h"
14760 +#include "sys-files.h"
14761 +
14762  handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
14763  
14764  
14765  /**
14766   * the basic and digest auth framework
14767 - * 
14768 + *
14769   * - config handling
14770   * - protocol handling
14771 - * 
14772 - * http_auth.c 
14773 - * http_auth_digest.c 
14774 - * 
14775 + *
14776 + * http_auth.c
14777 + * http_auth_digest.c
14778 + *
14779   * do the real work
14780   */
14781  
14782  INIT_FUNC(mod_auth_init) {
14783         mod_auth_plugin_data *p;
14784 -       
14785 +
14786         p = calloc(1, sizeof(*p));
14787 -       
14788 +
14789         p->tmp_buf = buffer_init();
14790 -       
14791 +
14792         p->auth_user = buffer_init();
14793  #ifdef USE_LDAP
14794         p->ldap_filter = buffer_init();
14795  #endif
14796 -       
14797 +
14798         return p;
14799  }
14800  
14801  FREE_FUNC(mod_auth_free) {
14802         mod_auth_plugin_data *p = p_d;
14803 -       
14804 +
14805         UNUSED(srv);
14806  
14807         if (!p) return HANDLER_GO_ON;
14808 -       
14809 +
14810         buffer_free(p->tmp_buf);
14811         buffer_free(p->auth_user);
14812  #ifdef USE_LDAP
14813         buffer_free(p->ldap_filter);
14814  #endif
14815 -       
14816 +
14817         if (p->config_storage) {
14818                 size_t i;
14819                 for (i = 0; i < srv->config_context->used; i++) {
14820                         mod_auth_plugin_config *s = p->config_storage[i];
14821 -                       
14822 +
14823                         if (!s) continue;
14824 -                       
14825 +
14826                         array_free(s->auth_require);
14827                         buffer_free(s->auth_plain_groupfile);
14828                         buffer_free(s->auth_plain_userfile);
14829                         buffer_free(s->auth_htdigest_userfile);
14830                         buffer_free(s->auth_htpasswd_userfile);
14831                         buffer_free(s->auth_backend_conf);
14832 -                       
14833 +
14834                         buffer_free(s->auth_ldap_hostname);
14835                         buffer_free(s->auth_ldap_basedn);
14836                         buffer_free(s->auth_ldap_binddn);
14837                         buffer_free(s->auth_ldap_bindpw);
14838                         buffer_free(s->auth_ldap_filter);
14839                         buffer_free(s->auth_ldap_cafile);
14840 -                       
14841 +
14842  #ifdef USE_LDAP
14843                         buffer_free(s->ldap_filter_pre);
14844                         buffer_free(s->ldap_filter_post);
14845 -                       
14846 +
14847                         if (s->ldap) ldap_unbind_s(s->ldap);
14848  #endif
14849 -                       
14850 +
14851                         free(s);
14852                 }
14853                 free(p->config_storage);
14854         }
14855 -       
14856 +
14857         free(p);
14858 -       
14859 +
14860         return HANDLER_GO_ON;
14861  }
14862  
14863 -#define PATCH(x) \
14864 -       p->conf.x = s->x;
14865  static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
14866         size_t i, j;
14867         mod_auth_plugin_config *s = p->config_storage[0];
14868  
14869 -       PATCH(auth_backend);
14870 -       PATCH(auth_plain_groupfile);
14871 -       PATCH(auth_plain_userfile);
14872 -       PATCH(auth_htdigest_userfile);
14873 -       PATCH(auth_htpasswd_userfile);
14874 -       PATCH(auth_require);
14875 -       PATCH(auth_debug);
14876 -       PATCH(auth_ldap_hostname);
14877 -       PATCH(auth_ldap_basedn);
14878 -       PATCH(auth_ldap_binddn);
14879 -       PATCH(auth_ldap_bindpw);
14880 -       PATCH(auth_ldap_filter);
14881 -       PATCH(auth_ldap_cafile);
14882 -       PATCH(auth_ldap_starttls);
14883 +       PATCH_OPTION(auth_backend);
14884 +       PATCH_OPTION(auth_plain_groupfile);
14885 +       PATCH_OPTION(auth_plain_userfile);
14886 +       PATCH_OPTION(auth_htdigest_userfile);
14887 +       PATCH_OPTION(auth_htpasswd_userfile);
14888 +       PATCH_OPTION(auth_require);
14889 +       PATCH_OPTION(auth_debug);
14890 +       PATCH_OPTION(auth_ldap_hostname);
14891 +       PATCH_OPTION(auth_ldap_basedn);
14892 +       PATCH_OPTION(auth_ldap_binddn);
14893 +       PATCH_OPTION(auth_ldap_bindpw);
14894 +       PATCH_OPTION(auth_ldap_filter);
14895 +       PATCH_OPTION(auth_ldap_cafile);
14896 +       PATCH_OPTION(auth_ldap_starttls);
14897  #ifdef USE_LDAP
14898 -       PATCH(ldap);
14899 -       PATCH(ldap_filter_pre);
14900 -       PATCH(ldap_filter_post);
14901 +       PATCH_OPTION(ldap);
14902 +       PATCH_OPTION(ldap_filter_pre);
14903 +       PATCH_OPTION(ldap_filter_post);
14904  #endif
14905 -       
14906 +
14907         /* skip the first, the global context */
14908         for (i = 1; i < srv->config_context->used; i++) {
14909                 data_config *dc = (data_config *)srv->config_context->data[i];
14910                 s = p->config_storage[i];
14911 -               
14912 +
14913                 /* condition didn't match */
14914                 if (!config_check_cond(srv, con, dc)) continue;
14915 -               
14916 +
14917                 /* merge config */
14918                 for (j = 0; j < dc->value->used; j++) {
14919                         data_unset *du = dc->value->data[j];
14920 -                       
14921 +
14922                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
14923 -                               PATCH(auth_backend);
14924 +                               PATCH_OPTION(auth_backend);
14925                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
14926 -                               PATCH(auth_plain_groupfile);
14927 +                               PATCH_OPTION(auth_plain_groupfile);
14928                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
14929 -                               PATCH(auth_plain_userfile);
14930 +                               PATCH_OPTION(auth_plain_userfile);
14931                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
14932 -                               PATCH(auth_htdigest_userfile);
14933 +                               PATCH_OPTION(auth_htdigest_userfile);
14934                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
14935 -                               PATCH(auth_htpasswd_userfile);
14936 +                               PATCH_OPTION(auth_htpasswd_userfile);
14937                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
14938 -                               PATCH(auth_require);
14939 +                               PATCH_OPTION(auth_require);
14940                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
14941 -                               PATCH(auth_debug);
14942 +                               PATCH_OPTION(auth_debug);
14943                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
14944 -                               PATCH(auth_ldap_hostname);
14945 +                               PATCH_OPTION(auth_ldap_hostname);
14946  #ifdef USE_LDAP
14947 -                               PATCH(ldap);
14948 -                               PATCH(ldap_filter_pre);
14949 -                               PATCH(ldap_filter_post);
14950 +                               PATCH_OPTION(ldap);
14951 +                               PATCH_OPTION(ldap_filter_pre);
14952 +                               PATCH_OPTION(ldap_filter_post);
14953  #endif
14954                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
14955 -                               PATCH(auth_ldap_basedn);
14956 +                               PATCH_OPTION(auth_ldap_basedn);
14957                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
14958 -                               PATCH(auth_ldap_filter);
14959 +                               PATCH_OPTION(auth_ldap_filter);
14960                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
14961 -                               PATCH(auth_ldap_cafile);
14962 +                               PATCH_OPTION(auth_ldap_cafile);
14963                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
14964 -                               PATCH(auth_ldap_starttls);
14965 +                               PATCH_OPTION(auth_ldap_starttls);
14966                         }
14967                 }
14968         }
14969 -       
14970 +
14971         return 0;
14972  }
14973 -#undef PATCH
14974  
14975  static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
14976         size_t k;
14977 @@ -175,22 +174,22 @@
14978         data_string *ds;
14979         mod_auth_plugin_data *p = p_d;
14980         array *req;
14981 -       
14982 +
14983         /* select the right config */
14984         mod_auth_patch_connection(srv, con, p);
14985 -       
14986 +
14987         if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
14988 -       
14989 +
14990         /*
14991          * AUTH
14992 -        *  
14993 +        *
14994          */
14995 -       
14996 +
14997         /* do we have to ask for auth ? */
14998 -       
14999 +
15000         auth_required = 0;
15001         auth_satisfied = 0;
15002 -       
15003 +
15004         /* search auth-directives for path */
15005         for (k = 0; k < p->conf.auth_require->used; k++) {
15006                 buffer *req = p->conf.auth_require->data[k]->key;
15007 @@ -212,31 +211,31 @@
15008                         }
15009                 }
15010         }
15011 -       
15012 +
15013         /* nothing to do for us */
15014         if (auth_required == 0) return HANDLER_GO_ON;
15015 -       
15016 +
15017         req = ((data_array *)(p->conf.auth_require->data[k]))->value;
15018 -       
15019 +
15020         /* try to get Authorization-header */
15021 -               
15022 +
15023         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
15024                 http_authorization = ds->value->ptr;
15025         }
15026 -       
15027 +
15028         if (ds && ds->value && ds->value->used) {
15029                 char *auth_realm;
15030                 data_string *method;
15031 -               
15032 +
15033                 method = (data_string *)array_get_element(req, "method");
15034 -               
15035 +
15036                 /* parse auth-header */
15037                 if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
15038                         int auth_type_len = auth_realm - http_authorization;
15039 -                       
15040 +
15041                         if ((auth_type_len == 5) &&
15042                             (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
15043 -                               
15044 +
15045                                 if (0 == strcmp(method->value->ptr, "basic")) {
15046                                         auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
15047                                 }
15048 @@ -245,43 +244,43 @@
15049                                 if (0 == strcmp(method->value->ptr, "digest")) {
15050                                         if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
15051                                                 con->http_status = 400;
15052 -                                               
15053 +
15054                                                 /* a field was missing */
15055 -                                               
15056 +
15057                                                 return HANDLER_FINISHED;
15058                                         }
15059                                 }
15060                         } else {
15061 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15062 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15063                                                 "unknown authentification type:",
15064                                                 http_authorization);
15065                         }
15066                 }
15067         }
15068 -       
15069 +
15070         if (!auth_satisfied) {
15071                 data_string *method, *realm;
15072                 method = (data_string *)array_get_element(req, "method");
15073                 realm = (data_string *)array_get_element(req, "realm");
15074 -               
15075 +
15076                 con->http_status = 401;
15077 -                       
15078 +
15079                 if (0 == strcmp(method->value->ptr, "basic")) {
15080                         buffer_copy_string(p->tmp_buf, "Basic realm=\"");
15081                         buffer_append_string_buffer(p->tmp_buf, realm->value);
15082                         buffer_append_string(p->tmp_buf, "\"");
15083 -                       
15084 +
15085                         response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15086                 } else if (0 == strcmp(method->value->ptr, "digest")) {
15087                         char hh[33];
15088                         http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
15089 -                       
15090 +
15091                         buffer_copy_string(p->tmp_buf, "Digest realm=\"");
15092                         buffer_append_string_buffer(p->tmp_buf, realm->value);
15093                         buffer_append_string(p->tmp_buf, "\", nonce=\"");
15094                         buffer_append_string(p->tmp_buf, hh);
15095                         buffer_append_string(p->tmp_buf, "\", qop=\"auth\"");
15096 -                       
15097 +
15098                         response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15099                 } else {
15100                         /* evil */
15101 @@ -289,18 +288,18 @@
15102                 return HANDLER_FINISHED;
15103         } else {
15104                 /* the REMOTE_USER header */
15105 -               
15106 +
15107                 buffer_copy_string_buffer(con->authed_user, p->auth_user);
15108         }
15109 -       
15110 +
15111         return HANDLER_GO_ON;
15112  }
15113  
15114  SETDEFAULTS_FUNC(mod_auth_set_defaults) {
15115         mod_auth_plugin_data *p = p_d;
15116         size_t i;
15117 -       
15118 -       config_values_t cv[] = { 
15119 +
15120 +       config_values_t cv[] = {
15121                 { "auth.backend",                   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15122                 { "auth.backend.plain.groupfile",   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15123                 { "auth.backend.plain.userfile",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15124 @@ -317,7 +316,7 @@
15125                 { "auth.debug",                     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },  /* 13 */
15126                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
15127         };
15128 -       
15129 +
15130         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15131  
15132         for (i = 0; i < srv->config_context->used; i++) {
15133 @@ -325,14 +324,14 @@
15134                 size_t n;
15135                 data_array *da;
15136                 array *ca;
15137 -               
15138 +
15139                 s = calloc(1, sizeof(mod_auth_plugin_config));
15140                 s->auth_plain_groupfile = buffer_init();
15141                 s->auth_plain_userfile = buffer_init();
15142                 s->auth_htdigest_userfile = buffer_init();
15143                 s->auth_htpasswd_userfile = buffer_init();
15144                 s->auth_backend_conf = buffer_init();
15145 -               
15146 +
15147                 s->auth_ldap_hostname = buffer_init();
15148                 s->auth_ldap_basedn = buffer_init();
15149                 s->auth_ldap_binddn = buffer_init();
15150 @@ -341,15 +340,15 @@
15151                 s->auth_ldap_cafile = buffer_init();
15152                 s->auth_ldap_starttls = 0;
15153                 s->auth_debug = 0;
15154 -               
15155 +
15156                 s->auth_require = array_init();
15157 -               
15158 +
15159  #ifdef USE_LDAP
15160                 s->ldap_filter_pre = buffer_init();
15161                 s->ldap_filter_post = buffer_init();
15162                 s->ldap = NULL;
15163  #endif
15164 -       
15165 +
15166                 cv[0].destination = s->auth_backend_conf;
15167                 cv[1].destination = s->auth_plain_groupfile;
15168                 cv[2].destination = s->auth_plain_userfile;
15169 @@ -364,14 +363,14 @@
15170                 cv[11].destination = s->auth_htdigest_userfile;
15171                 cv[12].destination = s->auth_htpasswd_userfile;
15172                 cv[13].destination = &(s->auth_debug);
15173 -               
15174 +
15175                 p->config_storage[i] = s;
15176                 ca = ((data_config *)srv->config_context->data[i])->value;
15177 -               
15178 +
15179                 if (0 != config_insert_values_global(srv, ca, cv)) {
15180                         return HANDLER_ERROR;
15181                 }
15182 -               
15183 +
15184                 if (s->auth_backend_conf->used) {
15185                         if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
15186                                 s->auth_backend = AUTH_BACKEND_HTPASSWD;
15187 @@ -383,31 +382,31 @@
15188                                 s->auth_backend = AUTH_BACKEND_LDAP;
15189                         } else {
15190                                 log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
15191 -                               
15192 +
15193                                 return HANDLER_ERROR;
15194                         }
15195                 }
15196  
15197                 /* no auth.require for this section */
15198                 if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
15199 -               
15200 +
15201                 if (da->type != TYPE_ARRAY) continue;
15202 -               
15203 +
15204                 for (n = 0; n < da->value->used; n++) {
15205                         size_t m;
15206                         data_array *da_file = (data_array *)da->value->data[n];
15207                         const char *method, *realm, *require;
15208 -                       
15209 +
15210                         if (da->value->data[n]->type != TYPE_ARRAY) {
15211 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15212 -                                               "auth.require should contain an array as in:", 
15213 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15214 +                                               "auth.require should contain an array as in:",
15215                                                 "auth.require = ( \"...\" => ( ..., ...) )");
15216  
15217                                 return HANDLER_ERROR;
15218                         }
15219 -                                       
15220 +
15221                         method = realm = require = NULL;
15222 -                                       
15223 +
15224                         for (m = 0; m < da_file->value->used; m++) {
15225                                 if (da_file->value->data[m]->type == TYPE_STRING) {
15226                                         if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
15227 @@ -417,8 +416,8 @@
15228                                         } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
15229                                                 require = ((data_string *)(da_file->value->data[m]))->value->ptr;
15230                                         } else {
15231 -                                               log_error_write(srv, __FILE__, __LINE__, "ssbs", 
15232 -                                                       "the field is unknown in:", 
15233 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbs",
15234 +                                                       "the field is unknown in:",
15235                                                         "auth.require = ( \"...\" => ( ..., -> \"",
15236                                                         da_file->value->data[m]->key,
15237                                                         "\" <- => \"...\" ) )");
15238 @@ -426,19 +425,19 @@
15239                                                 return HANDLER_ERROR;
15240                                         }
15241                                 } else {
15242 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbs", 
15243 -                                               "a string was expected for:", 
15244 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbs",
15245 +                                               "a string was expected for:",
15246                                                 "auth.require = ( \"...\" => ( ..., -> \"",
15247                                                 da_file->value->data[m]->key,
15248                                                 "\" <- => \"...\" ) )");
15249 -                                       
15250 +
15251                                         return HANDLER_ERROR;
15252                                 }
15253                         }
15254 -                                       
15255 +
15256                         if (method == NULL) {
15257 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15258 -                                               "the require field is missing in:", 
15259 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15260 +                                               "the require field is missing in:",
15261                                                 "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
15262                                 return HANDLER_ERROR;
15263                         } else {
15264 @@ -450,60 +449,60 @@
15265                                         return HANDLER_ERROR;
15266                                 }
15267                         }
15268 -                       
15269 +
15270                         if (realm == NULL) {
15271 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15272 -                                               "the require field is missing in:", 
15273 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15274 +                                               "the require field is missing in:",
15275                                                 "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
15276                                 return HANDLER_ERROR;
15277                         }
15278 -                       
15279 +
15280                         if (require == NULL) {
15281 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15282 -                                               "the require field is missing in:", 
15283 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15284 +                                               "the require field is missing in:",
15285                                                 "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
15286                                 return HANDLER_ERROR;
15287                         }
15288 -                       
15289 +
15290                         if (method && realm && require) {
15291                                 data_string *ds;
15292                                 data_array *a;
15293 -                               
15294 +
15295                                 a = data_array_init();
15296                                 buffer_copy_string_buffer(a->key, da_file->key);
15297 -                               
15298 +
15299                                 ds = data_string_init();
15300 -                               
15301 +
15302                                 buffer_copy_string(ds->key, "method");
15303                                 buffer_copy_string(ds->value, method);
15304 -                               
15305 +
15306                                 array_insert_unique(a->value, (data_unset *)ds);
15307 -                               
15308 +
15309                                 ds = data_string_init();
15310 -                               
15311 +
15312                                 buffer_copy_string(ds->key, "realm");
15313                                 buffer_copy_string(ds->value, realm);
15314 -                               
15315 +
15316                                 array_insert_unique(a->value, (data_unset *)ds);
15317 -                               
15318 +
15319                                 ds = data_string_init();
15320 -                               
15321 +
15322                                 buffer_copy_string(ds->key, "require");
15323                                 buffer_copy_string(ds->value, require);
15324 -                               
15325 +
15326                                 array_insert_unique(a->value, (data_unset *)ds);
15327 -                               
15328 +
15329                                 array_insert_unique(s->auth_require, (data_unset *)a);
15330                         }
15331                 }
15332 -       
15333 +
15334                 switch(s->auth_backend) {
15335                 case AUTH_BACKEND_PLAIN:
15336                         if (s->auth_plain_userfile->used) {
15337                                 int fd;
15338                                 /* try to read */
15339                                 if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) {
15340 -                                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
15341 +                                       log_error_write(srv, __FILE__, __LINE__, "sbss",
15342                                                         "opening auth.backend.plain.userfile:", s->auth_plain_userfile,
15343                                                         "failed:", strerror(errno));
15344                                         return HANDLER_ERROR;
15345 @@ -516,7 +515,7 @@
15346                                 int fd;
15347                                 /* try to read */
15348                                 if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) {
15349 -                                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
15350 +                                       log_error_write(srv, __FILE__, __LINE__, "sbss",
15351                                                         "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile,
15352                                                         "failed:", strerror(errno));
15353                                         return HANDLER_ERROR;
15354 @@ -529,7 +528,7 @@
15355                                 int fd;
15356                                 /* try to read */
15357                                 if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) {
15358 -                                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
15359 +                                       log_error_write(srv, __FILE__, __LINE__, "sbss",
15360                                                         "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile,
15361                                                         "failed:", strerror(errno));
15362                                         return HANDLER_ERROR;
15363 @@ -554,75 +553,75 @@
15364  handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
15365  #ifdef USE_LDAP
15366                         int ret;
15367 -#if 0                  
15368 +#if 0
15369                         if (s->auth_ldap_basedn->used == 0) {
15370                                 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
15371 -                               
15372 +
15373                                 return HANDLER_ERROR;
15374                         }
15375  #endif
15376 -                       
15377 +
15378                         if (s->auth_ldap_filter->used) {
15379                                 char *dollar;
15380 -                               
15381 +
15382                                 /* parse filter */
15383 -                       
15384 +
15385                                 if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
15386                                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
15387 -                                       
15388 +
15389                                         return HANDLER_ERROR;
15390                                 }
15391 -                               
15392 +
15393                                 buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
15394                                 buffer_copy_string(s->ldap_filter_post, dollar+1);
15395                         }
15396 -                       
15397 +
15398                         if (s->auth_ldap_hostname->used) {
15399                                 if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
15400                                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
15401 -                                       
15402 +
15403                                         return HANDLER_ERROR;
15404                                 }
15405 -                               
15406 +
15407                                 ret = LDAP_VERSION3;
15408                                 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
15409                                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15410 -                               
15411 +
15412                                         return HANDLER_ERROR;
15413                                 }
15414  
15415                                 if (s->auth_ldap_starttls) {
15416 -                                       /* if no CA file is given, it is ok, as we will use encryption 
15417 +                                       /* if no CA file is given, it is ok, as we will use encryption
15418                                          * if the server requires a CAfile it will tell us */
15419                                         if (!buffer_is_empty(s->auth_ldap_cafile)) {
15420 -                                               if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, 
15421 +                                               if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
15422                                                                                 s->auth_ldap_cafile->ptr))) {
15423 -                                                       log_error_write(srv, __FILE__, __LINE__, "ss", 
15424 +                                                       log_error_write(srv, __FILE__, __LINE__, "ss",
15425                                                                         "Loading CA certificate failed:", ldap_err2string(ret));
15426 -                                               
15427 +
15428                                                         return HANDLER_ERROR;
15429                                                 }
15430                                         }
15431 -       
15432 +
15433                                         if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL,  NULL))) {
15434                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
15435 -                                               
15436 +
15437                                                 return HANDLER_ERROR;
15438                                         }
15439                                 }
15440 -                               
15441 -                               
15442 +
15443 +
15444                                 /* 1. */
15445                                 if (s->auth_ldap_binddn->used) {
15446                                         if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
15447                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15448 -                                               
15449 +
15450                                                 return HANDLER_ERROR;
15451                                         }
15452                                 } else {
15453                                         if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
15454                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15455 -                                               
15456 +
15457                                                 return HANDLER_ERROR;
15458                                         }
15459                                 }
15460 @@ -641,8 +640,8 @@
15461         p->set_defaults = mod_auth_set_defaults;
15462         p->handle_uri_clean = mod_auth_uri_handler;
15463         p->cleanup     = mod_auth_free;
15464 -       
15465 +
15466         p->data        = NULL;
15467 -       
15468 +
15469         return 0;
15470  }
15471 --- ../lighttpd-1.4.11/src/mod_cgi.c    2006-02-22 15:15:10.000000000 +0200
15472 +++ lighttpd-1.4.12/src/mod_cgi.c       2006-07-11 22:07:51.000000000 +0300
15473 @@ -1,21 +1,8 @@
15474  #include <sys/types.h>
15475 -#ifdef __WIN32
15476 -#include <winsock2.h>
15477 -#else
15478 -#include <sys/socket.h>
15479 -#include <sys/wait.h>
15480 -#include <sys/mman.h>
15481 -
15482 -#include <netinet/in.h>
15483 -
15484 -#include <arpa/inet.h>
15485 -#endif
15486  
15487 -#include <unistd.h>
15488  #include <errno.h>
15489  #include <stdlib.h>
15490  #include <string.h>
15491 -#include <fdevent.h>
15492  #include <signal.h>
15493  #include <ctype.h>
15494  #include <assert.h>
15495 @@ -29,9 +16,16 @@
15496  #include "connections.h"
15497  #include "joblist.h"
15498  #include "http_chunk.h"
15499 +#include "fdevent.h"
15500  
15501  #include "plugin.h"
15502  
15503 +#include "sys-files.h"
15504 +#include "sys-mmap.h"
15505 +#include "sys-socket.h"
15506 +#include "sys-strings.h"
15507 +#include "sys-process.h"
15508 +
15509  #ifdef HAVE_SYS_FILIO_H
15510  # include <sys/filio.h>
15511  #endif
15512 @@ -40,11 +34,12 @@
15513  
15514  typedef struct {
15515         char **ptr;
15516 -       
15517 +
15518         size_t size;
15519         size_t used;
15520  } char_array;
15521  
15522 +#define pid_t int
15523  typedef struct {
15524         pid_t *ptr;
15525         size_t used;
15526 @@ -58,23 +53,23 @@
15527  typedef struct {
15528         PLUGIN_DATA;
15529         buffer_pid_t cgi_pid;
15530 -       
15531 +
15532         buffer *tmp_buf;
15533         buffer *parse_response;
15534 -       
15535 +
15536         plugin_config **config_storage;
15537 -       
15538 -       plugin_config conf; 
15539 +
15540 +       plugin_config conf;
15541  } plugin_data;
15542  
15543  typedef struct {
15544         pid_t pid;
15545         int fd;
15546         int fde_ndx; /* index into the fd-event buffer */
15547 -       
15548 +
15549         connection *remote_conn;  /* dumb pointer */
15550         plugin_data *plugin_data; /* dumb pointer */
15551 -       
15552 +
15553         buffer *response;
15554         buffer *response_header;
15555  } handler_ctx;
15556 @@ -83,17 +78,17 @@
15557         handler_ctx *hctx = calloc(1, sizeof(*hctx));
15558  
15559         assert(hctx);
15560 -       
15561 +
15562         hctx->response = buffer_init();
15563         hctx->response_header = buffer_init();
15564 -       
15565 +
15566         return hctx;
15567  }
15568  
15569  static void cgi_handler_ctx_free(handler_ctx *hctx) {
15570         buffer_free(hctx->response);
15571         buffer_free(hctx->response_header);
15572 -       
15573 +
15574         free(hctx);
15575  }
15576  
15577 @@ -101,14 +96,14 @@
15578  
15579  INIT_FUNC(mod_cgi_init) {
15580         plugin_data *p;
15581 -       
15582 +
15583         p = calloc(1, sizeof(*p));
15584  
15585         assert(p);
15586 -       
15587 +
15588         p->tmp_buf = buffer_init();
15589         p->parse_response = buffer_init();
15590 -       
15591 +
15592         return p;
15593  }
15594  
15595 @@ -116,62 +111,62 @@
15596  FREE_FUNC(mod_cgi_free) {
15597         plugin_data *p = p_d;
15598         buffer_pid_t *r = &(p->cgi_pid);
15599 -       
15600 +
15601         UNUSED(srv);
15602 -       
15603 +
15604         if (p->config_storage) {
15605                 size_t i;
15606                 for (i = 0; i < srv->config_context->used; i++) {
15607                         plugin_config *s = p->config_storage[i];
15608 -                       
15609 +
15610                         array_free(s->cgi);
15611 -                       
15612 +
15613                         free(s);
15614                 }
15615                 free(p->config_storage);
15616         }
15617 -       
15618 +
15619  
15620         if (r->ptr) free(r->ptr);
15621 -       
15622 +
15623         buffer_free(p->tmp_buf);
15624         buffer_free(p->parse_response);
15625 -       
15626 +
15627         free(p);
15628 -       
15629 +
15630         return HANDLER_GO_ON;
15631  }
15632  
15633  SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
15634         plugin_data *p = p_d;
15635         size_t i = 0;
15636 -       
15637 -       config_values_t cv[] = { 
15638 +
15639 +       config_values_t cv[] = {
15640                 { "cgi.assign",                  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
15641                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
15642         };
15643  
15644         if (!p) return HANDLER_ERROR;
15645 -       
15646 +
15647         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15648 -       
15649 +
15650         for (i = 0; i < srv->config_context->used; i++) {
15651                 plugin_config *s;
15652 -               
15653 +
15654                 s = calloc(1, sizeof(plugin_config));
15655                 assert(s);
15656 -               
15657 +
15658                 s->cgi    = array_init();
15659 -               
15660 +
15661                 cv[0].destination = s->cgi;
15662 -               
15663 +
15664                 p->config_storage[i] = s;
15665 -       
15666 +
15667                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
15668                         return HANDLER_ERROR;
15669                 }
15670         }
15671 -       
15672 +
15673         return HANDLER_GO_ON;
15674  }
15675  
15676 @@ -180,13 +175,13 @@
15677         int m = -1;
15678         size_t i;
15679         buffer_pid_t *r = &(p->cgi_pid);
15680 -       
15681 +
15682         UNUSED(srv);
15683  
15684         for (i = 0; i < r->used; i++) {
15685                 if (r->ptr[i] > m) m = r->ptr[i];
15686         }
15687 -       
15688 +
15689         if (r->size == 0) {
15690                 r->size = 16;
15691                 r->ptr = malloc(sizeof(*r->ptr) * r->size);
15692 @@ -194,31 +189,31 @@
15693                 r->size += 16;
15694                 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
15695         }
15696 -       
15697 +
15698         r->ptr[r->used++] = pid;
15699 -       
15700 +
15701         return m;
15702  }
15703  
15704  static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
15705         size_t i;
15706         buffer_pid_t *r = &(p->cgi_pid);
15707 -       
15708 +
15709         UNUSED(srv);
15710  
15711         for (i = 0; i < r->used; i++) {
15712                 if (r->ptr[i] == pid) break;
15713         }
15714 -       
15715 +
15716         if (i != r->used) {
15717                 /* found */
15718 -               
15719 +
15720                 if (i != r->used - 1) {
15721                         r->ptr[i] = r->ptr[r->used - 1];
15722                 }
15723                 r->used--;
15724         }
15725 -       
15726 +
15727         return 0;
15728  }
15729  
15730 @@ -226,32 +221,32 @@
15731         char *ns;
15732         const char *s;
15733         int line = 0;
15734 -       
15735 +
15736         UNUSED(srv);
15737 -       
15738 +
15739         buffer_copy_string_buffer(p->parse_response, in);
15740 -       
15741 -       for (s = p->parse_response->ptr; 
15742 -            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); 
15743 +
15744 +       for (s = p->parse_response->ptr;
15745 +            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
15746              s = ns + (eol == EOL_RN ? 2 : 1), line++) {
15747                 const char *key, *value;
15748                 int key_len;
15749                 data_string *ds;
15750 -               
15751 +
15752                 ns[0] = '\0';
15753 -               
15754 -               if (line == 0 && 
15755 +
15756 +               if (line == 0 &&
15757                     0 == strncmp(s, "HTTP/1.", 7)) {
15758                         /* non-parsed header ... we parse them anyway */
15759 -                       
15760 +
15761                         if ((s[7] == '1' ||
15762                              s[7] == '0') &&
15763                             s[8] == ' ') {
15764                                 int status;
15765                                 /* after the space should be a status code for us */
15766 -                               
15767 +
15768                                 status = strtol(s+9, NULL, 10);
15769 -                               
15770 +
15771                                 if (con->http_status >= 100 &&
15772                                     con->http_status < 1000) {
15773                                         /* we expected 3 digits and didn't got them */
15774 @@ -260,27 +255,27 @@
15775                                 }
15776                         }
15777                 } else {
15778 -               
15779 +
15780                         key = s;
15781                         if (NULL == (value = strchr(s, ':'))) {
15782                                 /* we expect: "<key>: <value>\r\n" */
15783                                 continue;
15784                         }
15785 -                       
15786 +
15787                         key_len = value - key;
15788                         value += 1;
15789 -                       
15790 +
15791                         /* skip LWS */
15792                         while (*value == ' ' || *value == '\t') value++;
15793 -                       
15794 +
15795                         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
15796                                 ds = data_response_init();
15797                         }
15798                         buffer_copy_string_len(ds->key, key, key_len);
15799                         buffer_copy_string(ds->value, value);
15800 -                       
15801 +
15802                         array_insert_unique(con->response.headers, (data_unset *)ds);
15803 -                       
15804 +
15805                         switch(key_len) {
15806                         case 4:
15807                                 if (0 == strncasecmp(key, "Date", key_len)) {
15808 @@ -315,13 +310,13 @@
15809                         }
15810                 }
15811         }
15812 -       
15813 +
15814         /* CGI/1.1 rev 03 - 7.2.1.2 */
15815         if ((con->parsed_response & HTTP_LOCATION) &&
15816             !(con->parsed_response & HTTP_STATUS)) {
15817                 con->http_status = 302;
15818         }
15819 -       
15820 +
15821         return 0;
15822  }
15823  
15824 @@ -329,10 +324,10 @@
15825  static int cgi_demux_response(server *srv, handler_ctx *hctx) {
15826         plugin_data *p    = hctx->plugin_data;
15827         connection  *con  = hctx->remote_conn;
15828 -       
15829 +
15830         while(1) {
15831                 int n;
15832 -               
15833 +
15834                 buffer_prepare_copy(hctx->response, 1024);
15835                 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
15836                         if (errno == EAGAIN || errno == EINTR) {
15837 @@ -343,125 +338,125 @@
15838                         log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
15839                         return FDEVENT_HANDLED_ERROR;
15840                 }
15841 -               
15842 +
15843                 if (n == 0) {
15844                         /* read finished */
15845 -                       
15846 +
15847                         con->file_finished = 1;
15848 -                       
15849 +
15850                         /* send final chunk */
15851                         http_chunk_append_mem(srv, con, NULL, 0);
15852                         joblist_append(srv, con);
15853 -                       
15854 +
15855                         return FDEVENT_HANDLED_FINISHED;
15856                 }
15857 -               
15858 +
15859                 hctx->response->ptr[n] = '\0';
15860                 hctx->response->used = n+1;
15861 -               
15862 +
15863                 /* split header from body */
15864 -               
15865 +
15866                 if (con->file_started == 0) {
15867                         char *c;
15868                         int in_header = 0;
15869                         int header_end = 0;
15870                         int cp, eol = EOL_UNSET;
15871                         size_t used = 0;
15872 -                       
15873 +
15874                         buffer_append_string_buffer(hctx->response_header, hctx->response);
15875 -                       
15876 +
15877                         /* nph (non-parsed headers) */
15878                         if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
15879 -                       
15880 +
15881                         /* search for the \r\n\r\n or \n\n in the string */
15882                         for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
15883                                 if (*c == ':') in_header = 1;
15884                                 else if (*c == '\n') {
15885                                         if (in_header == 0) {
15886                                                 /* got a response without a response header */
15887 -                                               
15888 +
15889                                                 c = NULL;
15890                                                 header_end = 1;
15891                                                 break;
15892                                         }
15893 -                                       
15894 +
15895                                         if (eol == EOL_UNSET) eol = EOL_N;
15896 -                                       
15897 +
15898                                         if (*(c+1) == '\n') {
15899                                                 header_end = 1;
15900                                                 break;
15901                                         }
15902 -                                       
15903 +
15904                                 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
15905                                         if (in_header == 0) {
15906                                                 /* got a response without a response header */
15907 -                                               
15908 +
15909                                                 c = NULL;
15910                                                 header_end = 1;
15911                                                 break;
15912                                         }
15913 -                                       
15914 +
15915                                         if (eol == EOL_UNSET) eol = EOL_RN;
15916 -                                       
15917 +
15918                                         if (used > 3 &&
15919 -                                           *(c+2) == '\r' && 
15920 +                                           *(c+2) == '\r' &&
15921                                             *(c+3) == '\n') {
15922                                                 header_end = 1;
15923                                                 break;
15924                                         }
15925 -                                       
15926 +
15927                                         /* skip the \n */
15928                                         c++;
15929                                         cp++;
15930                                         used--;
15931                                 }
15932                         }
15933 -                       
15934 +
15935                         if (header_end) {
15936                                 if (c == NULL) {
15937                                         /* no header, but a body */
15938 -                                       
15939 +
15940                                         if (con->request.http_version == HTTP_VERSION_1_1) {
15941                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
15942                                         }
15943 -                                       
15944 +
15945                                         http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
15946                                         joblist_append(srv, con);
15947                                 } else {
15948                                         size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
15949                                         size_t blen = hctx->response_header->used - hlen - 1;
15950 -                               
15951 +
15952                                         /* a small hack: terminate after at the second \r */
15953                                         hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
15954                                         hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
15955 -                               
15956 +
15957                                         /* parse the response header */
15958                                         cgi_response_parse(srv, con, p, hctx->response_header, eol);
15959 -                                       
15960 +
15961                                         /* enable chunked-transfer-encoding */
15962                                         if (con->request.http_version == HTTP_VERSION_1_1 &&
15963                                             !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
15964                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
15965                                         }
15966 -                                       
15967 +
15968                                         if ((hctx->response->used != hlen) && blen > 0) {
15969                                                 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
15970                                                 joblist_append(srv, con);
15971                                         }
15972                                 }
15973 -                               
15974 +
15975                                 con->file_started = 1;
15976                         }
15977                 } else {
15978                         http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
15979                         joblist_append(srv, con);
15980                 }
15981 -               
15982 -#if 0          
15983 +
15984 +#if 0
15985                 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
15986  #endif
15987         }
15988 -       
15989 +
15990         return FDEVENT_HANDLED_NOT_FINISHED;
15991  }
15992  
15993 @@ -470,45 +465,46 @@
15994         pid_t pid;
15995         plugin_data *p;
15996         connection  *con;
15997 -       
15998 +
15999         if (NULL == hctx) return HANDLER_GO_ON;
16000 -       
16001 +
16002         p    = hctx->plugin_data;
16003         con  = hctx->remote_conn;
16004 -       
16005 +
16006         if (con->mode != p->id) return HANDLER_GO_ON;
16007  
16008 -#ifndef __WIN32
16009 -       
16010 +#ifndef _WIN32
16011 +
16012         /* the connection to the browser went away, but we still have a connection
16013 -        * to the CGI script 
16014 +        * to the CGI script
16015          *
16016          * close cgi-connection
16017          */
16018 -       
16019 +
16020         if (hctx->fd != -1) {
16021                 /* close connection to the cgi-script */
16022                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16023                 fdevent_unregister(srv->ev, hctx->fd);
16024 -               
16025 +
16026                 if (close(hctx->fd)) {
16027                         log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16028                 }
16029 -               
16030 +
16031                 hctx->fd = -1;
16032                 hctx->fde_ndx = -1;
16033         }
16034 -       
16035 +
16036         pid = hctx->pid;
16037 -       
16038 +
16039         con->plugin_ctx[p->id] = NULL;
16040 -       
16041 +
16042         /* is this a good idea ? */
16043         cgi_handler_ctx_free(hctx);
16044 -       
16045 +
16046         /* if waitpid hasn't been called by response.c yet, do it here */
16047         if (pid) {
16048                 /* check if the CGI-script is already gone */
16049 +#ifndef _WIN32
16050                 switch(waitpid(pid, &status, WNOHANG)) {
16051                 case 0:
16052                         /* not finished yet */
16053 @@ -519,19 +515,19 @@
16054                 case -1:
16055                         /* */
16056                         if (errno == EINTR) break;
16057 -                       
16058 -                       /* 
16059 -                        * errno == ECHILD happens if _subrequest catches the process-status before 
16060 +
16061 +                       /*
16062 +                        * errno == ECHILD happens if _subrequest catches the process-status before
16063                          * we have read the response of the cgi process
16064 -                        * 
16065 +                        *
16066                          * -> catch status
16067                          * -> WAIT_FOR_EVENT
16068                          * -> read response
16069                          * -> we get here with waitpid == ECHILD
16070 -                        * 
16071 +                        *
16072                          */
16073                         if (errno == ECHILD) return HANDLER_GO_ON;
16074 -                       
16075 +
16076                         log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16077                         return HANDLER_ERROR;
16078                 default:
16079 @@ -541,13 +537,13 @@
16080                                 con->http_status = 500;
16081                                 con->mode = DIRECT;
16082                         }
16083 -                               
16084 +
16085                         if (WIFEXITED(status)) {
16086  #if 0
16087                                 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
16088  #endif
16089                                 pid = 0;
16090 -                               
16091 +
16092                                 return HANDLER_GO_ON;
16093                         } else {
16094                                 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
16095 @@ -555,20 +551,20 @@
16096                                 return HANDLER_GO_ON;
16097                         }
16098                 }
16099 -               
16100 -       
16101 +
16102 +
16103                 kill(pid, SIGTERM);
16104 -               
16105 +#endif
16106                 /* cgi-script is still alive, queue the PID for removal */
16107                 cgi_pid_add(srv, p, pid);
16108         }
16109 -#endif 
16110 +#endif
16111         return HANDLER_GO_ON;
16112  }
16113  
16114  static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
16115         plugin_data *p = p_d;
16116 -       
16117 +
16118         return cgi_connection_close(srv, con->plugin_ctx[p->id]);
16119  }
16120  
16121 @@ -577,43 +573,43 @@
16122         server      *srv  = (server *)s;
16123         handler_ctx *hctx = ctx;
16124         connection  *con  = hctx->remote_conn;
16125 -       
16126 +
16127         joblist_append(srv, con);
16128 -       
16129 +
16130         if (hctx->fd == -1) {
16131                 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
16132 -               
16133 +
16134                 return HANDLER_ERROR;
16135         }
16136 -       
16137 +
16138         if (revents & FDEVENT_IN) {
16139                 switch (cgi_demux_response(srv, hctx)) {
16140                 case FDEVENT_HANDLED_NOT_FINISHED:
16141                         break;
16142                 case FDEVENT_HANDLED_FINISHED:
16143                         /* we are done */
16144 -                       
16145 +
16146  #if 0
16147                         log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
16148  #endif
16149                         cgi_connection_close(srv, hctx);
16150 -                       
16151 -                       /* if we get a IN|HUP and have read everything don't exec the close twice */ 
16152 +
16153 +                       /* if we get a IN|HUP and have read everything don't exec the close twice */
16154                         return HANDLER_FINISHED;
16155                 case FDEVENT_HANDLED_ERROR:
16156                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
16157                         con->http_status = 500;
16158                         con->mode = DIRECT;
16159 -                       
16160 +
16161                         log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
16162                         break;
16163                 }
16164         }
16165 -       
16166 +
16167         if (revents & FDEVENT_OUT) {
16168                 /* nothing to do */
16169         }
16170 -       
16171 +
16172         /* perhaps this issue is already handled */
16173         if (revents & FDEVENT_HUP) {
16174                 /* check if we still have a unfinished header package which is a body in reality */
16175 @@ -623,54 +619,54 @@
16176                         http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16177                         joblist_append(srv, con);
16178                 }
16179 -               
16180 +
16181                 if (con->file_finished == 0) {
16182                         http_chunk_append_mem(srv, con, NULL, 0);
16183                         joblist_append(srv, con);
16184                 }
16185 -               
16186 +
16187                 con->file_finished = 1;
16188 -               
16189 +
16190                 if (chunkqueue_is_empty(con->write_queue)) {
16191                         /* there is nothing left to write */
16192                         connection_set_state(srv, con, CON_STATE_RESPONSE_END);
16193                 } else {
16194                         /* used the write-handler to finish the request on demand */
16195 -                       
16196 +
16197                 }
16198 -               
16199 +
16200  # if 0
16201                 log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
16202  # endif
16203 -               
16204 +
16205                 /* rtsigs didn't liked the close */
16206                 cgi_connection_close(srv, hctx);
16207         } else if (revents & FDEVENT_ERR) {
16208                 con->file_finished = 1;
16209 -               
16210 +
16211                 /* kill all connections to the cgi process */
16212                 cgi_connection_close(srv, hctx);
16213  #if 1
16214                 log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
16215 -#endif                 
16216 +#endif
16217                 return HANDLER_ERROR;
16218         }
16219 -       
16220 +
16221         return HANDLER_FINISHED;
16222  }
16223  
16224  
16225  static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
16226         char *dst;
16227 -       
16228 +
16229         if (!key || !val) return -1;
16230 -       
16231 +
16232         dst = malloc(key_len + val_len + 3);
16233         memcpy(dst, key, key_len);
16234         dst[key_len] = '=';
16235         /* add the \0 from the value */
16236         memcpy(dst + key_len + 1, val, val_len + 1);
16237 -       
16238 +
16239         if (env->size == 0) {
16240                 env->size = 16;
16241                 env->ptr = malloc(env->size * sizeof(*env->ptr));
16242 @@ -678,45 +674,45 @@
16243                 env->size += 16;
16244                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
16245         }
16246 -       
16247 +
16248         env->ptr[env->used++] = dst;
16249 -       
16250 +
16251         return 0;
16252  }
16253  
16254  static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
16255         pid_t pid;
16256 -       
16257 +
16258  #ifdef HAVE_IPV6
16259         char b2[INET6_ADDRSTRLEN + 1];
16260  #endif
16261 -       
16262 +
16263         int to_cgi_fds[2];
16264         int from_cgi_fds[2];
16265         struct stat st;
16266 -       
16267 -#ifndef __WIN32        
16268 -       
16269 +
16270 +#ifndef _WIN32
16271 +
16272         if (cgi_handler->used > 1) {
16273                 /* stat the exec file */
16274                 if (-1 == (stat(cgi_handler->ptr, &st))) {
16275 -                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
16276 +                       log_error_write(srv, __FILE__, __LINE__, "sbss",
16277                                         "stat for cgi-handler", cgi_handler,
16278                                         "failed:", strerror(errno));
16279                         return -1;
16280                 }
16281         }
16282 -       
16283 +
16284         if (pipe(to_cgi_fds)) {
16285                 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16286                 return -1;
16287         }
16288 -       
16289 +
16290         if (pipe(from_cgi_fds)) {
16291                 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16292                 return -1;
16293         }
16294 -       
16295 +
16296         /* fork, execve */
16297         switch (pid = fork()) {
16298         case 0: {
16299 @@ -730,22 +726,22 @@
16300                 char *c;
16301                 const char *s;
16302                 server_socket *srv_sock = con->srv_socket;
16303 -               
16304 +
16305                 /* move stdout to from_cgi_fd[1] */
16306                 close(STDOUT_FILENO);
16307                 dup2(from_cgi_fds[1], STDOUT_FILENO);
16308                 close(from_cgi_fds[1]);
16309                 /* not needed */
16310                 close(from_cgi_fds[0]);
16311 -               
16312 +
16313                 /* move the stdin to to_cgi_fd[0] */
16314                 close(STDIN_FILENO);
16315                 dup2(to_cgi_fds[0], STDIN_FILENO);
16316                 close(to_cgi_fds[0]);
16317                 /* not needed */
16318                 close(to_cgi_fds[1]);
16319 -               
16320 -               /* HACK: 
16321 +
16322 +               /* HACK:
16323                  * this is not nice, but it works
16324                  *
16325                  * we feed the stderr of the CGI to our errorlog, if possible
16326 @@ -754,20 +750,20 @@
16327                         close(STDERR_FILENO);
16328                         dup2(srv->errorlog_fd, STDERR_FILENO);
16329                 }
16330 -               
16331 +
16332                 /* create environment */
16333                 env.ptr = NULL;
16334                 env.size = 0;
16335                 env.used = 0;
16336 -               
16337 +
16338                 cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
16339  
16340                 if (!buffer_is_empty(con->server_name)) {
16341                         cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
16342                 } else {
16343  #ifdef HAVE_IPV6
16344 -                       s = inet_ntop(srv_sock->addr.plain.sa_family, 
16345 -                                     srv_sock->addr.plain.sa_family == AF_INET6 ? 
16346 +                       s = inet_ntop(srv_sock->addr.plain.sa_family,
16347 +                                     srv_sock->addr.plain.sa_family == AF_INET6 ?
16348                                       (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16349                                       (const void *) &(srv_sock->addr.ipv4.sin_addr),
16350                                       b2, sizeof(b2)-1);
16351 @@ -779,10 +775,10 @@
16352                 cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
16353  
16354                 s = get_http_version_name(con->request.http_version);
16355 -               
16356 +
16357                 cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
16358 -               
16359 -               ltostr(buf, 
16360 +
16361 +               ltostr(buf,
16362  #ifdef HAVE_IPV6
16363                         ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
16364  #else
16365 @@ -790,10 +786,10 @@
16366  #endif
16367                         );
16368                 cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
16369 -               
16370 +
16371  #ifdef HAVE_IPV6
16372 -               s = inet_ntop(srv_sock->addr.plain.sa_family, 
16373 -                             srv_sock->addr.plain.sa_family == AF_INET6 ? 
16374 +               s = inet_ntop(srv_sock->addr.plain.sa_family,
16375 +                             srv_sock->addr.plain.sa_family == AF_INET6 ?
16376                               (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16377                               (const void *) &(srv_sock->addr.ipv4.sin_addr),
16378                               b2, sizeof(b2)-1);
16379 @@ -811,15 +807,18 @@
16380                 cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
16381                 if (!buffer_is_empty(con->uri.query)) {
16382                         cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
16383 +               } else {
16384 +                       /* set a empty QUERY_STRING */
16385 +                       cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
16386                 }
16387                 if (!buffer_is_empty(con->request.orig_uri)) {
16388                         cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
16389                 }
16390 -               
16391 -               
16392 +
16393 +
16394  #ifdef HAVE_IPV6
16395 -               s = inet_ntop(con->dst_addr.plain.sa_family, 
16396 -                             con->dst_addr.plain.sa_family == AF_INET6 ? 
16397 +               s = inet_ntop(con->dst_addr.plain.sa_family,
16398 +                             con->dst_addr.plain.sa_family == AF_INET6 ?
16399                               (const void *) &(con->dst_addr.ipv6.sin6_addr) :
16400                               (const void *) &(con->dst_addr.ipv4.sin_addr),
16401                               b2, sizeof(b2)-1);
16402 @@ -828,7 +827,7 @@
16403  #endif
16404                 cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
16405  
16406 -               ltostr(buf, 
16407 +               ltostr(buf,
16408  #ifdef HAVE_IPV6
16409                         ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
16410  #else
16411 @@ -836,19 +835,19 @@
16412  #endif
16413                         );
16414                 cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
16415 -               
16416 +
16417                 if (!buffer_is_empty(con->authed_user)) {
16418                         cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
16419                                     CONST_BUF_LEN(con->authed_user));
16420                 }
16421 -               
16422 +
16423                 /* request.content_length < SSIZE_MAX, see request.c */
16424                 ltostr(buf, con->request.content_length);
16425                 cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
16426                 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
16427                 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
16428                 cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
16429 -               
16430 +
16431                 /* for valgrind */
16432                 if (NULL != (s = getenv("LD_PRELOAD"))) {
16433                         cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
16434 @@ -863,24 +862,24 @@
16435                         cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
16436                 }
16437  #endif
16438 -               
16439 +
16440                 for (n = 0; n < con->request.headers->used; n++) {
16441                         data_string *ds;
16442 -                       
16443 +
16444                         ds = (data_string *)con->request.headers->data[n];
16445 -                       
16446 +
16447                         if (ds->value->used && ds->key->used) {
16448                                 size_t j;
16449 -                               
16450 +
16451                                 buffer_reset(p->tmp_buf);
16452 -                               
16453 +
16454                                 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
16455                                         buffer_copy_string(p->tmp_buf, "HTTP_");
16456                                         p->tmp_buf->used--; /* strip \0 after HTTP_ */
16457                                 }
16458 -                               
16459 +
16460                                 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16461 -                               
16462 +
16463                                 for (j = 0; j < ds->key->used - 1; j++) {
16464                                         char cr = '_';
16465                                         if (light_isalpha(ds->key->ptr[j])) {
16466 @@ -893,46 +892,46 @@
16467                                         p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
16468                                 }
16469                                 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16470 -                               
16471 +
16472                                 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16473                         }
16474                 }
16475 -               
16476 +
16477                 for (n = 0; n < con->environment->used; n++) {
16478                         data_string *ds;
16479 -                       
16480 +
16481                         ds = (data_string *)con->environment->data[n];
16482 -                       
16483 +
16484                         if (ds->value->used && ds->key->used) {
16485                                 size_t j;
16486 -                               
16487 +
16488                                 buffer_reset(p->tmp_buf);
16489 -                               
16490 +
16491                                 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16492 -                               
16493 +
16494                                 for (j = 0; j < ds->key->used - 1; j++) {
16495 -                                       p->tmp_buf->ptr[p->tmp_buf->used++] = 
16496 -                                               isalpha((unsigned char)ds->key->ptr[j]) ? 
16497 +                                       p->tmp_buf->ptr[p->tmp_buf->used++] =
16498 +                                               isalpha((unsigned char)ds->key->ptr[j]) ?
16499                                                 toupper((unsigned char)ds->key->ptr[j]) : '_';
16500                                 }
16501                                 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16502 -                               
16503 +
16504                                 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16505                         }
16506                 }
16507 -               
16508 +
16509                 if (env.size == env.used) {
16510                         env.size += 16;
16511                         env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
16512                 }
16513 -               
16514 +
16515                 env.ptr[env.used] = NULL;
16516 -               
16517 +
16518                 /* set up args */
16519                 argc = 3;
16520                 args = malloc(sizeof(*args) * argc);
16521                 i = 0;
16522 -               
16523 +
16524                 if (cgi_handler->used > 1) {
16525                         args[i++] = cgi_handler->ptr;
16526                 }
16527 @@ -942,7 +941,7 @@
16528                 /* search for the last / */
16529                 if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
16530                         *c = '\0';
16531 -                       
16532 +
16533                         /* change to the physical directory */
16534                         if (-1 == chdir(con->physical.path->ptr)) {
16535                                 log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
16536 @@ -954,12 +953,12 @@
16537                 for (i = 3; i < 256; i++) {
16538                         if (i != srv->errorlog_fd) close(i);
16539                 }
16540 -               
16541 +
16542                 /* exec the cgi */
16543                 execve(args[0], args, env.ptr);
16544 -               
16545 +
16546                 log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
16547 -               
16548 +
16549                 /* */
16550                 SEGFAULT();
16551                 break;
16552 @@ -974,11 +973,11 @@
16553  
16554                 close(from_cgi_fds[1]);
16555                 close(to_cgi_fds[0]);
16556 -               
16557 +
16558                 if (con->request.content_length) {
16559                         chunkqueue *cq = con->request_content_queue;
16560                         chunk *c;
16561 -               
16562 +
16563                         assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
16564  
16565                         /* there is content to send */
16566 @@ -993,16 +992,16 @@
16567                                                 if (-1 == c->file.fd &&  /* open the file if not already open */
16568                                                     -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
16569                                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
16570 -                                       
16571 +
16572                                                         close(from_cgi_fds[0]);
16573                                                         close(to_cgi_fds[1]);
16574                                                         return -1;
16575                                                 }
16576  
16577                                                 c->file.mmap.length = c->file.length;
16578 -                               
16579 +
16580                                                 if (MAP_FAILED == (c->file.mmap.start = mmap(0,  c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
16581 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 
16582 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
16583                                                                         strerror(errno), c->file.name,  c->file.fd);
16584  
16585                                                         close(from_cgi_fds[0]);
16586 @@ -1012,7 +1011,7 @@
16587  
16588                                                 close(c->file.fd);
16589                                                 c->file.fd = -1;
16590 -       
16591 +
16592                                                 /* chunk_reset() or chunk_free() will cleanup for us */
16593                                         }
16594  
16595 @@ -1020,7 +1019,7 @@
16596                                                 switch(errno) {
16597                                                 case ENOSPC:
16598                                                         con->http_status = 507;
16599 -               
16600 +
16601                                                         break;
16602                                                 default:
16603                                                         con->http_status = 403;
16604 @@ -1033,7 +1032,7 @@
16605                                                 switch(errno) {
16606                                                 case ENOSPC:
16607                                                         con->http_status = 507;
16608 -               
16609 +
16610                                                         break;
16611                                                 default:
16612                                                         con->http_status = 403;
16613 @@ -1056,103 +1055,100 @@
16614                 }
16615  
16616                 close(to_cgi_fds[1]);
16617 -                               
16618 +
16619                 /* register PID and wait for them asyncronously */
16620                 con->mode = p->id;
16621                 buffer_reset(con->physical.path);
16622 -               
16623 +
16624                 hctx = cgi_handler_ctx_init();
16625 -               
16626 +
16627                 hctx->remote_conn = con;
16628                 hctx->plugin_data = p;
16629                 hctx->pid = pid;
16630                 hctx->fd = from_cgi_fds[0];
16631                 hctx->fde_ndx = -1;
16632 -               
16633 +
16634                 con->plugin_ctx[p->id] = hctx;
16635 -               
16636 +
16637                 fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
16638                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
16639 -               
16640 +
16641                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
16642                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
16643 -                       
16644 +
16645                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16646                         fdevent_unregister(srv->ev, hctx->fd);
16647 -                       
16648 +
16649                         log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
16650 -                       
16651 +
16652                         close(hctx->fd);
16653 -                       
16654 +
16655                         cgi_handler_ctx_free(hctx);
16656 -                       
16657 +
16658                         con->plugin_ctx[p->id] = NULL;
16659 -                       
16660 +
16661                         return -1;
16662                 }
16663 -               
16664 +
16665                 break;
16666         }
16667         }
16668 -       
16669 +
16670         return 0;
16671  #else
16672         return -1;
16673  #endif
16674  }
16675  
16676 -#define PATCH(x) \
16677 -       p->conf.x = s->x;
16678  static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
16679         size_t i, j;
16680         plugin_config *s = p->config_storage[0];
16681 -       
16682 -       PATCH(cgi);
16683 -       
16684 +
16685 +       PATCH_OPTION(cgi);
16686 +
16687         /* skip the first, the global context */
16688         for (i = 1; i < srv->config_context->used; i++) {
16689                 data_config *dc = (data_config *)srv->config_context->data[i];
16690                 s = p->config_storage[i];
16691 -               
16692 +
16693                 /* condition didn't match */
16694                 if (!config_check_cond(srv, con, dc)) continue;
16695 -               
16696 +
16697                 /* merge config */
16698                 for (j = 0; j < dc->value->used; j++) {
16699                         data_unset *du = dc->value->data[j];
16700 -                       
16701 +
16702                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
16703 -                               PATCH(cgi);
16704 +                               PATCH_OPTION(cgi);
16705                         }
16706                 }
16707         }
16708 -       
16709 +
16710         return 0;
16711  }
16712 -#undef PATCH
16713  
16714  URIHANDLER_FUNC(cgi_is_handled) {
16715         size_t k, s_len;
16716         plugin_data *p = p_d;
16717         buffer *fn = con->physical.path;
16718 -       
16719 +
16720         if (fn->used == 0) return HANDLER_GO_ON;
16721 -       
16722 +
16723         mod_cgi_patch_connection(srv, con, p);
16724 -       
16725 +
16726         s_len = fn->used - 1;
16727 -       
16728 +
16729         for (k = 0; k < p->conf.cgi->used; k++) {
16730                 data_string *ds = (data_string *)p->conf.cgi->data[k];
16731                 size_t ct_len = ds->key->used - 1;
16732 -               
16733 +
16734                 if (ds->key->used == 0) continue;
16735                 if (s_len < ct_len) continue;
16736 -               
16737 +
16738                 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
16739                         if (cgi_create_env(srv, con, p, ds->value)) {
16740                                 con->http_status = 500;
16741 -                               
16742 +
16743                                 buffer_reset(con->physical.path);
16744                                 return HANDLER_FINISHED;
16745                         }
16746 @@ -1160,7 +1156,7 @@
16747                         break;
16748                 }
16749         }
16750 -       
16751 +
16752         return HANDLER_GO_ON;
16753  }
16754  
16755 @@ -1168,11 +1164,11 @@
16756         plugin_data *p = p_d;
16757         size_t ndx;
16758         /* the trigger handle only cares about lonely PID which we have to wait for */
16759 -#ifndef __WIN32
16760 +#ifndef _WIN32
16761  
16762         for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
16763                 int status;
16764 -               
16765 +
16766                 switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
16767                 case 0:
16768                         /* not finished yet */
16769 @@ -1182,7 +1178,7 @@
16770                         break;
16771                 case -1:
16772                         log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16773 -                       
16774 +
16775                         return HANDLER_ERROR;
16776                 default:
16777  
16778 @@ -1193,16 +1189,16 @@
16779                         } else {
16780                                 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
16781                         }
16782 -                       
16783 +
16784                         cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
16785 -                       /* del modified the buffer structure 
16786 +                       /* del modified the buffer structure
16787                          * and copies the last entry to the current one
16788                          * -> recheck the current index
16789                          */
16790                         ndx--;
16791                 }
16792         }
16793 -#endif 
16794 +#endif
16795         return HANDLER_GO_ON;
16796  }
16797  
16798 @@ -1210,15 +1206,15 @@
16799         int status;
16800         plugin_data *p = p_d;
16801         handler_ctx *hctx = con->plugin_ctx[p->id];
16802 -       
16803 +
16804         if (con->mode != p->id) return HANDLER_GO_ON;
16805         if (NULL == hctx) return HANDLER_GO_ON;
16806 -       
16807 +
16808  #if 0
16809         log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
16810 -#endif 
16811 +#endif
16812         if (hctx->pid == 0) return HANDLER_FINISHED;
16813 -#ifndef __WIN32        
16814 +#ifndef _WIN32
16815         switch(waitpid(hctx->pid, &status, WNOHANG)) {
16816         case 0:
16817                 /* we only have for events here if we don't have the header yet,
16818 @@ -1228,61 +1224,61 @@
16819                 return HANDLER_WAIT_FOR_EVENT;
16820         case -1:
16821                 if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
16822 -               
16823 +
16824                 if (errno == ECHILD && con->file_started == 0) {
16825                         /*
16826 -                        * second round but still not response 
16827 +                        * second round but still not response
16828                          */
16829 -                       return HANDLER_WAIT_FOR_EVENT; 
16830 +                       return HANDLER_WAIT_FOR_EVENT;
16831                 }
16832 -               
16833 +
16834                 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16835                 con->mode = DIRECT;
16836                 con->http_status = 500;
16837 -               
16838 +
16839                 hctx->pid = 0;
16840 -               
16841 +
16842                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16843                 fdevent_unregister(srv->ev, hctx->fd);
16844 -               
16845 +
16846                 if (close(hctx->fd)) {
16847                         log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16848                 }
16849 -               
16850 +
16851                 cgi_handler_ctx_free(hctx);
16852 -               
16853 +
16854                 con->plugin_ctx[p->id] = NULL;
16855 -               
16856 +
16857                 return HANDLER_FINISHED;
16858         default:
16859 -               /* cgi process exited cleanly 
16860 -                * 
16861 -                * check if we already got the response 
16862 +               /* cgi process exited cleanly
16863 +                *
16864 +                * check if we already got the response
16865                  */
16866 -               
16867 +
16868                 if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
16869 -               
16870 +
16871                 if (WIFEXITED(status)) {
16872                         /* nothing */
16873                 } else {
16874                         log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
16875 -                       
16876 +
16877                         con->mode = DIRECT;
16878                         con->http_status = 500;
16879 -                       
16880 +
16881                 }
16882 -               
16883 +
16884                 hctx->pid = 0;
16885 -               
16886 +
16887                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16888                 fdevent_unregister(srv->ev, hctx->fd);
16889 -               
16890 +
16891                 if (close(hctx->fd)) {
16892                         log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16893                 }
16894 -               
16895 +
16896                 cgi_handler_ctx_free(hctx);
16897 -               
16898 +
16899                 con->plugin_ctx[p->id] = NULL;
16900                 return HANDLER_FINISHED;
16901         }
16902 @@ -1306,8 +1302,8 @@
16903         p->init           = mod_cgi_init;
16904         p->cleanup        = mod_cgi_free;
16905         p->set_defaults   = mod_fastcgi_set_defaults;
16906 -       
16907 +
16908         p->data        = NULL;
16909 -       
16910 +
16911         return 0;
16912  }
16913 --- ../lighttpd-1.4.11/src/mod_cml.c    2006-01-30 13:51:48.000000000 +0200
16914 +++ lighttpd-1.4.12/src/mod_cml.c       2006-07-11 22:07:51.000000000 +0300
16915 @@ -4,7 +4,6 @@
16916  #include <stdlib.h>
16917  #include <string.h>
16918  #include <errno.h>
16919 -#include <unistd.h>
16920  #include <stdio.h>
16921  
16922  #include "buffer.h"
16923 @@ -20,50 +19,50 @@
16924  /* init the plugin data */
16925  INIT_FUNC(mod_cml_init) {
16926         plugin_data *p;
16927 -       
16928 +
16929         p = calloc(1, sizeof(*p));
16930 -       
16931 +
16932         p->basedir         = buffer_init();
16933         p->baseurl         = buffer_init();
16934         p->trigger_handler = buffer_init();
16935 -       
16936 +
16937         return p;
16938  }
16939  
16940  /* detroy the plugin data */
16941  FREE_FUNC(mod_cml_free) {
16942         plugin_data *p = p_d;
16943 -       
16944 +
16945         UNUSED(srv);
16946  
16947         if (!p) return HANDLER_GO_ON;
16948 -       
16949 +
16950         if (p->config_storage) {
16951                 size_t i;
16952                 for (i = 0; i < srv->config_context->used; i++) {
16953                         plugin_config *s = p->config_storage[i];
16954 -                       
16955 +
16956                         buffer_free(s->ext);
16957 -                       
16958 +
16959                         buffer_free(s->mc_namespace);
16960                         buffer_free(s->power_magnet);
16961                         array_free(s->mc_hosts);
16962 -                       
16963 +
16964  #if defined(HAVE_MEMCACHE_H)
16965                         if (s->mc) mc_free(s->mc);
16966  #endif
16967 -                       
16968 +
16969                         free(s);
16970                 }
16971                 free(p->config_storage);
16972         }
16973 -       
16974 +
16975         buffer_free(p->trigger_handler);
16976         buffer_free(p->basedir);
16977         buffer_free(p->baseurl);
16978 -       
16979 +
16980         free(p);
16981 -       
16982 +
16983         return HANDLER_GO_ON;
16984  }
16985  
16986 @@ -72,22 +71,22 @@
16987  SETDEFAULTS_FUNC(mod_cml_set_defaults) {
16988         plugin_data *p = p_d;
16989         size_t i = 0;
16990 -       
16991 -       config_values_t cv[] = { 
16992 +
16993 +       config_values_t cv[] = {
16994                 { "cml.extension",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
16995                 { "cml.memcache-hosts",         NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 1 */
16996                 { "cml.memcache-namespace",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
16997                 { "cml.power-magnet",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
16998                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
16999         };
17000 -       
17001 +
17002         if (!p) return HANDLER_ERROR;
17003 -       
17004 +
17005         p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
17006 -       
17007 +
17008         for (i = 0; i < srv->config_context->used; i++) {
17009                 plugin_config *s;
17010 -               
17011 +
17012                 s = malloc(sizeof(plugin_config));
17013                 s->ext    = buffer_init();
17014                 s->mc_hosts       = array_init();
17015 @@ -96,87 +95,84 @@
17016  #if defined(HAVE_MEMCACHE_H)
17017                 s->mc = NULL;
17018  #endif
17019 -               
17020 +
17021                 cv[0].destination = s->ext;
17022                 cv[1].destination = s->mc_hosts;
17023                 cv[2].destination = s->mc_namespace;
17024                 cv[3].destination = s->power_magnet;
17025 -               
17026 +
17027                 p->config_storage[i] = s;
17028 -       
17029 +
17030                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
17031                         return HANDLER_ERROR;
17032                 }
17033 -               
17034 +
17035                 if (s->mc_hosts->used) {
17036  #if defined(HAVE_MEMCACHE_H)
17037                         size_t k;
17038                         s->mc = mc_new();
17039 -               
17040 +
17041                         for (k = 0; k < s->mc_hosts->used; k++) {
17042                                 data_string *ds = (data_string *)s->mc_hosts->data[k];
17043 -                               
17044 +
17045                                 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
17046 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
17047 -                                                       "connection to host failed:", 
17048 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
17049 +                                                       "connection to host failed:",
17050                                                         ds->value);
17051 -                                       
17052 +
17053                                         return HANDLER_ERROR;
17054                                 }
17055                         }
17056  #else
17057 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
17058 +                       log_error_write(srv, __FILE__, __LINE__, "s",
17059                                         "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
17060                         return HANDLER_ERROR;
17061  #endif
17062                 }
17063         }
17064 -       
17065 +
17066         return HANDLER_GO_ON;
17067  }
17068  
17069 -#define PATCH(x) \
17070 -       p->conf.x = s->x;
17071  static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
17072         size_t i, j;
17073         plugin_config *s = p->config_storage[0];
17074 -       
17075 -       PATCH(ext);
17076 +
17077 +       PATCH_OPTION(ext);
17078  #if defined(HAVE_MEMCACHE_H)
17079 -       PATCH(mc);
17080 +       PATCH_OPTION(mc);
17081  #endif
17082 -       PATCH(mc_namespace);
17083 -       PATCH(power_magnet);
17084 -       
17085 +       PATCH_OPTION(mc_namespace);
17086 +       PATCH_OPTION(power_magnet);
17087 +
17088         /* skip the first, the global context */
17089         for (i = 1; i < srv->config_context->used; i++) {
17090                 data_config *dc = (data_config *)srv->config_context->data[i];
17091                 s = p->config_storage[i];
17092 -               
17093 +
17094                 /* condition didn't match */
17095                 if (!config_check_cond(srv, con, dc)) continue;
17096 -               
17097 +
17098                 /* merge config */
17099                 for (j = 0; j < dc->value->used; j++) {
17100                         data_unset *du = dc->value->data[j];
17101 -                       
17102 +
17103                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
17104 -                               PATCH(ext);
17105 +                               PATCH_OPTION(ext);
17106                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
17107  #if defined(HAVE_MEMCACHE_H)
17108 -                               PATCH(mc);
17109 +                               PATCH_OPTION(mc);
17110  #endif
17111                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
17112 -                               PATCH(mc_namespace);
17113 +                               PATCH_OPTION(mc_namespace);
17114                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
17115 -                               PATCH(power_magnet);
17116 +                               PATCH_OPTION(power_magnet);
17117                         }
17118                 }
17119         }
17120 -       
17121 +
17122         return 0;
17123  }
17124 -#undef PATCH
17125  
17126  int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
17127         buffer *b;
17128 @@ -187,57 +183,57 @@
17129         b = p->baseurl;
17130         buffer_copy_string_buffer(b, con->uri.path);
17131         for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17132 -       
17133 +
17134         if (*c == '/') {
17135                 b->used = c - b->ptr + 2;
17136                 *(c+1) = '\0';
17137         }
17138 -       
17139 +
17140         b = p->basedir;
17141         buffer_copy_string_buffer(b, con->physical.path);
17142         for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17143 -       
17144 +
17145         if (*c == '/') {
17146                 b->used = c - b->ptr + 2;
17147                 *(c+1) = '\0';
17148         }
17149 -       
17150 +
17151  
17152         /* prepare variables
17153          *   - cookie-based
17154          *   - get-param-based
17155          */
17156 -       
17157 +
17158         return cache_parse_lua(srv, con, p, cml_file);
17159 -       
17160 +
17161  }
17162  
17163  URIHANDLER_FUNC(mod_cml_power_magnet) {
17164         plugin_data *p = p_d;
17165 -       
17166 +
17167         mod_cml_patch_connection(srv, con, p);
17168 -       
17169 +
17170         buffer_reset(p->basedir);
17171         buffer_reset(p->baseurl);
17172         buffer_reset(p->trigger_handler);
17173  
17174         if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
17175 -       
17176 -       /* 
17177 +
17178 +       /*
17179          * power-magnet:
17180          * cml.power-magnet = server.docroot + "/rewrite.cml"
17181          *
17182          * is called on EACH request, take the original REQUEST_URI and modifies the
17183 -        * request header as neccesary. 
17184 +        * request header as neccesary.
17185          *
17186          * First use:
17187          * if file_exists("/maintainance.html") {
17188          *   output_include = ( "/maintainance.html" )
17189 -        *   return CACHE_HIT 
17190 +        *   return CACHE_HIT
17191          * }
17192          *
17193          * as we only want to rewrite HTML like requests we should cover it in a conditional
17194 -        * 
17195 +        *
17196          * */
17197  
17198         switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
17199 @@ -266,20 +262,20 @@
17200  
17201  URIHANDLER_FUNC(mod_cml_is_handled) {
17202         plugin_data *p = p_d;
17203 -       
17204 +
17205         if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
17206 -       
17207 +
17208         mod_cml_patch_connection(srv, con, p);
17209 -       
17210 +
17211         buffer_reset(p->basedir);
17212         buffer_reset(p->baseurl);
17213         buffer_reset(p->trigger_handler);
17214  
17215         if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
17216 -       
17217 +
17218         if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
17219                 return HANDLER_GO_ON;
17220 -       } 
17221 +       }
17222  
17223         switch(cache_call_lua(srv, con, p, con->physical.path)) {
17224         case -1:
17225 @@ -311,15 +307,15 @@
17226  int mod_cml_plugin_init(plugin *p) {
17227         p->version     = LIGHTTPD_VERSION_ID;
17228         p->name        = buffer_init_string("cache");
17229 -       
17230 +
17231         p->init        = mod_cml_init;
17232         p->cleanup     = mod_cml_free;
17233         p->set_defaults  = mod_cml_set_defaults;
17234 -       
17235 +
17236         p->handle_subrequest_start = mod_cml_is_handled;
17237         p->handle_physical         = mod_cml_power_magnet;
17238 -       
17239 +
17240         p->data        = NULL;
17241 -       
17242 +
17243         return 0;
17244  }
17245 --- ../lighttpd-1.4.11/src/mod_cml.h    2006-01-30 13:51:35.000000000 +0200
17246 +++ lighttpd-1.4.12/src/mod_cml.h       2006-07-11 22:07:51.000000000 +0300
17247 @@ -16,10 +16,10 @@
17248  
17249  typedef struct {
17250         buffer *ext;
17251 -       
17252 +
17253         array  *mc_hosts;
17254         buffer *mc_namespace;
17255 -#if defined(HAVE_MEMCACHE_H) 
17256 +#if defined(HAVE_MEMCACHE_H)
17257         struct memcache *mc;
17258  #endif
17259         buffer *power_magnet;
17260 @@ -27,15 +27,15 @@
17261  
17262  typedef struct {
17263         PLUGIN_DATA;
17264 -       
17265 +
17266         buffer *basedir;
17267         buffer *baseurl;
17268 -       
17269 +
17270         buffer *trigger_handler;
17271 -       
17272 +
17273         plugin_config **config_storage;
17274 -       
17275 -       plugin_config conf; 
17276 +
17277 +       plugin_config conf;
17278  } plugin_data;
17279  
17280  int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
17281 --- ../lighttpd-1.4.11/src/mod_cml_funcs.c      2005-11-17 16:15:08.000000000 +0200
17282 +++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-11 22:07:52.000000000 +0300
17283 @@ -4,8 +4,7 @@
17284  #include <stdlib.h>
17285  #include <string.h>
17286  #include <errno.h>
17287 -#include <unistd.h>
17288 -#include <dirent.h>
17289 +
17290  #include <stdio.h>
17291  
17292  #include "buffer.h"
17293 @@ -13,6 +12,7 @@
17294  #include "log.h"
17295  #include "plugin.h"
17296  #include "response.h"
17297 +#include "sys-files.h"
17298  
17299  #include "mod_cml.h"
17300  #include "mod_cml_funcs.h"
17301 @@ -30,7 +30,7 @@
17302  #ifdef USE_OPENSSL
17303  #define IN const
17304  #else
17305 -#define IN 
17306 +#define IN
17307  #endif
17308  #define OUT
17309  
17310 @@ -42,29 +42,29 @@
17311         buffer b;
17312         char hex[33];
17313         int n = lua_gettop(L);
17314 -       
17315 +
17316         b.ptr = hex;
17317         b.used = 0;
17318         b.size = sizeof(hex);
17319 -       
17320 +
17321         if (n != 1) {
17322                 lua_pushstring(L, "md5: expected one argument");
17323                 lua_error(L);
17324         }
17325 -       
17326 +
17327         if (!lua_isstring(L, 1)) {
17328                 lua_pushstring(L, "md5: argument has to be a string");
17329                 lua_error(L);
17330         }
17331 -       
17332 +
17333         MD5_Init(&Md5Ctx);
17334         MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
17335         MD5_Final(HA1, &Md5Ctx);
17336 -       
17337 +
17338         buffer_copy_string_hex(&b, (char *)HA1, 16);
17339 -       
17340 +
17341         lua_pushstring(L, b.ptr);
17342 -       
17343 +
17344         return 1;
17345  }
17346  
17347 @@ -72,37 +72,37 @@
17348  int f_file_mtime(lua_State *L) {
17349         struct stat st;
17350         int n = lua_gettop(L);
17351 -       
17352 +
17353         if (n != 1) {
17354                 lua_pushstring(L, "file_mtime: expected one argument");
17355                 lua_error(L);
17356         }
17357 -       
17358 +
17359         if (!lua_isstring(L, 1)) {
17360                 lua_pushstring(L, "file_mtime: argument has to be a string");
17361                 lua_error(L);
17362         }
17363 -       
17364 +
17365         if (-1 == stat(lua_tostring(L, 1), &st)) {
17366                 lua_pushnil(L);
17367                 return 1;
17368         }
17369 -       
17370 +
17371         lua_pushnumber(L, st.st_mtime);
17372 -       
17373 +
17374         return 1;
17375  }
17376 -
17377 +#ifndef _WIN32
17378  int f_dir_files_iter(lua_State *L) {
17379         DIR *d;
17380         struct dirent *de;
17381 -       
17382 +
17383         d = lua_touserdata(L, lua_upvalueindex(1));
17384 -       
17385 +
17386         if (NULL == (de = readdir(d))) {
17387                 /* EOF */
17388                 closedir(d);
17389 -               
17390 +
17391                 return 0;
17392         } else {
17393                 lua_pushstring(L, de->d_name);
17394 @@ -113,75 +113,75 @@
17395  int f_dir_files(lua_State *L) {
17396         DIR *d;
17397         int n = lua_gettop(L);
17398 -       
17399 +
17400         if (n != 1) {
17401                 lua_pushstring(L, "dir_files: expected one argument");
17402                 lua_error(L);
17403         }
17404 -       
17405 +
17406         if (!lua_isstring(L, 1)) {
17407                 lua_pushstring(L, "dir_files: argument has to be a string");
17408                 lua_error(L);
17409         }
17410 -       
17411 -       /* check if there is a valid DIR handle on the stack */ 
17412 +
17413 +       /* check if there is a valid DIR handle on the stack */
17414         if (NULL == (d = opendir(lua_tostring(L, 1)))) {
17415                 lua_pushnil(L);
17416                 return 1;
17417         }
17418 -       
17419 +
17420         /* push d into registry */
17421         lua_pushlightuserdata(L, d);
17422         lua_pushcclosure(L, f_dir_files_iter, 1);
17423 -       
17424 +
17425         return 1;
17426  }
17427 -
17428 +#endif
17429  int f_file_isreg(lua_State *L) {
17430         struct stat st;
17431         int n = lua_gettop(L);
17432 -       
17433 +
17434         if (n != 1) {
17435                 lua_pushstring(L, "file_isreg: expected one argument");
17436                 lua_error(L);
17437         }
17438 -       
17439 +
17440         if (!lua_isstring(L, 1)) {
17441                 lua_pushstring(L, "file_isreg: argument has to be a string");
17442                 lua_error(L);
17443         }
17444 -       
17445 +
17446         if (-1 == stat(lua_tostring(L, 1), &st)) {
17447                 lua_pushnil(L);
17448                 return 1;
17449         }
17450 -       
17451 +
17452         lua_pushnumber(L, S_ISREG(st.st_mode));
17453 -       
17454 +
17455         return 1;
17456  }
17457  
17458  int f_file_isdir(lua_State *L) {
17459         struct stat st;
17460         int n = lua_gettop(L);
17461 -       
17462 +
17463         if (n != 1) {
17464                 lua_pushstring(L, "file_isreg: expected one argument");
17465                 lua_error(L);
17466         }
17467 -       
17468 +
17469         if (!lua_isstring(L, 1)) {
17470                 lua_pushstring(L, "file_isreg: argument has to be a string");
17471                 lua_error(L);
17472         }
17473 -       
17474 +
17475         if (-1 == stat(lua_tostring(L, 1), &st)) {
17476                 lua_pushnil(L);
17477                 return 1;
17478         }
17479 -       
17480 +
17481         lua_pushnumber(L, S_ISDIR(st.st_mode));
17482 -       
17483 +
17484         return 1;
17485  }
17486  
17487 @@ -192,33 +192,33 @@
17488         char *r;
17489         int n = lua_gettop(L);
17490         struct memcache *mc;
17491 -       
17492 +
17493         if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17494                 lua_pushstring(L, "where is my userdata ?");
17495                 lua_error(L);
17496         }
17497 -       
17498 +
17499         mc = lua_touserdata(L, lua_upvalueindex(1));
17500 -       
17501 +
17502         if (n != 1) {
17503                 lua_pushstring(L, "expected one argument");
17504                 lua_error(L);
17505         }
17506 -       
17507 +
17508         if (!lua_isstring(L, 1)) {
17509                 lua_pushstring(L, "argument has to be a string");
17510                 lua_error(L);
17511         }
17512 -       
17513 -       if (NULL == (r = mc_aget(mc, 
17514 +
17515 +       if (NULL == (r = mc_aget(mc,
17516                                  lua_tostring(L, 1), lua_strlen(L, 1)))) {
17517 -                               
17518 +
17519                 lua_pushboolean(L, 0);
17520                 return 1;
17521         }
17522 -       
17523 +
17524         free(r);
17525 -       
17526 +
17527         lua_pushboolean(L, 1);
17528         return 1;
17529  }
17530 @@ -226,74 +226,74 @@
17531  int f_memcache_get_string(lua_State *L) {
17532         char *r;
17533         int n = lua_gettop(L);
17534 -       
17535 +
17536         struct memcache *mc;
17537 -       
17538 +
17539         if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17540                 lua_pushstring(L, "where is my userdata ?");
17541                 lua_error(L);
17542         }
17543 -       
17544 +
17545         mc = lua_touserdata(L, lua_upvalueindex(1));
17546 -       
17547 -       
17548 +
17549 +
17550         if (n != 1) {
17551                 lua_pushstring(L, "expected one argument");
17552                 lua_error(L);
17553         }
17554 -       
17555 +
17556         if (!lua_isstring(L, 1)) {
17557                 lua_pushstring(L, "argument has to be a string");
17558                 lua_error(L);
17559         }
17560 -       
17561 -       if (NULL == (r = mc_aget(mc, 
17562 +
17563 +       if (NULL == (r = mc_aget(mc,
17564                                  lua_tostring(L, 1), lua_strlen(L, 1)))) {
17565                 lua_pushnil(L);
17566                 return 1;
17567         }
17568 -       
17569 +
17570         lua_pushstring(L, r);
17571 -       
17572 +
17573         free(r);
17574 -       
17575 +
17576         return 1;
17577  }
17578  
17579  int f_memcache_get_long(lua_State *L) {
17580         char *r;
17581         int n = lua_gettop(L);
17582 -       
17583 +
17584         struct memcache *mc;
17585 -       
17586 +
17587         if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17588                 lua_pushstring(L, "where is my userdata ?");
17589                 lua_error(L);
17590         }
17591 -       
17592 +
17593         mc = lua_touserdata(L, lua_upvalueindex(1));
17594 -       
17595 -       
17596 +
17597 +
17598         if (n != 1) {
17599                 lua_pushstring(L, "expected one argument");
17600                 lua_error(L);
17601         }
17602 -       
17603 +
17604         if (!lua_isstring(L, 1)) {
17605                 lua_pushstring(L, "argument has to be a string");
17606                 lua_error(L);
17607         }
17608 -       
17609 -       if (NULL == (r = mc_aget(mc, 
17610 +
17611 +       if (NULL == (r = mc_aget(mc,
17612                                  lua_tostring(L, 1), lua_strlen(L, 1)))) {
17613                 lua_pushnil(L);
17614                 return 1;
17615         }
17616 -       
17617 +
17618         lua_pushnumber(L, strtol(r, NULL, 10));
17619 -       
17620 +
17621         free(r);
17622 -       
17623 +
17624         return 1;
17625  }
17626  #endif
17627 --- ../lighttpd-1.4.11/src/mod_cml_lua.c        2006-01-30 13:56:40.000000000 +0200
17628 +++ lighttpd-1.4.12/src/mod_cml_lua.c   2006-07-11 22:07:53.000000000 +0300
17629 @@ -23,7 +23,7 @@
17630  #ifdef USE_OPENSSL
17631  #define IN const
17632  #else
17633 -#define IN 
17634 +#define IN
17635  #endif
17636  #define OUT
17637  
17638 @@ -31,6 +31,7 @@
17639  
17640  #include <lua.h>
17641  #include <lualib.h>
17642 +#include <lauxlib.h>
17643  
17644  typedef struct {
17645         stream st;
17646 @@ -39,11 +40,11 @@
17647  
17648  static const char * load_file(lua_State *L, void *data, size_t *size) {
17649         readme *rm = data;
17650 -       
17651 +
17652         UNUSED(L);
17653 -       
17654 +
17655         if (rm->done) return 0;
17656 -       
17657 +
17658         *size = rm->st.size;
17659         rm->done = 1;
17660         return rm->st.start;
17661 @@ -51,47 +52,47 @@
17662  
17663  static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
17664         int curelem;
17665 -       
17666 +
17667         lua_pushstring(L, varname);
17668 -       
17669 +
17670         curelem = lua_gettop(L);
17671         lua_gettable(L, LUA_GLOBALSINDEX);
17672 -       
17673 +
17674         /* it should be a table */
17675         if (!lua_isstring(L, curelem)) {
17676                 lua_settop(L, curelem - 1);
17677 -               
17678 +
17679                 return -1;
17680         }
17681 -       
17682 +
17683         buffer_copy_string(b, lua_tostring(L, curelem));
17684 -       
17685 +
17686         lua_pop(L, 1);
17687 -       
17688 +
17689         assert(curelem - 1 == lua_gettop(L));
17690 -       
17691 +
17692         return 0;
17693  }
17694  
17695  static int lua_to_c_is_table(lua_State *L, const char *varname) {
17696         int curelem;
17697 -       
17698 +
17699         lua_pushstring(L, varname);
17700 -       
17701 +
17702         curelem = lua_gettop(L);
17703         lua_gettable(L, LUA_GLOBALSINDEX);
17704 -       
17705 +
17706         /* it should be a table */
17707         if (!lua_istable(L, curelem)) {
17708                 lua_settop(L, curelem - 1);
17709 -               
17710 +
17711                 return 0;
17712         }
17713 -       
17714 +
17715         lua_settop(L, curelem - 1);
17716 -       
17717 +
17718         assert(curelem - 1 == lua_gettop(L));
17719 -       
17720 +
17721         return 1;
17722  }
17723  
17724 @@ -99,7 +100,7 @@
17725         lua_pushlstring(L, key, key_len);
17726         lua_pushlstring(L, val, val_len);
17727         lua_settable(L, tbl);
17728 -       
17729 +
17730         return 0;
17731  }
17732  
17733 @@ -108,21 +109,21 @@
17734         size_t is_key = 1;
17735         size_t i;
17736         char *key = NULL, *val = NULL;
17737 -       
17738 +
17739         key = qrystr->ptr;
17740 -       
17741 +
17742         /* we need the \0 */
17743         for (i = 0; i < qrystr->used; i++) {
17744                 switch(qrystr->ptr[i]) {
17745                 case '=':
17746                         if (is_key) {
17747                                 val = qrystr->ptr + i + 1;
17748 -                               
17749 +
17750                                 qrystr->ptr[i] = '\0';
17751 -                               
17752 +
17753                                 is_key = 0;
17754                         }
17755 -                       
17756 +
17757                         break;
17758                 case '&':
17759                 case '\0': /* fin symbol */
17760 @@ -131,19 +132,19 @@
17761  
17762                                 /* terminate the value */
17763                                 qrystr->ptr[i] = '\0';
17764 -                               
17765 -                               c_to_lua_push(L, tbl, 
17766 +
17767 +                               c_to_lua_push(L, tbl,
17768                                               key, strlen(key),
17769                                               val, strlen(val));
17770                         }
17771 -                       
17772 +
17773                         key = qrystr->ptr + i + 1;
17774                         val = NULL;
17775                         is_key = 1;
17776                         break;
17777                 }
17778         }
17779 -       
17780 +
17781         return 0;
17782  }
17783  #if 0
17784 @@ -151,21 +152,21 @@
17785         data_unset *d;
17786  
17787         UNUSED(srv);
17788 -       
17789 +
17790         if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
17791                 data_string *ds = (data_string *)d;
17792                 size_t key = 0, value = 0;
17793                 size_t is_key = 1, is_sid = 0;
17794                 size_t i;
17795 -               
17796 +
17797                 /* found COOKIE */
17798                 if (!DATA_IS_STRING(d)) return -1;
17799                 if (ds->value->used == 0) return -1;
17800 -                       
17801 +
17802                 if (ds->value->ptr[0] == '\0' ||
17803                     ds->value->ptr[0] == '=' ||
17804                     ds->value->ptr[0] == ';') return -1;
17805 -               
17806 +
17807                 buffer_reset(p->session_id);
17808                 for (i = 0; i < ds->value->used; i++) {
17809                         switch(ds->value->ptr[i]) {
17810 @@ -176,16 +177,16 @@
17811                                                 is_sid = 1;
17812                                         }
17813                                         value = i + 1;
17814 -                               
17815 +
17816                                         is_key = 0;
17817                                 }
17818 -                               
17819 +
17820                                 break;
17821                         case ';':
17822                                 if (is_sid) {
17823                                         buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
17824                                 }
17825 -                               
17826 +
17827                                 is_sid = 0;
17828                                 key = i + 1;
17829                                 value = 0;
17830 @@ -204,48 +205,43 @@
17831                         }
17832                 }
17833         }
17834 -       
17835 +
17836         return 0;
17837  }
17838  #endif
17839  
17840  int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
17841 -       lua_State *L; 
17842 +       lua_State *L;
17843         readme rm;
17844         int ret = -1;
17845         buffer *b = buffer_init();
17846         int header_tbl = 0;
17847 -       
17848 +
17849         rm.done = 0;
17850         stream_open(&rm.st, fn);
17851 -       
17852 +
17853         /* push the lua file to the interpreter and see what happends */
17854 -       L = lua_open();
17855 -       
17856 -       luaopen_base(L);
17857 -       luaopen_table(L);
17858 -       luaopen_string(L);
17859 -       luaopen_math(L);
17860 -       luaopen_io(L);
17861 -       
17862 +       L = luaL_newstate();
17863 +       luaL_openlibs(L);
17864 +
17865         /* register functions */
17866         lua_register(L, "md5", f_crypto_md5);
17867         lua_register(L, "file_mtime", f_file_mtime);
17868         lua_register(L, "file_isreg", f_file_isreg);
17869         lua_register(L, "file_isdir", f_file_isreg);
17870         lua_register(L, "dir_files", f_dir_files);
17871 -       
17872 +
17873  #ifdef HAVE_MEMCACHE_H
17874         lua_pushliteral(L, "memcache_get_long");
17875         lua_pushlightuserdata(L, p->conf.mc);
17876         lua_pushcclosure(L, f_memcache_get_long, 1);
17877         lua_settable(L, LUA_GLOBALSINDEX);
17878 -       
17879 +
17880         lua_pushliteral(L, "memcache_get_string");
17881         lua_pushlightuserdata(L, p->conf.mc);
17882         lua_pushcclosure(L, f_memcache_get_string, 1);
17883         lua_settable(L, LUA_GLOBALSINDEX);
17884 -       
17885 +
17886         lua_pushliteral(L, "memcache_exists");
17887         lua_pushlightuserdata(L, p->conf.mc);
17888         lua_pushcclosure(L, f_memcache_exists, 1);
17889 @@ -255,11 +251,11 @@
17890         lua_pushliteral(L, "request");
17891         lua_newtable(L);
17892         lua_settable(L, LUA_GLOBALSINDEX);
17893 -       
17894 +
17895         lua_pushliteral(L, "request");
17896         header_tbl = lua_gettop(L);
17897         lua_gettable(L, LUA_GLOBALSINDEX);
17898 -       
17899 +
17900         c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
17901         c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
17902         c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
17903 @@ -267,84 +263,84 @@
17904         if (!buffer_is_empty(con->request.pathinfo)) {
17905                 c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
17906         }
17907 -       
17908 +
17909         c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
17910         c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
17911 -       
17912 +
17913         /* register GET parameter */
17914         lua_pushliteral(L, "get");
17915         lua_newtable(L);
17916         lua_settable(L, LUA_GLOBALSINDEX);
17917 -       
17918 +
17919         lua_pushliteral(L, "get");
17920         header_tbl = lua_gettop(L);
17921         lua_gettable(L, LUA_GLOBALSINDEX);
17922 -       
17923 +
17924         buffer_copy_string_buffer(b, con->uri.query);
17925         cache_export_get_params(L, header_tbl, b);
17926         buffer_reset(b);
17927  
17928 -       /* 2 default constants */       
17929 +       /* 2 default constants */
17930         lua_pushliteral(L, "CACHE_HIT");
17931         lua_pushboolean(L, 0);
17932         lua_settable(L, LUA_GLOBALSINDEX);
17933 -       
17934 +
17935         lua_pushliteral(L, "CACHE_MISS");
17936         lua_pushboolean(L, 1);
17937         lua_settable(L, LUA_GLOBALSINDEX);
17938 -       
17939 +
17940         /* load lua program */
17941         if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
17942                 log_error_write(srv, __FILE__, __LINE__, "s",
17943                                 lua_tostring(L,-1));
17944 -               
17945 +
17946                 goto error;
17947         }
17948 -       
17949 +
17950         /* get return value */
17951         ret = (int)lua_tonumber(L, -1);
17952         lua_pop(L, 1);
17953 -       
17954 -       /* fetch the data from lua */ 
17955 +
17956 +       /* fetch the data from lua */
17957         lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
17958 -       
17959 +
17960         if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
17961                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
17962         }
17963 -       
17964 +
17965         if (ret == 0) {
17966                 /* up to now it is a cache-hit, check if all files exist */
17967 -               
17968 +
17969                 int curelem;
17970                 time_t mtime = 0;
17971 -       
17972 +
17973                 if (!lua_to_c_is_table(L, "output_include")) {
17974                         log_error_write(srv, __FILE__, __LINE__, "s",
17975                                 "output_include is missing or not a table");
17976                         ret = -1;
17977 -               
17978 +
17979                         goto error;
17980                 }
17981 -               
17982 +
17983                 lua_pushstring(L, "output_include");
17984 -               
17985 +
17986                 curelem = lua_gettop(L);
17987                 lua_gettable(L, LUA_GLOBALSINDEX);
17988  
17989                 /* HOW-TO build a etag ?
17990 -                * as we don't just have one file we have to take the stat() 
17991 +                * as we don't just have one file we have to take the stat()
17992                  * from all base files, merge them and build the etag from
17993                  * it later.
17994 -                * 
17995 +                *
17996                  * The mtime of the content is the mtime of the freshest base file
17997 -                * 
17998 +                *
17999                  * */
18000 -               
18001 +
18002                 lua_pushnil(L);  /* first key */
18003                 while (lua_next(L, curelem) != 0) {
18004                         stat_cache_entry *sce = NULL;
18005                         /* key' is at index -2 and value' at index -1 */
18006 -                       
18007 +
18008                         if (lua_isstring(L, -1)) {
18009                                 const char *s = lua_tostring(L, -1);
18010  
18011 @@ -364,18 +360,18 @@
18012                                                 /* a file is missing, call the handler to generate it */
18013                                                 if (!buffer_is_empty(p->trigger_handler)) {
18014                                                         ret = 1; /* cache-miss */
18015 -                                                       
18016 +
18017                                                         log_error_write(srv, __FILE__, __LINE__, "s",
18018                                                                         "a file is missing, calling handler");
18019 -                                                       
18020 +
18021                                                         break;
18022                                                 } else {
18023                                                         /* handler not set -> 500 */
18024                                                         ret = -1;
18025 -                                                       
18026 +
18027                                                         log_error_write(srv, __FILE__, __LINE__, "s",
18028                                                                         "a file missing and no handler set");
18029 -                                                       
18030 +
18031                                                         break;
18032                                                 }
18033                                                 break;
18034 @@ -393,12 +389,12 @@
18035                                                 "not a string");
18036                                 break;
18037                         }
18038 -               
18039 +
18040                         lua_pop(L, 1);  /* removes value'; keeps key' for next iteration */
18041                 }
18042 -               
18043 +
18044                 lua_settop(L, curelem - 1);
18045 -               
18046 +
18047                 if (ret == 0) {
18048                         data_string *ds;
18049                         char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
18050 @@ -410,9 +406,9 @@
18051  
18052                         /* no Last-Modified specified */
18053                         if ((mtime) && (NULL == ds)) {
18054 -               
18055 +
18056                                 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
18057 -                               
18058 +
18059                                 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
18060  
18061  
18062 @@ -428,9 +424,9 @@
18063                                 tbuf.used = 0;
18064                                 tbuf.ptr = NULL;
18065                         }
18066 -                       
18067 +
18068                         if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
18069 -                               /* ok, the client already has our content, 
18070 +                               /* ok, the client already has our content,
18071                                  * no need to send it again */
18072  
18073                                 chunkqueue_reset(con->write_queue);
18074 @@ -440,24 +436,24 @@
18075                         chunkqueue_reset(con->write_queue);
18076                 }
18077         }
18078 -       
18079 +
18080         if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
18081                 /* cache-miss */
18082                 buffer_copy_string_buffer(con->uri.path, p->baseurl);
18083                 buffer_append_string_buffer(con->uri.path, p->trigger_handler);
18084 -       
18085 +
18086                 buffer_copy_string_buffer(con->physical.path, p->basedir);
18087                 buffer_append_string_buffer(con->physical.path, p->trigger_handler);
18088 -               
18089 +
18090                 chunkqueue_reset(con->write_queue);
18091         }
18092 -       
18093 +
18094  error:
18095         lua_close(L);
18096 -       
18097 +
18098         stream_close(&rm.st);
18099         buffer_free(b);
18100 -       
18101 +
18102         return ret /* cache-error */;
18103  }
18104  #else
18105 --- ../lighttpd-1.4.11/src/mod_compress.c       2005-11-18 13:49:14.000000000 +0200
18106 +++ lighttpd-1.4.12/src/mod_compress.c  2006-07-11 22:07:53.000000000 +0300
18107 @@ -2,7 +2,6 @@
18108  #include <sys/stat.h>
18109  
18110  #include <fcntl.h>
18111 -#include <unistd.h>
18112  #include <ctype.h>
18113  #include <stdlib.h>
18114  #include <string.h>
18115 @@ -14,6 +13,7 @@
18116  #include "buffer.h"
18117  #include "response.h"
18118  #include "stat_cache.h"
18119 +#include "http_chunk.h"
18120  
18121  #include "plugin.h"
18122  
18123 @@ -33,6 +33,7 @@
18124  #endif
18125  
18126  #include "sys-mmap.h"
18127 +#include "sys-files.h"
18128  
18129  /* request: accept-encoding */
18130  #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
18131 @@ -55,97 +56,127 @@
18132         PLUGIN_DATA;
18133         buffer *ofn;
18134         buffer *b;
18135 -       
18136 +
18137         plugin_config **config_storage;
18138 -       plugin_config conf; 
18139 +       plugin_config conf;
18140  } plugin_data;
18141  
18142  INIT_FUNC(mod_compress_init) {
18143         plugin_data *p;
18144 -       
18145 +
18146         p = calloc(1, sizeof(*p));
18147 -       
18148 +
18149         p->ofn = buffer_init();
18150         p->b = buffer_init();
18151 -       
18152 +
18153         return p;
18154  }
18155  
18156  FREE_FUNC(mod_compress_free) {
18157         plugin_data *p = p_d;
18158 -       
18159 +
18160         UNUSED(srv);
18161  
18162         if (!p) return HANDLER_GO_ON;
18163 -       
18164 +
18165         buffer_free(p->ofn);
18166         buffer_free(p->b);
18167 -       
18168 +
18169         if (p->config_storage) {
18170                 size_t i;
18171                 for (i = 0; i < srv->config_context->used; i++) {
18172                         plugin_config *s = p->config_storage[i];
18173  
18174                         if (!s) continue;
18175 -                       
18176 +
18177                         array_free(s->compress);
18178                         buffer_free(s->compress_cache_dir);
18179 -                       
18180 +
18181                         free(s);
18182                 }
18183                 free(p->config_storage);
18184         }
18185 -       
18186 -       
18187 +
18188 +
18189         free(p);
18190 -       
18191 +
18192         return HANDLER_GO_ON;
18193  }
18194  
18195 +void mkdir_recursive(const char *dir) {
18196 +
18197 +       char dir_copy[256];
18198 +       char *p = dir_copy;
18199 +
18200 +       if (!dir || !dir[0])
18201 +               return;
18202 +
18203 +       strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
18204 +
18205 +       while ((p = strchr(p + 1, '/')) != NULL) {
18206 +
18207 +               *p = '\0';
18208 +               if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
18209 +                       return;
18210 +
18211 +               *p++ = '/';
18212 +       }
18213 +
18214 +       mkdir(dir, 0700);
18215 +}
18216 +
18217  SETDEFAULTS_FUNC(mod_compress_setdefaults) {
18218         plugin_data *p = p_d;
18219         size_t i = 0;
18220 -       
18221 -       config_values_t cv[] = { 
18222 +
18223 +       config_values_t cv[] = {
18224                 { "compress.cache-dir",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
18225                 { "compress.filetype",              NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
18226                 { "compress.max-filesize",          NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
18227                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
18228         };
18229 -       
18230 +
18231         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
18232 -       
18233 +
18234         for (i = 0; i < srv->config_context->used; i++) {
18235                 plugin_config *s;
18236 -               
18237 +
18238                 s = calloc(1, sizeof(plugin_config));
18239                 s->compress_cache_dir = buffer_init();
18240                 s->compress = array_init();
18241                 s->compress_max_filesize = 0;
18242 -               
18243 +
18244                 cv[0].destination = s->compress_cache_dir;
18245                 cv[1].destination = s->compress;
18246                 cv[2].destination = &(s->compress_max_filesize);
18247 -               
18248 +
18249                 p->config_storage[i] = s;
18250 -       
18251 +
18252                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18253                         return HANDLER_ERROR;
18254                 }
18255 -               
18256 +
18257                 if (!buffer_is_empty(s->compress_cache_dir)) {
18258                         struct stat st;
18259                         if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18260 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir", 
18261 +
18262 +                               log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
18263                                                 s->compress_cache_dir, strerror(errno));
18264 -                               
18265 -                               return HANDLER_ERROR;
18266 +                               mkdir_recursive(s->compress_cache_dir->ptr);
18267 +
18268 +                               if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18269 +
18270 +                                       log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
18271 +                                                                       s->compress_cache_dir, strerror(errno));
18272 +
18273 +                                       return HANDLER_ERROR;
18274 +                               }
18275                         }
18276                 }
18277         }
18278 -       
18279 +
18280         return HANDLER_GO_ON;
18281 -       
18282 +
18283  }
18284  
18285  #ifdef USE_ZLIB
18286 @@ -153,32 +184,32 @@
18287         unsigned char *c;
18288         unsigned long crc;
18289         z_stream z;
18290 -       
18291 +
18292         UNUSED(srv);
18293         UNUSED(con);
18294  
18295         z.zalloc = Z_NULL;
18296         z.zfree = Z_NULL;
18297         z.opaque = Z_NULL;
18298 -       
18299 -       if (Z_OK != deflateInit2(&z, 
18300 +
18301 +       if (Z_OK != deflateInit2(&z,
18302                                  Z_DEFAULT_COMPRESSION,
18303 -                                Z_DEFLATED, 
18304 +                                Z_DEFLATED,
18305                                  -MAX_WBITS,  /* supress zlib-header */
18306                                  8,
18307                                  Z_DEFAULT_STRATEGY)) {
18308                 return -1;
18309         }
18310 -               
18311 +
18312         z.next_in = (unsigned char *)start;
18313         z.avail_in = st_size;
18314         z.total_in = 0;
18315 -               
18316 -                       
18317 +
18318 +
18319         buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
18320 -               
18321 +
18322         /* write gzip header */
18323 -               
18324 +
18325         c = (unsigned char *)p->b->ptr;
18326         c[0] = 0x1f;
18327         c[1] = 0x8b;
18328 @@ -190,24 +221,24 @@
18329         c[7] = (mtime >> 24) & 0xff;
18330         c[8] = 0x00; /* extra flags */
18331         c[9] = 0x03; /* UNIX */
18332 -       
18333 +
18334         p->b->used = 10;
18335         z.next_out = (unsigned char *)p->b->ptr + p->b->used;
18336         z.avail_out = p->b->size - p->b->used - 8;
18337         z.total_out = 0;
18338 -       
18339 +
18340         if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18341                 deflateEnd(&z);
18342                 return -1;
18343         }
18344 -       
18345 +
18346         /* trailer */
18347         p->b->used += z.total_out;
18348 -       
18349 +
18350         crc = generate_crc32c(start, st_size);
18351 -               
18352 +
18353         c = (unsigned char *)p->b->ptr + p->b->used;
18354 -               
18355 +
18356         c[0] = (crc >>  0) & 0xff;
18357         c[1] = (crc >>  8) & 0xff;
18358         c[2] = (crc >> 16) & 0xff;
18359 @@ -221,51 +252,51 @@
18360         if (Z_OK != deflateEnd(&z)) {
18361                 return -1;
18362         }
18363 -       
18364 +
18365         return 0;
18366  }
18367  
18368  static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18369         z_stream z;
18370 -       
18371 +
18372         UNUSED(srv);
18373         UNUSED(con);
18374  
18375         z.zalloc = Z_NULL;
18376         z.zfree = Z_NULL;
18377         z.opaque = Z_NULL;
18378 -       
18379 -       if (Z_OK != deflateInit2(&z, 
18380 +
18381 +       if (Z_OK != deflateInit2(&z,
18382                                  Z_DEFAULT_COMPRESSION,
18383 -                                Z_DEFLATED, 
18384 +                                Z_DEFLATED,
18385                                  -MAX_WBITS,  /* supress zlib-header */
18386                                  8,
18387                                  Z_DEFAULT_STRATEGY)) {
18388                 return -1;
18389         }
18390 -               
18391 +
18392         z.next_in = start;
18393         z.avail_in = st_size;
18394         z.total_in = 0;
18395 -               
18396 +
18397         buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
18398 -       
18399 +
18400         z.next_out = (unsigned char *)p->b->ptr;
18401         z.avail_out = p->b->size;
18402         z.total_out = 0;
18403 -       
18404 +
18405         if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18406                 deflateEnd(&z);
18407                 return -1;
18408         }
18409 -       
18410 +
18411         /* trailer */
18412         p->b->used += z.total_out;
18413 -       
18414 +
18415         if (Z_OK != deflateEnd(&z)) {
18416                 return -1;
18417         }
18418 -       
18419 +
18420         return 0;
18421  }
18422  
18423 @@ -274,48 +305,48 @@
18424  #ifdef USE_BZ2LIB
18425  static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18426         bz_stream bz;
18427 -       
18428 +
18429         UNUSED(srv);
18430         UNUSED(con);
18431  
18432         bz.bzalloc = NULL;
18433         bz.bzfree = NULL;
18434         bz.opaque = NULL;
18435 -       
18436 -       if (BZ_OK != BZ2_bzCompressInit(&bz, 
18437 +
18438 +       if (BZ_OK != BZ2_bzCompressInit(&bz,
18439                                         9, /* blocksize = 900k */
18440                                         0, /* no output */
18441                                         0)) { /* workFactor: default */
18442                 return -1;
18443         }
18444 -               
18445 +
18446         bz.next_in = (char *)start;
18447         bz.avail_in = st_size;
18448         bz.total_in_lo32 = 0;
18449         bz.total_in_hi32 = 0;
18450 -               
18451 +
18452         buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
18453 -       
18454 +
18455         bz.next_out = p->b->ptr;
18456         bz.avail_out = p->b->size;
18457         bz.total_out_lo32 = 0;
18458         bz.total_out_hi32 = 0;
18459 -       
18460 +
18461         if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
18462                 BZ2_bzCompressEnd(&bz);
18463                 return -1;
18464         }
18465 -       
18466 +
18467         /* file is too large for now */
18468         if (bz.total_out_hi32) return -1;
18469 -       
18470 +
18471         /* trailer */
18472         p->b->used = bz.total_out_lo32;
18473 -       
18474 +
18475         if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
18476                 return -1;
18477         }
18478 -       
18479 +
18480         return 0;
18481  }
18482  #endif
18483 @@ -326,47 +357,50 @@
18484         void *start;
18485         const char *filename = fn->ptr;
18486         ssize_t r;
18487 -       
18488 +       stat_cache_entry *compressed_sce = NULL;
18489 +
18490 +       if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
18491 +
18492         /* overflow */
18493         if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18494 -       
18495 -       /* don't mmap files > 128Mb 
18496 -        * 
18497 +
18498 +       /* don't mmap files > 128Mb
18499 +        *
18500          * we could use a sliding window, but currently there is no need for it
18501          */
18502 -       
18503 +
18504         if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18505 -       
18506 +
18507         buffer_reset(p->ofn);
18508         buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
18509 -       BUFFER_APPEND_SLASH(p->ofn);
18510 -       
18511 +       PATHNAME_APPEND_SLASH(p->ofn);
18512 +
18513         if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
18514                 size_t offset = p->ofn->used - 1;
18515                 char *dir, *nextdir;
18516 -               
18517 +
18518                 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
18519 -               
18520 +
18521                 buffer_copy_string_buffer(p->b, p->ofn);
18522 -               
18523 +
18524                 /* mkdir -p ... */
18525                 for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
18526                         *nextdir = '\0';
18527 -                       
18528 +
18529                         if (-1 == mkdir(p->b->ptr, 0700)) {
18530                                 if (errno != EEXIST) {
18531                                         log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
18532 -                                       
18533 +
18534                                         return -1;
18535                                 }
18536                         }
18537 -                       
18538 +
18539                         *nextdir = '/';
18540                 }
18541         } else {
18542                 buffer_append_string_buffer(p->ofn, con->uri.path);
18543         }
18544 -       
18545 +
18546         switch(type) {
18547         case HTTP_ACCEPT_ENCODING_GZIP:
18548                 buffer_append_string(p->ofn, "-gzip-");
18549 @@ -381,55 +415,64 @@
18550                 log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type);
18551                 return -1;
18552         }
18553 -       
18554 +
18555         buffer_append_string_buffer(p->ofn, sce->etag);
18556 -       
18557 +
18558 +
18559 +       if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
18560 +               /* file exists */
18561 +
18562 +               http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
18563 +               con->file_finished = 1;
18564 +
18565 +               return 0;
18566 +       }
18567 +
18568         if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
18569                 if (errno == EEXIST) {
18570                         /* cache-entry exists */
18571 -#if 0
18572 -                       log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
18573 -#endif
18574 -                       buffer_copy_string_buffer(con->physical.path, p->ofn);
18575 -                       
18576 -                       return 0;
18577 +
18578                 }
18579 -               
18580 -               log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
18581 -               
18582 +
18583 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
18584 +                               "creating cachefile", p->ofn,
18585 +                               "failed", strerror(errno));
18586 +
18587                 return -1;
18588         }
18589 -#if 0
18590 -       log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
18591 -#endif 
18592 +
18593         if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
18594 -               log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18595 -               
18596 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
18597 +                               "opening plain-file", fn,
18598 +                               "failed", strerror(errno));
18599 +
18600                 close(ofd);
18601 -               
18602 +
18603                 return -1;
18604         }
18605 -       
18606 -       
18607 +
18608 +
18609         if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18610 -               log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18611 -               
18612 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
18613 +                               "mmaping", fn,
18614 +                               "failed", strerror(errno));
18615 +
18616                 close(ofd);
18617                 close(ifd);
18618                 return -1;
18619         }
18620 -       
18621 +
18622         switch(type) {
18623  #ifdef USE_ZLIB
18624 -       case HTTP_ACCEPT_ENCODING_GZIP: 
18625 +       case HTTP_ACCEPT_ENCODING_GZIP:
18626                 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
18627                 break;
18628 -       case HTTP_ACCEPT_ENCODING_DEFLATE: 
18629 +       case HTTP_ACCEPT_ENCODING_DEFLATE:
18630                 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
18631                 break;
18632  #endif
18633  #ifdef USE_BZ2LIB
18634 -       case HTTP_ACCEPT_ENCODING_BZIP2: 
18635 +       case HTTP_ACCEPT_ENCODING_BZIP2:
18636                 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
18637                 break;
18638  #endif
18639 @@ -437,26 +480,27 @@
18640                 ret = -1;
18641                 break;
18642         }
18643 -       
18644 +
18645         if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
18646 -               munmap(start, sce->st.st_size); 
18647 +               munmap(start, sce->st.st_size);
18648                 close(ofd);
18649                 close(ifd);
18650                 return -1;
18651         }
18652 -       
18653 +
18654         if ((size_t)r != p->b->used) {
18655 -               
18656 +
18657         }
18658 -               
18659 +
18660         munmap(start, sce->st.st_size);
18661         close(ofd);
18662         close(ifd);
18663 -       
18664 +
18665         if (ret != 0) return -1;
18666 -       
18667 -       buffer_copy_string_buffer(con->physical.path, p->ofn);
18668 -       
18669 +
18670 +       http_chunk_append_file(srv, con, p->ofn, 0, r);
18671 +       con->file_finished = 1;
18672 +
18673         return 0;
18674  }
18675  
18676 @@ -465,43 +509,44 @@
18677         int ret = -1;
18678         void *start;
18679         buffer *b;
18680 -       
18681 +
18682         /* overflow */
18683         if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18684 -       
18685 +
18686         /* don't mmap files > 128M
18687 -        * 
18688 +        *
18689          * we could use a sliding window, but currently there is no need for it
18690          */
18691 -       
18692 +
18693         if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18694 -       
18695 -       
18696 +
18697         if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
18698                 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18699 -               
18700 +
18701                 return -1;
18702         }
18703 -       
18704 -       
18705 -       if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18706 +
18707 +       start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
18708 +
18709 +       close(ifd);
18710 +
18711 +       if (MAP_FAILED == start) {
18712                 log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18713 -               
18714 -               close(ifd);
18715 +
18716                 return -1;
18717         }
18718 -       
18719 +
18720         switch(type) {
18721  #ifdef USE_ZLIB
18722 -       case HTTP_ACCEPT_ENCODING_GZIP: 
18723 +       case HTTP_ACCEPT_ENCODING_GZIP:
18724                 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
18725                 break;
18726 -       case HTTP_ACCEPT_ENCODING_DEFLATE: 
18727 +       case HTTP_ACCEPT_ENCODING_DEFLATE:
18728                 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
18729                 break;
18730  #endif
18731  #ifdef USE_BZ2LIB
18732 -       case HTTP_ACCEPT_ENCODING_BZIP2: 
18733 +       case HTTP_ACCEPT_ENCODING_BZIP2:
18734                 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
18735                 break;
18736  #endif
18737 @@ -509,69 +554,64 @@
18738                 ret = -1;
18739                 break;
18740         }
18741 -               
18742 +
18743         munmap(start, sce->st.st_size);
18744 -       close(ifd);
18745 -       
18746 +
18747         if (ret != 0) return -1;
18748 -       
18749 +
18750         chunkqueue_reset(con->write_queue);
18751         b = chunkqueue_get_append_buffer(con->write_queue);
18752         buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
18753 -       
18754 +
18755         buffer_reset(con->physical.path);
18756 -       
18757 +
18758         con->file_finished = 1;
18759         con->file_started  = 1;
18760 -       
18761 +
18762         return 0;
18763  }
18764  
18765 -
18766 -#define PATCH(x) \
18767 -       p->conf.x = s->x;
18768  static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
18769         size_t i, j;
18770         plugin_config *s = p->config_storage[0];
18771  
18772 -       PATCH(compress_cache_dir);
18773 -       PATCH(compress);
18774 -       PATCH(compress_max_filesize);
18775 -       
18776 +       PATCH_OPTION(compress_cache_dir);
18777 +       PATCH_OPTION(compress);
18778 +       PATCH_OPTION(compress_max_filesize);
18779 +
18780         /* skip the first, the global context */
18781         for (i = 1; i < srv->config_context->used; i++) {
18782                 data_config *dc = (data_config *)srv->config_context->data[i];
18783                 s = p->config_storage[i];
18784 -               
18785 +
18786                 /* condition didn't match */
18787                 if (!config_check_cond(srv, con, dc)) continue;
18788 -               
18789 +
18790                 /* merge config */
18791                 for (j = 0; j < dc->value->used; j++) {
18792                         data_unset *du = dc->value->data[j];
18793 -                       
18794 +
18795                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
18796 -                               PATCH(compress_cache_dir);
18797 +                               PATCH_OPTION(compress_cache_dir);
18798                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
18799 -                               PATCH(compress);
18800 +                               PATCH_OPTION(compress);
18801                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
18802 -                               PATCH(compress_max_filesize);
18803 +                               PATCH_OPTION(compress_max_filesize);
18804                         }
18805                 }
18806         }
18807 -       
18808 +
18809         return 0;
18810  }
18811 -#undef PATCH
18812  
18813  PHYSICALPATH_FUNC(mod_compress_physical) {
18814         plugin_data *p = p_d;
18815         size_t m;
18816         off_t max_fsize;
18817         stat_cache_entry *sce = NULL;
18818 -       
18819 +
18820         /* only GET and POST can get compressed */
18821 -       if (con->request.http_method != HTTP_METHOD_GET && 
18822 +       if (con->request.http_method != HTTP_METHOD_GET &&
18823             con->request.http_method != HTTP_METHOD_POST) {
18824                 return HANDLER_GO_ON;
18825         }
18826 @@ -579,46 +619,49 @@
18827         if (buffer_is_empty(con->physical.path)) {
18828                 return HANDLER_GO_ON;
18829         }
18830 -       
18831 +
18832         mod_compress_patch_connection(srv, con, p);
18833 -       
18834 +
18835         max_fsize = p->conf.compress_max_filesize;
18836  
18837         stat_cache_get_entry(srv, con, con->physical.path, &sce);
18838  
18839         /* don't compress files that are too large as we need to much time to handle them */
18840         if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
18841 -               
18842 +
18843 +       /* compressing the file might lead to larger files instead */
18844 +       if (sce->st.st_size < 128) return HANDLER_GO_ON;
18845 +
18846         /* check if mimetype is in compress-config */
18847         for (m = 0; m < p->conf.compress->used; m++) {
18848                 data_string *compress_ds = (data_string *)p->conf.compress->data[m];
18849 -                       
18850 +
18851                 if (!compress_ds) {
18852                         log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
18853 -                       
18854 +
18855                         return HANDLER_GO_ON;
18856                 }
18857 -               
18858 +
18859                 if (buffer_is_equal(compress_ds->value, sce->content_type)) {
18860                         /* mimetype found */
18861                         data_string *ds;
18862 -                               
18863 +
18864                         /* the response might change according to Accept-Encoding */
18865                         response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
18866 -                               
18867 +
18868                         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
18869                                 int accept_encoding = 0;
18870                                 char *value = ds->value->ptr;
18871                                 int srv_encodings = 0;
18872                                 int matched_encodings = 0;
18873 -                               
18874 +
18875                                 /* get client side support encodings */
18876                                 if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
18877                                 if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
18878                                 if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
18879                                 if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
18880                                 if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
18881 -                               
18882 +
18883                                 /* get server side supported ones */
18884  #ifdef USE_BZ2LIB
18885                                 srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
18886 @@ -627,18 +670,31 @@
18887                                 srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
18888                                 srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
18889  #endif
18890 -                               
18891 +
18892                                 /* find matching entries */
18893                                 matched_encodings = accept_encoding & srv_encodings;
18894 -                               
18895 +
18896                                 if (matched_encodings) {
18897                                         const char *dflt_gzip = "gzip";
18898                                         const char *dflt_deflate = "deflate";
18899                                         const char *dflt_bzip2 = "bzip2";
18900 -                                       
18901 +
18902                                         const char *compression_name = NULL;
18903                                         int compression_type = 0;
18904 -                                       
18905 +                                       buffer *mtime;
18906 +
18907 +                                       mtime = strftime_cache_get(srv, sce->st.st_mtime);
18908 +                                       etag_mutate(con->physical.etag, sce->etag);
18909 +
18910 +                                       response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
18911 +                                       response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
18912 +
18913 +                                       /* perhaps we don't even have to compress the file as the browser still has the
18914 +                                        * current version */
18915 +                                       if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
18916 +                                               return HANDLER_FINISHED;
18917 +                                       }
18918 +
18919                                         /* select best matching encoding */
18920                                         if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
18921                                                 compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
18922 @@ -650,31 +706,21 @@
18923                                                 compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
18924                                                 compression_name = dflt_deflate;
18925                                         }
18926 -                                       
18927 -                                       /* deflate it */
18928 -                                       if (p->conf.compress_cache_dir->used) {
18929 -                                               if (0 == deflate_file_to_file(srv, con, p,
18930 -                                                                             con->physical.path, sce, compression_type)) {
18931 -                                                       buffer *mtime;
18932 -                                                       
18933 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
18934 -                                                       
18935 -                                                       mtime = strftime_cache_get(srv, sce->st.st_mtime);
18936 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
18937 -
18938 -                                                       etag_mutate(con->physical.etag, sce->etag);
18939 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
18940 -
18941 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
18942 -
18943 -                                                       return HANDLER_GO_ON;
18944 -                                               }
18945 -                                       } else if (0 == deflate_file_to_buffer(srv, con, p,
18946 -                                                                              con->physical.path, sce, compression_type)) {
18947 -                                                       
18948 -                                               response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
18949 -                                               response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
18950 -                                               
18951 +
18952 +                                       /* deflate it to file (cached) or to memory */
18953 +                                       if (0 == deflate_file_to_file(srv, con, p,
18954 +                                                       con->physical.path, sce, compression_type) ||
18955 +                                           0 == deflate_file_to_buffer(srv, con, p,
18956 +                                                       con->physical.path, sce, compression_type)) {
18957 +
18958 +                                               response_header_overwrite(srv, con,
18959 +                                                               CONST_STR_LEN("Content-Encoding"),
18960 +                                                               compression_name, strlen(compression_name));
18961 +
18962 +                                               response_header_overwrite(srv, con,
18963 +                                                               CONST_STR_LEN("Content-Type"),
18964 +                                                               CONST_BUF_LEN(sce->content_type));
18965 +
18966                                                 return HANDLER_FINISHED;
18967                                         }
18968                                         break;
18969 @@ -682,20 +728,20 @@
18970                         }
18971                 }
18972         }
18973 -       
18974 +
18975         return HANDLER_GO_ON;
18976  }
18977  
18978  int mod_compress_plugin_init(plugin *p) {
18979         p->version     = LIGHTTPD_VERSION_ID;
18980         p->name        = buffer_init_string("compress");
18981 -       
18982 +
18983         p->init        = mod_compress_init;
18984         p->set_defaults = mod_compress_setdefaults;
18985         p->handle_subrequest_start  = mod_compress_physical;
18986         p->cleanup     = mod_compress_free;
18987 -       
18988 +
18989         p->data        = NULL;
18990 -       
18991 +
18992         return 0;
18993  }
18994 --- ../lighttpd-1.4.11/src/mod_dirlisting.c     2006-01-13 00:00:45.000000000 +0200
18995 +++ lighttpd-1.4.12/src/mod_dirlisting.c        2006-07-15 22:43:21.000000000 +0300
18996 @@ -1,11 +1,9 @@
18997  #include <ctype.h>
18998  #include <stdlib.h>
18999  #include <string.h>
19000 -#include <dirent.h>
19001  #include <assert.h>
19002  #include <errno.h>
19003  #include <stdio.h>
19004 -#include <unistd.h>
19005  #include <time.h>
19006  
19007  #include "base.h"
19008 @@ -17,6 +15,9 @@
19009  #include "response.h"
19010  #include "stat_cache.h"
19011  #include "stream.h"
19012 +#include "etag.h"
19013 +
19014 +#include "sys-strings.h"
19015  
19016  /**
19017   * this is a dirlisting for a lighttpd plugin
19018 @@ -27,10 +28,13 @@
19019  #include <sys/syslimits.h>
19020  #endif
19021  
19022 -#ifdef HAVE_ATTR_ATTRIBUTES_H
19023 +#ifdef HAVE_XATTR
19024  #include <attr/attributes.h>
19025  #endif
19026  
19027 +#include "sys-files.h"
19028 +#include "sys-strings.h"
19029 +
19030  /* plugin config for all request/connections */
19031  
19032  typedef struct {
19033 @@ -54,7 +58,7 @@
19034         unsigned short hide_readme_file;
19035         unsigned short show_header;
19036         unsigned short hide_header_file;
19037 -       
19038 +
19039         excludes_buffer *excludes;
19040  
19041         buffer *external_css;
19042 @@ -63,13 +67,14 @@
19043  
19044  typedef struct {
19045         PLUGIN_DATA;
19046 -       
19047 +
19048         buffer *tmp_buf;
19049         buffer *content_charset;
19050 -       
19051 +       buffer *path;
19052 +
19053         plugin_config **config_storage;
19054 -       
19055 -       plugin_config conf; 
19056 +
19057 +       plugin_config conf;
19058  } plugin_data;
19059  
19060  excludes_buffer *excludes_buffer_init(void) {
19061 @@ -146,44 +151,46 @@
19062  /* init the plugin data */
19063  INIT_FUNC(mod_dirlisting_init) {
19064         plugin_data *p;
19065 -       
19066 +
19067         p = calloc(1, sizeof(*p));
19068  
19069         p->tmp_buf = buffer_init();
19070         p->content_charset = buffer_init();
19071 -       
19072 +       p->path = buffer_init();
19073 +
19074         return p;
19075  }
19076  
19077  /* detroy the plugin data */
19078  FREE_FUNC(mod_dirlisting_free) {
19079         plugin_data *p = p_d;
19080 -       
19081 +
19082         UNUSED(srv);
19083  
19084         if (!p) return HANDLER_GO_ON;
19085 -       
19086 +
19087         if (p->config_storage) {
19088                 size_t i;
19089                 for (i = 0; i < srv->config_context->used; i++) {
19090                         plugin_config *s = p->config_storage[i];
19091 -                       
19092 +
19093                         if (!s) continue;
19094 -                       
19095 +
19096                         excludes_buffer_free(s->excludes);
19097                         buffer_free(s->external_css);
19098                         buffer_free(s->encoding);
19099 -                       
19100 +
19101                         free(s);
19102                 }
19103                 free(p->config_storage);
19104         }
19105 -       
19106 +
19107         buffer_free(p->tmp_buf);
19108 +       buffer_free(p->path);
19109         buffer_free(p->content_charset);
19110 -       
19111 +
19112         free(p);
19113 -       
19114 +
19115         return HANDLER_GO_ON;
19116  }
19117  
19118 @@ -215,10 +222,10 @@
19119                         if (0 != excludes_buffer_append(s->excludes,
19120                                     ((data_string *)(da->value->data[j]))->value)) {
19121  #ifdef HAVE_PCRE_H
19122 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
19123 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
19124                                                 "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
19125  #else
19126 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
19127 +                               log_error_write(srv, __FILE__, __LINE__, "s",
19128                                                 "pcre support is missing, please install libpcre and the headers");
19129  #endif
19130                         }
19131 @@ -233,8 +240,8 @@
19132  SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
19133         plugin_data *p = p_d;
19134         size_t i = 0;
19135 -       
19136 -       config_values_t cv[] = { 
19137 +
19138 +       config_values_t cv[] = {
19139                 { "dir-listing.exclude",          NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },   /* 0 */
19140                 { "dir-listing.activate",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
19141                 { "dir-listing.hide-dotfiles",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
19142 @@ -245,18 +252,18 @@
19143                 { "dir-listing.show-header",      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
19144                 { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
19145                 { "server.dir-listing",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
19146 -               
19147 +
19148                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19149         };
19150 -       
19151 +
19152         if (!p) return HANDLER_ERROR;
19153 -       
19154 +
19155         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19156 -       
19157 +
19158         for (i = 0; i < srv->config_context->used; i++) {
19159                 plugin_config *s;
19160                 array *ca;
19161 -               
19162 +
19163                 s = calloc(1, sizeof(plugin_config));
19164                 s->excludes = excludes_buffer_init();
19165                 s->dir_listing = 0;
19166 @@ -267,7 +274,7 @@
19167                 s->show_header = 0;
19168                 s->hide_header_file = 0;
19169                 s->encoding = buffer_init();
19170 -               
19171 +
19172                 cv[0].destination = s->excludes;
19173                 cv[1].destination = &(s->dir_listing);
19174                 cv[2].destination = &(s->hide_dot_files);
19175 @@ -292,60 +299,57 @@
19176         return HANDLER_GO_ON;
19177  }
19178  
19179 -#define PATCH(x) \
19180 -       p->conf.x = s->x;
19181  static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
19182         size_t i, j;
19183         plugin_config *s = p->config_storage[0];
19184  
19185 -       PATCH(dir_listing);
19186 -       PATCH(external_css);
19187 -       PATCH(hide_dot_files);
19188 -       PATCH(encoding);
19189 -       PATCH(show_readme);
19190 -       PATCH(hide_readme_file);
19191 -       PATCH(show_header);
19192 -       PATCH(hide_header_file);
19193 -       PATCH(excludes);
19194 -       
19195 +       PATCH_OPTION(dir_listing);
19196 +       PATCH_OPTION(external_css);
19197 +       PATCH_OPTION(hide_dot_files);
19198 +       PATCH_OPTION(encoding);
19199 +       PATCH_OPTION(show_readme);
19200 +       PATCH_OPTION(hide_readme_file);
19201 +       PATCH_OPTION(show_header);
19202 +       PATCH_OPTION(hide_header_file);
19203 +       PATCH_OPTION(excludes);
19204 +
19205         /* skip the first, the global context */
19206         for (i = 1; i < srv->config_context->used; i++) {
19207                 data_config *dc = (data_config *)srv->config_context->data[i];
19208                 s = p->config_storage[i];
19209 -               
19210 +
19211                 /* condition didn't match */
19212                 if (!config_check_cond(srv, con, dc)) continue;
19213 -               
19214 +
19215                 /* merge config */
19216                 for (j = 0; j < dc->value->used; j++) {
19217                         data_unset *du = dc->value->data[j];
19218 -                       
19219 +
19220                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
19221                             buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
19222 -                               PATCH(dir_listing);
19223 +                               PATCH_OPTION(dir_listing);
19224                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
19225 -                               PATCH(hide_dot_files);
19226 +                               PATCH_OPTION(hide_dot_files);
19227                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
19228 -                               PATCH(external_css);
19229 +                               PATCH_OPTION(external_css);
19230                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
19231 -                               PATCH(encoding);
19232 +                               PATCH_OPTION(encoding);
19233                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
19234 -                               PATCH(show_readme);
19235 +                               PATCH_OPTION(show_readme);
19236                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
19237 -                               PATCH(hide_readme_file);
19238 +                               PATCH_OPTION(hide_readme_file);
19239                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
19240 -                               PATCH(show_header);
19241 +                               PATCH_OPTION(show_header);
19242                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
19243 -                               PATCH(hide_header_file);
19244 +                               PATCH_OPTION(hide_header_file);
19245                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
19246 -                               PATCH(excludes);
19247 +                               PATCH_OPTION(excludes);
19248                         }
19249                 }
19250         }
19251 -       
19252 +
19253         return 0;
19254  }
19255 -#undef PATCH
19256  
19257  typedef struct {
19258         size_t  namelen;
19259 @@ -432,7 +436,7 @@
19260  
19261  static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
19262         UNUSED(srv);
19263 -       
19264 +
19265         BUFFER_APPEND_STRING_CONST(out,
19266                 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
19267                 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
19268 @@ -492,11 +496,11 @@
19269         if (p->conf.show_header) {
19270                 stream s;
19271                 /* if we have a HEADER file, display it in <pre class="header"></pre> */
19272 -               
19273 +
19274                 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
19275 -               BUFFER_APPEND_SLASH(p->tmp_buf);
19276 +               PATHNAME_APPEND_SLASH(p->tmp_buf);
19277                 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
19278 -               
19279 +
19280                 if (-1 != stream_open(&s, p->tmp_buf)) {
19281                         BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
19282                         buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19283 @@ -531,21 +535,21 @@
19284  
19285  static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
19286         UNUSED(srv);
19287 -       
19288 +
19289         BUFFER_APPEND_STRING_CONST(out,
19290                 "</tbody>\n"
19291                 "</table>\n"
19292                 "</div>\n"
19293         );
19294 -       
19295 +
19296         if (p->conf.show_readme) {
19297                 stream s;
19298                 /* if we have a README file, display it in <pre class="readme"></pre> */
19299 -               
19300 +
19301                 buffer_copy_string_buffer(p->tmp_buf,  con->physical.path);
19302 -               BUFFER_APPEND_SLASH(p->tmp_buf);
19303 +               PATHNAME_APPEND_SLASH(p->tmp_buf);
19304                 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
19305 -               
19306 +
19307                 if (-1 != stream_open(&s, p->tmp_buf)) {
19308                         BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
19309                         buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19310 @@ -553,7 +557,7 @@
19311                 }
19312                 stream_close(&s);
19313         }
19314 -       
19315 +
19316         BUFFER_APPEND_STRING_CONST(out,
19317                 "<div class=\"foot\">"
19318         );
19319 @@ -576,7 +580,6 @@
19320         buffer *out;
19321         struct dirent *dent;
19322         struct stat st;
19323 -       char *path, *path_file;
19324         size_t i;
19325         int hide_dotfiles = p->conf.hide_dot_files;
19326         dirls_list_t dirs, files, *list;
19327 @@ -586,6 +589,7 @@
19328         size_t k;
19329         const char *content_type;
19330         long name_max;
19331 +
19332  #ifdef HAVE_XATTR
19333         char attrval[128];
19334         int attrlen;
19335 @@ -594,10 +598,10 @@
19336         struct tm tm;
19337  #endif
19338  
19339 -       if (dir->used == 0) return -1;
19340 -       
19341 -       i = dir->used - 1;
19342 +       /* empty pathname, never ... */
19343 +       if (buffer_is_empty(dir)) return -1;
19344  
19345 +       /* max-length for the opendir */
19346  #ifdef HAVE_PATHCONF
19347         if (-1 == (name_max = pathconf(dir->ptr, _PC_NAME_MAX))) {
19348  #ifdef NAME_MAX
19349 @@ -606,22 +610,24 @@
19350                 name_max = 256; /* stupid default */
19351  #endif
19352         }
19353 -#elif defined __WIN32
19354 +#elif defined _WIN32
19355         name_max = FILENAME_MAX;
19356  #else
19357         name_max = NAME_MAX;
19358  #endif
19359 -       
19360 -       path = malloc(dir->used + name_max);
19361 -       assert(path);
19362 -       strcpy(path, dir->ptr);
19363 -       path_file = path + i;
19364  
19365 -       if (NULL == (dp = opendir(path))) {
19366 -               log_error_write(srv, __FILE__, __LINE__, "sbs", 
19367 +       buffer_copy_string_buffer(p->path, dir);
19368 +       PATHNAME_APPEND_SLASH(p->path);
19369 +
19370 +#ifdef _WIN32
19371 +       /* append *.* to the path */
19372 +       buffer_append_string(path, "*.*");
19373 +#endif
19374 +
19375 +       if (NULL == (dp = opendir(p->path->ptr))) {
19376 +               log_error_write(srv, __FILE__, __LINE__, "sbs",
19377                         "opendir failed:", dir, strerror(errno));
19378  
19379 -               free(path);
19380                 return -1;
19381         }
19382  
19383 @@ -633,7 +639,7 @@
19384         assert(files.ent);
19385         files.size = DIRLIST_BLOB_SIZE;
19386         files.used = 0;
19387 -       
19388 +
19389         while ((dent = readdir(dp)) != NULL) {
19390                 unsigned short exclude_match = 0;
19391  
19392 @@ -686,15 +692,21 @@
19393  #endif
19394  
19395                 i = strlen(dent->d_name);
19396 -               
19397 +
19398                 /* NOTE: the manual says, d_name is never more than NAME_MAX
19399                  *       so this should actually not be a buffer-overflow-risk
19400                  */
19401                 if (i > (size_t)name_max) continue;
19402 -               
19403 -               memcpy(path_file, dent->d_name, i + 1);
19404 -               if (stat(path, &st) != 0)
19405 +
19406 +               /* build the dirname */
19407 +               buffer_copy_string_buffer(p->path, dir);
19408 +               PATHNAME_APPEND_SLASH(p->path);
19409 +               buffer_append_string(p->path, dent->d_name);
19410 +
19411 +               if (stat(p->path->ptr, &st) != 0) {
19412 +                       fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, p->path->ptr, strerror(errno));
19413                         continue;
19414 +               }
19415  
19416                 list = &files;
19417                 if (S_ISDIR(st.st_mode))
19418 @@ -740,7 +752,7 @@
19419  #else
19420                 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
19421  #endif
19422 -               
19423 +
19424                 BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
19425                 buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
19426                 BUFFER_APPEND_STRING_CONST(out, "/\">");
19427 @@ -757,18 +769,22 @@
19428                 tmp = files.ent[i];
19429  
19430                 content_type = NULL;
19431 +
19432  #ifdef HAVE_XATTR
19433 -               
19434                 if (con->conf.use_xattr) {
19435 -                       memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
19436 +                       /* build the dirname */
19437 +                       buffer_copy_string_buffer(p->path, dir);
19438 +                       PATHNAME_APPEND_SLASH(p->path);
19439 +                       buffer_append_string_len(p->path, DIRLIST_ENT_NAME(tmp), tmp->namelen);
19440 +
19441                         attrlen = sizeof(attrval) - 1;
19442 -                       if (attr_get(path, "Content-Type", attrval, &attrlen, 0) == 0) {
19443 +                       if (attr_get(p->path->ptr, "Content-Type", attrval, &attrlen, 0) == 0) {
19444                                 attrval[attrlen] = '\0';
19445                                 content_type = attrval;
19446                         }
19447                 }
19448  #endif
19449 -               
19450 +
19451                 if (content_type == NULL) {
19452                         content_type = "application/octet-stream";
19453                         for (k = 0; k < con->conf.mimetypes->used; k++) {
19454 @@ -788,7 +804,7 @@
19455                                 }
19456                         }
19457                 }
19458 -                       
19459 +
19460  #ifdef HAVE_LOCALTIME_R
19461                 localtime_r(&(tmp->mtime), &tm);
19462                 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
19463 @@ -814,7 +830,6 @@
19464  
19465         free(files.ent);
19466         free(dirs.ent);
19467 -       free(path);
19468  
19469         http_list_directory_footer(srv, con, p, out);
19470  
19471 @@ -837,36 +852,55 @@
19472  URIHANDLER_FUNC(mod_dirlisting_subrequest) {
19473         plugin_data *p = p_d;
19474         stat_cache_entry *sce = NULL;
19475 -       
19476 -       UNUSED(srv);
19477 -       
19478 -       if (con->physical.path->used == 0) return HANDLER_GO_ON;
19479 -       if (con->uri.path->used == 0) return HANDLER_GO_ON;
19480 +       buffer *mtime;
19481 +       data_string *ds;
19482 +
19483 +       if (con->uri.path->used < 2) return HANDLER_GO_ON;
19484         if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
19485 -       
19486 +       if (con->physical.path->used == 0) return HANDLER_GO_ON;
19487 +
19488         mod_dirlisting_patch_connection(srv, con, p);
19489  
19490         if (!p->conf.dir_listing) return HANDLER_GO_ON;
19491 -       
19492 +
19493 +       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19494 +               /* just a second ago the file was still there */
19495 +               return HANDLER_GO_ON;
19496 +       }
19497 +
19498 +       if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
19499 +
19500         if (con->conf.log_request_handling) {
19501                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling the request as Dir-Listing");
19502                 log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
19503         }
19504 -       
19505 -       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19506 -               fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
19507 -               SEGFAULT();
19508 +
19509 +       /* perhaps this a cachable request
19510 +        * - we use the etag of the directory
19511 +        * */
19512 +
19513 +       etag_mutate(con->physical.etag, sce->etag);
19514 +       response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19515 +
19516 +       /* prepare header */
19517 +       if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
19518 +               mtime = strftime_cache_get(srv, sce->st.st_mtime);
19519 +               response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19520 +       } else {
19521 +               mtime = ds->value;
19522         }
19523 -       
19524 -       if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
19525 -       
19526 +
19527 +       if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
19528 +               return HANDLER_FINISHED;
19529 +       }
19530 +
19531         if (http_list_directory(srv, con, p, con->physical.path)) {
19532                 /* dirlisting failed */
19533                 con->http_status = 403;
19534         }
19535 -       
19536 +
19537         buffer_reset(con->physical.path);
19538 -       
19539 +
19540         /* not found */
19541         return HANDLER_FINISHED;
19542  }
19543 @@ -876,13 +910,13 @@
19544  int mod_dirlisting_plugin_init(plugin *p) {
19545         p->version     = LIGHTTPD_VERSION_ID;
19546         p->name        = buffer_init_string("dirlisting");
19547 -       
19548 +
19549         p->init        = mod_dirlisting_init;
19550         p->handle_subrequest_start  = mod_dirlisting_subrequest;
19551         p->set_defaults  = mod_dirlisting_set_defaults;
19552         p->cleanup     = mod_dirlisting_free;
19553 -       
19554 +
19555         p->data        = NULL;
19556 -       
19557 +
19558         return 0;
19559  }
19560 --- ../lighttpd-1.4.11/src/mod_evasive.c        2006-01-04 15:24:51.000000000 +0200
19561 +++ lighttpd-1.4.12/src/mod_evasive.c   2006-07-11 22:07:53.000000000 +0300
19562 @@ -31,100 +31,97 @@
19563  
19564  typedef struct {
19565         PLUGIN_DATA;
19566 -       
19567 +
19568         plugin_config **config_storage;
19569 -       
19570 -       plugin_config conf; 
19571 +
19572 +       plugin_config conf;
19573  } plugin_data;
19574  
19575  INIT_FUNC(mod_evasive_init) {
19576         plugin_data *p;
19577 -       
19578 +
19579         p = calloc(1, sizeof(*p));
19580 -       
19581 +
19582         return p;
19583  }
19584  
19585  FREE_FUNC(mod_evasive_free) {
19586         plugin_data *p = p_d;
19587 -       
19588 +
19589         UNUSED(srv);
19590  
19591         if (!p) return HANDLER_GO_ON;
19592 -       
19593 +
19594         if (p->config_storage) {
19595                 size_t i;
19596                 for (i = 0; i < srv->config_context->used; i++) {
19597                         plugin_config *s = p->config_storage[i];
19598 -                                               
19599 +
19600                         free(s);
19601                 }
19602                 free(p->config_storage);
19603         }
19604 -       
19605 +
19606         free(p);
19607 -       
19608 +
19609         return HANDLER_GO_ON;
19610  }
19611  
19612  SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
19613         plugin_data *p = p_d;
19614         size_t i = 0;
19615 -       
19616 -       config_values_t cv[] = { 
19617 +
19618 +       config_values_t cv[] = {
19619                 { "evasive.max-conns-per-ip",    NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
19620                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19621         };
19622 -       
19623 +
19624         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19625 -       
19626 +
19627         for (i = 0; i < srv->config_context->used; i++) {
19628                 plugin_config *s;
19629 -               
19630 +
19631                 s = calloc(1, sizeof(plugin_config));
19632                 s->max_conns       = 0;
19633 -               
19634 +
19635                 cv[0].destination = &(s->max_conns);
19636 -               
19637 +
19638                 p->config_storage[i] = s;
19639 -       
19640 +
19641                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19642                         return HANDLER_ERROR;
19643                 }
19644         }
19645 -       
19646 +
19647         return HANDLER_GO_ON;
19648  }
19649  
19650 -#define PATCH(x) \
19651 -       p->conf.x = s->x;
19652  static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
19653         size_t i, j;
19654         plugin_config *s = p->config_storage[0];
19655  
19656 -       PATCH(max_conns);
19657 -       
19658 +       PATCH_OPTION(max_conns);
19659 +
19660         /* skip the first, the global context */
19661         for (i = 1; i < srv->config_context->used; i++) {
19662                 data_config *dc = (data_config *)srv->config_context->data[i];
19663                 s = p->config_storage[i];
19664 -               
19665 +
19666                 /* condition didn't match */
19667                 if (!config_check_cond(srv, con, dc)) continue;
19668 -               
19669 +
19670                 /* merge config */
19671                 for (j = 0; j < dc->value->used; j++) {
19672                         data_unset *du = dc->value->data[j];
19673 -                       
19674 +
19675                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
19676 -                               PATCH(max_conns);
19677 +                               PATCH_OPTION(max_conns);
19678                         }
19679                 }
19680         }
19681 -       
19682 +
19683         return 0;
19684  }
19685 -#undef PATCH
19686  
19687  URIHANDLER_FUNC(mod_evasive_uri_handler) {
19688         plugin_data *p = p_d;
19689 @@ -132,10 +129,10 @@
19690         size_t j;
19691  
19692         if (con->uri.path->used == 0) return HANDLER_GO_ON;
19693 -       
19694 +
19695         mod_evasive_patch_connection(srv, con, p);
19696 -       
19697 -       /* no limit set, nothing to block */    
19698 +
19699 +       /* no limit set, nothing to block */
19700         if (p->conf.max_conns == 0) return HANDLER_GO_ON;
19701  
19702         for (j = 0; j < srv->conns->used; j++) {
19703 @@ -147,7 +144,7 @@
19704                 if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
19705                     c->state > CON_STATE_REQUEST_END) {
19706                         conns_by_ip++;
19707 -       
19708 +
19709                         if (conns_by_ip > p->conf.max_conns) {
19710                                 log_error_write(srv, __FILE__, __LINE__, "ss",
19711                                         inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
19712 @@ -158,7 +155,7 @@
19713                         }
19714                 }
19715         }
19716 -       
19717 +
19718         return HANDLER_GO_ON;
19719  }
19720  
19721 @@ -166,13 +163,13 @@
19722  int mod_evasive_plugin_init(plugin *p) {
19723         p->version     = LIGHTTPD_VERSION_ID;
19724         p->name        = buffer_init_string("evasive");
19725 -       
19726 +
19727         p->init        = mod_evasive_init;
19728         p->set_defaults = mod_evasive_set_defaults;
19729         p->handle_uri_clean  = mod_evasive_uri_handler;
19730         p->cleanup     = mod_evasive_free;
19731 -       
19732 +
19733         p->data        = NULL;
19734 -       
19735 +
19736         return 0;
19737  }
19738 --- ../lighttpd-1.4.11/src/mod_evhost.c 2005-08-17 10:42:03.000000000 +0300
19739 +++ lighttpd-1.4.12/src/mod_evhost.c    2006-07-11 22:07:51.000000000 +0300
19740 @@ -7,10 +7,12 @@
19741  #include "response.h"
19742  #include "stat_cache.h"
19743  
19744 +#include "sys-files.h"
19745 +
19746  typedef struct {
19747         /* unparsed pieces */
19748         buffer *path_pieces_raw;
19749 -       
19750 +
19751         /* pieces for path creation */
19752         size_t len;
19753         buffer **path_pieces;
19754 @@ -21,14 +23,14 @@
19755         buffer *tmp_buf;
19756  
19757         plugin_config **config_storage;
19758 -       plugin_config conf; 
19759 +       plugin_config conf;
19760  } plugin_data;
19761  
19762  INIT_FUNC(mod_evhost_init) {
19763         plugin_data *p;
19764 -       
19765 +
19766         p = calloc(1, sizeof(*p));
19767 -       
19768 +
19769         p->tmp_buf = buffer_init();
19770  
19771         return p;
19772 @@ -36,34 +38,34 @@
19773  
19774  FREE_FUNC(mod_evhost_free) {
19775         plugin_data *p = p_d;
19776 -       
19777 +
19778         UNUSED(srv);
19779  
19780         if (!p) return HANDLER_GO_ON;
19781 -       
19782 +
19783         if (p->config_storage) {
19784                 size_t i;
19785                 for (i = 0; i < srv->config_context->used; i++) {
19786                         plugin_config *s = p->config_storage[i];
19787  
19788                         if (!s) continue;
19789 -                       
19790 +
19791                         if(s->path_pieces) {
19792                                 size_t j;
19793                                 for (j = 0; j < s->len; j++) {
19794                                         buffer_free(s->path_pieces[j]);
19795                                 }
19796 -                               
19797 +
19798                                 free(s->path_pieces);
19799                         }
19800 -                       
19801 +
19802                         buffer_free(s->path_pieces_raw);
19803 -                       
19804 +
19805                         free(s);
19806                 }
19807                 free(p->config_storage);
19808         }
19809 -       
19810 +
19811         buffer_free(p->tmp_buf);
19812  
19813         free(p);
19814 @@ -73,30 +75,30 @@
19815  
19816  static void mod_evhost_parse_pattern(plugin_config *s) {
19817         char *ptr = s->path_pieces_raw->ptr,*pos;
19818 -       
19819 +
19820         s->path_pieces = NULL;
19821 -       
19822 +
19823         for(pos=ptr;*ptr;ptr++) {
19824                 if(*ptr == '%') {
19825                         s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
19826                         s->path_pieces[s->len] = buffer_init();
19827                         s->path_pieces[s->len+1] = buffer_init();
19828 -                       
19829 +
19830                         buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
19831                         pos = ptr + 2;
19832 -                       
19833 +
19834                         buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
19835 -                       
19836 +
19837                         s->len += 2;
19838                 }
19839         }
19840 -       
19841 +
19842         if(*pos != '\0') {
19843                 s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
19844                 s->path_pieces[s->len] = buffer_init();
19845 -               
19846 +
19847                 buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
19848 -               
19849 +
19850                 s->len += 1;
19851         }
19852  }
19853 @@ -104,9 +106,9 @@
19854  SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
19855         plugin_data *p = p_d;
19856         size_t i;
19857 -       
19858 +
19859         /**
19860 -        * 
19861 +        *
19862          * #
19863          * # define a pattern for the host url finding
19864          * # %% => % sign
19865 @@ -117,39 +119,39 @@
19866          * # %4 => subdomain 2 name
19867          * #
19868          * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
19869 -        * 
19870 +        *
19871          */
19872 -       
19873 -       config_values_t cv[] = { 
19874 +
19875 +       config_values_t cv[] = {
19876                 { "evhost.path-pattern",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
19877                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19878         };
19879 -       
19880 +
19881         if (!p) return HANDLER_ERROR;
19882 -       
19883 +
19884         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19885 -       
19886 +
19887         for (i = 0; i < srv->config_context->used; i++) {
19888                 plugin_config *s;
19889 -               
19890 +
19891                 s = calloc(1, sizeof(plugin_config));
19892                 s->path_pieces_raw = buffer_init();
19893                 s->path_pieces     = NULL;
19894                 s->len             = 0;
19895 -       
19896 +
19897                 cv[0].destination = s->path_pieces_raw;
19898 -               
19899 +
19900                 p->config_storage[i] = s;
19901 -               
19902 +
19903                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value,  cv)) {
19904                         return HANDLER_ERROR;
19905                 }
19906 -               
19907 +
19908                 if (s->path_pieces_raw->used != 0) {
19909                         mod_evhost_parse_pattern(s);
19910                 }
19911         }
19912 -       
19913 +
19914         return HANDLER_GO_ON;
19915  }
19916  
19917 @@ -158,7 +160,7 @@
19918   * - %0 - full hostname (authority w/o port)
19919   * - %1 - tld
19920   * - %2 - domain.tld
19921 - * - %3 - 
19922 + * - %3 -
19923   */
19924  
19925  static int mod_evhost_parse_host(connection *con,array *host) {
19926 @@ -168,7 +170,7 @@
19927         int first = 1;
19928         data_string *ds;
19929         int i;
19930 -       
19931 +
19932         /* first, find the domain + tld */
19933         for(;ptr > con->uri.authority->ptr;ptr--) {
19934                 if(*ptr == '.') {
19935 @@ -179,18 +181,18 @@
19936                         first = 1;
19937                 }
19938         }
19939 -       
19940 +
19941         ds = data_string_init();
19942         buffer_copy_string(ds->key,"%0");
19943 -       
19944 +
19945         /* if we stopped at a dot, skip the dot */
19946         if (*ptr == '.') ptr++;
19947         buffer_copy_string_len(ds->value, ptr, colon-ptr);
19948 -       
19949 +
19950         array_insert_unique(host,(data_unset *)ds);
19951 -       
19952 +
19953         /* if the : is not the start of the authority, go on parsing the hostname */
19954 -       
19955 +
19956         if (colon != con->uri.authority->ptr) {
19957                 for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
19958                         if(*ptr == '.') {
19959 @@ -200,59 +202,55 @@
19960                                         buffer_copy_string(ds->key,"%");
19961                                         buffer_append_long(ds->key, i++);
19962                                         buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
19963 -                                       
19964 +
19965                                         array_insert_unique(host,(data_unset *)ds);
19966                                 }
19967                                 colon = ptr;
19968                         }
19969                 }
19970 -               
19971 +
19972                 /* if the . is not the first charactor of the hostname */
19973                 if (colon != ptr) {
19974                         ds = data_string_init();
19975                         buffer_copy_string(ds->key,"%");
19976                         buffer_append_long(ds->key, i++);
19977                         buffer_copy_string_len(ds->value,ptr,colon-ptr);
19978 -                       
19979 +
19980                         array_insert_unique(host,(data_unset *)ds);
19981                 }
19982         }
19983 -       
19984 +
19985         return 0;
19986  }
19987  
19988 -#define PATCH(x) \
19989 -       p->conf.x = s->x;
19990  static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
19991         size_t i, j;
19992         plugin_config *s = p->config_storage[0];
19993 -       
19994 -       PATCH(path_pieces);
19995 -       PATCH(len);
19996 -       
19997 +
19998 +       PATCH_OPTION(path_pieces);
19999 +       PATCH_OPTION(len);
20000 +
20001         /* skip the first, the global context */
20002         for (i = 1; i < srv->config_context->used; i++) {
20003                 data_config *dc = (data_config *)srv->config_context->data[i];
20004                 s = p->config_storage[i];
20005 -               
20006 +
20007                 /* condition didn't match */
20008                 if (!config_check_cond(srv, con, dc)) continue;
20009 -               
20010 +
20011                 /* merge config */
20012                 for (j = 0; j < dc->value->used; j++) {
20013                         data_unset *du = dc->value->data[j];
20014 -                       
20015 +
20016                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
20017 -                               PATCH(path_pieces);
20018 -                               PATCH(len);
20019 +                               PATCH_OPTION(path_pieces);
20020 +                               PATCH_OPTION(len);
20021                         }
20022                 }
20023         }
20024 -       
20025 +
20026         return 0;
20027  }
20028 -#undef PATCH
20029 -
20030  
20031  static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
20032         plugin_data *p = p_d;
20033 @@ -261,29 +259,29 @@
20034         register char *ptr;
20035         int not_good = 0;
20036         stat_cache_entry *sce = NULL;
20037 -       
20038 +
20039         /* not authority set */
20040         if (con->uri.authority->used == 0) return HANDLER_GO_ON;
20041 -       
20042 +
20043         mod_evhost_patch_connection(srv, con, p);
20044 -       
20045 +
20046         /* missing even default(global) conf */
20047         if (0 == p->conf.len) {
20048                 return HANDLER_GO_ON;
20049         }
20050  
20051         parsed_host = array_init();
20052 -       
20053 +
20054         mod_evhost_parse_host(con, parsed_host);
20055 -       
20056 +
20057         /* build document-root */
20058         buffer_reset(p->tmp_buf);
20059 -       
20060 +
20061         for (i = 0; i < p->conf.len; i++) {
20062                 ptr = p->conf.path_pieces[i]->ptr;
20063                 if (*ptr == '%') {
20064                         data_string *ds;
20065 -                       
20066 +
20067                         if (*(ptr+1) == '%') {
20068                                 /* %% */
20069                                 BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
20070 @@ -298,11 +296,11 @@
20071                         buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
20072                 }
20073         }
20074 -       
20075 -       BUFFER_APPEND_SLASH(p->tmp_buf);
20076 -       
20077 +
20078 +       PATHNAME_APPEND_SLASH(p->tmp_buf);
20079 +
20080         array_free(parsed_host);
20081 -       
20082 +
20083         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
20084                 log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
20085                 not_good = 1;
20086 @@ -310,11 +308,11 @@
20087                 log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
20088                 not_good = 1;
20089         }
20090 -       
20091 +
20092         if (!not_good) {
20093                 buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
20094         }
20095 -       
20096 +
20097         return HANDLER_GO_ON;
20098  }
20099  
20100 @@ -325,9 +323,9 @@
20101         p->set_defaults            = mod_evhost_set_defaults;
20102         p->handle_docroot          = mod_evhost_uri_handler;
20103         p->cleanup                 = mod_evhost_free;
20104 -       
20105 +
20106         p->data                    = NULL;
20107 -       
20108 +
20109         return 0;
20110  }
20111  
20112 --- ../lighttpd-1.4.11/src/mod_expire.c 2005-11-03 09:52:13.000000000 +0200
20113 +++ lighttpd-1.4.12/src/mod_expire.c    2006-07-11 22:07:52.000000000 +0300
20114 @@ -12,8 +12,8 @@
20115  #include "stat_cache.h"
20116  
20117  /**
20118 - * this is a expire module for a lighttpd 
20119 - * 
20120 + * this is a expire module for a lighttpd
20121 + *
20122   * set 'Expires:' HTTP Headers on demand
20123   */
20124  
20125 @@ -27,51 +27,51 @@
20126  
20127  typedef struct {
20128         PLUGIN_DATA;
20129 -       
20130 +
20131         buffer *expire_tstmp;
20132 -       
20133 +
20134         plugin_config **config_storage;
20135 -       
20136 -       plugin_config conf; 
20137 +
20138 +       plugin_config conf;
20139  } plugin_data;
20140  
20141  /* init the plugin data */
20142  INIT_FUNC(mod_expire_init) {
20143         plugin_data *p;
20144 -       
20145 +
20146         p = calloc(1, sizeof(*p));
20147 -       
20148 +
20149         p->expire_tstmp = buffer_init();
20150 -       
20151 +
20152         buffer_prepare_copy(p->expire_tstmp, 255);
20153 -       
20154 +
20155         return p;
20156  }
20157  
20158  /* detroy the plugin data */
20159  FREE_FUNC(mod_expire_free) {
20160         plugin_data *p = p_d;
20161 -       
20162 +
20163         UNUSED(srv);
20164  
20165         if (!p) return HANDLER_GO_ON;
20166 -       
20167 +
20168         buffer_free(p->expire_tstmp);
20169 -       
20170 +
20171         if (p->config_storage) {
20172                 size_t i;
20173                 for (i = 0; i < srv->config_context->used; i++) {
20174                         plugin_config *s = p->config_storage[i];
20175 -                       
20176 +
20177                         array_free(s->expire_url);
20178 -                       
20179 +
20180                         free(s);
20181                 }
20182                 free(p->config_storage);
20183         }
20184 -       
20185 +
20186         free(p);
20187 -       
20188 +
20189         return HANDLER_GO_ON;
20190  }
20191  
20192 @@ -79,25 +79,25 @@
20193         char *ts;
20194         int type = -1;
20195         int retts = 0;
20196 -               
20197 +
20198         UNUSED(p);
20199  
20200 -       /* 
20201 +       /*
20202          * parse
20203 -        * 
20204 +        *
20205          * '(access|modification) [plus] {<num> <type>}*'
20206 -        * 
20207 +        *
20208          * e.g. 'access 1 years'
20209          */
20210 -       
20211 +
20212         if (expire->used == 0) {
20213 -               log_error_write(srv, __FILE__, __LINE__, "s", 
20214 +               log_error_write(srv, __FILE__, __LINE__, "s",
20215                                 "empty:");
20216                 return -1;
20217         }
20218 -       
20219 +
20220         ts = expire->ptr;
20221 -       
20222 +
20223         if (0 == strncmp(ts, "access ", 7)) {
20224                 type  = 0;
20225                 ts   += 7;
20226 @@ -110,39 +110,39 @@
20227                                 "invalid <base>:", ts);
20228                 return -1;
20229         }
20230 -       
20231 +
20232         if (0 == strncmp(ts, "plus ", 5)) {
20233                 /* skip the optional plus */
20234                 ts   += 5;
20235         }
20236 -       
20237 +
20238         /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
20239         while (1) {
20240                 char *space, *err;
20241                 int num;
20242 -               
20243 +
20244                 if (NULL == (space = strchr(ts, ' '))) {
20245 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
20246 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
20247                                         "missing space after <num>:", ts);
20248                         return -1;
20249                 }
20250 -               
20251 +
20252                 num = strtol(ts, &err, 10);
20253                 if (*err != ' ') {
20254 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
20255 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
20256                                         "missing <type> after <num>:", ts);
20257                         return -1;
20258                 }
20259 -               
20260 +
20261                 ts = space + 1;
20262 -               
20263 +
20264                 if (NULL != (space = strchr(ts, ' '))) {
20265                         int slen;
20266                         /* */
20267 -                       
20268 +
20269                         slen = space - ts;
20270 -                       
20271 -                       if (slen == 5 && 
20272 +
20273 +                       if (slen == 5 &&
20274                             0 == strncmp(ts, "years", slen)) {
20275                                 num *= 60 * 60 * 24 * 30 * 12;
20276                         } else if (slen == 6 &&
20277 @@ -161,13 +161,13 @@
20278                                    0 == strncmp(ts, "seconds", slen)) {
20279                                 num *= 1;
20280                         } else {
20281 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
20282 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
20283                                                 "unknown type:", ts);
20284                                 return -1;
20285                         }
20286 -                       
20287 +
20288                         retts += num;
20289 -                       
20290 +
20291                         ts = space + 1;
20292                 } else {
20293                         if (0 == strcmp(ts, "years")) {
20294 @@ -183,19 +183,19 @@
20295                         } else if (0 == strcmp(ts, "seconds")) {
20296                                 num *= 1;
20297                         } else {
20298 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
20299 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
20300                                                 "unknown type:", ts);
20301                                 return -1;
20302                         }
20303 -                       
20304 +
20305                         retts += num;
20306 -                       
20307 +
20308                         break;
20309                 }
20310         }
20311 -       
20312 +
20313         if (offset != NULL) *offset = retts;
20314 -       
20315 +
20316         return type;
20317  }
20318  
20319 @@ -205,102 +205,99 @@
20320  SETDEFAULTS_FUNC(mod_expire_set_defaults) {
20321         plugin_data *p = p_d;
20322         size_t i = 0, k;
20323 -       
20324 -       config_values_t cv[] = { 
20325 +
20326 +       config_values_t cv[] = {
20327                 { "expire.url",                 NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
20328                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20329         };
20330 -       
20331 +
20332         if (!p) return HANDLER_ERROR;
20333 -       
20334 +
20335         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20336 -       
20337 +
20338         for (i = 0; i < srv->config_context->used; i++) {
20339                 plugin_config *s;
20340 -               
20341 +
20342                 s = calloc(1, sizeof(plugin_config));
20343                 s->expire_url    = array_init();
20344 -               
20345 +
20346                 cv[0].destination = s->expire_url;
20347 -               
20348 +
20349                 p->config_storage[i] = s;
20350 -       
20351 +
20352                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
20353                         return HANDLER_ERROR;
20354                 }
20355 -       
20356 +
20357                 for (k = 0; k < s->expire_url->used; k++) {
20358                         data_string *ds = (data_string *)s->expire_url->data[k];
20359 -                       
20360 +
20361                         /* parse lines */
20362                         if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
20363 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
20364 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
20365                                                 "parsing expire.url failed:", ds->value);
20366                                 return HANDLER_ERROR;
20367                         }
20368                 }
20369         }
20370 -       
20371 -       
20372 +
20373 +
20374         return HANDLER_GO_ON;
20375  }
20376  
20377 -#define PATCH(x) \
20378 -       p->conf.x = s->x;
20379  static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
20380         size_t i, j;
20381         plugin_config *s = p->config_storage[0];
20382 -       
20383 -       PATCH(expire_url);
20384 -       
20385 +
20386 +       PATCH_OPTION(expire_url);
20387 +
20388         /* skip the first, the global context */
20389         for (i = 1; i < srv->config_context->used; i++) {
20390                 data_config *dc = (data_config *)srv->config_context->data[i];
20391                 s = p->config_storage[i];
20392 -               
20393 +
20394                 /* condition didn't match */
20395                 if (!config_check_cond(srv, con, dc)) continue;
20396 -               
20397 +
20398                 /* merge config */
20399                 for (j = 0; j < dc->value->used; j++) {
20400                         data_unset *du = dc->value->data[j];
20401 -                       
20402 +
20403                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
20404 -                               PATCH(expire_url);
20405 +                               PATCH_OPTION(expire_url);
20406                         }
20407                 }
20408         }
20409 -       
20410 +
20411         return 0;
20412  }
20413 -#undef PATCH
20414  
20415  URIHANDLER_FUNC(mod_expire_path_handler) {
20416         plugin_data *p = p_d;
20417         int s_len;
20418         size_t k;
20419 -       
20420 +
20421         if (con->uri.path->used == 0) return HANDLER_GO_ON;
20422 -       
20423 +
20424         mod_expire_patch_connection(srv, con, p);
20425 -       
20426 +
20427         s_len = con->uri.path->used - 1;
20428 -       
20429 +
20430         for (k = 0; k < p->conf.expire_url->used; k++) {
20431                 data_string *ds = (data_string *)p->conf.expire_url->data[k];
20432                 int ct_len = ds->key->used - 1;
20433 -               
20434 +
20435                 if (ct_len > s_len) continue;
20436                 if (ds->key->used == 0) continue;
20437 -               
20438 +
20439                 if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
20440                         int ts;
20441                         time_t t;
20442                         size_t len;
20443                         stat_cache_entry *sce = NULL;
20444 -               
20445 +
20446                         stat_cache_get_entry(srv, con, con->physical.path, &sce);
20447 -                       
20448 +
20449                         switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
20450                         case 0:
20451                                 /* access */
20452 @@ -308,38 +305,38 @@
20453                                 break;
20454                         case 1:
20455                                 /* modification */
20456 -                               
20457 +
20458                                 t = (ts + sce->st.st_mtime);
20459                                 break;
20460                         default:
20461                                 /* -1 is handled at parse-time */
20462                                 break;
20463                         }
20464 -                       
20465 -                       
20466 -                       if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1, 
20467 +
20468 +
20469 +                       if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
20470                                            "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
20471                                 /* could not set expire header, out of mem */
20472 -                               
20473 +
20474                                 return HANDLER_GO_ON;
20475 -                               
20476 +
20477                         }
20478 -                           
20479 +
20480                         p->expire_tstmp->used = len + 1;
20481 -               
20482 -                       /* HTTP/1.0 */  
20483 +
20484 +                       /* HTTP/1.0 */
20485                         response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
20486  
20487 -                       /* HTTP/1.1 */  
20488 +                       /* HTTP/1.1 */
20489                         buffer_copy_string(p->expire_tstmp, "max-age=");
20490                         buffer_append_long(p->expire_tstmp, ts);
20491 -                       
20492 +
20493                         response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
20494 -                       
20495 +
20496                         return HANDLER_GO_ON;
20497                 }
20498         }
20499 -       
20500 +
20501         /* not found */
20502         return HANDLER_GO_ON;
20503  }
20504 @@ -349,13 +346,13 @@
20505  int mod_expire_plugin_init(plugin *p) {
20506         p->version     = LIGHTTPD_VERSION_ID;
20507         p->name        = buffer_init_string("expire");
20508 -       
20509 +
20510         p->init        = mod_expire_init;
20511         p->handle_subrequest_start = mod_expire_path_handler;
20512         p->set_defaults  = mod_expire_set_defaults;
20513         p->cleanup     = mod_expire_free;
20514 -       
20515 +
20516         p->data        = NULL;
20517 -       
20518 +
20519         return 0;
20520  }
20521 --- ../lighttpd-1.4.11/src/mod_fastcgi.c        2006-03-09 13:18:39.000000000 +0200
20522 +++ lighttpd-1.4.12/src/mod_fastcgi.c   2006-07-11 22:07:53.000000000 +0300
20523 @@ -1,5 +1,4 @@
20524  #include <sys/types.h>
20525 -#include <unistd.h>
20526  #include <errno.h>
20527  #include <fcntl.h>
20528  #include <string.h>
20529 @@ -24,7 +23,7 @@
20530  #include "inet_ntop_cache.h"
20531  #include "stat_cache.h"
20532  
20533 -#include <fastcgi.h>
20534 +#include "fastcgi.h"
20535  #include <stdio.h>
20536  
20537  #ifdef HAVE_SYS_FILIO_H
20538 @@ -32,7 +31,11 @@
20539  #endif
20540  
20541  #include "sys-socket.h"
20542 +#include "sys-files.h"
20543 +#include "sys-strings.h"
20544 +#include "sys-process.h"
20545  
20546 +#include "http_resp.h"
20547  
20548  #ifndef UNIX_PATH_MAX
20549  # define UNIX_PATH_MAX 108
20550 @@ -45,14 +48,13 @@
20551  #include <sys/wait.h>
20552  #endif
20553  
20554 -
20555  /*
20556 - * 
20557 + *
20558   * TODO:
20559 - * 
20560 + *
20561   * - add timeout for a connect to a non-fastcgi process
20562   *   (use state_timestamp + state)
20563 - * 
20564 + *
20565   */
20566  
20567  typedef struct fcgi_proc {
20568 @@ -61,7 +63,7 @@
20569         unsigned port;  /* config.port + pno */
20570  
20571         buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
20572 -       
20573 +
20574         pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
20575  
20576  
20577 @@ -70,20 +72,20 @@
20578         time_t last_used; /* see idle_timeout */
20579         size_t requests;  /* see max_requests */
20580         struct fcgi_proc *prev, *next; /* see first */
20581 -       
20582 +
20583         time_t disabled_until; /* this proc is disabled until, use something else until than */
20584 -       
20585 +
20586         int is_local;
20587  
20588 -       enum { 
20589 +       enum {
20590                 PROC_STATE_UNSET,    /* init-phase */
20591                 PROC_STATE_RUNNING,  /* alive */
20592 -               PROC_STATE_OVERLOADED, /* listen-queue is full, 
20593 +               PROC_STATE_OVERLOADED, /* listen-queue is full,
20594                                           don't send something to this proc for the next 2 seconds */
20595                 PROC_STATE_DIED_WAIT_FOR_PID, /* */
20596                 PROC_STATE_DIED,     /* marked as dead, should be restarted */
20597                 PROC_STATE_KILLED    /* was killed as we don't have the load anymore */
20598 -       } state; 
20599 +       } state;
20600  } fcgi_proc;
20601  
20602  typedef struct {
20603 @@ -94,20 +96,20 @@
20604          * sorted by lowest load
20605          *
20606          * whenever a job is done move it up in the list
20607 -        * until it is sorted, move it down as soon as the 
20608 +        * until it is sorted, move it down as soon as the
20609          * job is started
20610          */
20611 -       fcgi_proc *first; 
20612 -       fcgi_proc *unused_procs; 
20613 +       fcgi_proc *first;
20614 +       fcgi_proc *unused_procs;
20615  
20616 -       /* 
20617 +       /*
20618          * spawn at least min_procs, at max_procs.
20619          *
20620 -        * as soon as the load of the first entry 
20621 +        * as soon as the load of the first entry
20622          * is max_load_per_proc we spawn a new one
20623 -        * and add it to the first entry and give it 
20624 +        * and add it to the first entry and give it
20625          * the load
20626 -        * 
20627 +        *
20628          */
20629  
20630         unsigned short min_procs;
20631 @@ -119,44 +121,44 @@
20632  
20633         /*
20634          * kick the process from the list if it was not
20635 -        * used for idle_timeout until min_procs is 
20636 +        * used for idle_timeout until min_procs is
20637          * reached. this helps to get the processlist
20638          * small again we had a small peak load.
20639          *
20640          */
20641 -       
20642 +
20643         unsigned short idle_timeout;
20644 -       
20645 +
20646         /*
20647          * time after a disabled remote connection is tried to be re-enabled
20648 -        * 
20649 -        * 
20650 +        *
20651 +        *
20652          */
20653 -       
20654 +
20655         unsigned short disable_time;
20656  
20657         /*
20658          * same fastcgi processes get a little bit larger
20659 -        * than wanted. max_requests_per_proc kills a 
20660 +        * than wanted. max_requests_per_proc kills a
20661          * process after a number of handled requests.
20662          *
20663          */
20664         size_t max_requests_per_proc;
20665 -       
20666 +
20667  
20668         /* config */
20669  
20670 -       /* 
20671 -        * host:port 
20672 +       /*
20673 +        * host:port
20674          *
20675 -        * if host is one of the local IP adresses the 
20676 +        * if host is one of the local IP adresses the
20677          * whole connection is local
20678          *
20679          * if tcp/ip should be used host AND port have
20680 -        * to be specified 
20681 -        * 
20682 -        */ 
20683 -       buffer *host; 
20684 +        * to be specified
20685 +        *
20686 +        */
20687 +       buffer *host;
20688         unsigned short port;
20689  
20690         /*
20691 @@ -169,7 +171,7 @@
20692          */
20693         buffer *unixsocket;
20694  
20695 -       /* if socket is local we can start the fastcgi 
20696 +       /* if socket is local we can start the fastcgi
20697          * process ourself
20698          *
20699          * bin-path is the path to the binary
20700 @@ -177,19 +179,19 @@
20701          * check min_procs and max_procs for the number
20702          * of process to start-up
20703          */
20704 -       buffer *bin_path; 
20705 -       
20706 -       /* bin-path is set bin-environment is taken to 
20707 +       buffer *bin_path;
20708 +
20709 +       /* bin-path is set bin-environment is taken to
20710          * create the environement before starting the
20711          * FastCGI process
20712 -        * 
20713 +        *
20714          */
20715         array *bin_env;
20716 -       
20717 +
20718         array *bin_env_copy;
20719 -       
20720 +
20721         /*
20722 -        * docroot-translation between URL->phys and the 
20723 +        * docroot-translation between URL->phys and the
20724          * remote host
20725          *
20726          * reasons:
20727 @@ -208,7 +210,7 @@
20728         unsigned short mode;
20729  
20730         /*
20731 -        * check_local tell you if the phys file is stat()ed 
20732 +        * check_local tell you if the phys file is stat()ed
20733          * or not. FastCGI doesn't care if the service is
20734          * remote. If the web-server side doesn't contain
20735          * the fastcgi-files we should not stat() for them
20736 @@ -218,11 +220,11 @@
20737  
20738         /*
20739          * append PATH_INFO to SCRIPT_FILENAME
20740 -        * 
20741 +        *
20742          * php needs this if cgi.fix_pathinfo is provied
20743 -        * 
20744 +        *
20745          */
20746 -       
20747 +
20748         unsigned short break_scriptfilename_for_php;
20749  
20750         /*
20751 @@ -231,12 +233,12 @@
20752          *
20753          */
20754         unsigned short allow_xsendfile;
20755 -               
20756 +
20757         ssize_t load; /* replace by host->load */
20758  
20759         size_t max_id; /* corresponds most of the time to
20760         num_procs.
20761 -       
20762 +
20763         only if a process is killed max_id waits for the process itself
20764         to die and decrements its afterwards */
20765  
20766 @@ -245,17 +247,17 @@
20767  
20768  /*
20769   * one extension can have multiple hosts assigned
20770 - * one host can spawn additional processes on the same 
20771 + * one host can spawn additional processes on the same
20772   *   socket (if we control it)
20773   *
20774   * ext -> host -> procs
20775   *    1:n     1:n
20776   *
20777 - * if the fastcgi process is remote that whole goes down 
20778 + * if the fastcgi process is remote that whole goes down
20779   * to
20780   *
20781   * ext -> host -> procs
20782 - *    1:n     1:1 
20783 + *    1:n     1:1
20784   *
20785   * in case of PHP and FCGI_CHILDREN we have again a procs
20786   * but we don't control it directly.
20787 @@ -268,7 +270,7 @@
20788         int note_is_sent;
20789  
20790         fcgi_extension_host **hosts;
20791 -       
20792 +
20793         size_t used;
20794         size_t size;
20795  } fcgi_extension;
20796 @@ -282,10 +284,10 @@
20797  
20798  
20799  typedef struct {
20800 -       fcgi_exts *exts; 
20801 +       fcgi_exts *exts;
20802  
20803         array *ext_mapping;
20804 -       
20805 +
20806         int debug;
20807  } plugin_config;
20808  
20809 @@ -297,7 +299,7 @@
20810  
20811  typedef struct {
20812         char **ptr;
20813 -       
20814 +
20815         size_t size;
20816         size_t used;
20817  } char_array;
20818 @@ -306,44 +308,44 @@
20819  typedef struct {
20820         PLUGIN_DATA;
20821         buffer_uint fcgi_request_id;
20822 -       
20823 +
20824         buffer *fcgi_env;
20825 -       
20826 +
20827         buffer *path;
20828 -       buffer *parse_response;
20829  
20830         buffer *statuskey;
20831 -       
20832 +
20833 +       http_resp *resp;
20834 +
20835         plugin_config **config_storage;
20836 -       
20837 +
20838         plugin_config conf; /* this is only used as long as no handler_ctx is setup */
20839  } plugin_data;
20840  
20841  /* connection specific data */
20842 -typedef enum { 
20843 +typedef enum {
20844         FCGI_STATE_UNSET,
20845 -       FCGI_STATE_INIT, 
20846 -       FCGI_STATE_CONNECT_DELAYED, 
20847 -       FCGI_STATE_PREPARE_WRITE, 
20848 -       FCGI_STATE_WRITE, 
20849 -       FCGI_STATE_READ 
20850 +       FCGI_STATE_INIT,
20851 +       FCGI_STATE_CONNECT_DELAYED,
20852 +       FCGI_STATE_PREPARE_WRITE,
20853 +       FCGI_STATE_WRITE,
20854 +       FCGI_STATE_READ
20855  } fcgi_connection_state_t;
20856  
20857  typedef struct {
20858         fcgi_proc *proc;
20859         fcgi_extension_host *host;
20860         fcgi_extension *ext;
20861 -       
20862 +
20863         fcgi_connection_state_t state;
20864         time_t   state_timestamp;
20865 -       
20866 +
20867         int      reconnects; /* number of reconnect attempts */
20868 -       
20869 -       chunkqueue *rb; /* read queue */
20870 +
20871 +       chunkqueue *rb; /* the raw fcgi read-queue */
20872 +       chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
20873         chunkqueue *wb; /* write queue */
20874 -       
20875 -       buffer   *response_header;
20876 -       
20877 +
20878         size_t    request_id;
20879         int       fd;        /* fd to the fastcgi process */
20880         int       fde_ndx;   /* index into the fd-event buffer */
20881 @@ -352,9 +354,9 @@
20882         int       got_proc;
20883  
20884         int       send_content_body;
20885 -       
20886 +
20887         plugin_config conf;
20888 -       
20889 +
20890         connection *remote_conn;  /* dumb pointer */
20891         plugin_data *plugin_data; /* dumb pointer */
20892  } handler_ctx;
20893 @@ -380,7 +382,7 @@
20894         return di;
20895  }
20896  
20897 -/* dummies of the statistic framework functions 
20898 +/* dummies of the statistic framework functions
20899   * they will be moved to a statistics.c later */
20900  int status_counter_inc(server *srv, const char *s, size_t len) {
20901         data_integer *di = status_counter_get_counter(srv, s, len);
20902 @@ -429,7 +431,7 @@
20903         CLEAN(".connected");
20904         CLEAN(".load");
20905  
20906 -#undef CLEAN   
20907 +#undef CLEAN
20908  
20909  #define CLEAN(x) \
20910         fastcgi_status_copy_procname(b, host, NULL); \
20911 @@ -438,33 +440,32 @@
20912  
20913         CLEAN(".load");
20914  
20915 -#undef CLEAN   
20916 +#undef CLEAN
20917  
20918         return 0;
20919  }
20920  
20921  static handler_ctx * handler_ctx_init() {
20922         handler_ctx * hctx;
20923 -       
20924 +
20925         hctx = calloc(1, sizeof(*hctx));
20926         assert(hctx);
20927 -       
20928 +
20929         hctx->fde_ndx = -1;
20930 -       
20931 -       hctx->response_header = buffer_init();
20932 -       
20933 +
20934         hctx->request_id = 0;
20935         hctx->state = FCGI_STATE_INIT;
20936         hctx->proc = NULL;
20937 -       
20938 +
20939         hctx->fd = -1;
20940 -       
20941 +
20942         hctx->reconnects = 0;
20943         hctx->send_content_body = 1;
20944  
20945         hctx->rb = chunkqueue_init();
20946 +       hctx->http_rb = chunkqueue_init();
20947         hctx->wb = chunkqueue_init();
20948 -       
20949 +
20950         return hctx;
20951  }
20952  
20953 @@ -473,10 +474,9 @@
20954                 hctx->host->load--;
20955                 hctx->host = NULL;
20956         }
20957 -       
20958 -       buffer_free(hctx->response_header);
20959  
20960         chunkqueue_free(hctx->rb);
20961 +       chunkqueue_free(hctx->http_rb);
20962         chunkqueue_free(hctx->wb);
20963  
20964         free(hctx);
20965 @@ -488,21 +488,21 @@
20966         f = calloc(1, sizeof(*f));
20967         f->unixsocket = buffer_init();
20968         f->connection_name = buffer_init();
20969 -       
20970 +
20971         f->prev = NULL;
20972         f->next = NULL;
20973 -       
20974 +
20975         return f;
20976  }
20977  
20978  void fastcgi_process_free(fcgi_proc *f) {
20979         if (!f) return;
20980 -       
20981 +
20982         fastcgi_process_free(f->next);
20983 -       
20984 +
20985         buffer_free(f->unixsocket);
20986         buffer_free(f->connection_name);
20987 -       
20988 +
20989         free(f);
20990  }
20991  
20992 @@ -519,13 +519,13 @@
20993         f->bin_env = array_init();
20994         f->bin_env_copy = array_init();
20995         f->strip_request_uri = buffer_init();
20996 -       
20997 +
20998         return f;
20999  }
21000  
21001  void fastcgi_host_free(fcgi_extension_host *h) {
21002         if (!h) return;
21003 -       
21004 +
21005         buffer_free(h->id);
21006         buffer_free(h->host);
21007         buffer_free(h->unixsocket);
21008 @@ -534,49 +534,49 @@
21009         buffer_free(h->strip_request_uri);
21010         array_free(h->bin_env);
21011         array_free(h->bin_env_copy);
21012 -       
21013 +
21014         fastcgi_process_free(h->first);
21015         fastcgi_process_free(h->unused_procs);
21016 -       
21017 +
21018         free(h);
21019 -       
21020 +
21021  }
21022  
21023  fcgi_exts *fastcgi_extensions_init() {
21024         fcgi_exts *f;
21025  
21026         f = calloc(1, sizeof(*f));
21027 -       
21028 +
21029         return f;
21030  }
21031  
21032  void fastcgi_extensions_free(fcgi_exts *f) {
21033         size_t i;
21034 -       
21035 +
21036         if (!f) return;
21037 -       
21038 +
21039         for (i = 0; i < f->used; i++) {
21040                 fcgi_extension *fe;
21041                 size_t j;
21042 -               
21043 +
21044                 fe = f->exts[i];
21045 -               
21046 +
21047                 for (j = 0; j < fe->used; j++) {
21048                         fcgi_extension_host *h;
21049 -                       
21050 +
21051                         h = fe->hosts[j];
21052 -                       
21053 +
21054                         fastcgi_host_free(h);
21055                 }
21056 -               
21057 +
21058                 buffer_free(fe->key);
21059                 free(fe->hosts);
21060 -               
21061 +
21062                 free(fe);
21063         }
21064 -       
21065 +
21066         free(f->exts);
21067 -       
21068 +
21069         free(f);
21070  }
21071  
21072 @@ -625,24 +625,25 @@
21073                 assert(fe->hosts);
21074         }
21075  
21076 -       fe->hosts[fe->used++] = fh; 
21077 +       fe->hosts[fe->used++] = fh;
21078  
21079         return 0;
21080 -       
21081 +
21082  }
21083  
21084  INIT_FUNC(mod_fastcgi_init) {
21085         plugin_data *p;
21086 -       
21087 +
21088         p = calloc(1, sizeof(*p));
21089 -       
21090 +
21091         p->fcgi_env = buffer_init();
21092 -       
21093 +
21094         p->path = buffer_init();
21095 -       p->parse_response = buffer_init();
21096 +
21097 +       p->resp = http_response_init();
21098  
21099         p->statuskey = buffer_init();
21100 -       
21101 +
21102         return p;
21103  }
21104  
21105 @@ -650,81 +651,82 @@
21106  FREE_FUNC(mod_fastcgi_free) {
21107         plugin_data *p = p_d;
21108         buffer_uint *r = &(p->fcgi_request_id);
21109 -       
21110 +
21111         UNUSED(srv);
21112  
21113         if (r->ptr) free(r->ptr);
21114 -       
21115 +
21116         buffer_free(p->fcgi_env);
21117         buffer_free(p->path);
21118 -       buffer_free(p->parse_response);
21119         buffer_free(p->statuskey);
21120 -       
21121 +
21122 +       http_response_free(p->resp);
21123 +
21124         if (p->config_storage) {
21125                 size_t i, j, n;
21126                 for (i = 0; i < srv->config_context->used; i++) {
21127                         plugin_config *s = p->config_storage[i];
21128                         fcgi_exts *exts;
21129 -                       
21130 +
21131                         if (!s) continue;
21132 -                       
21133 +
21134                         exts = s->exts;
21135  
21136                         for (j = 0; j < exts->used; j++) {
21137                                 fcgi_extension *ex;
21138 -                               
21139 +
21140                                 ex = exts->exts[j];
21141 -                               
21142 +
21143                                 for (n = 0; n < ex->used; n++) {
21144                                         fcgi_proc *proc;
21145                                         fcgi_extension_host *host;
21146 -                                       
21147 +
21148                                         host = ex->hosts[n];
21149 -                                       
21150 +
21151                                         for (proc = host->first; proc; proc = proc->next) {
21152                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21153 -                                               
21154 -                                               if (proc->is_local && 
21155 +
21156 +                                               if (proc->is_local &&
21157                                                     !buffer_is_empty(proc->unixsocket)) {
21158                                                         unlink(proc->unixsocket->ptr);
21159                                                 }
21160                                         }
21161 -                                       
21162 +
21163                                         for (proc = host->unused_procs; proc; proc = proc->next) {
21164                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21165 -                                               
21166 -                                               if (proc->is_local && 
21167 +
21168 +                                               if (proc->is_local &&
21169                                                     !buffer_is_empty(proc->unixsocket)) {
21170                                                         unlink(proc->unixsocket->ptr);
21171                                                 }
21172                                         }
21173                                 }
21174                         }
21175 -                       
21176 +
21177                         fastcgi_extensions_free(s->exts);
21178                         array_free(s->ext_mapping);
21179 -                       
21180 +
21181                         free(s);
21182                 }
21183                 free(p->config_storage);
21184         }
21185 -       
21186 +
21187         free(p);
21188 -       
21189 +
21190         return HANDLER_GO_ON;
21191  }
21192  
21193  static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
21194         char *dst;
21195 -       
21196 +
21197         if (!key || !val) return -1;
21198 -       
21199 +
21200         dst = malloc(key_len + val_len + 3);
21201         memcpy(dst, key, key_len);
21202         dst[key_len] = '=';
21203         /* add the \0 from the value */
21204         memcpy(dst + key_len + 1, val, val_len + 1);
21205 -       
21206 +
21207         if (env->size == 0) {
21208                 env->size = 16;
21209                 env->ptr = malloc(env->size * sizeof(*env->ptr));
21210 @@ -732,9 +734,9 @@
21211                 env->size += 16;
21212                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21213         }
21214 -       
21215 +
21216         env->ptr[env->used++] = dst;
21217 -       
21218 +
21219         return 0;
21220  }
21221  
21222 @@ -753,15 +755,15 @@
21223                         if (env->size == 0) {
21224                                 env->size = 16;
21225                                 env->ptr = malloc(env->size * sizeof(*env->ptr));
21226 -                       } else if (env->size == env->used) { 
21227 +                       } else if (env->size == env->used) {
21228                                 env->size += 16;
21229                                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21230                         }
21231 -                       
21232 +
21233                         b->ptr[i] = '\0';
21234  
21235                         env->ptr[env->used++] = start;
21236 -                       
21237 +
21238                         start = b->ptr + i + 1;
21239                         break;
21240                 default:
21241 @@ -794,7 +796,7 @@
21242         return 0;
21243  }
21244  
21245 -static int fcgi_spawn_connection(server *srv, 
21246 +static int fcgi_spawn_connection(server *srv,
21247                                  plugin_data *p,
21248                                  fcgi_extension_host *host,
21249                                  fcgi_proc *proc) {
21250 @@ -806,31 +808,27 @@
21251  #endif
21252         struct sockaddr_in fcgi_addr_in;
21253         struct sockaddr *fcgi_addr;
21254 -       
21255 +
21256         socklen_t servlen;
21257 -       
21258 +
21259  #ifndef HAVE_FORK
21260         return -1;
21261  #endif
21262 -       
21263 +
21264         if (p->conf.debug) {
21265                 log_error_write(srv, __FILE__, __LINE__, "sdb",
21266                                 "new proc, socket:", proc->port, proc->unixsocket);
21267         }
21268 -               
21269 +
21270         if (!buffer_is_empty(proc->unixsocket)) {
21271                 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
21272 -               
21273 +
21274  #ifdef HAVE_SYS_UN_H
21275                 fcgi_addr_un.sun_family = AF_UNIX;
21276                 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
21277 -               
21278 -#ifdef SUN_LEN
21279 +
21280                 servlen = SUN_LEN(&fcgi_addr_un);
21281 -#else
21282 -               /* stevens says: */
21283 -               servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
21284 -#endif
21285 +
21286                 socket_type = AF_UNIX;
21287                 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
21288  
21289 @@ -844,108 +842,108 @@
21290  #endif
21291         } else {
21292                 fcgi_addr_in.sin_family = AF_INET;
21293 -               
21294 +
21295                 if (buffer_is_empty(host->host)) {
21296                         fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21297                 } else {
21298                         struct hostent *he;
21299 -                       
21300 +
21301                         /* set a usefull default */
21302                         fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21303 -                       
21304 -                       
21305 +
21306 +
21307                         if (NULL == (he = gethostbyname(host->host->ptr))) {
21308 -                               log_error_write(srv, __FILE__, __LINE__, 
21309 -                                               "sdb", "gethostbyname failed: ", 
21310 +                               log_error_write(srv, __FILE__, __LINE__,
21311 +                                               "sdb", "gethostbyname failed: ",
21312                                                 h_errno, host->host);
21313                                 return -1;
21314                         }
21315 -                       
21316 +
21317                         if (he->h_addrtype != AF_INET) {
21318                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
21319                                 return -1;
21320                         }
21321 -                       
21322 +
21323                         if (he->h_length != sizeof(struct in_addr)) {
21324                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
21325                                 return -1;
21326                         }
21327 -                       
21328 +
21329                         memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
21330 -                       
21331 +
21332                 }
21333                 fcgi_addr_in.sin_port = htons(proc->port);
21334                 servlen = sizeof(fcgi_addr_in);
21335 -               
21336 +
21337                 socket_type = AF_INET;
21338                 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
21339 -               
21340 +
21341                 buffer_copy_string(proc->connection_name, "tcp:");
21342                 buffer_append_string_buffer(proc->connection_name, host->host);
21343                 buffer_append_string(proc->connection_name, ":");
21344                 buffer_append_long(proc->connection_name, proc->port);
21345         }
21346 -       
21347 +
21348         if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21349 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
21350 +               log_error_write(srv, __FILE__, __LINE__, "ss",
21351                                 "failed:", strerror(errno));
21352                 return -1;
21353         }
21354 -       
21355 +
21356         if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
21357                 /* server is not up, spawn in  */
21358                 pid_t child;
21359                 int val;
21360 -               
21361 -               if (errno != ENOENT && 
21362 +
21363 +               if (errno != ENOENT &&
21364                     !buffer_is_empty(proc->unixsocket)) {
21365                         unlink(proc->unixsocket->ptr);
21366                 }
21367 -               
21368 +
21369                 close(fcgi_fd);
21370 -               
21371 +
21372                 /* reopen socket */
21373                 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21374 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
21375 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
21376                                 "socket failed:", strerror(errno));
21377                         return -1;
21378                 }
21379 -               
21380 +
21381                 val = 1;
21382                 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
21383 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
21384 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
21385                                         "socketsockopt failed:", strerror(errno));
21386                         return -1;
21387                 }
21388 -               
21389 +
21390                 /* create socket */
21391                 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
21392 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
21393 -                               "bind failed for:", 
21394 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
21395 +                               "bind failed for:",
21396                                 proc->connection_name,
21397                                 strerror(errno));
21398                         return -1;
21399                 }
21400 -               
21401 +
21402                 if (-1 == listen(fcgi_fd, 1024)) {
21403 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
21404 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
21405                                 "listen failed:", strerror(errno));
21406                         return -1;
21407                 }
21408 -               
21409 -#ifdef HAVE_FORK       
21410 +
21411 +#ifndef _WIN32
21412                 switch ((child = fork())) {
21413                 case 0: {
21414                         size_t i = 0;
21415                         char *c;
21416                         char_array env;
21417                         char_array arg;
21418 -                       
21419 +
21420                         /* create environment */
21421                         env.ptr = NULL;
21422                         env.size = 0;
21423                         env.used = 0;
21424 -                       
21425 +
21426                         arg.ptr = NULL;
21427                         arg.size = 0;
21428                         arg.used = 0;
21429 @@ -955,18 +953,18 @@
21430                                 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
21431                                 close(fcgi_fd);
21432                         }
21433 -                       
21434 +
21435                         /* we don't need the client socket */
21436                         for (i = 3; i < 256; i++) {
21437                                 close(i);
21438                         }
21439 -                       
21440 +
21441                         /* build clean environment */
21442                         if (host->bin_env_copy->used) {
21443                                 for (i = 0; i < host->bin_env_copy->used; i++) {
21444                                         data_string *ds = (data_string *)host->bin_env_copy->data[i];
21445                                         char *ge;
21446 -                                       
21447 +
21448                                         if (NULL != (ge = getenv(ds->value->ptr))) {
21449                                                 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
21450                                         }
21451 @@ -974,39 +972,39 @@
21452                         } else {
21453                                 for (i = 0; environ[i]; i++) {
21454                                         char *eq;
21455 -                                       
21456 +
21457                                         if (NULL != (eq = strchr(environ[i], '='))) {
21458                                                 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
21459                                         }
21460                                 }
21461                         }
21462 -                       
21463 +
21464                         /* create environment */
21465                         for (i = 0; i < host->bin_env->used; i++) {
21466                                 data_string *ds = (data_string *)host->bin_env->data[i];
21467 -                               
21468 +
21469                                 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
21470                         }
21471 -                       
21472 +
21473                         for (i = 0; i < env.used; i++) {
21474                                 /* search for PHP_FCGI_CHILDREN */
21475                                 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
21476                         }
21477 -                       
21478 +
21479                         /* not found, add a default */
21480                         if (i == env.used) {
21481                                 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
21482                         }
21483 -                       
21484 +
21485                         env.ptr[env.used] = NULL;
21486  
21487                         parse_binpath(&arg, host->bin_path);
21488 -                       
21489 +
21490                         /* chdir into the base of the bin-path,
21491                          * search for the last / */
21492                         if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
21493                                 *c = '\0';
21494 -                       
21495 +
21496                                 /* change to the physical directory */
21497                                 if (-1 == chdir(arg.ptr[0])) {
21498                                         *c = '/';
21499 @@ -1018,12 +1016,12 @@
21500  
21501                         /* exec the cgi */
21502                         execve(arg.ptr[0], arg.ptr, env.ptr);
21503 -                       
21504 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
21505 +
21506 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
21507                                         "execve failed for:", host->bin_path, strerror(errno));
21508 -                       
21509 +
21510                         exit(errno);
21511 -                       
21512 +
21513                         break;
21514                 }
21515                 case -1:
21516 @@ -1031,17 +1029,17 @@
21517                         break;
21518                 default:
21519                         /* father */
21520 -                       
21521 +
21522                         /* wait */
21523                         select(0, NULL, NULL, NULL, &tv);
21524 -                       
21525 +
21526                         switch (waitpid(child, &status, WNOHANG)) {
21527                         case 0:
21528                                 /* child still running after timeout, good */
21529                                 break;
21530                         case -1:
21531                                 /* no PID found ? should never happen */
21532 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
21533 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
21534                                                 "pid not found:", strerror(errno));
21535                                 return -1;
21536                         default:
21537 @@ -1049,10 +1047,10 @@
21538                                                 "the fastcgi-backend", host->bin_path, "failed to start:");
21539                                 /* the child should not terminate at all */
21540                                 if (WIFEXITED(status)) {
21541 -                                       log_error_write(srv, __FILE__, __LINE__, "sdb", 
21542 -                                                       "child exited with status", 
21543 +                                       log_error_write(srv, __FILE__, __LINE__, "sdb",
21544 +                                                       "child exited with status",
21545                                                         WEXITSTATUS(status), host->bin_path);
21546 -                                       log_error_write(srv, __FILE__, __LINE__, "s", 
21547 +                                       log_error_write(srv, __FILE__, __LINE__, "s",
21548                                                         "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n"
21549                                                         "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' "
21550                                                         "in the output, NOT (cgi) NOR (cli)\n"
21551 @@ -1060,8 +1058,8 @@
21552                                         log_error_write(srv, __FILE__, __LINE__, "s",
21553                                                         "If this is PHP on Gentoo add fastcgi to the USE flags");
21554                                 } else if (WIFSIGNALED(status)) {
21555 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
21556 -                                                       "terminated by signal:", 
21557 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
21558 +                                                       "terminated by signal:",
21559                                                         WTERMSIG(status));
21560  
21561                                         if (WTERMSIG(status) == 11) {
21562 @@ -1071,8 +1069,8 @@
21563                                                                 "If this is PHP try to remove the byte-code caches for now and try again.");
21564                                         }
21565                                 } else {
21566 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
21567 -                                                       "child died somehow:", 
21568 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
21569 +                                                       "child died somehow:",
21570                                                         status);
21571                                 }
21572                                 return -1;
21573 @@ -1082,26 +1080,26 @@
21574                         proc->pid = child;
21575                         proc->last_used = srv->cur_ts;
21576                         proc->is_local = 1;
21577 -                                               
21578 +
21579                         break;
21580                 }
21581  #endif
21582         } else {
21583                 proc->is_local = 0;
21584                 proc->pid = 0;
21585 -               
21586 +
21587                 if (p->conf.debug) {
21588                         log_error_write(srv, __FILE__, __LINE__, "sb",
21589                                         "(debug) socket is already used, won't spawn:",
21590                                         proc->connection_name);
21591                 }
21592         }
21593 -       
21594 +
21595         proc->state = PROC_STATE_RUNNING;
21596         host->active_procs++;
21597 -       
21598 +
21599         close(fcgi_fd);
21600 -       
21601 +
21602         return 0;
21603  }
21604  
21605 @@ -1111,93 +1109,93 @@
21606         data_unset *du;
21607         size_t i = 0;
21608         buffer *fcgi_mode = buffer_init();
21609 -       
21610 -       config_values_t cv[] = { 
21611 +
21612 +       config_values_t cv[] = {
21613                 { "fastcgi.server",              NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
21614                 { "fastcgi.debug",               NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
21615                 { "fastcgi.map-extensions",      NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
21616                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21617         };
21618 -       
21619 +
21620         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21621 -       
21622 +
21623         for (i = 0; i < srv->config_context->used; i++) {
21624                 plugin_config *s;
21625                 array *ca;
21626 -               
21627 +
21628                 s = malloc(sizeof(plugin_config));
21629                 s->exts          = fastcgi_extensions_init();
21630                 s->debug         = 0;
21631                 s->ext_mapping   = array_init();
21632 -               
21633 +
21634                 cv[0].destination = s->exts;
21635                 cv[1].destination = &(s->debug);
21636                 cv[2].destination = s->ext_mapping;
21637 -               
21638 +
21639                 p->config_storage[i] = s;
21640                 ca = ((data_config *)srv->config_context->data[i])->value;
21641 -       
21642 +
21643                 if (0 != config_insert_values_global(srv, ca, cv)) {
21644                         return HANDLER_ERROR;
21645                 }
21646 -               
21647 -               /* 
21648 +
21649 +               /*
21650                  * <key> = ( ... )
21651                  */
21652 -               
21653 +
21654                 if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
21655                         size_t j;
21656                         data_array *da = (data_array *)du;
21657 -                       
21658 +
21659                         if (du->type != TYPE_ARRAY) {
21660 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
21661 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
21662                                                 "unexpected type for key: ", "fastcgi.server", "array of strings");
21663 -                               
21664 +
21665                                 return HANDLER_ERROR;
21666                         }
21667 -                       
21668 -                       
21669 -                       /* 
21670 -                        * fastcgi.server = ( "<ext>" => ( ... ), 
21671 +
21672 +
21673 +                       /*
21674 +                        * fastcgi.server = ( "<ext>" => ( ... ),
21675                          *                    "<ext>" => ( ... ) )
21676                          */
21677 -                       
21678 +
21679                         for (j = 0; j < da->value->used; j++) {
21680                                 size_t n;
21681                                 data_array *da_ext = (data_array *)da->value->data[j];
21682 -                               
21683 +
21684                                 if (da->value->data[j]->type != TYPE_ARRAY) {
21685 -                                       log_error_write(srv, __FILE__, __LINE__, "sssbs", 
21686 -                                                       "unexpected type for key: ", "fastcgi.server", 
21687 +                                       log_error_write(srv, __FILE__, __LINE__, "sssbs",
21688 +                                                       "unexpected type for key: ", "fastcgi.server",
21689                                                         "[", da->value->data[j]->key, "](string)");
21690 -                                       
21691 +
21692                                         return HANDLER_ERROR;
21693                                 }
21694 -                               
21695 -                               /* 
21696 -                                * da_ext->key == name of the extension 
21697 +
21698 +                               /*
21699 +                                * da_ext->key == name of the extension
21700                                  */
21701 -                               
21702 -                               /* 
21703 -                                * fastcgi.server = ( "<ext>" => 
21704 -                                *                     ( "<host>" => ( ... ), 
21705 +
21706 +                               /*
21707 +                                * fastcgi.server = ( "<ext>" =>
21708 +                                *                     ( "<host>" => ( ... ),
21709                                  *                       "<host>" => ( ... )
21710 -                                *                     ), 
21711 +                                *                     ),
21712                                  *                    "<ext>" => ... )
21713                                  */
21714 -                                       
21715 +
21716                                 for (n = 0; n < da_ext->value->used; n++) {
21717                                         data_array *da_host = (data_array *)da_ext->value->data[n];
21718 -                                       
21719 +
21720                                         fcgi_extension_host *host;
21721 -                                       
21722 -                                       config_values_t fcv[] = { 
21723 +
21724 +                                       config_values_t fcv[] = {
21725                                                 { "host",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
21726                                                 { "docroot",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
21727                                                 { "mode",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
21728                                                 { "socket",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
21729                                                 { "bin-path",          NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 4 */
21730 -                                               
21731 +
21732                                                 { "check-local",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 5 */
21733                                                 { "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 6 */
21734                                                 { "min-procs-not-working",         NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 7 this is broken for now */
21735 @@ -1205,28 +1203,28 @@
21736                                                 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 9 */
21737                                                 { "idle-timeout",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 10 */
21738                                                 { "disable-time",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 11 */
21739 -                                               
21740 +
21741                                                 { "bin-environment",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 12 */
21742                                                 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },     /* 13 */
21743 -                                               
21744 +
21745                                                 { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },  /* 14 */
21746                                                 { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 15 */
21747                                                 { "strip-request-uri",  NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 16 */
21748 -                                               
21749 +
21750                                                 { NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21751                                         };
21752 -                                       
21753 +
21754                                         if (da_host->type != TYPE_ARRAY) {
21755 -                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS", 
21756 -                                                               "unexpected type for key:", 
21757 -                                                               "fastcgi.server", 
21758 +                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS",
21759 +                                                               "unexpected type for key:",
21760 +                                                               "fastcgi.server",
21761                                                                 "[", da_host->key, "](string)");
21762 -                                               
21763 +
21764                                                 return HANDLER_ERROR;
21765                                         }
21766 -                                       
21767 +
21768                                         host = fastcgi_host_init();
21769 -                                       
21770 +
21771                                         buffer_copy_string_buffer(host->id, da_host->key);
21772  
21773                                         host->check_local  = 1;
21774 @@ -1238,13 +1236,13 @@
21775                                         host->disable_time = 60;
21776                                         host->break_scriptfilename_for_php = 0;
21777                                         host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
21778 -                                       
21779 +
21780                                         fcv[0].destination = host->host;
21781                                         fcv[1].destination = host->docroot;
21782                                         fcv[2].destination = fcgi_mode;
21783                                         fcv[3].destination = host->unixsocket;
21784                                         fcv[4].destination = host->bin_path;
21785 -                                       
21786 +
21787                                         fcv[5].destination = &(host->check_local);
21788                                         fcv[6].destination = &(host->port);
21789                                         fcv[7].destination = &(host->min_procs);
21790 @@ -1252,35 +1250,35 @@
21791                                         fcv[9].destination = &(host->max_load_per_proc);
21792                                         fcv[10].destination = &(host->idle_timeout);
21793                                         fcv[11].destination = &(host->disable_time);
21794 -                                       
21795 +
21796                                         fcv[12].destination = host->bin_env;
21797                                         fcv[13].destination = host->bin_env_copy;
21798                                         fcv[14].destination = &(host->break_scriptfilename_for_php);
21799                                         fcv[15].destination = &(host->allow_xsendfile);
21800                                         fcv[16].destination = host->strip_request_uri;
21801 -                                       
21802 +
21803                                         if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
21804                                                 return HANDLER_ERROR;
21805                                         }
21806 -                                                       
21807 -                                       if ((!buffer_is_empty(host->host) || host->port) && 
21808 +
21809 +                                       if ((!buffer_is_empty(host->host) || host->port) &&
21810                                             !buffer_is_empty(host->unixsocket)) {
21811 -                                               log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
21812 +                                               log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21813                                                                 "either host/port or socket have to be set in:",
21814 -                                                               da->key, "= (", 
21815 +                                                               da->key, "= (",
21816                                                                 da_ext->key, " => (",
21817                                                                 da_host->key, " ( ...");
21818  
21819                                                 return HANDLER_ERROR;
21820                                         }
21821 -                                       
21822 +
21823                                         if (!buffer_is_empty(host->unixsocket)) {
21824                                                 /* unix domain socket */
21825 -                                               
21826 +
21827                                                 if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
21828 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
21829 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21830                                                                         "unixsocket is too long in:",
21831 -                                                                       da->key, "= (", 
21832 +                                                                       da->key, "= (",
21833                                                                         da_ext->key, " => (",
21834                                                                         da_host->key, " ( ...");
21835  
21836 @@ -1288,37 +1286,37 @@
21837                                                 }
21838                                         } else {
21839                                                 /* tcp/ip */
21840 -                                               
21841 -                                               if (buffer_is_empty(host->host) && 
21842 +
21843 +                                               if (buffer_is_empty(host->host) &&
21844                                                     buffer_is_empty(host->bin_path)) {
21845 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
21846 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21847                                                                         "host or binpath have to be set in:",
21848 -                                                                       da->key, "= (", 
21849 +                                                                       da->key, "= (",
21850                                                                         da_ext->key, " => (",
21851                                                                         da_host->key, " ( ...");
21852 -                                                       
21853 +
21854                                                         return HANDLER_ERROR;
21855                                                 } else if (host->port == 0) {
21856 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
21857 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21858                                                                         "port has to be set in:",
21859 -                                                                       da->key, "= (", 
21860 +                                                                       da->key, "= (",
21861                                                                         da_ext->key, " => (",
21862                                                                         da_host->key, " ( ...");
21863  
21864                                                         return HANDLER_ERROR;
21865                                                 }
21866                                         }
21867 -                                               
21868 -                                       if (!buffer_is_empty(host->bin_path)) { 
21869 +
21870 +                                       if (!buffer_is_empty(host->bin_path)) {
21871                                                 /* a local socket + self spawning */
21872                                                 size_t pno;
21873  
21874                                                 /* HACK:  just to make sure the adaptive spawing is disabled */
21875                                                 host->min_procs = host->max_procs;
21876 -                                               
21877 +
21878                                                 if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
21879                                                 if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
21880 -                                               
21881 +
21882                                                 if (s->debug) {
21883                                                         log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
21884                                                                         "--- fastcgi spawning local",
21885 @@ -1328,7 +1326,7 @@
21886                                                                         "\n\tmin-procs:", host->min_procs,
21887                                                                         "\n\tmax-procs:", host->max_procs);
21888                                                 }
21889 -                                               
21890 +
21891                                                 for (pno = 0; pno < host->min_procs; pno++) {
21892                                                         fcgi_proc *proc;
21893  
21894 @@ -1343,7 +1341,7 @@
21895                                                                 buffer_append_string(proc->unixsocket, "-");
21896                                                                 buffer_append_long(proc->unixsocket, pno);
21897                                                         }
21898 -                                                       
21899 +
21900                                                         if (s->debug) {
21901                                                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
21902                                                                                 "--- fastcgi spawning",
21903 @@ -1351,7 +1349,7 @@
21904                                                                                 "\n\tsocket", host->unixsocket,
21905                                                                                 "\n\tcurrent:", pno, "/", host->min_procs);
21906                                                         }
21907 -                                                       
21908 +
21909                                                         if (fcgi_spawn_connection(srv, p, host, proc)) {
21910                                                                 log_error_write(srv, __FILE__, __LINE__, "s",
21911                                                                                 "[ERROR]: spawning fcgi failed.");
21912 @@ -1359,35 +1357,35 @@
21913                                                         }
21914  
21915                                                         fastcgi_status_init(srv, p->statuskey, host, proc);
21916 -                                                       
21917 +
21918                                                         proc->next = host->first;
21919                                                         if (host->first)        host->first->prev = proc;
21920 -                                                       
21921 +
21922                                                         host->first = proc;
21923                                                 }
21924                                         } else {
21925                                                 fcgi_proc *proc;
21926 -                                               
21927 +
21928                                                 proc = fastcgi_process_init();
21929                                                 proc->id = host->num_procs++;
21930                                                 host->max_id++;
21931                                                 host->active_procs++;
21932                                                 proc->state = PROC_STATE_RUNNING;
21933 -                                               
21934 +
21935                                                 if (buffer_is_empty(host->unixsocket)) {
21936                                                         proc->port = host->port;
21937                                                 } else {
21938                                                         buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
21939                                                 }
21940 -                                               
21941 +
21942                                                 fastcgi_status_init(srv, p->statuskey, host, proc);
21943  
21944                                                 host->first = proc;
21945 -                                               
21946 +
21947                                                 host->min_procs = 1;
21948                                                 host->max_procs = 1;
21949                                         }
21950 -                                       
21951 +
21952                                         if (!buffer_is_empty(fcgi_mode)) {
21953                                                 if (strcmp(fcgi_mode->ptr, "responder") == 0) {
21954                                                         host->mode = FCGI_RESPONDER;
21955 @@ -1411,16 +1409,16 @@
21956                         }
21957                 }
21958         }
21959 -       
21960 +
21961         buffer_free(fcgi_mode);
21962 -       
21963 +
21964         return HANDLER_GO_ON;
21965  }
21966  
21967  static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) {
21968         hctx->state = state;
21969         hctx->state_timestamp = srv->cur_ts;
21970 -       
21971 +
21972         return 0;
21973  }
21974  
21975 @@ -1429,13 +1427,13 @@
21976         size_t m = 0;
21977         size_t i;
21978         buffer_uint *r = &(p->fcgi_request_id);
21979 -       
21980 +
21981         UNUSED(srv);
21982  
21983         for (i = 0; i < r->used; i++) {
21984                 if (r->ptr[i] > m) m = r->ptr[i];
21985         }
21986 -       
21987 +
21988         if (r->size == 0) {
21989                 r->size = 16;
21990                 r->ptr = malloc(sizeof(*r->ptr) * r->size);
21991 @@ -1443,54 +1441,54 @@
21992                 r->size += 16;
21993                 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
21994         }
21995 -       
21996 +
21997         r->ptr[r->used++] = ++m;
21998 -       
21999 +
22000         return m;
22001  }
22002  
22003  static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
22004         size_t i;
22005         buffer_uint *r = &(p->fcgi_request_id);
22006 -       
22007 +
22008         UNUSED(srv);
22009  
22010         for (i = 0; i < r->used; i++) {
22011                 if (r->ptr[i] == request_id) break;
22012         }
22013 -       
22014 +
22015         if (i != r->used) {
22016                 /* found */
22017 -               
22018 +
22019                 if (i != r->used - 1) {
22020                         r->ptr[i] = r->ptr[r->used - 1];
22021                 }
22022                 r->used--;
22023         }
22024 -       
22025 +
22026         return 0;
22027  }
22028  void fcgi_connection_close(server *srv, handler_ctx *hctx) {
22029         plugin_data *p;
22030         connection  *con;
22031 -       
22032 +
22033         if (NULL == hctx) return;
22034 -       
22035 +
22036         p    = hctx->plugin_data;
22037         con  = hctx->remote_conn;
22038 -       
22039 +
22040         if (con->mode != p->id) {
22041                 WP();
22042                 return;
22043         }
22044 -       
22045 +
22046         if (hctx->fd != -1) {
22047                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
22048                 fdevent_unregister(srv->ev, hctx->fd);
22049                 close(hctx->fd);
22050                 srv->cur_fds--;
22051         }
22052 -       
22053 +
22054         if (hctx->request_id != 0) {
22055                 fcgi_requestid_del(srv, p, hctx->request_id);
22056         }
22057 @@ -1499,7 +1497,7 @@
22058                 if (hctx->got_proc) {
22059                         /* after the connect the process gets a load */
22060                         hctx->proc->load--;
22061 -                       
22062 +
22063                         status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
22064  
22065                         fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
22066 @@ -1509,39 +1507,39 @@
22067  
22068                         if (p->conf.debug) {
22069                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
22070 -                                               "released proc:", 
22071 -                                               "pid:", hctx->proc->pid, 
22072 -                                               "socket:", hctx->proc->connection_name, 
22073 +                                               "released proc:",
22074 +                                               "pid:", hctx->proc->pid,
22075 +                                               "socket:", hctx->proc->connection_name,
22076                                                 "load:", hctx->proc->load);
22077                         }
22078                 }
22079         }
22080  
22081 -       
22082 +
22083         handler_ctx_free(hctx);
22084 -       con->plugin_ctx[p->id] = NULL;  
22085 +       con->plugin_ctx[p->id] = NULL;
22086  }
22087  
22088  static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
22089         plugin_data *p    = hctx->plugin_data;
22090 -       
22091 -       /* child died 
22092 -        * 
22093 -        * 1. 
22094 -        * 
22095 +
22096 +       /* child died
22097 +        *
22098 +        * 1.
22099 +        *
22100          * connect was ok, connection was accepted
22101          * but the php accept loop checks after the accept if it should die or not.
22102 -        * 
22103 -        * if yes we can only detect it at a write() 
22104 -        * 
22105 +        *
22106 +        * if yes we can only detect it at a write()
22107 +        *
22108          * next step is resetting this attemp and setup a connection again
22109 -        * 
22110 +        *
22111          * if we have more then 5 reconnects for the same request, die
22112 -        * 
22113 -        * 2. 
22114 -        * 
22115 +        *
22116 +        * 2.
22117 +        *
22118          * we have a connection but the child died by some other reason
22119 -        * 
22120 +        *
22121          */
22122  
22123         if (hctx->fd != -1) {
22124 @@ -1551,59 +1549,59 @@
22125                 srv->cur_fds--;
22126                 hctx->fd = -1;
22127         }
22128 -       
22129 +
22130         fcgi_requestid_del(srv, p, hctx->request_id);
22131 -       
22132 +
22133         fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
22134 -       
22135 +
22136         hctx->request_id = 0;
22137         hctx->reconnects++;
22138 -       
22139 +
22140         if (p->conf.debug > 2) {
22141                 if (hctx->proc) {
22142                         log_error_write(srv, __FILE__, __LINE__, "sdb",
22143 -                                       "release proc for reconnect:", 
22144 +                                       "release proc for reconnect:",
22145                                         hctx->proc->pid, hctx->proc->connection_name);
22146                 } else {
22147                         log_error_write(srv, __FILE__, __LINE__, "sb",
22148 -                                       "release proc for reconnect:", 
22149 +                                       "release proc for reconnect:",
22150                                         hctx->host->unixsocket);
22151                 }
22152         }
22153  
22154 -       if (hctx->proc && hctx->got_proc) {     
22155 +       if (hctx->proc && hctx->got_proc) {
22156                 hctx->proc->load--;
22157         }
22158  
22159         /* perhaps another host gives us more luck */
22160         hctx->host->load--;
22161         hctx->host = NULL;
22162 -       
22163 +
22164         return 0;
22165  }
22166  
22167  
22168  static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
22169         plugin_data *p = p_d;
22170 -       
22171 +
22172         fcgi_connection_close(srv, con->plugin_ctx[p->id]);
22173 -       
22174 +
22175         return HANDLER_GO_ON;
22176  }
22177  
22178  
22179  static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
22180         size_t len;
22181 -       
22182 +
22183         if (!key || !val) return -1;
22184 -       
22185 +
22186         len = key_len + val_len;
22187 -       
22188 +
22189         len += key_len > 127 ? 4 : 1;
22190         len += val_len > 127 ? 4 : 1;
22191 -       
22192 +
22193         buffer_prepare_append(env, len);
22194 -       
22195 +
22196         if (key_len > 127) {
22197                 env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
22198                 env->ptr[env->used++] = (key_len >> 16) & 0xff;
22199 @@ -1612,7 +1610,7 @@
22200         } else {
22201                 env->ptr[env->used++] = (key_len >> 0) & 0xff;
22202         }
22203 -       
22204 +
22205         if (val_len > 127) {
22206                 env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
22207                 env->ptr[env->used++] = (val_len >> 16) & 0xff;
22208 @@ -1621,12 +1619,12 @@
22209         } else {
22210                 env->ptr[env->used++] = (val_len >> 0) & 0xff;
22211         }
22212 -       
22213 +
22214         memcpy(env->ptr + env->used, key, key_len);
22215         env->used += key_len;
22216         memcpy(env->ptr + env->used, val, val_len);
22217         env->used += val_len;
22218 -       
22219 +
22220         return 0;
22221  }
22222  
22223 @@ -1639,11 +1637,11 @@
22224         header->contentLengthB1 = (contentLength >> 8) & 0xff;
22225         header->paddingLength = paddingLength;
22226         header->reserved = 0;
22227 -       
22228 +
22229         return 0;
22230  }
22231  /**
22232 - * 
22233 + *
22234   * returns
22235   *   -1 error
22236   *    0 connected
22237 @@ -1665,26 +1663,23 @@
22238         struct sockaddr_un fcgi_addr_un;
22239  #endif
22240         socklen_t servlen;
22241 -       
22242 +
22243         fcgi_extension_host *host = hctx->host;
22244         fcgi_proc *proc   = hctx->proc;
22245         int fcgi_fd       = hctx->fd;
22246 -       
22247 +
22248         memset(&fcgi_addr, 0, sizeof(fcgi_addr));
22249 -       
22250 +
22251         if (!buffer_is_empty(proc->unixsocket)) {
22252  #ifdef HAVE_SYS_UN_H
22253                 /* use the unix domain socket */
22254                 fcgi_addr_un.sun_family = AF_UNIX;
22255                 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
22256 -#ifdef SUN_LEN
22257 +
22258                 servlen = SUN_LEN(&fcgi_addr_un);
22259 -#else
22260 -               /* stevens says: */
22261 -               servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
22262 -#endif
22263 +
22264                 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
22265 -       
22266 +
22267                 if (buffer_is_empty(proc->connection_name)) {
22268                         /* on remote spawing we have to set the connection-name now */
22269                         buffer_copy_string(proc->connection_name, "unix:");
22270 @@ -1695,16 +1690,18 @@
22271  #endif
22272         } else {
22273                 fcgi_addr_in.sin_family = AF_INET;
22274 +
22275                 if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
22276 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
22277 -                                       "converting IP-adress failed for", host->host, 
22278 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
22279 +                                       "converting IP-adress failed for", host->host,
22280                                         "\nBe sure to specify an IP address here");
22281 -                       
22282 +
22283                         return -1;
22284                 }
22285 +
22286                 fcgi_addr_in.sin_port = htons(proc->port);
22287                 servlen = sizeof(fcgi_addr_in);
22288 -               
22289 +
22290                 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
22291  
22292                 if (buffer_is_empty(proc->connection_name)) {
22293 @@ -1715,20 +1712,20 @@
22294                         buffer_append_long(proc->connection_name, proc->port);
22295                 }
22296         }
22297 -       
22298 +
22299         if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
22300 -               if (errno == EINPROGRESS || 
22301 +               if (errno == EINPROGRESS ||
22302                     errno == EALREADY ||
22303                     errno == EINTR) {
22304                         if (hctx->conf.debug > 2) {
22305 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
22306 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
22307                                         "connect delayed, will continue later:", proc->connection_name);
22308                         }
22309 -                       
22310 +
22311                         return CONNECTION_DELAYED;
22312                 } else if (errno == EAGAIN) {
22313                         if (hctx->conf.debug) {
22314 -                               log_error_write(srv, __FILE__, __LINE__, "sbsd", 
22315 +                               log_error_write(srv, __FILE__, __LINE__, "sbsd",
22316                                         "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
22317                                         "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
22318                                         "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
22319 @@ -1736,8 +1733,8 @@
22320  
22321                         return CONNECTION_OVERLOADED;
22322                 } else {
22323 -                       log_error_write(srv, __FILE__, __LINE__, "sssb", 
22324 -                                       "connect failed:", 
22325 +                       log_error_write(srv, __FILE__, __LINE__, "sssb",
22326 +                                       "connect failed:",
22327                                         strerror(errno), "on",
22328                                         proc->connection_name);
22329  
22330 @@ -1747,7 +1744,7 @@
22331  
22332         hctx->reconnects = 0;
22333         if (hctx->conf.debug > 1) {
22334 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
22335 +               log_error_write(srv, __FILE__, __LINE__, "sd",
22336                                 "connect succeeded: ", fcgi_fd);
22337         }
22338  
22339 @@ -1756,21 +1753,21 @@
22340  
22341  static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
22342         size_t i;
22343 -       
22344 +
22345         for (i = 0; i < con->request.headers->used; i++) {
22346                 data_string *ds;
22347 -               
22348 +
22349                 ds = (data_string *)con->request.headers->data[i];
22350 -               
22351 +
22352                 if (ds->value->used && ds->key->used) {
22353                         size_t j;
22354                         buffer_reset(srv->tmp_buf);
22355 -                       
22356 +
22357                         if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
22358                                 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
22359                                 srv->tmp_buf->used--;
22360                         }
22361 -                       
22362 +
22363                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22364                         for (j = 0; j < ds->key->used - 1; j++) {
22365                                 char c = '_';
22366 @@ -1784,20 +1781,20 @@
22367                                 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22368                         }
22369                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22370 -                       
22371 +
22372                         fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22373                 }
22374         }
22375 -       
22376 +
22377         for (i = 0; i < con->environment->used; i++) {
22378                 data_string *ds;
22379 -               
22380 +
22381                 ds = (data_string *)con->environment->data[i];
22382 -               
22383 +
22384                 if (ds->value->used && ds->key->used) {
22385                         size_t j;
22386                         buffer_reset(srv->tmp_buf);
22387 -                       
22388 +
22389                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22390                         for (j = 0; j < ds->key->used - 1; j++) {
22391                                 char c = '_';
22392 @@ -1811,11 +1808,11 @@
22393                                 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22394                         }
22395                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22396 -                       
22397 +
22398                         fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22399                 }
22400         }
22401 -       
22402 +
22403         return 0;
22404  }
22405  
22406 @@ -1824,24 +1821,24 @@
22407         FCGI_BeginRequestRecord beginRecord;
22408         FCGI_Header header;
22409         buffer *b;
22410 -       
22411 +
22412         char buf[32];
22413         const char *s;
22414  #ifdef HAVE_IPV6
22415         char b2[INET6_ADDRSTRLEN + 1];
22416  #endif
22417 -       
22418 +
22419         plugin_data *p    = hctx->plugin_data;
22420         fcgi_extension_host *host= hctx->host;
22421  
22422         connection *con   = hctx->remote_conn;
22423         server_socket *srv_sock = con->srv_socket;
22424 -       
22425 +
22426         sock_addr our_addr;
22427         socklen_t our_addr_len;
22428 -       
22429 +
22430         /* send FCGI_BEGIN_REQUEST */
22431 -       
22432 +
22433         fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0);
22434         beginRecord.body.roleB0 = host->mode;
22435         beginRecord.body.roleB1 = 0;
22436 @@ -1849,21 +1846,21 @@
22437         memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
22438  
22439         b = chunkqueue_get_append_buffer(hctx->wb);
22440 -       
22441 +
22442         buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
22443 -       
22444 +
22445         /* send FCGI_PARAMS */
22446         buffer_prepare_copy(p->fcgi_env, 1024);
22447  
22448  
22449         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
22450 -       
22451 +
22452         if (con->server_name->used) {
22453                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
22454         } else {
22455  #ifdef HAVE_IPV6
22456 -               s = inet_ntop(srv_sock->addr.plain.sa_family, 
22457 -                             srv_sock->addr.plain.sa_family == AF_INET6 ? 
22458 +               s = inet_ntop(srv_sock->addr.plain.sa_family,
22459 +                             srv_sock->addr.plain.sa_family == AF_INET6 ?
22460                               (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
22461                               (const void *) &(srv_sock->addr.ipv4.sin_addr),
22462                               b2, sizeof(b2)-1);
22463 @@ -1872,50 +1869,50 @@
22464  #endif
22465                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
22466         }
22467 -       
22468 +
22469         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
22470 -       
22471 -       ltostr(buf, 
22472 +
22473 +       ltostr(buf,
22474  #ifdef HAVE_IPV6
22475                ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
22476  #else
22477                ntohs(srv_sock->addr.ipv4.sin_port)
22478  #endif
22479                );
22480 -       
22481 +
22482         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
22483 -       
22484 +
22485         /* get the server-side of the connection to the client */
22486         our_addr_len = sizeof(our_addr);
22487 -       
22488 +
22489         if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
22490                 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
22491         } else {
22492                 s = inet_ntop_cache_get_ip(srv, &(our_addr));
22493         }
22494         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
22495 -       
22496 -       ltostr(buf, 
22497 +
22498 +       ltostr(buf,
22499  #ifdef HAVE_IPV6
22500                ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
22501  #else
22502                ntohs(con->dst_addr.ipv4.sin_port)
22503  #endif
22504                );
22505 -       
22506 +
22507         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
22508 -       
22509 +
22510         s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
22511         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
22512 -       
22513 +
22514         if (!buffer_is_empty(con->authed_user)) {
22515                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
22516                              CONST_BUF_LEN(con->authed_user));
22517         }
22518 -       
22519 +
22520         if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
22521                 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
22522 -               
22523 +
22524                 /* request.content_length < SSIZE_MAX, see request.c */
22525                 ltostr(buf, con->request.content_length);
22526                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
22527 @@ -1930,12 +1927,12 @@
22528                  */
22529  
22530                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
22531 -               
22532 +
22533                 if (!buffer_is_empty(con->request.pathinfo)) {
22534                         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
22535 -                       
22536 +
22537                         /* PATH_TRANSLATED is only defined if PATH_INFO is set */
22538 -                       
22539 +
22540                         if (!buffer_is_empty(host->docroot)) {
22541                                 buffer_copy_string_buffer(p->path, host->docroot);
22542                         } else {
22543 @@ -1957,27 +1954,27 @@
22544          */
22545  
22546         if (!buffer_is_empty(host->docroot)) {
22547 -               /* 
22548 -                * rewrite SCRIPT_FILENAME 
22549 -                * 
22550 +               /*
22551 +                * rewrite SCRIPT_FILENAME
22552 +                *
22553                  */
22554 -               
22555 +
22556                 buffer_copy_string_buffer(p->path, host->docroot);
22557                 buffer_append_string_buffer(p->path, con->uri.path);
22558 -               
22559 +
22560                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22561                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
22562         } else {
22563                 buffer_copy_string_buffer(p->path, con->physical.path);
22564 -               
22565 -               /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself 
22566 -                * 
22567 +
22568 +               /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22569 +                *
22570                  * see src/sapi/cgi_main.c, init_request_info()
22571                  */
22572                 if (host->break_scriptfilename_for_php) {
22573                         buffer_append_string_buffer(p->path, con->request.pathinfo);
22574                 }
22575 -               
22576 +
22577                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22578                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
22579         }
22580 @@ -1987,7 +1984,7 @@
22581                 /**
22582                  * /app1/index/list
22583                  *
22584 -                * stripping /app1 or /app1/ should lead to 
22585 +                * stripping /app1 or /app1/ should lead to
22586                  *
22587                  * /index/list
22588                  *
22589 @@ -2001,7 +1998,7 @@
22590                     0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
22591                         /* the left is the same */
22592  
22593 -                       fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), 
22594 +                       fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
22595                                         con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
22596                                         con->request.orig_uri->used - (host->strip_request_uri->used - 2));
22597                 } else {
22598 @@ -2018,26 +2015,26 @@
22599         } else {
22600                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
22601         }
22602 -       
22603 +
22604         s = get_http_method_name(con->request.http_method);
22605         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
22606         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
22607         s = get_http_version_name(con->request.http_version);
22608         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
22609 -       
22610 +
22611  #ifdef USE_OPENSSL
22612         if (srv_sock->is_ssl) {
22613                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
22614         }
22615  #endif
22616 -       
22617 -       
22618 +
22619 +
22620         fcgi_env_add_request_headers(srv, con, p);
22621 -       
22622 +
22623         fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
22624         buffer_append_memory(b, (const char *)&header, sizeof(header));
22625         buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used);
22626 -       
22627 +
22628         fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
22629         buffer_append_memory(b, (const char *)&header, sizeof(header));
22630  
22631 @@ -2057,7 +2054,7 @@
22632  
22633                         /* we announce toWrite octects
22634                          * now take all the request_content chunk that we need to fill this request
22635 -                        * */   
22636 +                        * */
22637  
22638                         b = chunkqueue_get_append_buffer(hctx->wb);
22639                         fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0);
22640 @@ -2080,16 +2077,16 @@
22641                                         if (weHave > weWant - written) weHave = weWant - written;
22642  
22643                                         if (p->conf.debug > 10) {
22644 -                                               fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n", 
22645 -                                                               __FILE__, __LINE__, 
22646 -                                                               weHave, 
22647 -                                                               req_c->offset, 
22648 -                                                               req_c->file.length, 
22649 +                                               fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22650 +                                                               __FILE__, __LINE__,
22651 +                                                               weHave,
22652 +                                                               req_c->offset,
22653 +                                                               req_c->file.length,
22654                                                                 req_c->file.name->ptr);
22655                                         }
22656  
22657                                         assert(weHave != 0);
22658 -                                       
22659 +
22660                                         chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
22661  
22662                                         req_c->offset += weHave;
22663 @@ -2104,7 +2101,7 @@
22664                                          * - we reference the tempfile from the request-content-queue several times
22665                                          *   if the req_c is larger than FCGI_MAX_LENGTH
22666                                          * - we can't simply cleanup the request-content-queue as soon as possible
22667 -                                        *   as it would remove the tempfiles 
22668 +                                        *   as it would remove the tempfiles
22669                                          * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
22670                                          *   referencing chunk of the fastcgi-write-queue
22671                                          *
22672 @@ -2141,7 +2138,7 @@
22673                                         req_c->offset += weHave;
22674                                         req_cq->bytes_out += weHave;
22675                                         written += weHave;
22676 -                                       
22677 +
22678                                         hctx->wb->bytes_in += weHave;
22679  
22680                                         if (req_c->offset == req_c->mem->used - 1) {
22681 @@ -2155,12 +2152,12 @@
22682                                         break;
22683                                 }
22684                         }
22685 -                       
22686 +
22687                         b->used++; /* add virtual \0 */
22688                         offset += weWant;
22689                 }
22690         }
22691 -       
22692 +
22693         b = chunkqueue_get_append_buffer(hctx->wb);
22694         /* terminate STDIN */
22695         fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0);
22696 @@ -2175,118 +2172,19 @@
22697                 if ((i+1) % 16 == 0) {
22698                         size_t j;
22699                         for (j = i-15; j <= i; j++) {
22700 -                               fprintf(stderr, "%c", 
22701 +                               fprintf(stderr, "%c",
22702                                         isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
22703                         }
22704                         fprintf(stderr, "\n");
22705                 }
22706         }
22707  #endif
22708 -       
22709 -       return 0;
22710 -}
22711 -
22712 -static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
22713 -       char *s, *ns;
22714 -       
22715 -       handler_ctx *hctx = con->plugin_ctx[p->id];
22716 -       fcgi_extension_host *host= hctx->host;
22717 -       
22718 -       UNUSED(srv);
22719  
22720 -       buffer_copy_string_buffer(p->parse_response, in);
22721 -       
22722 -       /* search for \n */
22723 -       for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
22724 -               char *key, *value;
22725 -               int key_len;
22726 -               data_string *ds;
22727 -               
22728 -               /* a good day. Someone has read the specs and is sending a \r\n to us */
22729 -               
22730 -               if (ns > p->parse_response->ptr &&
22731 -                   *(ns-1) == '\r') {
22732 -                       *(ns-1) = '\0';
22733 -               }
22734 -               
22735 -               ns[0] = '\0';
22736 -               
22737 -               key = s;
22738 -               if (NULL == (value = strchr(s, ':'))) {
22739 -                       /* we expect: "<key>: <value>\n" */
22740 -                       continue;
22741 -               }
22742 -               
22743 -               key_len = value - key;
22744 -               
22745 -               value++;
22746 -               /* strip WS */
22747 -               while (*value == ' ' || *value == '\t') value++;
22748 -               
22749 -               if (host->mode != FCGI_AUTHORIZER ||
22750 -                   !(con->http_status == 0 ||
22751 -                     con->http_status == 200)) {
22752 -                       /* authorizers shouldn't affect the response headers sent back to the client */
22753 -                       
22754 -                       /* don't forward Status: */
22755 -                       if (0 != strncasecmp(key, "Status", key_len)) {
22756 -                               if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
22757 -                                       ds = data_response_init();
22758 -                               }
22759 -                               buffer_copy_string_len(ds->key, key, key_len);
22760 -                               buffer_copy_string(ds->value, value);
22761 -                               
22762 -                               array_insert_unique(con->response.headers, (data_unset *)ds);
22763 -                       }
22764 -               }
22765 -               
22766 -               switch(key_len) {
22767 -               case 4:
22768 -                       if (0 == strncasecmp(key, "Date", key_len)) {
22769 -                               con->parsed_response |= HTTP_DATE;
22770 -                       }
22771 -                       break;
22772 -               case 6:
22773 -                       if (0 == strncasecmp(key, "Status", key_len)) {
22774 -                               con->http_status = strtol(value, NULL, 10);
22775 -                               con->parsed_response |= HTTP_STATUS;
22776 -                       }
22777 -                       break;
22778 -               case 8:
22779 -                       if (0 == strncasecmp(key, "Location", key_len)) {
22780 -                               con->parsed_response |= HTTP_LOCATION;
22781 -                       }
22782 -                       break;
22783 -               case 10:
22784 -                       if (0 == strncasecmp(key, "Connection", key_len)) {
22785 -                               con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
22786 -                               con->parsed_response |= HTTP_CONNECTION;
22787 -                       }
22788 -                       break;
22789 -               case 14:
22790 -                       if (0 == strncasecmp(key, "Content-Length", key_len)) {
22791 -                               con->response.content_length = strtol(value, NULL, 10);
22792 -                               con->parsed_response |= HTTP_CONTENT_LENGTH;
22793 -                               
22794 -                               if (con->response.content_length < 0) con->response.content_length = 0;
22795 -                       }
22796 -                       break;
22797 -               default:
22798 -                       break;
22799 -               }
22800 -       }
22801 -       
22802 -       /* CGI/1.1 rev 03 - 7.2.1.2 */
22803 -       if ((con->parsed_response & HTTP_LOCATION) &&
22804 -           !(con->parsed_response & HTTP_STATUS)) {
22805 -               con->http_status = 302;
22806 -       }
22807 -       
22808         return 0;
22809  }
22810  
22811  typedef struct {
22812 -       buffer  *b; 
22813 +       buffer  *b;
22814         size_t   len;
22815         int      type;
22816         int      padding;
22817 @@ -2327,9 +2225,9 @@
22818                 return -1;
22819         }
22820  
22821 -       /* we have at least a header, now check how much me have to fetch */ 
22822 +       /* we have at least a header, now check how much me have to fetch */
22823         header = (FCGI_Header *)(packet->b->ptr);
22824 -                       
22825 +
22826         packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
22827         packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
22828         packet->type = header->type;
22829 @@ -2348,7 +2246,7 @@
22830                         size_t weHave = c->mem->used - c->offset - offset - 1;
22831  
22832                         if (weHave > weWant) weHave = weWant;
22833 -                                               
22834 +
22835                         buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
22836  
22837                         /* we only skipped the first 8 bytes as they are the fcgi header */
22838 @@ -2380,65 +2278,37 @@
22839         }
22840  
22841         chunkqueue_remove_finished_chunks(hctx->rb);
22842 -       
22843 +
22844         return 0;
22845  }
22846  
22847  static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
22848         int fin = 0;
22849 -       int toread;
22850 -       ssize_t r;
22851 -       
22852 +
22853         plugin_data *p    = hctx->plugin_data;
22854         connection *con   = hctx->remote_conn;
22855 -       int fcgi_fd       = hctx->fd;
22856         fcgi_extension_host *host= hctx->host;
22857         fcgi_proc *proc   = hctx->proc;
22858 -       
22859 -       /* 
22860 -        * check how much we have to read 
22861 -        */
22862 -       if (ioctl(hctx->fd, FIONREAD, &toread)) {
22863 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
22864 -                               "unexpected end-of-file (perhaps the fastcgi process died):",
22865 -                               fcgi_fd);
22866 -               return -1;
22867 -       }
22868 -       
22869 -       /* init read-buffer */
22870 -       
22871 -       if (toread > 0) {
22872 -               buffer *b;
22873 -
22874 -               b = chunkqueue_get_append_buffer(hctx->rb);
22875 -               buffer_prepare_copy(b, toread + 1);
22876 -
22877 -               /* append to read-buffer */
22878 -               if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
22879 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
22880 -                                       "unexpected end-of-file (perhaps the fastcgi process died):",
22881 -                                       fcgi_fd, strerror(errno));
22882 -                       return -1;
22883 -               }
22884 -               
22885 -               /* this should be catched by the b > 0 above */
22886 -               assert(r);
22887  
22888 -               b->used = r + 1; /* one extra for the fake \0 */
22889 -               b->ptr[b->used - 1] = '\0';
22890 -       } else {
22891 -               log_error_write(srv, __FILE__, __LINE__, "ssdsb", 
22892 +       switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) {
22893 +       case NETWORK_STATUS_WAIT_FOR_EVENT:
22894 +               /* we are only triggered when there is a event */
22895 +               log_error_write(srv, __FILE__, __LINE__, "ssdsb",
22896                                 "unexpected end-of-file (perhaps the fastcgi process died):",
22897                                 "pid:", proc->pid,
22898                                 "socket:", proc->connection_name);
22899 -               
22900 +               return -1;
22901 +       case NETWORK_STATUS_SUCCESS:
22902 +               break;
22903 +       default:
22904 +               log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
22905                 return -1;
22906         }
22907  
22908         /*
22909          * parse the fastcgi packets and forward the content to the write-queue
22910          *
22911 -        */     
22912 +        */
22913         while (fin == 0) {
22914                 fastcgi_response_packet packet;
22915  
22916 @@ -2454,92 +2324,135 @@
22917  
22918                         /* is the header already finished */
22919                         if (0 == con->file_started) {
22920 -                               char *c;
22921 -                               size_t blen;
22922 -                               data_string *ds;
22923 -                                       
22924 -                               /* search for header terminator 
22925 -                                * 
22926 -                                * if we start with \r\n check if last packet terminated with \r\n
22927 -                                * if we start with \n check if last packet terminated with \n
22928 -                                * search for \r\n\r\n
22929 -                                * search for \n\n
22930 -                                */
22931 -
22932 -                               if (hctx->response_header->used == 0) {
22933 -                                       buffer_copy_string_buffer(hctx->response_header, packet.b);
22934 -                               } else {
22935 -                                       buffer_append_string_buffer(hctx->response_header, packet.b);
22936 -                               }
22937 -
22938 -                               if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
22939 -                                       blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
22940 -                                       hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
22941 -                                       c += 4; /* point the the start of the response */
22942 -                               } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
22943 -                                       blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
22944 -                                       hctx->response_header->used = c - hctx->response_header->ptr + 2;
22945 -                                       c += 2; /* point the the start of the response */
22946 -                               } else {
22947 -                                       /* no luck, no header found */
22948 +                               int have_content_length = 0;
22949 +                               int need_more = 0;
22950 +                               size_t i;
22951 +
22952 +                               /* append the current packet to the chunk queue */
22953 +                               chunkqueue_append_buffer(hctx->http_rb, packet.b);
22954 +                               http_response_reset(p->resp);
22955 +
22956 +                               switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
22957 +                               case PARSE_ERROR:
22958 +                                       /* parsing the response header failed */
22959 +
22960 +                                       con->http_status = 502; /* Bad Gateway */
22961 +
22962 +                                       return 1;
22963 +                               case PARSE_NEED_MORE:
22964 +                                       need_more = 1;
22965 +                                       break; /* leave the loop */
22966 +                               case PARSE_SUCCESS:
22967                                         break;
22968 +                               default:
22969 +                                       /* should not happen */
22970 +                                       SEGFAULT();
22971                                 }
22972  
22973 -                               /* parse the response header */
22974 -                               fcgi_response_parse(srv, con, p, hctx->response_header);
22975 +                               if (need_more) break;
22976  
22977 -                               con->file_started = 1;
22978 +                               chunkqueue_remove_finished_chunks(hctx->http_rb);
22979  
22980 -                               if (host->mode == FCGI_AUTHORIZER &&
22981 -                                   (con->http_status == 0 ||
22982 -                                    con->http_status == 200)) {
22983 -                                       /* a authorizer with approved the static request, ignore the content here */
22984 -                                       hctx->send_content_body = 0;
22985 -                               }
22986 -
22987 -                               if (host->allow_xsendfile &&
22988 -                                   NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
22989 -                                       stat_cache_entry *sce;
22990 -
22991 -                                       if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
22992 -                                               /* found */
22993 -
22994 -                                               http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
22995 -                                               hctx->send_content_body = 0; /* ignore the content */
22996 -                                               joblist_append(srv, con);
22997 +                               con->http_status = p->resp->status;
22998 +
22999 +                               /* handle the header fields */
23000 +                               if (host->mode == FCGI_AUTHORIZER) {
23001 +                                       /* auth mode is a bit different */
23002 +
23003 +                                       if (con->http_status == 0 ||
23004 +                                           con->http_status == 200) {
23005 +                                               /* a authorizer with approved the static request, ignore the content here */
23006 +                                               hctx->send_content_body = 0;
23007                                         }
23008                                 }
23009  
23010 +                               /* copy the http-headers */
23011 +                               for (i = 0; i < p->resp->headers->used; i++) {
23012 +                                       const char *ign[] = { "Status", NULL };
23013 +                                       size_t j;
23014 +                                       data_string *ds;
23015 +
23016 +                                       data_string *header = (data_string *)p->resp->headers->data[i];
23017 +
23018 +                                       /* ignore all headers in AUTHORIZER mode */
23019 +                                       if (host->mode == FCGI_AUTHORIZER) continue;
23020 +
23021 +                                       /* some headers are ignored by default */
23022 +                                       for (j = 0; ign[j]; j++) {
23023 +                                               if (0 == strcasecmp(ign[j], header->key->ptr)) break;
23024 +                                       }
23025 +                                       if (ign[j]) continue;
23026 +
23027 +                                       if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
23028 +                                               /* CGI/1.1 rev 03 - 7.2.1.2 */
23029 +                                               con->http_status = 302;
23030 +                                       } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
23031 +                                               have_content_length = 1;
23032 +                                       } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) || 
23033 +                                                  0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
23034 +                                               
23035 +                                               stat_cache_entry *sce;
23036                                                 
23037 -                               if (hctx->send_content_body && blen > 1) {                                              
23038 -                                       /* enable chunked-transfer-encoding */
23039 +                                               if (host->allow_xsendfile &&
23040 +                                                   HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
23041 +                                                       http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
23042 +                                                       hctx->send_content_body = 0; /* ignore the content */
23043 +                                       
23044 +                                                       joblist_append(srv, con);
23045 +                                               }
23046 +
23047 +                                               continue; /* ignore header */
23048 +                                       }
23049 +                                       
23050 +                                       if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
23051 +                                               ds = data_response_init();
23052 +                                       }
23053 +                                       buffer_copy_string_buffer(ds->key, header->key);
23054 +                                       buffer_copy_string_buffer(ds->value, header->value);
23055 +
23056 +                                       array_insert_unique(con->response.headers, (data_unset *)ds);
23057 +                               }
23058 +
23059 +                               /* header is complete ... go on with the body */
23060 +
23061 +                               con->file_started = 1;
23062 +
23063 +                               if (hctx->send_content_body) {
23064 +                                       chunk *c = hctx->http_rb->first;
23065 +
23066 +                                       /* if we don't have a content-length enable chunked encoding 
23067 +                                        * if possible
23068 +                                        * 
23069 +                                        * TODO: move this to a later stage in the filter-queue
23070 +                                        *  */
23071                                         if (con->request.http_version == HTTP_VERSION_1_1 &&
23072 -                                           !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23073 +                                           !have_content_length) {
23074                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23075                                         }
23076  
23077 -                                       http_chunk_append_mem(srv, con, c, blen);
23078 +                                       /* copy the rest of the data */
23079 +                                       for (c = hctx->http_rb->first; c; c = c->next) {
23080 +                                               if (c->mem->used > 1) {
23081 +                                                       http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
23082 +                                                       c->offset = c->mem->used - 1;
23083 +                                               }
23084 +                                       }
23085 +                                       chunkqueue_remove_finished_chunks(hctx->http_rb);
23086                                         joblist_append(srv, con);
23087                                 }
23088                         } else if (hctx->send_content_body && packet.b->used > 1) {
23089 -                               if (con->request.http_version == HTTP_VERSION_1_1 &&
23090 -                                   !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23091 -                                       /* enable chunked-transfer-encoding */
23092 -                                       con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23093 -                               }
23094 -
23095                                 http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
23096                                 joblist_append(srv, con);
23097                         }
23098                         break;
23099                 case FCGI_STDERR:
23100 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
23101 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
23102                                         "FastCGI-stderr:", packet.b);
23103 -                       
23104 +
23105                         break;
23106                 case FCGI_END_REQUEST:
23107                         con->file_finished = 1;
23108 -                       
23109 +
23110                         if (host->mode != FCGI_AUTHORIZER ||
23111                             !(con->http_status == 0 ||
23112                               con->http_status == 200)) {
23113 @@ -2547,39 +2460,39 @@
23114                                 http_chunk_append_mem(srv, con, NULL, 0);
23115                                 joblist_append(srv, con);
23116                         }
23117 -                       
23118 +
23119                         fin = 1;
23120                         break;
23121                 default:
23122 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23123 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
23124                                         "FastCGI: header.type not handled: ", packet.type);
23125                         break;
23126                 }
23127                 buffer_free(packet.b);
23128         }
23129 -       
23130 +
23131         return fin;
23132  }
23133  
23134  static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
23135         fcgi_proc *proc;
23136 -       
23137 +
23138         for (proc = host->first; proc; proc = proc->next) {
23139                 int status;
23140  
23141                 if (p->conf.debug > 2) {
23142 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdddd", 
23143 -                                       "proc:", 
23144 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdddd",
23145 +                                       "proc:",
23146                                         proc->connection_name,
23147                                         proc->state,
23148                                         proc->is_local,
23149                                         proc->load,
23150                                         proc->pid);
23151                 }
23152 -               
23153 -               /* 
23154 +
23155 +               /*
23156                  * if the remote side is overloaded, we check back after <n> seconds
23157 -                * 
23158 +                *
23159                  */
23160                 switch (proc->state) {
23161                 case PROC_STATE_KILLED:
23162 @@ -2592,13 +2505,13 @@
23163                         break;
23164                 case PROC_STATE_OVERLOADED:
23165                         if (srv->cur_ts <= proc->disabled_until) break;
23166 -                       
23167 +
23168                         proc->state = PROC_STATE_RUNNING;
23169                         host->active_procs++;
23170 -                       
23171 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", 
23172 -                                       "fcgi-server re-enabled:", 
23173 -                                       host->host, host->port, 
23174 +
23175 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdb",
23176 +                                       "fcgi-server re-enabled:",
23177 +                                       host->host, host->port,
23178                                         host->unixsocket);
23179                         break;
23180                 case PROC_STATE_DIED_WAIT_FOR_PID:
23181 @@ -2606,7 +2519,7 @@
23182                         if (!proc->is_local) break;
23183  
23184                         /* the child should not terminate at all */
23185 -                       
23186 +#ifndef _WIN32
23187                         switch(waitpid(proc->pid, &status, WNOHANG)) {
23188                         case 0:
23189                                 /* child is still alive */
23190 @@ -2616,45 +2529,45 @@
23191                         default:
23192                                 if (WIFEXITED(status)) {
23193  #if 0
23194 -                                       log_error_write(srv, __FILE__, __LINE__, "sdsd", 
23195 +                                       log_error_write(srv, __FILE__, __LINE__, "sdsd",
23196                                                         "child exited, pid:", proc->pid,
23197                                                         "status:", WEXITSTATUS(status));
23198  #endif
23199                                 } else if (WIFSIGNALED(status)) {
23200 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23201 -                                                       "child signaled:", 
23202 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
23203 +                                                       "child signaled:",
23204                                                         WTERMSIG(status));
23205                                 } else {
23206 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23207 -                                                       "child died somehow:", 
23208 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
23209 +                                                       "child died somehow:",
23210                                                         status);
23211                                 }
23212 -                               
23213 +
23214                                 proc->state = PROC_STATE_DIED;
23215                                 break;
23216                         }
23217 -
23218 +#endif
23219                         /* fall through if we have a dead proc now */
23220                         if (proc->state != PROC_STATE_DIED) break;
23221  
23222                 case PROC_STATE_DIED:
23223 -                       /* local proc get restarted by us, 
23224 +                       /* local proc get restarted by us,
23225                          * remote ones hopefully by the admin */
23226 -                       
23227 +
23228                         if (proc->is_local) {
23229                                 /* we still have connections bound to this proc,
23230                                  * let them terminate first */
23231                                 if (proc->load != 0) break;
23232 -                       
23233 +
23234                                 /* restart the child */
23235 -                               
23236 +
23237                                 if (p->conf.debug) {
23238                                         log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23239                                                         "--- fastcgi spawning",
23240                                                         "\n\tsocket", proc->connection_name,
23241                                                         "\n\tcurrent:", 1, "/", host->min_procs);
23242                                 }
23243 -                               
23244 +
23245                                 if (fcgi_spawn_connection(srv, p, host, proc)) {
23246                                         log_error_write(srv, __FILE__, __LINE__, "s",
23247                                                         "ERROR: spawning fcgi failed.");
23248 @@ -2662,18 +2575,18 @@
23249                                 }
23250                         } else {
23251                                 if (srv->cur_ts <= proc->disabled_until) break;
23252 -                       
23253 +
23254                                 proc->state = PROC_STATE_RUNNING;
23255                                 host->active_procs++;
23256 -                       
23257 -                               log_error_write(srv, __FILE__, __LINE__,  "sb", 
23258 -                                               "fcgi-server re-enabled:", 
23259 +
23260 +                               log_error_write(srv, __FILE__, __LINE__,  "sb",
23261 +                                               "fcgi-server re-enabled:",
23262                                                 proc->connection_name);
23263                         }
23264                         break;
23265                 }
23266         }
23267 -       
23268 +
23269         return 0;
23270  }
23271  
23272 @@ -2682,19 +2595,19 @@
23273         fcgi_extension_host *host= hctx->host;
23274         connection *con   = hctx->remote_conn;
23275         fcgi_proc  *proc;
23276 -       
23277 +
23278         int ret;
23279  
23280 -       /* sanity check */      
23281 +       /* sanity check */
23282         if (!host ||
23283             ((!host->host->used || !host->port) && !host->unixsocket->used)) {
23284 -               log_error_write(srv, __FILE__, __LINE__, "sxddd", 
23285 +               log_error_write(srv, __FILE__, __LINE__, "sxddd",
23286                                 "write-req: error",
23287                                 host,
23288                                 host->host->used,
23289                                 host->port,
23290                                 host->unixsocket->used);
23291 -                       
23292 +
23293                 hctx->proc->disabled_until = srv->cur_ts + 10;
23294                 hctx->proc->state = PROC_STATE_DIED;
23295  
23296 @@ -2705,12 +2618,12 @@
23297         if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23298                 int socket_error;
23299                 socklen_t socket_error_len = sizeof(socket_error);
23300 -                       
23301 +
23302                 /* try to finish the connect() */
23303                 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
23304 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
23305 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
23306                                         "getsockopt failed:", strerror(errno));
23307 -                       
23308 +
23309                         hctx->proc->disabled_until = srv->cur_ts + 10;
23310                         hctx->proc->state = PROC_STATE_DIED;
23311  
23312 @@ -2719,12 +2632,12 @@
23313                 if (socket_error != 0) {
23314                         if (!hctx->proc->is_local || p->conf.debug) {
23315                                 /* local procs get restarted */
23316 -                               
23317 +
23318                                 log_error_write(srv, __FILE__, __LINE__, "sssb",
23319 -                                               "establishing connection failed:", strerror(socket_error), 
23320 +                                               "establishing connection failed:", strerror(socket_error),
23321                                                 "socket:", hctx->proc->connection_name);
23322                         }
23323 -       
23324 +
23325                         hctx->proc->disabled_until = srv->cur_ts + 5;
23326  
23327                         if (hctx->proc->is_local) {
23328 @@ -2732,17 +2645,17 @@
23329                         } else {
23330                                 hctx->proc->state = PROC_STATE_DIED;
23331                         }
23332 -       
23333 +
23334                         hctx->proc->state = PROC_STATE_DIED;
23335 -               
23336 +
23337                         fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23338                         buffer_append_string(p->statuskey, ".died");
23339  
23340                         status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23341 -               
23342 +
23343                         return HANDLER_ERROR;
23344                 }
23345 -               /* go on with preparing the request */ 
23346 +               /* go on with preparing the request */
23347                 hctx->state = FCGI_STATE_PREPARE_WRITE;
23348         }
23349  
23350 @@ -2755,14 +2668,14 @@
23351                 /* do we have a running process for this host (max-procs) ? */
23352                 hctx->proc = NULL;
23353  
23354 -               for (proc = hctx->host->first; 
23355 -                    proc && proc->state != PROC_STATE_RUNNING; 
23356 +               for (proc = hctx->host->first;
23357 +                    proc && proc->state != PROC_STATE_RUNNING;
23358                      proc = proc->next);
23359 -                       
23360 +
23361                 /* all childs are dead */
23362                 if (proc == NULL) {
23363                         hctx->fde_ndx = -1;
23364 -               
23365 +
23366                         return HANDLER_ERROR;
23367                 }
23368  
23369 @@ -2775,50 +2688,50 @@
23370                 }
23371  
23372                 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
23373 -               
23374 +
23375                 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
23376                         if (errno == EMFILE ||
23377                             errno == EINTR) {
23378 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
23379 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
23380                                                 "wait for fd at connection:", con->fd);
23381 -                               
23382 +
23383                                 return HANDLER_WAIT_FOR_FD;
23384                         }
23385 -                       
23386 -                       log_error_write(srv, __FILE__, __LINE__, "ssdd", 
23387 +
23388 +                       log_error_write(srv, __FILE__, __LINE__, "ssdd",
23389                                         "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
23390                         return HANDLER_ERROR;
23391                 }
23392                 hctx->fde_ndx = -1;
23393 -               
23394 +
23395                 srv->cur_fds++;
23396 -               
23397 +
23398                 fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
23399 -               
23400 +
23401                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
23402 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
23403 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
23404                                         "fcntl failed:", strerror(errno));
23405 -                       
23406 +
23407                         return HANDLER_ERROR;
23408                 }
23409 -                       
23410 +
23411                 if (hctx->proc->is_local) {
23412                         hctx->pid = hctx->proc->pid;
23413                 }
23414 -                       
23415 +
23416                 switch (fcgi_establish_connection(srv, hctx)) {
23417                 case CONNECTION_DELAYED:
23418                         /* connection is in progress, wait for an event and call getsockopt() below */
23419 -                       
23420 +
23421                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23422 -                       
23423 +
23424                         fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED);
23425                         return HANDLER_WAIT_FOR_EVENT;
23426                 case CONNECTION_OVERLOADED:
23427                         /* cool down the backend, it is overloaded
23428                          * -> EAGAIN */
23429  
23430 -                       log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
23431 +                       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23432                                 "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
23433                                 "reconnects:", hctx->reconnects,
23434                                 "load:", host->load);
23435 @@ -2831,7 +2744,7 @@
23436                         buffer_append_string(p->statuskey, ".overloaded");
23437  
23438                         status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23439 -                       
23440 +
23441                         return HANDLER_ERROR;
23442                 case CONNECTION_DEAD:
23443                         /* we got a hard error from the backend like
23444 @@ -2840,19 +2753,19 @@
23445                          *
23446                          * for check if the host is back in 5 seconds
23447                          *  */
23448 -                       
23449 +
23450                         hctx->proc->disabled_until = srv->cur_ts + 5;
23451                         if (hctx->proc->is_local) {
23452                                 hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
23453                         } else {
23454                                 hctx->proc->state = PROC_STATE_DIED;
23455                         }
23456 -       
23457 -                       log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
23458 +
23459 +                       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23460                                 "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
23461                                 "reconnects:", hctx->reconnects,
23462                                 "load:", host->load);
23463 -       
23464 +
23465                         fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23466                         buffer_append_string(p->statuskey, ".died");
23467  
23468 @@ -2863,19 +2776,19 @@
23469                         /* everything is ok, go on */
23470  
23471                         fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
23472 -                       
23473 +
23474                         break;
23475                 case CONNECTION_UNSET:
23476                         break;
23477                 }
23478 -               
23479 +
23480         case FCGI_STATE_PREPARE_WRITE:
23481                 /* ok, we have the connection */
23482 -               
23483 +
23484                 hctx->proc->load++;
23485                 hctx->proc->last_used = srv->cur_ts;
23486                 hctx->got_proc = 1;
23487 -       
23488 +
23489                 status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
23490                 status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
23491  
23492 @@ -2898,9 +2811,9 @@
23493  
23494                 if (p->conf.debug) {
23495                         log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
23496 -                                       "got proc:", 
23497 -                                       "pid:", hctx->proc->pid, 
23498 -                                       "socket:", hctx->proc->connection_name, 
23499 +                                       "got proc:",
23500 +                                       "pid:", hctx->proc->pid,
23501 +                                       "socket:", hctx->proc->connection_name,
23502                                         "load:", hctx->proc->load);
23503                 }
23504  
23505 @@ -2908,62 +2821,63 @@
23506                 if (hctx->request_id == 0) {
23507                         hctx->request_id = fcgi_requestid_new(srv, p);
23508                 } else {
23509 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23510 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
23511                                         "fcgi-request is already in use:", hctx->request_id);
23512                 }
23513 -               
23514 +
23515                 /* fall through */
23516                 fcgi_create_env(srv, hctx, hctx->request_id);
23517 -               
23518 +
23519                 fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
23520 -               
23521 +
23522                 /* fall through */
23523         case FCGI_STATE_WRITE:
23524 -               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); 
23525 +               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
23526  
23527                 chunkqueue_remove_finished_chunks(hctx->wb);
23528 -               
23529 +
23530                 if (ret < 0) {
23531                         switch(errno) {
23532                         case ENOTCONN:
23533 -                               /* the connection got dropped after accept() 
23534 -                                * 
23535 -                                * this is most of the time a PHP which dies 
23536 +                               /* the connection got dropped after accept()
23537 +                                *
23538 +                                * this is most of the time a PHP which dies
23539                                  * after PHP_FCGI_MAX_REQUESTS
23540 -                                * 
23541 -                                */ 
23542 +                                *
23543 +                                */
23544                                 if (hctx->wb->bytes_out == 0 &&
23545                                     hctx->reconnects < 5) {
23546 -                                       usleep(10000); /* take away the load of the webserver 
23547 -                                                       * to let the php a chance to restart 
23548 +#ifndef _WIN32
23549 +                                       usleep(10000); /* take away the load of the webserver
23550 +                                                       * to let the php a chance to restart
23551                                                         */
23552 -                                       
23553 +#endif
23554                                         fcgi_reconnect(srv, hctx);
23555 -                               
23556 +
23557                                         return HANDLER_WAIT_FOR_FD;
23558                                 }
23559 -                               
23560 +
23561                                 /* not reconnected ... why
23562 -                                * 
23563 +                                *
23564                                  * far@#lighttpd report this for FreeBSD
23565 -                                * 
23566 +                                *
23567                                  */
23568 -                               
23569 -                               log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
23570 +
23571 +                               log_error_write(srv, __FILE__, __LINE__, "ssosd",
23572                                                 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
23573                                                 "write-offset:", hctx->wb->bytes_out,
23574                                                 "reconnect attempts:", hctx->reconnects);
23575 -                               
23576 +
23577                                 return HANDLER_ERROR;
23578                         case EAGAIN:
23579                         case EINTR:
23580                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23581 -                               
23582 +
23583                                 return HANDLER_WAIT_FOR_EVENT;
23584                         default:
23585 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", 
23586 +                               log_error_write(srv, __FILE__, __LINE__, "ssd",
23587                                                 "write failed:", strerror(errno), errno);
23588 -                               
23589 +
23590                                 return HANDLER_ERROR;
23591                         }
23592                 }
23593 @@ -2975,7 +2889,7 @@
23594                         fcgi_set_state(srv, hctx, FCGI_STATE_READ);
23595                 } else {
23596                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23597 -                               
23598 +
23599                         return HANDLER_WAIT_FOR_EVENT;
23600                 }
23601  
23602 @@ -2987,7 +2901,7 @@
23603                 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
23604                 return HANDLER_ERROR;
23605         }
23606 -       
23607 +
23608         return HANDLER_WAIT_FOR_EVENT;
23609  }
23610  
23611 @@ -2996,18 +2910,18 @@
23612   * */
23613  SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
23614         plugin_data *p = p_d;
23615 -       
23616 +
23617         handler_ctx *hctx = con->plugin_ctx[p->id];
23618         fcgi_proc *proc;
23619         fcgi_extension_host *host;
23620 -       
23621 +
23622         if (NULL == hctx) return HANDLER_GO_ON;
23623 -       
23624 +
23625         /* not my job */
23626         if (con->mode != p->id) return HANDLER_GO_ON;
23627  
23628         /* we don't have a host yet, choose one
23629 -        * -> this happens in the first round 
23630 +        * -> this happens in the first round
23631          *    and when the host died and we have to select a new one */
23632         if (hctx->host == NULL) {
23633                 size_t k;
23634 @@ -3016,23 +2930,23 @@
23635                 /* get best server */
23636                 for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
23637                         host = hctx->ext->hosts[k];
23638 -               
23639 +
23640                         /* we should have at least one proc that can do something */
23641                         if (host->active_procs == 0) continue;
23642  
23643                         if (used == -1 || host->load < used) {
23644                                 used = host->load;
23645 -                       
23646 +
23647                                 ndx = k;
23648                         }
23649                 }
23650 -       
23651 +
23652                 /* found a server */
23653                 if (ndx == -1) {
23654                         /* all hosts are down */
23655  
23656                         fcgi_connection_close(srv, hctx);
23657 -                       
23658 +
23659                         con->http_status = 500;
23660                         con->mode = DIRECT;
23661  
23662 @@ -3040,16 +2954,16 @@
23663                 }
23664  
23665                 host = hctx->ext->hosts[ndx];
23666 -               
23667 -               /* 
23668 -                * if check-local is disabled, use the uri.path handler 
23669 -                * 
23670 +
23671 +               /*
23672 +                * if check-local is disabled, use the uri.path handler
23673 +                *
23674                  */
23675 -               
23676 +
23677                 /* init handler-context */
23678                 hctx->host = host;
23679  
23680 -               /* we put a connection on this host, move the other new connections to other hosts 
23681 +               /* we put a connection on this host, move the other new connections to other hosts
23682                  *
23683                  * as soon as hctx->host is unassigned, decrease the load again */
23684                 hctx->host->load++;
23685 @@ -3063,7 +2977,7 @@
23686         case HANDLER_ERROR:
23687                 proc = hctx->proc;
23688                 host = hctx->host;
23689 -               
23690 +
23691                 if (hctx->state == FCGI_STATE_INIT ||
23692                     hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23693                         if (proc) host->active_procs--;
23694 @@ -3078,7 +2992,7 @@
23695                                 return HANDLER_WAIT_FOR_FD;
23696                         } else {
23697                                 fcgi_connection_close(srv, hctx);
23698 -                       
23699 +
23700                                 buffer_reset(con->physical.path);
23701                                 con->mode = DIRECT;
23702                                 con->http_status = 500;
23703 @@ -3088,12 +3002,12 @@
23704                         }
23705                 } else {
23706                         fcgi_connection_close(srv, hctx);
23707 -                       
23708 +
23709                         buffer_reset(con->physical.path);
23710                         con->mode = DIRECT;
23711                         con->http_status = 503;
23712                         joblist_append(srv, con); /* really ? */
23713 -                       
23714 +
23715                         return HANDLER_FINISHED;
23716                 }
23717         case HANDLER_WAIT_FOR_EVENT:
23718 @@ -3115,7 +3029,7 @@
23719         handler_ctx *hctx = ctx;
23720         connection  *con  = hctx->remote_conn;
23721         plugin_data *p    = hctx->plugin_data;
23722 -       
23723 +
23724         fcgi_proc *proc   = hctx->proc;
23725         fcgi_extension_host *host= hctx->host;
23726  
23727 @@ -3125,8 +3039,8 @@
23728                 case 0:
23729                         break;
23730                 case 1:
23731 -                       
23732 -                       if (host->mode == FCGI_AUTHORIZER && 
23733 +
23734 +                       if (host->mode == FCGI_AUTHORIZER &&
23735                             (con->http_status == 200 ||
23736                              con->http_status == 0)) {
23737                                 /*
23738 @@ -3136,26 +3050,26 @@
23739                                  */
23740  
23741                                 buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
23742 -                               
23743 +
23744                                 buffer_copy_string_buffer(con->physical.path, host->docroot);
23745                                 buffer_append_string_buffer(con->physical.path, con->uri.path);
23746                                 fcgi_connection_close(srv, hctx);
23747 -                               
23748 +
23749                                 con->mode = DIRECT;
23750                                 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
23751                         } else {
23752                                 /* we are done */
23753                                 fcgi_connection_close(srv, hctx);
23754                         }
23755 -                       
23756 +
23757                         joblist_append(srv, con);
23758                         return HANDLER_FINISHED;
23759                 case -1:
23760                         if (proc->pid && proc->state != PROC_STATE_DIED) {
23761                                 int status;
23762 -                               
23763 +
23764                                 /* only fetch the zombie if it is not already done */
23765 -                               
23766 +#ifndef _WIN32
23767                                 switch(waitpid(proc->pid, &status, WNOHANG)) {
23768                                 case 0:
23769                                         /* child is still alive */
23770 @@ -3165,60 +3079,61 @@
23771                                 default:
23772                                         /* the child should not terminate at all */
23773                                         if (WIFEXITED(status)) {
23774 -                                               log_error_write(srv, __FILE__, __LINE__, "sdsd", 
23775 +                                               log_error_write(srv, __FILE__, __LINE__, "sdsd",
23776                                                                 "child exited, pid:", proc->pid,
23777                                                                 "status:", WEXITSTATUS(status));
23778                                         } else if (WIFSIGNALED(status)) {
23779 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
23780 -                                                               "child signaled:", 
23781 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
23782 +                                                               "child signaled:",
23783                                                                 WTERMSIG(status));
23784                                         } else {
23785 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
23786 -                                                               "child died somehow:", 
23787 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
23788 +                                                               "child died somehow:",
23789                                                                 status);
23790                                         }
23791 -                                       
23792 +
23793                                         if (p->conf.debug) {
23794                                                 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23795                                                                 "--- fastcgi spawning",
23796                                                                 "\n\tsocket", proc->connection_name,
23797                                                                 "\n\tcurrent:", 1, "/", host->min_procs);
23798                                         }
23799 -                                       
23800 +
23801                                         if (fcgi_spawn_connection(srv, p, host, proc)) {
23802                                                 /* respawning failed, retry later */
23803                                                 proc->state = PROC_STATE_DIED;
23804  
23805 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
23806 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
23807                                                                 "respawning failed, will retry later");
23808                                         }
23809 -                                       
23810 +
23811                                         break;
23812                                 }
23813 +#endif
23814                         }
23815  
23816                         if (con->file_started == 0) {
23817                                 /* nothing has been send out yet, try to use another child */
23818 -                               
23819 +
23820                                 if (hctx->wb->bytes_out == 0 &&
23821                                     hctx->reconnects < 5) {
23822                                         fcgi_reconnect(srv, hctx);
23823 -                                       
23824 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbsbs", 
23825 +
23826 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23827                                                 "response not received, request not sent",
23828 -                                               "on socket:", proc->connection_name, 
23829 +                                               "on socket:", proc->connection_name,
23830                                                 "for", con->uri.path, ", reconnecting");
23831 -                                       
23832 +
23833                                         return HANDLER_WAIT_FOR_FD;
23834                                 }
23835 -                       
23836 -                               log_error_write(srv, __FILE__, __LINE__, "sosbsbs", 
23837 +
23838 +                               log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
23839                                                 "response not received, request sent:", hctx->wb->bytes_out,
23840 -                                               "on socket:", proc->connection_name, 
23841 +                                               "on socket:", proc->connection_name,
23842                                                 "for", con->uri.path, ", closing connection");
23843 -                               
23844 +
23845                                 fcgi_connection_close(srv, hctx);
23846 -                               
23847 +
23848                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
23849                                 buffer_reset(con->physical.path);
23850                                 con->http_status = 500;
23851 @@ -3226,76 +3141,76 @@
23852                         } else {
23853                                 /* response might have been already started, kill the connection */
23854                                 fcgi_connection_close(srv, hctx);
23855 -                               
23856 -                               log_error_write(srv, __FILE__, __LINE__, "ssbsbs", 
23857 +
23858 +                               log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23859                                                 "response already sent out, but backend returned error",
23860 -                                               "on socket:", proc->connection_name, 
23861 +                                               "on socket:", proc->connection_name,
23862                                                 "for", con->uri.path, ", terminating connection");
23863 -                               
23864 +
23865                                 connection_set_state(srv, con, CON_STATE_ERROR);
23866                         }
23867  
23868                         /* */
23869 -                       
23870 -                       
23871 +
23872 +
23873                         joblist_append(srv, con);
23874                         return HANDLER_FINISHED;
23875                 }
23876         }
23877 -       
23878 +
23879         if (revents & FDEVENT_OUT) {
23880                 if (hctx->state == FCGI_STATE_CONNECT_DELAYED ||
23881                     hctx->state == FCGI_STATE_WRITE) {
23882                         /* we are allowed to send something out
23883 -                        * 
23884 +                        *
23885                          * 1. in a unfinished connect() call
23886                          * 2. in a unfinished write() call (long POST request)
23887                          */
23888                         return mod_fastcgi_handle_subrequest(srv, con, p);
23889                 } else {
23890 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23891 -                                       "got a FDEVENT_OUT and didn't know why:", 
23892 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
23893 +                                       "got a FDEVENT_OUT and didn't know why:",
23894                                         hctx->state);
23895                 }
23896         }
23897 -       
23898 +
23899         /* perhaps this issue is already handled */
23900         if (revents & FDEVENT_HUP) {
23901                 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23902                         /* getoptsock will catch this one (right ?)
23903 -                        * 
23904 -                        * if we are in connect we might get a EINPROGRESS 
23905 -                        * in the first call and a FDEVENT_HUP in the 
23906 +                        *
23907 +                        * if we are in connect we might get a EINPROGRESS
23908 +                        * in the first call and a FDEVENT_HUP in the
23909                          * second round
23910 -                        * 
23911 +                        *
23912                          * FIXME: as it is a bit ugly.
23913 -                        * 
23914 +                        *
23915                          */
23916                         return mod_fastcgi_handle_subrequest(srv, con, p);
23917                 } else if (hctx->state == FCGI_STATE_READ &&
23918                            hctx->proc->port == 0) {
23919                         /* FIXME:
23920 -                        * 
23921 +                        *
23922                          * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
23923                          * even if the FCGI_FIN packet is not received yet
23924                          */
23925                 } else {
23926 -                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", 
23927 -                                       "error: unexpected close of fastcgi connection for", 
23928 +                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
23929 +                                       "error: unexpected close of fastcgi connection for",
23930                                         con->uri.path,
23931 -                                       "(no fastcgi process on host:", 
23932 +                                       "(no fastcgi process on host:",
23933                                         host->host,
23934 -                                       ", port: ", 
23935 +                                       ", port: ",
23936                                         host->port,
23937                                         " ?)",
23938                                         hctx->state);
23939 -                       
23940 +
23941                         connection_set_state(srv, con, CON_STATE_ERROR);
23942                         fcgi_connection_close(srv, hctx);
23943                         joblist_append(srv, con);
23944                 }
23945         } else if (revents & FDEVENT_ERR) {
23946 -               log_error_write(srv, __FILE__, __LINE__, "s", 
23947 +               log_error_write(srv, __FILE__, __LINE__, "s",
23948                                 "fcgi: got a FDEVENT_ERR. Don't know why.");
23949                 /* kill all connections to the fastcgi process */
23950  
23951 @@ -3304,45 +3219,42 @@
23952                 fcgi_connection_close(srv, hctx);
23953                 joblist_append(srv, con);
23954         }
23955 -       
23956 +
23957         return HANDLER_FINISHED;
23958  }
23959 -#define PATCH(x) \
23960 -       p->conf.x = s->x;
23961 +
23962  static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
23963         size_t i, j;
23964         plugin_config *s = p->config_storage[0];
23965 -       
23966 -       PATCH(exts);
23967 -       PATCH(debug);
23968 -       PATCH(ext_mapping);
23969 -       
23970 +
23971 +       PATCH_OPTION(exts);
23972 +       PATCH_OPTION(debug);
23973 +       PATCH_OPTION(ext_mapping);
23974 +
23975         /* skip the first, the global context */
23976         for (i = 1; i < srv->config_context->used; i++) {
23977                 data_config *dc = (data_config *)srv->config_context->data[i];
23978                 s = p->config_storage[i];
23979 -               
23980 +
23981                 /* condition didn't match */
23982                 if (!config_check_cond(srv, con, dc)) continue;
23983 -               
23984 +
23985                 /* merge config */
23986                 for (j = 0; j < dc->value->used; j++) {
23987                         data_unset *du = dc->value->data[j];
23988 -                       
23989 +
23990                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
23991 -                               PATCH(exts);
23992 +                               PATCH_OPTION(exts);
23993                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
23994 -                               PATCH(debug);
23995 +                               PATCH_OPTION(debug);
23996                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
23997 -                               PATCH(ext_mapping);
23998 +                               PATCH_OPTION(ext_mapping);
23999                         }
24000                 }
24001         }
24002 -       
24003 +
24004         return 0;
24005  }
24006 -#undef PATCH
24007 -
24008  
24009  static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
24010         plugin_data *p = p_d;
24011 @@ -3351,16 +3263,16 @@
24012         buffer *fn;
24013         fcgi_extension *extension = NULL;
24014         fcgi_extension_host *host = NULL;
24015 -       
24016 +
24017         /* Possibly, we processed already this request */
24018         if (con->file_started == 1) return HANDLER_GO_ON;
24019  
24020         fn = uri_path_handler ? con->uri.path : con->physical.path;
24021  
24022         if (buffer_is_empty(fn)) return HANDLER_GO_ON;
24023 -       
24024 +
24025         s_len = fn->used - 1;
24026 -       
24027 +
24028         fcgi_patch_connection(srv, con, p);
24029  
24030         /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
24031 @@ -3368,24 +3280,24 @@
24032          * fastcgi.map-extensions = ( ".php3" => ".php" )
24033          *
24034          * fastcgi.server = ( ".php" => ... )
24035 -        * 
24036 +        *
24037          * */
24038  
24039         /* check if extension-mapping matches */
24040         for (k = 0; k < p->conf.ext_mapping->used; k++) {
24041                 data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
24042                 size_t ct_len; /* length of the config entry */
24043 -               
24044 +
24045                 if (ds->key->used == 0) continue;
24046 -               
24047 +
24048                 ct_len = ds->key->used - 1;
24049 -               
24050 +
24051                 if (s_len < ct_len) continue;
24052 -               
24053 +
24054                 /* found a mapping */
24055                 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
24056                         /* check if we know the extension */
24057 -                       
24058 +
24059                         /* we can reuse k here */
24060                         for (k = 0; k < p->conf.exts->used; k++) {
24061                                 extension = p->conf.exts->exts[k];
24062 @@ -3407,15 +3319,15 @@
24063                 /* check if extension matches */
24064                 for (k = 0; k < p->conf.exts->used; k++) {
24065                         size_t ct_len; /* length of the config entry */
24066 -               
24067 +
24068                         extension = p->conf.exts->exts[k];
24069 -               
24070 +
24071                         if (extension->key->used == 0) continue;
24072 -               
24073 +
24074                         ct_len = extension->key->used - 1;
24075 -               
24076 +
24077                         if (s_len < ct_len) continue;
24078 -               
24079 +
24080                         /* check extension in the form "/fcgi_pattern" */
24081                         if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
24082                                 break;
24083 @@ -3441,10 +3353,10 @@
24084                         continue;
24085                 }
24086  
24087 -               /* we found one host that is alive */ 
24088 +               /* we found one host that is alive */
24089                 break;
24090         }
24091 -       
24092 +
24093         if (!host) {
24094                 /* sorry, we don't have a server alive for this ext */
24095                 buffer_reset(con->physical.path);
24096 @@ -3459,72 +3371,72 @@
24097                                         "on", extension->key,
24098                                         "are down.");
24099                 }
24100 -               
24101 +
24102                 return HANDLER_FINISHED;
24103         }
24104  
24105         /* a note about no handler is not sent yey */
24106         extension->note_is_sent = 0;
24107  
24108 -       /* 
24109 -        * if check-local is disabled, use the uri.path handler 
24110 -        * 
24111 +       /*
24112 +        * if check-local is disabled, use the uri.path handler
24113 +        *
24114          */
24115 -       
24116 +
24117         /* init handler-context */
24118         if (uri_path_handler) {
24119                 if (host->check_local == 0) {
24120                         handler_ctx *hctx;
24121                         char *pathinfo;
24122 -                       
24123 +
24124                         hctx = handler_ctx_init();
24125 -                       
24126 +
24127                         hctx->remote_conn      = con;
24128                         hctx->plugin_data      = p;
24129                         hctx->proc             = NULL;
24130                         hctx->ext              = extension;
24131 -       
24132 +
24133  
24134                         hctx->conf.exts        = p->conf.exts;
24135                         hctx->conf.debug       = p->conf.debug;
24136 -                               
24137 +
24138                         con->plugin_ctx[p->id] = hctx;
24139 -                               
24140 +
24141                         con->mode = p->id;
24142 -                               
24143 +
24144                         if (con->conf.log_request_handling) {
24145 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
24146 +                               log_error_write(srv, __FILE__, __LINE__, "s",
24147                                 "handling it in mod_fastcgi");
24148                         }
24149 -                               
24150 -                       /* the prefix is the SCRIPT_NAME, 
24151 +
24152 +                       /* the prefix is the SCRIPT_NAME,
24153                          * everthing from start to the next slash
24154                          * this is important for check-local = "disable"
24155 -                        * 
24156 +                        *
24157                          * if prefix = /admin.fcgi
24158 -                        * 
24159 +                        *
24160                          * /admin.fcgi/foo/bar
24161 -                        * 
24162 +                        *
24163                          * SCRIPT_NAME = /admin.fcgi
24164                          * PATH_INFO   = /foo/bar
24165 -                        * 
24166 +                        *
24167                          * if prefix = /fcgi-bin/
24168 -                        * 
24169 +                        *
24170                          * /fcgi-bin/foo/bar
24171 -                        * 
24172 +                        *
24173                          * SCRIPT_NAME = /fcgi-bin/foo
24174                          * PATH_INFO   = /bar
24175 -                        * 
24176 +                        *
24177                          */
24178 -                       
24179 +
24180                         /* the rewrite is only done for /prefix/? matches */
24181                         if (extension->key->ptr[0] == '/' &&
24182                             con->uri.path->used > extension->key->used &&
24183                             NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
24184 -                               /* rewrite uri.path and pathinfo */ 
24185 -                               
24186 +                               /* rewrite uri.path and pathinfo */
24187 +
24188                                 buffer_copy_string(con->request.pathinfo, pathinfo);
24189 -                               
24190 +
24191                                 con->uri.path->used -= con->request.pathinfo->used - 1;
24192                                 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
24193                         }
24194 @@ -3532,19 +3444,19 @@
24195         } else {
24196                 handler_ctx *hctx;
24197                 hctx = handler_ctx_init();
24198 -               
24199 +
24200                 hctx->remote_conn      = con;
24201                 hctx->plugin_data      = p;
24202                 hctx->proc             = NULL;
24203                 hctx->ext              = extension;
24204 -               
24205 +
24206                 hctx->conf.exts        = p->conf.exts;
24207                 hctx->conf.debug       = p->conf.debug;
24208 -               
24209 +
24210                 con->plugin_ctx[p->id] = hctx;
24211 -               
24212 +
24213                 con->mode = p->id;
24214 -               
24215 +
24216                 if (con->conf.log_request_handling) {
24217                         log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
24218                 }
24219 @@ -3566,19 +3478,19 @@
24220  JOBLIST_FUNC(mod_fastcgi_handle_joblist) {
24221         plugin_data *p = p_d;
24222         handler_ctx *hctx = con->plugin_ctx[p->id];
24223 -       
24224 +
24225         if (hctx == NULL) return HANDLER_GO_ON;
24226  
24227         if (hctx->fd != -1) {
24228                 switch (hctx->state) {
24229                 case FCGI_STATE_READ:
24230                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
24231 -                       
24232 +
24233                         break;
24234                 case FCGI_STATE_CONNECT_DELAYED:
24235                 case FCGI_STATE_WRITE:
24236                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24237 -                       
24238 +
24239                         break;
24240                 case FCGI_STATE_INIT:
24241                         /* at reconnect */
24242 @@ -3595,7 +3507,7 @@
24243  
24244  static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
24245         plugin_data *p = p_d;
24246 -       
24247 +
24248         fcgi_connection_close(srv, con->plugin_ctx[p->id]);
24249  
24250         return HANDLER_GO_ON;
24251 @@ -3604,16 +3516,39 @@
24252  TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
24253         plugin_data *p = p_d;
24254         size_t i, j, n;
24255 -       
24256 -       
24257 +
24258 +
24259         /* perhaps we should kill a connect attempt after 10-15 seconds
24260 -        * 
24261 +        *
24262          * currently we wait for the TCP timeout which is on Linux 180 seconds
24263 -        * 
24264 -        * 
24265 -        * 
24266 +        *
24267          */
24268  
24269 +       for (i = 0; i < srv->conns->used; i++) {
24270 +               connection *con = srv->conns->ptr[i];
24271 +               handler_ctx *hctx = con->plugin_ctx[p->id];
24272 +
24273 +               /* if a connection is ours and is in handle-req for more than max-request-time
24274 +                * kill the connection */
24275 +
24276 +               if (con->mode != p->id) continue;
24277 +               if (con->state != CON_STATE_HANDLE_REQUEST) continue;
24278 +               if (srv->cur_ts < con->request_start + 60) continue;
24279 +
24280 +               /* the request is waiting for a FCGI_STDOUT since 60 seconds */
24281 +
24282 +               /* kill the connection */
24283 +
24284 +               log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
24285 +
24286 +               fcgi_connection_close(srv, hctx);
24287 +
24288 +               con->mode = DIRECT;
24289 +               con->http_status = 500;
24290 +
24291 +               joblist_append(srv, con);
24292 +       }
24293 +
24294         /* check all childs if they are still up */
24295  
24296         for (i = 0; i < srv->config_context->used; i++) {
24297 @@ -3628,45 +3563,45 @@
24298                         fcgi_extension *ex;
24299  
24300                         ex = exts->exts[j];
24301 -                       
24302 +
24303                         for (n = 0; n < ex->used; n++) {
24304 -                               
24305 +
24306                                 fcgi_proc *proc;
24307                                 unsigned long sum_load = 0;
24308                                 fcgi_extension_host *host;
24309 -                               
24310 +
24311                                 host = ex->hosts[n];
24312 -                               
24313 +
24314                                 fcgi_restart_dead_procs(srv, p, host);
24315 -                               
24316 +
24317                                 for (proc = host->first; proc; proc = proc->next) {
24318                                         sum_load += proc->load;
24319                                 }
24320 -                               
24321 +
24322                                 if (host->num_procs &&
24323                                     host->num_procs < host->max_procs &&
24324                                     (sum_load / host->num_procs) > host->max_load_per_proc) {
24325                                         /* overload, spawn new child */
24326                                         if (p->conf.debug) {
24327 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
24328 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
24329                                                                 "overload detected, spawning a new child");
24330                                         }
24331 -                                       
24332 +
24333                                         for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
24334 -                                       
24335 +
24336                                         if (proc) {
24337                                                 if (proc == host->unused_procs) host->unused_procs = proc->next;
24338 -                                               
24339 +
24340                                                 if (proc->next) proc->next->prev = NULL;
24341 -                                               
24342 +
24343                                                 host->max_id++;
24344                                         } else {
24345                                                 proc = fastcgi_process_init();
24346                                                 proc->id = host->max_id++;
24347                                         }
24348 -                                       
24349 +
24350                                         host->num_procs++;
24351 -                                       
24352 +
24353                                         if (buffer_is_empty(host->unixsocket)) {
24354                                                 proc->port = host->port + proc->id;
24355                                         } else {
24356 @@ -3674,13 +3609,13 @@
24357                                                 buffer_append_string(proc->unixsocket, "-");
24358                                                 buffer_append_long(proc->unixsocket, proc->id);
24359                                         }
24360 -                                       
24361 +
24362                                         if (fcgi_spawn_connection(srv, p, host, proc)) {
24363                                                 log_error_write(srv, __FILE__, __LINE__, "s",
24364                                                                 "ERROR: spawning fcgi failed.");
24365                                                 return HANDLER_ERROR;
24366                                         }
24367 -                                       
24368 +
24369                                         proc->prev = NULL;
24370                                         proc->next = host->first;
24371                                         if (host->first) {
24372 @@ -3688,56 +3623,56 @@
24373                                         }
24374                                         host->first = proc;
24375                                 }
24376 -                               
24377 +
24378                                 for (proc = host->first; proc; proc = proc->next) {
24379                                         if (proc->load != 0) break;
24380                                         if (host->num_procs <= host->min_procs) break;
24381                                         if (proc->pid == 0) continue;
24382 -                                       
24383 +
24384                                         if (srv->cur_ts - proc->last_used > host->idle_timeout) {
24385                                                 /* a proc is idling for a long time now,
24386                                                  * terminated it */
24387 -                                               
24388 +
24389                                                 if (p->conf.debug) {
24390 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
24391 -                                                                       "idle-timeout reached, terminating child:", 
24392 -                                                                       "socket:", proc->connection_name, 
24393 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24394 +                                                                       "idle-timeout reached, terminating child:",
24395 +                                                                       "socket:", proc->connection_name,
24396                                                                         "pid", proc->pid);
24397                                                 }
24398 -                                               
24399 -                                               
24400 +
24401 +
24402                                                 if (proc->next) proc->next->prev = proc->prev;
24403                                                 if (proc->prev) proc->prev->next = proc->next;
24404 -                                               
24405 +
24406                                                 if (proc->prev == NULL) host->first = proc->next;
24407 -                                               
24408 +
24409                                                 proc->prev = NULL;
24410                                                 proc->next = host->unused_procs;
24411 -                                               
24412 +
24413                                                 if (host->unused_procs) host->unused_procs->prev = proc;
24414                                                 host->unused_procs = proc;
24415 -                                               
24416 +
24417                                                 kill(proc->pid, SIGTERM);
24418 -                                               
24419 +
24420                                                 proc->state = PROC_STATE_KILLED;
24421 -                                               
24422 -                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
24423 -                                                                       "killed:", 
24424 -                                                                       "socket:", proc->connection_name, 
24425 +
24426 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24427 +                                                                       "killed:",
24428 +                                                                       "socket:", proc->connection_name,
24429                                                                         "pid", proc->pid);
24430 -                                               
24431 +
24432                                                 host->num_procs--;
24433 -                                               
24434 +
24435                                                 /* proc is now in unused, let the next second handle the next process */
24436                                                 break;
24437 -                                       }       
24438 +                                       }
24439                                 }
24440 -                               
24441 +
24442                                 for (proc = host->unused_procs; proc; proc = proc->next) {
24443                                         int status;
24444 -                                       
24445 +
24446                                         if (proc->pid == 0) continue;
24447 -                                       
24448 +#ifndef _WIN32
24449                                         switch (waitpid(proc->pid, &status, WNOHANG)) {
24450                                         case 0:
24451                                                 /* child still running after timeout, good */
24452 @@ -3745,10 +3680,10 @@
24453                                         case -1:
24454                                                 if (errno != EINTR) {
24455                                                         /* no PID found ? should never happen */
24456 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddss", 
24457 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddss",
24458                                                                         "pid ", proc->pid, proc->state,
24459                                                                         "not found:", strerror(errno));
24460 -                                                       
24461 +
24462  #if 0
24463                                                         if (errno == ECHILD) {
24464                                                                 /* someone else has cleaned up for us */
24465 @@ -3762,25 +3697,26 @@
24466                                                 /* the child should not terminate at all */
24467                                                 if (WIFEXITED(status)) {
24468                                                         if (proc->state != PROC_STATE_KILLED) {
24469 -                                                               log_error_write(srv, __FILE__, __LINE__, "sdb", 
24470 -                                                                               "child exited:", 
24471 +                                                               log_error_write(srv, __FILE__, __LINE__, "sdb",
24472 +                                                                               "child exited:",
24473                                                                                 WEXITSTATUS(status), proc->connection_name);
24474                                                         }
24475                                                 } else if (WIFSIGNALED(status)) {
24476                                                         if (WTERMSIG(status) != SIGTERM) {
24477 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
24478 -                                                                               "child signaled:", 
24479 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
24480 +                                                                               "child signaled:",
24481                                                                                 WTERMSIG(status));
24482                                                         }
24483                                                 } else {
24484 -                                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
24485 -                                                                       "child died somehow:", 
24486 +                                                       log_error_write(srv, __FILE__, __LINE__, "sd",
24487 +                                                                       "child died somehow:",
24488                                                                         status);
24489                                                 }
24490                                                 proc->pid = 0;
24491                                                 proc->state = PROC_STATE_UNSET;
24492                                                 host->max_id--;
24493                                         }
24494 +#endif
24495                                 }
24496                         }
24497                 }
24498 @@ -3804,8 +3740,8 @@
24499         p->handle_subrequest       = mod_fastcgi_handle_subrequest;
24500         p->handle_joblist          = mod_fastcgi_handle_joblist;
24501         p->handle_trigger          = mod_fastcgi_handle_trigger;
24502 -       
24503 +
24504         p->data         = NULL;
24505 -       
24506 +
24507         return 0;
24508  }
24509 --- ../lighttpd-1.4.11/src/mod_flv_streaming.c  2006-03-07 14:06:26.000000000 +0200
24510 +++ lighttpd-1.4.12/src/mod_flv_streaming.c     2006-07-11 22:07:52.000000000 +0300
24511 @@ -23,35 +23,35 @@
24512  
24513  typedef struct {
24514         PLUGIN_DATA;
24515 -       
24516 +
24517         buffer *query_str;
24518         array *get_params;
24519 -       
24520 +
24521         plugin_config **config_storage;
24522 -       
24523 -       plugin_config conf; 
24524 +
24525 +       plugin_config conf;
24526  } plugin_data;
24527  
24528  /* init the plugin data */
24529  INIT_FUNC(mod_flv_streaming_init) {
24530         plugin_data *p;
24531 -       
24532 +
24533         p = calloc(1, sizeof(*p));
24534 -       
24535 +
24536         p->query_str = buffer_init();
24537         p->get_params = array_init();
24538 -       
24539 +
24540         return p;
24541  }
24542  
24543  /* detroy the plugin data */
24544  FREE_FUNC(mod_flv_streaming_free) {
24545         plugin_data *p = p_d;
24546 -       
24547 +
24548         UNUSED(srv);
24549  
24550         if (!p) return HANDLER_GO_ON;
24551 -       
24552 +
24553         if (p->config_storage) {
24554                 size_t i;
24555  
24556 @@ -59,19 +59,19 @@
24557                         plugin_config *s = p->config_storage[i];
24558  
24559                         if (!s) continue;
24560 -                       
24561 +
24562                         array_free(s->extensions);
24563 -                       
24564 +
24565                         free(s);
24566                 }
24567                 free(p->config_storage);
24568         }
24569 -       
24570 +
24571         buffer_free(p->query_str);
24572         array_free(p->get_params);
24573 -       
24574 +
24575         free(p);
24576 -       
24577 +
24578         return HANDLER_GO_ON;
24579  }
24580  
24581 @@ -80,83 +80,80 @@
24582  SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
24583         plugin_data *p = p_d;
24584         size_t i = 0;
24585 -       
24586 -       config_values_t cv[] = { 
24587 +
24588 +       config_values_t cv[] = {
24589                 { "flv-streaming.extensions",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
24590                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
24591         };
24592 -       
24593 +
24594         if (!p) return HANDLER_ERROR;
24595 -       
24596 +
24597         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24598 -       
24599 +
24600         for (i = 0; i < srv->config_context->used; i++) {
24601                 plugin_config *s;
24602 -               
24603 +
24604                 s = calloc(1, sizeof(plugin_config));
24605                 s->extensions     = array_init();
24606 -               
24607 +
24608                 cv[0].destination = s->extensions;
24609 -               
24610 +
24611                 p->config_storage[i] = s;
24612 -       
24613 +
24614                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24615                         return HANDLER_ERROR;
24616                 }
24617         }
24618 -       
24619 +
24620         return HANDLER_GO_ON;
24621  }
24622  
24623 -#define PATCH(x) \
24624 -       p->conf.x = s->x;
24625  static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
24626         size_t i, j;
24627         plugin_config *s = p->config_storage[0];
24628 -       
24629 -       PATCH(extensions);
24630 -       
24631 +
24632 +       PATCH_OPTION(extensions);
24633 +
24634         /* skip the first, the global context */
24635         for (i = 1; i < srv->config_context->used; i++) {
24636                 data_config *dc = (data_config *)srv->config_context->data[i];
24637                 s = p->config_storage[i];
24638 -               
24639 +
24640                 /* condition didn't match */
24641                 if (!config_check_cond(srv, con, dc)) continue;
24642 -               
24643 +
24644                 /* merge config */
24645                 for (j = 0; j < dc->value->used; j++) {
24646                         data_unset *du = dc->value->data[j];
24647 -                       
24648 +
24649                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
24650 -                               PATCH(extensions);
24651 +                               PATCH_OPTION(extensions);
24652                         }
24653                 }
24654         }
24655 -       
24656 +
24657         return 0;
24658  }
24659 -#undef PATCH
24660  
24661 -static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
24662 +static int split_get_params(array *get_params, buffer *qrystr) {
24663         size_t is_key = 1;
24664         size_t i;
24665         char *key = NULL, *val = NULL;
24666 -       
24667 +
24668         key = qrystr->ptr;
24669 -       
24670 +
24671         /* we need the \0 */
24672         for (i = 0; i < qrystr->used; i++) {
24673                 switch(qrystr->ptr[i]) {
24674                 case '=':
24675                         if (is_key) {
24676                                 val = qrystr->ptr + i + 1;
24677 -                               
24678 +
24679                                 qrystr->ptr[i] = '\0';
24680 -                               
24681 +
24682                                 is_key = 0;
24683                         }
24684 -                       
24685 +
24686                         break;
24687                 case '&':
24688                 case '\0': /* fin symbol */
24689 @@ -167,7 +164,7 @@
24690                                 /* terminate the value */
24691                                 qrystr->ptr[i] = '\0';
24692  
24693 -                               if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
24694 +                               if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
24695                                         ds = data_string_init();
24696                                 }
24697                                 buffer_copy_string_len(ds->key, key, strlen(key));
24698 @@ -175,14 +172,14 @@
24699  
24700                                 array_insert_unique(get_params, (data_unset *)ds);
24701                         }
24702 -                       
24703 +
24704                         key = qrystr->ptr + i + 1;
24705                         val = NULL;
24706                         is_key = 1;
24707                         break;
24708                 }
24709         }
24710 -       
24711 +
24712         return 0;
24713  }
24714  
24715 @@ -190,34 +187,34 @@
24716         plugin_data *p = p_d;
24717         int s_len;
24718         size_t k;
24719 -       
24720 +
24721         UNUSED(srv);
24722  
24723         if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
24724 -       
24725 +
24726         mod_flv_streaming_patch_connection(srv, con, p);
24727  
24728         s_len = con->physical.path->used - 1;
24729 -       
24730 +
24731         for (k = 0; k < p->conf.extensions->used; k++) {
24732                 data_string *ds = (data_string *)p->conf.extensions->data[k];
24733                 int ct_len = ds->value->used - 1;
24734 -               
24735 +
24736                 if (ct_len > s_len) continue;
24737                 if (ds->value->used == 0) continue;
24738 -               
24739 +
24740                 if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
24741                         data_string *get_param;
24742                         stat_cache_entry *sce = NULL;
24743                         buffer *b;
24744                         int start;
24745                         char *err = NULL;
24746 -                       /* if there is a start=[0-9]+ in the header use it as start, 
24747 +                       /* if there is a start=[0-9]+ in the header use it as start,
24748                          * otherwise send the full file */
24749  
24750                         array_reset(p->get_params);
24751                         buffer_copy_string_buffer(p->query_str, con->uri.query);
24752 -                       split_get_params(srv, con, p->get_params, p->query_str);
24753 +                       split_get_params(p->get_params, p->query_str);
24754  
24755                         if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
24756                                 return HANDLER_GO_ON;
24757 @@ -256,7 +253,7 @@
24758                         return HANDLER_FINISHED;
24759                 }
24760         }
24761 -       
24762 +
24763         /* not found */
24764         return HANDLER_GO_ON;
24765  }
24766 @@ -266,13 +263,13 @@
24767  int mod_flv_streaming_plugin_init(plugin *p) {
24768         p->version     = LIGHTTPD_VERSION_ID;
24769         p->name        = buffer_init_string("flv_streaming");
24770 -       
24771 +
24772         p->init        = mod_flv_streaming_init;
24773         p->handle_physical = mod_flv_streaming_path_handler;
24774         p->set_defaults  = mod_flv_streaming_set_defaults;
24775         p->cleanup     = mod_flv_streaming_free;
24776 -       
24777 +
24778         p->data        = NULL;
24779 -       
24780 +
24781         return 0;
24782  }
24783 --- ../lighttpd-1.4.11/src/mod_indexfile.c      2005-09-30 01:08:53.000000000 +0300
24784 +++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-15 22:43:21.000000000 +0300
24785 @@ -12,6 +12,8 @@
24786  
24787  #include "stat_cache.h"
24788  
24789 +#include "sys-strings.h"
24790 +#include "sys-files.h"
24791  /* plugin config for all request/connections */
24792  
24793  typedef struct {
24794 @@ -20,51 +22,51 @@
24795  
24796  typedef struct {
24797         PLUGIN_DATA;
24798 -       
24799 +
24800         buffer *tmp_buf;
24801 -       
24802 +
24803         plugin_config **config_storage;
24804 -       
24805 -       plugin_config conf; 
24806 +
24807 +       plugin_config conf;
24808  } plugin_data;
24809  
24810  /* init the plugin data */
24811  INIT_FUNC(mod_indexfile_init) {
24812         plugin_data *p;
24813 -       
24814 +
24815         p = calloc(1, sizeof(*p));
24816 -       
24817 +
24818         p->tmp_buf = buffer_init();
24819 -       
24820 +
24821         return p;
24822  }
24823  
24824  /* detroy the plugin data */
24825  FREE_FUNC(mod_indexfile_free) {
24826         plugin_data *p = p_d;
24827 -       
24828 +
24829         UNUSED(srv);
24830  
24831         if (!p) return HANDLER_GO_ON;
24832 -       
24833 +
24834         if (p->config_storage) {
24835                 size_t i;
24836                 for (i = 0; i < srv->config_context->used; i++) {
24837                         plugin_config *s = p->config_storage[i];
24838  
24839                         if (!s) continue;
24840 -                       
24841 +
24842                         array_free(s->indexfiles);
24843 -                       
24844 +
24845                         free(s);
24846                 }
24847                 free(p->config_storage);
24848         }
24849 -       
24850 +
24851         buffer_free(p->tmp_buf);
24852 -       
24853 +
24854         free(p);
24855 -       
24856 +
24857         return HANDLER_GO_ON;
24858  }
24859  
24860 @@ -73,131 +75,139 @@
24861  SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
24862         plugin_data *p = p_d;
24863         size_t i = 0;
24864 -       
24865 -       config_values_t cv[] = { 
24866 +
24867 +       config_values_t cv[] = {
24868                 { "index-file.names",           NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
24869                 { "server.indexfiles",          NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
24870                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
24871         };
24872 -       
24873 +
24874         if (!p) return HANDLER_ERROR;
24875 -       
24876 +
24877         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24878 -       
24879 +
24880         for (i = 0; i < srv->config_context->used; i++) {
24881                 plugin_config *s;
24882 -               
24883 +
24884                 s = calloc(1, sizeof(plugin_config));
24885                 s->indexfiles    = array_init();
24886 -               
24887 +
24888                 cv[0].destination = s->indexfiles;
24889                 cv[1].destination = s->indexfiles; /* old name for [0] */
24890 -               
24891 +
24892                 p->config_storage[i] = s;
24893 -       
24894 +
24895                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24896                         return HANDLER_ERROR;
24897                 }
24898         }
24899 -       
24900 +
24901         return HANDLER_GO_ON;
24902  }
24903  
24904 -#define PATCH(x) \
24905 -       p->conf.x = s->x;
24906  static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
24907         size_t i, j;
24908         plugin_config *s = p->config_storage[0];
24909 -       
24910 -       PATCH(indexfiles);
24911 -       
24912 +
24913 +       PATCH_OPTION(indexfiles);
24914 +
24915         /* skip the first, the global context */
24916         for (i = 1; i < srv->config_context->used; i++) {
24917                 data_config *dc = (data_config *)srv->config_context->data[i];
24918                 s = p->config_storage[i];
24919 -               
24920 +
24921                 /* condition didn't match */
24922                 if (!config_check_cond(srv, con, dc)) continue;
24923 -               
24924 +
24925                 /* merge config */
24926                 for (j = 0; j < dc->value->used; j++) {
24927                         data_unset *du = dc->value->data[j];
24928 -                       
24929 +
24930                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
24931 -                               PATCH(indexfiles);
24932 +                               PATCH_OPTION(indexfiles);
24933                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
24934 -                               PATCH(indexfiles);
24935 +                               PATCH_OPTION(indexfiles);
24936                         }
24937                 }
24938         }
24939 -       
24940 +
24941         return 0;
24942  }
24943 -#undef PATCH
24944  
24945  URIHANDLER_FUNC(mod_indexfile_subrequest) {
24946         plugin_data *p = p_d;
24947         size_t k;
24948         stat_cache_entry *sce = NULL;
24949 -       
24950 +
24951         if (con->uri.path->used == 0) return HANDLER_GO_ON;
24952         if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
24953 -       
24954 +
24955         mod_indexfile_patch_connection(srv, con, p);
24956 -       
24957 +
24958 +       /* is the physical-path really a dir ? */
24959 +       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
24960 +               return HANDLER_GO_ON;
24961 +       }
24962 +
24963 +       if (!S_ISDIR(sce->st.st_mode)) {
24964 +               return HANDLER_GO_ON;
24965 +       }
24966 +
24967         if (con->conf.log_request_handling) {
24968                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling the request as Indexfile");
24969                 log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
24970         }
24971 -       
24972 +
24973 +
24974         /* indexfile */
24975         for (k = 0; k < p->conf.indexfiles->used; k++) {
24976                 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
24977 -               
24978 +
24979                 if (ds->value && ds->value->ptr[0] == '/') {
24980 -                       /* if the index-file starts with a prefix as use this file as 
24981 +                       /* if the index-file starts with a prefix as use this file as
24982                          * index-generator */
24983                         buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
24984                 } else {
24985                         buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
24986 +                       PATHNAME_APPEND_SLASH(p->tmp_buf);
24987                 }
24988                 buffer_append_string_buffer(p->tmp_buf, ds->value);
24989 -               
24990 +
24991                 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
24992                         if (errno == EACCES) {
24993                                 con->http_status = 403;
24994                                 buffer_reset(con->physical.path);
24995 -                               
24996 +
24997                                 return HANDLER_FINISHED;
24998                         }
24999 -                       
25000 +
25001                         if (errno != ENOENT &&
25002                             errno != ENOTDIR) {
25003                                 /* we have no idea what happend. let's tell the user so. */
25004 -                               
25005 +
25006                                 con->http_status = 500;
25007 -                               
25008 +
25009                                 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
25010                                                 "file not found ... or so: ", strerror(errno),
25011                                                 con->uri.path,
25012                                                 "->", con->physical.path);
25013 -                               
25014 +
25015                                 buffer_reset(con->physical.path);
25016 -                               
25017 +
25018                                 return HANDLER_FINISHED;
25019                         }
25020                         continue;
25021                 }
25022 -                       
25023 +
25024                 /* rewrite uri.path to the real path (/ -> /index.php) */
25025                 buffer_append_string_buffer(con->uri.path, ds->value);
25026                 buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
25027 -               
25028 +
25029                 /* fce is already set up a few lines above */
25030 -               
25031 +
25032                 return HANDLER_GO_ON;
25033         }
25034 -       
25035 +
25036         /* not found */
25037         return HANDLER_GO_ON;
25038  }
25039 @@ -207,13 +217,13 @@
25040  int mod_indexfile_plugin_init(plugin *p) {
25041         p->version     = LIGHTTPD_VERSION_ID;
25042         p->name        = buffer_init_string("indexfile");
25043 -       
25044 +
25045         p->init        = mod_indexfile_init;
25046         p->handle_subrequest_start = mod_indexfile_subrequest;
25047         p->set_defaults  = mod_indexfile_set_defaults;
25048         p->cleanup     = mod_indexfile_free;
25049 -       
25050 +
25051         p->data        = NULL;
25052 -       
25053 +
25054         return 0;
25055  }
25056 --- ../lighttpd-1.4.11/src/mod_mysql_vhost.c    2006-01-14 20:35:10.000000000 +0200
25057 +++ lighttpd-1.4.12/src/mod_mysql_vhost.c       2006-07-11 22:07:52.000000000 +0300
25058 @@ -1,13 +1,18 @@
25059 -#include <unistd.h>
25060  #include <stdio.h>
25061  #include <errno.h>
25062  #include <fcntl.h>
25063 -#include <strings.h>
25064 +#include <string.h>
25065  
25066  #ifdef HAVE_CONFIG_H
25067  #include "config.h"
25068  #endif
25069  
25070 +#ifdef HAVE_MYSQL_H 
25071 +# ifdef HAVE_LIBMYSQL
25072 +#  define HAVE_MYSQL
25073 +# endif
25074 +#endif
25075 +
25076  #ifdef HAVE_MYSQL
25077  #include <mysql.h>
25078  #endif
25079 @@ -16,61 +21,40 @@
25080  #include "log.h"
25081  
25082  #include "stat_cache.h"
25083 -#ifdef DEBUG_MOD_MYSQL_VHOST
25084 -#define DEBUG
25085 -#endif
25086 +#include "sys-files.h"
25087  
25088 -/*
25089 - * Plugin for lighttpd to use MySQL 
25090 - *   for domain to directory lookups,
25091 - *   i.e virtual hosts (vhosts).
25092 - *   
25093 - * Optionally sets fcgi_offset and fcgi_arg 
25094 - *   in preparation for fcgi.c to handle 
25095 - *   per-user fcgi chroot jails.
25096 - *
25097 - * /ada@riksnet.se 2004-12-06
25098 - */
25099 +#include "mod_sql_vhost_core.h"
25100  
25101  #ifdef HAVE_MYSQL
25102 +
25103 +#define CORE_PLUGIN "mod_sql_vhost_core"
25104 +
25105  typedef struct {
25106         MYSQL   *mysql;
25107 -       
25108 -       buffer  *mydb;
25109 -       buffer  *myuser;
25110 -       buffer  *mypass;
25111 -       buffer  *mysock;
25112 -       
25113 -       buffer  *hostname;
25114 -       unsigned short port;
25115 -       
25116 +
25117         buffer  *mysql_pre;
25118         buffer  *mysql_post;
25119 +
25120 +       mod_sql_vhost_core_plugin_config *core;
25121  } plugin_config;
25122  
25123  /* global plugin data */
25124  typedef struct {
25125         PLUGIN_DATA;
25126 -       
25127 +
25128         buffer  *tmp_buf;
25129 -       
25130 +
25131         plugin_config **config_storage;
25132 -       
25133 -       plugin_config conf; 
25134 +
25135 +       plugin_config conf;
25136  } plugin_data;
25137  
25138 -/* per connection plugin data */
25139 -typedef struct {
25140 -       buffer  *server_name;
25141 -       buffer  *document_root;
25142 -       buffer  *fcgi_arg;
25143 -       unsigned fcgi_offset;
25144 -} plugin_connection_data;
25145 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost); 
25146  
25147  /* init the plugin data */
25148  INIT_FUNC(mod_mysql_vhost_init) {
25149         plugin_data *p;
25150 -       
25151 +
25152         p = calloc(1, sizeof(*p));
25153  
25154         p->tmp_buf = buffer_init();
25155 @@ -83,144 +67,77 @@
25156         plugin_data *p = p_d;
25157  
25158         UNUSED(srv);
25159 -       
25160 -#ifdef DEBUG
25161 -       log_error_write(srv, __FILE__, __LINE__, "ss", 
25162 -               "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
25163 -#endif
25164 +
25165         if (!p) return HANDLER_GO_ON;
25166 -       
25167 +
25168         if (p->config_storage) {
25169                 size_t i;
25170                 for (i = 0; i < srv->config_context->used; i++) {
25171                         plugin_config *s = p->config_storage[i];
25172  
25173                         if (!s) continue;
25174 -                       
25175 +
25176                         mysql_close(s->mysql);
25177 -                       
25178 -                       buffer_free(s->mydb);
25179 -                       buffer_free(s->myuser);
25180 -                       buffer_free(s->mypass);
25181 -                       buffer_free(s->mysock);
25182 +
25183                         buffer_free(s->mysql_pre);
25184                         buffer_free(s->mysql_post);
25185 -                       
25186 +
25187                         free(s);
25188                 }
25189                 free(p->config_storage);
25190         }
25191         buffer_free(p->tmp_buf);
25192 -       
25193 -       free(p);
25194  
25195 -       return HANDLER_GO_ON;
25196 -}
25197 -
25198 -/* handle the plugin per connection data */
25199 -static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
25200 -{
25201 -       plugin_data *p = p_d;
25202 -       plugin_connection_data *c = con->plugin_ctx[p->id];
25203 -
25204 -       UNUSED(srv);
25205 -
25206 -#ifdef DEBUG
25207 -        log_error_write(srv, __FILE__, __LINE__, "ss", 
25208 -               "mod_mysql_connection_data", c ? "old" : "NEW");
25209 -#endif
25210 -
25211 -       if (c) return c;
25212 -       c = calloc(1, sizeof(*c));
25213 -
25214 -       c->server_name = buffer_init();
25215 -       c->document_root = buffer_init();
25216 -       c->fcgi_arg = buffer_init();
25217 -       c->fcgi_offset = 0;
25218 -
25219 -       return con->plugin_ctx[p->id] = c;
25220 -}
25221 -
25222 -/* destroy the plugin per connection data */
25223 -CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
25224 -       plugin_data *p = p_d;
25225 -       plugin_connection_data *c = con->plugin_ctx[p->id];
25226 -
25227 -       UNUSED(srv);
25228 -
25229 -#ifdef DEBUG
25230 -       log_error_write(srv, __FILE__, __LINE__, "ss", 
25231 -               "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
25232 -#endif
25233 -       
25234 -       if (!c) return HANDLER_GO_ON;
25235 -
25236 -       buffer_free(c->server_name);
25237 -       buffer_free(c->document_root);
25238 -       buffer_free(c->fcgi_arg);
25239 -       c->fcgi_offset = 0;
25240 -
25241 -       free(c);
25242 +       free(p);
25243  
25244 -       con->plugin_ctx[p->id] = NULL;
25245         return HANDLER_GO_ON;
25246  }
25247  
25248  /* set configuration values */
25249  SERVER_FUNC(mod_mysql_vhost_set_defaults) {
25250         plugin_data *p = p_d;
25251 +       mod_sql_vhost_core_plugin_data *core_config;
25252  
25253 -       char *qmark;
25254         size_t i = 0;
25255  
25256 -       config_values_t cv[] = {
25257 -               { "mysql-vhost.db",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25258 -               { "mysql-vhost.user",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25259 -               { "mysql-vhost.pass",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25260 -               { "mysql-vhost.sock",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25261 -               { "mysql-vhost.sql",    NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25262 -               { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
25263 -               { "mysql-vhost.port",   NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER },
25264 -                { NULL,                        NULL, T_CONFIG_UNSET,   T_CONFIG_SCOPE_UNSET }
25265 -        };
25266 -       
25267 +       /* our very own plugin storage, one entry for each conditional
25268 +        * 
25269 +        * srv->config_context->used is the number of conditionals
25270 +        * */
25271         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25272 -       
25273 +
25274 +       /* get the config of the core-plugin */
25275 +       core_config = plugin_get_config(srv, CORE_PLUGIN);
25276 +
25277 +
25278 +       /* walk through all conditionals and check for assignments */
25279         for (i = 0; i < srv->config_context->used; i++) {
25280                 plugin_config *s;
25281                 buffer *sel;
25282 -               
25283 -               
25284 +               char *qmark;
25285 +
25286 +               /* get the config from the core plugin for this conditional-context */
25287                 s = calloc(1, sizeof(plugin_config));
25288 -               s->mydb = buffer_init();
25289 -               s->myuser = buffer_init();
25290 -               s->mypass = buffer_init();
25291 -               s->mysock = buffer_init();
25292 -               s->hostname = buffer_init();
25293 -               s->port   = 0;               /* default port for mysql */
25294 -               sel = buffer_init();
25295 -               s->mysql = NULL;
25296 +
25297 +               s->core = core_config->config_storage[i];
25298                 
25299 +               s->mysql = NULL;
25300 +
25301                 s->mysql_pre = buffer_init();
25302                 s->mysql_post = buffer_init();
25303 -               
25304 -               cv[0].destination = s->mydb;
25305 -               cv[1].destination = s->myuser;
25306 -               cv[2].destination = s->mypass;
25307 -               cv[3].destination = s->mysock;
25308 -               cv[4].destination = sel;
25309 -               cv[5].destination = s->hostname;
25310 -               cv[6].destination = &(s->port);
25311 -               
25312 +
25313                 p->config_storage[i] = s;
25314 -               
25315 -               if (config_insert_values_global(srv, 
25316 -                       ((data_config *)srv->config_context->data[i])->value,
25317 -                       cv)) return HANDLER_ERROR;
25318 -               
25319 -               s->mysql_pre = buffer_init();
25320 -               s->mysql_post = buffer_init();
25321 -               
25322 +
25323 +               /* check if we are the plugin for this backend */
25324 +               if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
25325 +
25326 +               /* attach us to the core-plugin */
25327 +               s->core->backend_data = p;
25328 +               s->core->get_vhost = mod_mysql_vhost_get_vhost;
25329 +
25330 +               sel = buffer_init();
25331 +               buffer_copy_string_buffer(sel, s->core->select_vhost);
25332 +
25333                 if (sel->used && (qmark = index(sel->ptr, '?'))) {
25334                         *qmark = '\0';
25335                         buffer_copy_string(s->mysql_pre, sel->ptr);
25336 @@ -228,35 +145,35 @@
25337                 } else {
25338                         buffer_copy_string_buffer(s->mysql_pre, sel);
25339                 }
25340 -               
25341 +
25342                 /* required:
25343                  * - username
25344 -                * - database 
25345 -                * 
25346 +                * - database
25347 +                *
25348                  * optional:
25349                  * - password, default: empty
25350                  * - socket, default: mysql default
25351                  * - hostname, if set overrides socket
25352                  * - port, default: 3306
25353                  */
25354 -               
25355 +
25356                 /* all have to be set */
25357 -               if (!(buffer_is_empty(s->myuser) ||
25358 -                     buffer_is_empty(s->mydb))) {
25359 +               if (!(buffer_is_empty(s->core->user) ||
25360 +                     buffer_is_empty(s->core->db))) {
25361  
25362                         int fd;
25363 -               
25364 +
25365                         if (NULL == (s->mysql = mysql_init(NULL))) {
25366                                 log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
25367 -                               
25368 +
25369                                 return HANDLER_ERROR;
25370                         }
25371 -#define FOO(x) (s->x->used ? s->x->ptr : NULL)
25372 -                       
25373 -                       if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass), 
25374 -                                               FOO(mydb), s->port, FOO(mysock), 0)) {
25375 +#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
25376 +
25377 +                       if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
25378 +                                               FOO(db), s->core->port, FOO(sock), 0)) {
25379                                 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
25380 -                               
25381 +
25382                                 return HANDLER_ERROR;
25383                         }
25384  #undef FOO
25385 @@ -265,61 +182,47 @@
25386                         /* otherwise we cannot be sure that mysql is fd i-1 */
25387                         if (-1 == (fd = open("/dev/null", 0))) {
25388                                 close(fd);
25389 -                               fcntl(fd-1, F_SETFD, FD_CLOEXEC); 
25390 +                               fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25391                         }
25392                 }
25393         }
25394 -       
25395 -       
25396 +
25397 +
25398  
25399          return HANDLER_GO_ON;
25400  }
25401  
25402 -#define PATCH(x) \
25403 -       p->conf.x = s->x;
25404  static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
25405 -       size_t i, j;
25406 +       size_t i;
25407         plugin_config *s = p->config_storage[0];
25408 -       
25409 -       PATCH(mysql_pre);
25410 -       PATCH(mysql_post);
25411 -#ifdef HAVE_MYSQL
25412 -       PATCH(mysql);
25413 -#endif
25414 -       
25415 +
25416 +       PATCH_OPTION(mysql_pre);
25417 +       PATCH_OPTION(mysql_post);
25418 +       PATCH_OPTION(mysql);
25419 +
25420         /* skip the first, the global context */
25421         for (i = 1; i < srv->config_context->used; i++) {
25422                 data_config *dc = (data_config *)srv->config_context->data[i];
25423                 s = p->config_storage[i];
25424 -               
25425 +
25426                 /* condition didn't match */
25427                 if (!config_check_cond(srv, con, dc)) continue;
25428 -               
25429 -               /* merge config */
25430 -               for (j = 0; j < dc->value->used; j++) {
25431 -                       data_unset *du = dc->value->data[j];
25432 -                       
25433 -                       if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
25434 -                               PATCH(mysql_pre);
25435 -                               PATCH(mysql_post);
25436 -                       }
25437 -               }
25438 -               
25439 +
25440                 if (s->mysql) {
25441 -                       PATCH(mysql);
25442 +                       PATCH_OPTION(mysql);
25443 +                       PATCH_OPTION(mysql_pre);
25444 +                       PATCH_OPTION(mysql_post);
25445                 }
25446         }
25447 -       
25448 +
25449         return 0;
25450  }
25451 -#undef PATCH
25452  
25453 -
25454 -/* handle document root request */
25455 -CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
25456 +/**
25457 + * get the vhost info from the database 
25458 + */
25459 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
25460         plugin_data *p = p_d;
25461 -       plugin_connection_data *c;
25462 -       stat_cache_entry *sce;
25463  
25464         unsigned  cols;
25465         MYSQL_ROW row;
25466 @@ -332,13 +235,6 @@
25467  
25468         if (!p->conf.mysql) return HANDLER_GO_ON;
25469  
25470 -       /* sets up connection data if not done yet */
25471 -       c = mod_mysql_vhost_connection_data(srv, con, p_d);
25472 -
25473 -       /* check if cached this connection */
25474 -       if (c->server_name->used && /* con->uri.authority->used && */
25475 -            buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
25476 -
25477         /* build and run SQL query */
25478         buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
25479         if (p->conf.mysql_post->used) {
25480 @@ -347,77 +243,43 @@
25481         }
25482         if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
25483                 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
25484 -               goto ERR500;
25485 +
25486 +               mysql_free_result(result);
25487 +               return HANDLER_GO_ON;
25488         }
25489         result = mysql_store_result(p->conf.mysql);
25490         cols = mysql_num_fields(result);
25491         row = mysql_fetch_row(result);
25492 +
25493         if (!row || cols < 1) {
25494                 /* no such virtual host */
25495                 mysql_free_result(result);
25496                 return HANDLER_GO_ON;
25497         }
25498  
25499 -       /* sanity check that really is a directory */
25500 -       buffer_copy_string(p->tmp_buf, row[0]);
25501 -       BUFFER_APPEND_SLASH(p->tmp_buf);
25502 -
25503 -       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25504 -               log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
25505 -               goto ERR500;
25506 -       }
25507 -        if (!S_ISDIR(sce->st.st_mode)) {
25508 -               log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
25509 -               goto ERR500;
25510 -       }
25511 +       buffer_copy_string(docroot, row[0]);
25512  
25513 -       /* cache the data */
25514 -       buffer_copy_string_buffer(c->server_name, con->uri.authority);
25515 -       buffer_copy_string_buffer(c->document_root, p->tmp_buf);
25516 -
25517 -       /* fcgi_offset and fcgi_arg are optional */
25518 -       if (cols > 1 && row[1]) {
25519 -               c->fcgi_offset = atoi(row[1]);
25520 -               
25521 -               if (cols > 2 && row[2]) {
25522 -                       buffer_copy_string(c->fcgi_arg, row[2]);
25523 -               } else {
25524 -                       c->fcgi_arg->used = 0;
25525 -               }
25526 -       } else {
25527 -               c->fcgi_offset = c->fcgi_arg->used = 0;
25528 -       }
25529         mysql_free_result(result);
25530  
25531 -       /* fix virtual server and docroot */
25532 -GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
25533 -       buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
25534 -
25535 -#ifdef DEBUG
25536 -       log_error_write(srv, __FILE__, __LINE__, "sbbdb", 
25537 -               result ? "NOT CACHED" : "cached", 
25538 -               con->server_name, con->physical.doc_root,
25539 -               c->fcgi_offset, c->fcgi_arg);
25540 -#endif
25541 -       return HANDLER_GO_ON;   
25542 -
25543 -ERR500:        if (result) mysql_free_result(result);
25544 -       con->http_status = 500; /* Internal Error */
25545 -       return HANDLER_FINISHED;
25546 +       return HANDLER_GO_ON;
25547  }
25548  
25549  /* this function is called at dlopen() time and inits the callbacks */
25550  int mod_mysql_vhost_plugin_init(plugin *p) {
25551 +       data_string *ds;
25552 +       
25553         p->version     = LIGHTTPD_VERSION_ID;
25554         p->name                         = buffer_init_string("mysql_vhost");
25555  
25556         p->init                         = mod_mysql_vhost_init;
25557         p->cleanup                      = mod_mysql_vhost_cleanup;
25558 -       p->handle_request_done          = mod_mysql_vhost_handle_connection_close;
25559  
25560         p->set_defaults                 = mod_mysql_vhost_set_defaults;
25561 -       p->handle_docroot               = mod_mysql_vhost_handle_docroot;
25562         
25563 +       ds = data_string_init();
25564 +       buffer_copy_string(ds->value, CORE_PLUGIN);
25565 +       array_insert_unique(p->required_plugins, (data_unset *)ds);
25566 +
25567         return 0;
25568  }
25569  #else
25570 --- ../lighttpd-1.4.11/src/mod_proxy.c  2006-01-31 13:01:22.000000000 +0200
25571 +++ lighttpd-1.4.12/src/mod_proxy.c     2006-07-15 22:43:21.000000000 +0300
25572 @@ -1,6 +1,5 @@
25573  #include <sys/types.h>
25574  
25575 -#include <unistd.h>
25576  #include <errno.h>
25577  #include <fcntl.h>
25578  #include <string.h>
25579 @@ -23,6 +22,9 @@
25580  
25581  #include "inet_ntop_cache.h"
25582  #include "crc32.h"
25583 +#include "network.h"
25584 +
25585 +#include "http_resp.h"
25586  
25587  #include <stdio.h>
25588  
25589 @@ -31,6 +33,8 @@
25590  #endif
25591  
25592  #include "sys-socket.h"
25593 +#include "sys-files.h"
25594 +#include "sys-strings.h"
25595  
25596  #define data_proxy data_fastcgi
25597  #define data_proxy_init data_fastcgi_init
25598 @@ -38,22 +42,25 @@
25599  #define PROXY_RETRY_TIMEOUT 60
25600  
25601  /**
25602 - * 
25603 - * the proxy module is based on the fastcgi module 
25604 - * 
25605 + *
25606 + * the proxy module is based on the fastcgi module
25607 + *
25608   * 28.06.2004 Jan Kneschke     The first release
25609   * 01.07.2004 Evgeny Rodichev  Several bugfixes and cleanups
25610   *            - co-ordinate up- and downstream flows correctly (proxy_demux_response
25611   *              and proxy_handle_fdevent)
25612   *            - correctly transfer upstream http_response_status;
25613   *            - some unused structures removed.
25614 - * 
25615 + *
25616   * TODO:      - delay upstream read if write_queue is too large
25617   *              (to prevent memory eating, like in apache). Shoud be
25618   *              configurable).
25619   *            - persistent connection with upstream servers
25620   *            - HTTP/1.1
25621   */
25622 +
25623 +
25624 +
25625  typedef enum {
25626         PROXY_BALANCE_UNSET,
25627         PROXY_BALANCE_FAIR,
25628 @@ -66,26 +73,33 @@
25629         int debug;
25630  
25631         proxy_balance_t balance;
25632 +
25633 +       array *last_used_backends; /* "extension" : last_used_backend */
25634  } plugin_config;
25635  
25636  typedef struct {
25637         PLUGIN_DATA;
25638 -       
25639 +
25640         buffer *parse_response;
25641         buffer *balance_buf;
25642 -       
25643 +
25644 +       http_resp *resp;
25645 +
25646 +       array *ignore_headers;
25647 +
25648         plugin_config **config_storage;
25649 -       
25650 +
25651         plugin_config conf;
25652  } plugin_data;
25653  
25654 -typedef enum { 
25655 -       PROXY_STATE_INIT, 
25656 -       PROXY_STATE_CONNECT, 
25657 -       PROXY_STATE_PREPARE_WRITE, 
25658 -       PROXY_STATE_WRITE, 
25659 -       PROXY_STATE_READ, 
25660 -       PROXY_STATE_ERROR 
25661 +typedef enum {
25662 +       PROXY_STATE_INIT,
25663 +       PROXY_STATE_CONNECT,
25664 +       PROXY_STATE_PREPARE_WRITE,
25665 +       PROXY_STATE_WRITE,
25666 +       PROXY_STATE_RESPONSE_HEADER,
25667 +       PROXY_STATE_RESPONSE_CONTENT,
25668 +       PROXY_STATE_ERROR
25669  } proxy_connection_state_t;
25670  
25671  enum { PROXY_STDOUT, PROXY_END_REQUEST };
25672 @@ -93,19 +107,17 @@
25673  typedef struct {
25674         proxy_connection_state_t state;
25675         time_t state_timestamp;
25676 -       
25677 +
25678         data_proxy *host;
25679 -       
25680 -       buffer *response;
25681 -       buffer *response_header;
25682  
25683         chunkqueue *wb;
25684 -       
25685 +       chunkqueue *rb;
25686 +
25687         int fd; /* fd to the proxy process */
25688         int fde_ndx; /* index into the fd-event buffer */
25689  
25690         size_t path_info_offset; /* start of path_info in uri.path */
25691 -       
25692 +
25693         connection *remote_conn;  /* dump pointer */
25694         plugin_data *plugin_data; /* dump pointer */
25695  } handler_ctx;
25696 @@ -116,69 +128,88 @@
25697  
25698  static handler_ctx * handler_ctx_init() {
25699         handler_ctx * hctx;
25700 -       
25701 +
25702  
25703         hctx = calloc(1, sizeof(*hctx));
25704 -       
25705 +
25706         hctx->state = PROXY_STATE_INIT;
25707         hctx->host = NULL;
25708 -       
25709 -       hctx->response = buffer_init();
25710 -       hctx->response_header = buffer_init();
25711  
25712         hctx->wb = chunkqueue_init();
25713 +       hctx->rb = chunkqueue_init();
25714  
25715         hctx->fd = -1;
25716         hctx->fde_ndx = -1;
25717 -       
25718 +
25719         return hctx;
25720  }
25721  
25722  static void handler_ctx_free(handler_ctx *hctx) {
25723 -       buffer_free(hctx->response);
25724 -       buffer_free(hctx->response_header);
25725         chunkqueue_free(hctx->wb);
25726 -       
25727 +       chunkqueue_free(hctx->rb);
25728 +
25729         free(hctx);
25730  }
25731  
25732  INIT_FUNC(mod_proxy_init) {
25733         plugin_data *p;
25734 -       
25735 +       size_t i;
25736 +
25737 +       char *hop2hop_headers[] = {
25738 +               "Connection",
25739 +               "Keep-Alive",
25740 +               "Host",
25741 +               NULL
25742 +       };
25743 +
25744         p = calloc(1, sizeof(*p));
25745 -       
25746 -       p->parse_response = buffer_init();
25747 +
25748         p->balance_buf = buffer_init();
25749 -       
25750 +       p->ignore_headers = array_init();
25751 +       p->resp = http_response_init();
25752 +
25753 +       for (i = 0; hop2hop_headers[i]; i++) {
25754 +               data_string *ds;
25755 +
25756 +               if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
25757 +                       ds = data_string_init();
25758 +               }
25759 +
25760 +               buffer_copy_string(ds->key, hop2hop_headers[i]);
25761 +               buffer_copy_string(ds->value, hop2hop_headers[i]);
25762 +               array_insert_unique(p->ignore_headers, (data_unset *)ds);
25763 +       }
25764 +
25765         return p;
25766  }
25767  
25768  
25769  FREE_FUNC(mod_proxy_free) {
25770         plugin_data *p = p_d;
25771 -       
25772 +
25773         UNUSED(srv);
25774  
25775 -       buffer_free(p->parse_response);
25776 -       buffer_free(p->balance_buf);
25777 -       
25778         if (p->config_storage) {
25779                 size_t i;
25780                 for (i = 0; i < srv->config_context->used; i++) {
25781                         plugin_config *s = p->config_storage[i];
25782 -                       
25783 +
25784                         if (s) {
25785 -                       
25786                                 array_free(s->extensions);
25787 -                       
25788 +                               array_free(s->last_used_backends);
25789 +
25790                                 free(s);
25791                         }
25792                 }
25793                 free(p->config_storage);
25794         }
25795 -       
25796 +
25797 +       array_free(p->ignore_headers);
25798 +       buffer_free(p->balance_buf);
25799 +       http_response_free(p->resp);
25800 +
25801         free(p);
25802 -       
25803 +
25804         return HANDLER_GO_ON;
25805  }
25806  
25807 @@ -186,37 +217,38 @@
25808         plugin_data *p = p_d;
25809         data_unset *du;
25810         size_t i = 0;
25811 -       
25812 -       config_values_t cv[] = { 
25813 +
25814 +       config_values_t cv[] = {
25815                 { "proxy.server",              NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
25816                 { "proxy.debug",               NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
25817                 { "proxy.balance",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 2 */
25818                 { NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25819         };
25820 -       
25821 +
25822         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25823 -       
25824 +
25825         for (i = 0; i < srv->config_context->used; i++) {
25826                 plugin_config *s;
25827                 array *ca;
25828 -               
25829 +
25830                 s = malloc(sizeof(plugin_config));
25831 -               s->extensions    = array_init();
25832 +               s->extensions         = array_init();
25833 +               s->last_used_backends = array_init();
25834                 s->debug         = 0;
25835 -               
25836 +
25837                 cv[0].destination = s->extensions;
25838                 cv[1].destination = &(s->debug);
25839                 cv[2].destination = p->balance_buf;
25840  
25841                 buffer_reset(p->balance_buf);
25842 -               
25843 +
25844                 p->config_storage[i] = s;
25845                 ca = ((data_config *)srv->config_context->data[i])->value;
25846 -       
25847 +
25848                 if (0 != config_insert_values_global(srv, ca, cv)) {
25849                         return HANDLER_ERROR;
25850                 }
25851 -       
25852 +
25853                 if (buffer_is_empty(p->balance_buf)) {
25854                         s->balance = PROXY_BALANCE_FAIR;
25855                 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
25856 @@ -226,99 +258,99 @@
25857                 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
25858                         s->balance = PROXY_BALANCE_HASH;
25859                 } else {
25860 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
25861 -                                       "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
25862 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
25863 +                               "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
25864                         return HANDLER_ERROR;
25865                 }
25866  
25867                 if (NULL != (du = array_get_element(ca, "proxy.server"))) {
25868                         size_t j;
25869                         data_array *da = (data_array *)du;
25870 -                       
25871 +
25872                         if (du->type != TYPE_ARRAY) {
25873 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
25874 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
25875                                                 "unexpected type for key: ", "proxy.server", "array of strings");
25876 -                               
25877 +
25878                                 return HANDLER_ERROR;
25879                         }
25880 -                       
25881 -                       /* 
25882 +
25883 +                       /*
25884                          * proxy.server = ( "<ext>" => ...,
25885                          *                  "<ext>" => ... )
25886                          */
25887 -                       
25888 +
25889                         for (j = 0; j < da->value->used; j++) {
25890                                 data_array *da_ext = (data_array *)da->value->data[j];
25891                                 size_t n;
25892 -                               
25893 +
25894                                 if (da_ext->type != TYPE_ARRAY) {
25895 -                                       log_error_write(srv, __FILE__, __LINE__, "sssbs", 
25896 -                                                       "unexpected type for key: ", "proxy.server", 
25897 +                                       log_error_write(srv, __FILE__, __LINE__, "sssbs",
25898 +                                                       "unexpected type for key: ", "proxy.server",
25899                                                         "[", da->value->data[j]->key, "](string)");
25900 -                                       
25901 +
25902                                         return HANDLER_ERROR;
25903                                 }
25904 -                               
25905 -                               /* 
25906 -                                * proxy.server = ( "<ext>" => 
25907 -                                *                     ( "<host>" => ( ... ), 
25908 +
25909 +                               /*
25910 +                                * proxy.server = ( "<ext>" =>
25911 +                                *                     ( "<host>" => ( ... ),
25912                                  *                       "<host>" => ( ... )
25913 -                                *                     ), 
25914 +                                *                     ),
25915                                  *                    "<ext>" => ... )
25916                                  */
25917 -                               
25918 +
25919                                 for (n = 0; n < da_ext->value->used; n++) {
25920                                         data_array *da_host = (data_array *)da_ext->value->data[n];
25921 -                                       
25922 +
25923                                         data_proxy *df;
25924                                         data_array *dfa;
25925 -                                       
25926 -                                       config_values_t pcv[] = { 
25927 +
25928 +                                       config_values_t pcv[] = {
25929                                                 { "host",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 0 */
25930                                                 { "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
25931                                                 { NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25932                                         };
25933 -                                       
25934 +
25935                                         if (da_host->type != TYPE_ARRAY) {
25936 -                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS", 
25937 -                                                               "unexpected type for key:", 
25938 -                                                               "proxy.server", 
25939 +                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS",
25940 +                                                               "unexpected type for key:",
25941 +                                                               "proxy.server",
25942                                                                 "[", da_ext->value->data[n]->key, "](string)");
25943 -                                               
25944 +
25945                                                 return HANDLER_ERROR;
25946                                         }
25947 -                                       
25948 +
25949                                         df = data_proxy_init();
25950 -                                       
25951 +
25952                                         df->port = 80;
25953 -                                       
25954 +
25955                                         buffer_copy_string_buffer(df->key, da_host->key);
25956 -                                       
25957 +
25958                                         pcv[0].destination = df->host;
25959                                         pcv[1].destination = &(df->port);
25960 -                                       
25961 +
25962                                         if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
25963                                                 return HANDLER_ERROR;
25964                                         }
25965 -                                       
25966 +
25967                                         if (buffer_is_empty(df->host)) {
25968 -                                               log_error_write(srv, __FILE__, __LINE__, "sbbbs", 
25969 -                                                               "missing key (string):", 
25970 +                                               log_error_write(srv, __FILE__, __LINE__, "sbbbs",
25971 +                                                               "missing key (string):",
25972                                                                 da->key,
25973                                                                 da_ext->key,
25974                                                                 da_host->key,
25975                                                                 "host");
25976 -                                               
25977 +
25978                                                 return HANDLER_ERROR;
25979                                         }
25980 -                                       
25981 +
25982                                         /* if extension already exists, take it */
25983 -                                       
25984 +
25985                                         if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
25986                                                 dfa = data_array_init();
25987 -                                               
25988 +
25989                                                 buffer_copy_string_buffer(dfa->key, da_ext->key);
25990 -                                               
25991 +
25992                                                 array_insert_unique(dfa->value, (data_unset *)df);
25993                                                 array_insert_unique(s->extensions, (data_unset *)dfa);
25994                                         } else {
25995 @@ -328,19 +360,19 @@
25996                         }
25997                 }
25998         }
25999 -       
26000 +
26001         return HANDLER_GO_ON;
26002  }
26003  
26004  void proxy_connection_close(server *srv, handler_ctx *hctx) {
26005         plugin_data *p;
26006         connection *con;
26007 -       
26008 +
26009         if (NULL == hctx) return;
26010 -       
26011 +
26012         p    = hctx->plugin_data;
26013         con  = hctx->remote_conn;
26014 -       
26015 +
26016         if (hctx->fd != -1) {
26017                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26018                 fdevent_unregister(srv->ev, hctx->fd);
26019 @@ -348,47 +380,56 @@
26020                 close(hctx->fd);
26021                 srv->cur_fds--;
26022         }
26023 -       
26024 +
26025         handler_ctx_free(hctx);
26026 -       con->plugin_ctx[p->id] = NULL;  
26027 +       con->plugin_ctx[p->id] = NULL;
26028  }
26029  
26030  static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
26031         struct sockaddr *proxy_addr;
26032         struct sockaddr_in proxy_addr_in;
26033         socklen_t servlen;
26034 -       
26035 +
26036         plugin_data *p    = hctx->plugin_data;
26037         data_proxy *host= hctx->host;
26038         int proxy_fd       = hctx->fd;
26039 -       
26040 +
26041         memset(&proxy_addr, 0, sizeof(proxy_addr));
26042 -       
26043 +
26044         proxy_addr_in.sin_family = AF_INET;
26045         proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr);
26046         proxy_addr_in.sin_port = htons(host->port);
26047         servlen = sizeof(proxy_addr_in);
26048 -               
26049 +
26050         proxy_addr = (struct sockaddr *) &proxy_addr_in;
26051 -       
26052 +
26053         if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
26054 -               if (errno == EINPROGRESS || errno == EALREADY) {
26055 +#ifdef _WIN32
26056 +       errno = WSAGetLastError();
26057 +#endif
26058 +       switch(errno) {
26059 +#ifdef _WIN32
26060 +       case WSAEWOULDBLOCK:
26061 +#endif
26062 +       case EINPROGRESS:
26063 +       case EALREADY:
26064                         if (p->conf.debug) {
26065 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
26066 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
26067                                                 "connect delayed:", proxy_fd);
26068                         }
26069 -                       
26070 +
26071                         return 1;
26072 -               } else {
26073 -                       
26074 -                       log_error_write(srv, __FILE__, __LINE__, "sdsd", 
26075 +               default:
26076 +
26077 +                       log_error_write(srv, __FILE__, __LINE__, "sdsd",
26078                                         "connect failed:", proxy_fd, strerror(errno), errno);
26079 -                       
26080 +
26081                         return -1;
26082                 }
26083         }
26084 +       fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
26085         if (p->conf.debug) {
26086 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
26087 +               log_error_write(srv, __FILE__, __LINE__, "sd",
26088                                 "connect succeeded: ", proxy_fd);
26089         }
26090  
26091 @@ -396,51 +437,52 @@
26092  }
26093  
26094  void proxy_set_header(connection *con, const char *key, const char *value) {
26095 -    data_string *ds_dst;
26096 +       data_string *ds_dst;
26097  
26098 -    if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26099 -          ds_dst = data_string_init();
26100 -    }
26101 -
26102 -    buffer_copy_string(ds_dst->key, key);
26103 -    buffer_copy_string(ds_dst->value, value);
26104 -    array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26105 +       if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26106 +               ds_dst = data_string_init();
26107 +       }
26108 +
26109 +       buffer_copy_string(ds_dst->key, key);
26110 +       buffer_copy_string(ds_dst->value, value);
26111 +       array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26112  }
26113  
26114  void proxy_append_header(connection *con, const char *key, const char *value) {
26115 -    data_string *ds_dst;
26116 +       data_string *ds_dst;
26117  
26118 -    if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26119 -          ds_dst = data_string_init();
26120 -    }
26121 -
26122 -    buffer_copy_string(ds_dst->key, key);
26123 -    buffer_append_string(ds_dst->value, value);
26124 -    array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26125 +       if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26126 +               ds_dst = data_string_init();
26127 +       }
26128 +
26129 +       buffer_copy_string(ds_dst->key, key);
26130 +       buffer_append_string(ds_dst->value, value);
26131 +       array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26132  }
26133  
26134  
26135  static int proxy_create_env(server *srv, handler_ctx *hctx) {
26136         size_t i;
26137 -       
26138 +
26139         connection *con   = hctx->remote_conn;
26140 +       plugin_data *p    = hctx->plugin_data;
26141         buffer *b;
26142 -       
26143 +
26144         /* build header */
26145  
26146         b = chunkqueue_get_append_buffer(hctx->wb);
26147 -       
26148 +
26149         /* request line */
26150         buffer_copy_string(b, get_http_method_name(con->request.http_method));
26151         BUFFER_APPEND_STRING_CONST(b, " ");
26152 -       
26153 +
26154         buffer_append_string_buffer(b, con->request.uri);
26155         BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
26156  
26157         proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
26158 -       /* http_host is NOT is just a pointer to a buffer 
26159 +       /* http_host is NOT is just a pointer to a buffer
26160          * which is NULL if it is not set */
26161 -       if (con->request.http_host && 
26162 +       if (con->request.http_host &&
26163             !buffer_is_empty(con->request.http_host)) {
26164                 proxy_set_header(con, "X-Host", con->request.http_host->ptr);
26165         }
26166 @@ -449,24 +491,25 @@
26167         /* request header */
26168         for (i = 0; i < con->request.headers->used; i++) {
26169                 data_string *ds;
26170 -               
26171 +
26172                 ds = (data_string *)con->request.headers->data[i];
26173 -               
26174 -               if (ds->value->used && ds->key->used) {
26175 -                       if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
26176 -                       
26177 -                       buffer_append_string_buffer(b, ds->key);
26178 -                       BUFFER_APPEND_STRING_CONST(b, ": ");
26179 -                       buffer_append_string_buffer(b, ds->value);
26180 -                       BUFFER_APPEND_STRING_CONST(b, "\r\n");
26181 -               }
26182 +
26183 +               if (buffer_is_empty(ds->value) || buffer_is_empty(ds->key)) continue;
26184 +
26185 +               if (!buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
26186 +               if (!buffer_is_equal_string(ds->key, CONST_STR_LEN("Keep-Alive"))) continue;
26187 +
26188 +               buffer_append_string_buffer(b, ds->key);
26189 +               BUFFER_APPEND_STRING_CONST(b, ": ");
26190 +               buffer_append_string_buffer(b, ds->value);
26191 +               BUFFER_APPEND_STRING_CONST(b, "\r\n");
26192         }
26193 -       
26194 +
26195         BUFFER_APPEND_STRING_CONST(b, "\r\n");
26196 -       
26197 +
26198         hctx->wb->bytes_in += b->used - 1;
26199         /* body */
26200 -       
26201 +
26202         if (con->request.content_length) {
26203                 chunkqueue *req_cq = con->request_content_queue;
26204                 chunk *req_c;
26205 @@ -479,7 +522,7 @@
26206  
26207                         /* we announce toWrite octects
26208                          * now take all the request_content chunk that we need to fill this request
26209 -                        * */   
26210 +                        * */
26211  
26212                         switch (req_c->type) {
26213                         case FILE_CHUNK:
26214 @@ -507,223 +550,161 @@
26215  
26216                                 req_c->offset += weHave;
26217                                 req_cq->bytes_out += weHave;
26218 -                               
26219 +
26220                                 hctx->wb->bytes_in += weHave;
26221  
26222                                 break;
26223                         default:
26224                                 break;
26225                         }
26226 -                       
26227 +
26228                         offset += weHave;
26229                 }
26230  
26231         }
26232 -       
26233 +
26234         return 0;
26235  }
26236  
26237  static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) {
26238         hctx->state = state;
26239         hctx->state_timestamp = srv->cur_ts;
26240 -       
26241 +
26242         return 0;
26243  }
26244  
26245  
26246 -static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
26247 -       char *s, *ns;
26248 -       int http_response_status = -1;
26249 -       
26250 -       UNUSED(srv);
26251 +static void chunkqueue_print(chunkqueue *cq) {
26252 +       chunk *c;
26253  
26254 -       /* \r\n -> \0\0 */
26255 -       
26256 -       buffer_copy_string_buffer(p->parse_response, in);
26257 -       
26258 -       for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
26259 -               char *key, *value;
26260 -               int key_len;
26261 -               data_string *ds;
26262 -               int copy_header;
26263 -               
26264 -               ns[0] = '\0';
26265 -               ns[1] = '\0';
26266 -
26267 -               if (-1 == http_response_status) {
26268 -                       /* The first line of a Response message is the Status-Line */
26269 -
26270 -                       for (key=s; *key && *key != ' '; key++);
26271 -
26272 -                       if (*key) {
26273 -                               http_response_status = (int) strtol(key, NULL, 10);
26274 -                               if (http_response_status <= 0) http_response_status = 502;
26275 -                       } else {
26276 -                               http_response_status = 502;
26277 -                       }
26278 -
26279 -                       con->http_status = http_response_status;
26280 -                       con->parsed_response |= HTTP_STATUS;
26281 -                       continue;
26282 -               }
26283 -               
26284 -               if (NULL == (value = strchr(s, ':'))) {
26285 -                       /* now we expect: "<key>: <value>\n" */
26286 -
26287 -                       continue;
26288 -               }
26289 -
26290 -               key = s;
26291 -               key_len = value - key;
26292 -               
26293 -               value++;
26294 -               /* strip WS */
26295 -               while (*value == ' ' || *value == '\t') value++;
26296 -               
26297 -               copy_header = 1;
26298 -               
26299 -               switch(key_len) {
26300 -               case 4:
26301 -                       if (0 == strncasecmp(key, "Date", key_len)) {
26302 -                               con->parsed_response |= HTTP_DATE;
26303 -                       }
26304 -                       break;
26305 -               case 8:
26306 -                       if (0 == strncasecmp(key, "Location", key_len)) {
26307 -                               con->parsed_response |= HTTP_LOCATION;
26308 -                       }
26309 -                       break;
26310 -               case 10:
26311 -                       if (0 == strncasecmp(key, "Connection", key_len)) {
26312 -                               copy_header = 0;
26313 -                       }
26314 -                       break;
26315 -               case 14:
26316 -                       if (0 == strncasecmp(key, "Content-Length", key_len)) {
26317 -                               con->response.content_length = strtol(value, NULL, 10);
26318 -                               con->parsed_response |= HTTP_CONTENT_LENGTH;
26319 -                       }
26320 -                       break;
26321 -               default:
26322 -                       break;
26323 -               }
26324 -
26325 -               if (copy_header) {
26326 -                       if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26327 -                               ds = data_response_init();
26328 -                       }
26329 -                       buffer_copy_string_len(ds->key, key, key_len);
26330 -                       buffer_copy_string(ds->value, value);
26331 -                       
26332 -                       array_insert_unique(con->response.headers, (data_unset *)ds);
26333 -               }
26334 +       for (c = cq->first; c; c = c->next) {
26335 +               fprintf(stderr, "%s", c->mem->ptr + c->offset);
26336         }
26337 -       
26338 -       return 0;
26339 +       fprintf(stderr, "\r\n");
26340  }
26341  
26342 -
26343  static int proxy_demux_response(server *srv, handler_ctx *hctx) {
26344 -       int fin = 0;
26345 -       int b;
26346 -       ssize_t r;
26347 -       
26348         plugin_data *p    = hctx->plugin_data;
26349         connection *con   = hctx->remote_conn;
26350         int proxy_fd       = hctx->fd;
26351 -       
26352 -       /* check how much we have to read */
26353 -       if (ioctl(hctx->fd, FIONREAD, &b)) {
26354 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
26355 -                               "ioctl failed: ",
26356 -                               proxy_fd);
26357 +       chunkqueue *next_queue = NULL;
26358 +       chunk *c = NULL;
26359 +
26360 +       switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
26361 +       case NETWORK_STATUS_SUCCESS:
26362 +               /* we got content */
26363 +               break;
26364 +       case NETWORK_STATUS_WAIT_FOR_EVENT:
26365 +               /* the ioctl will return WAIT_FOR_EVENT on a read */
26366 +               if (0 == con->file_started) return -1;
26367 +       case NETWORK_STATUS_CONNECTION_CLOSE:
26368 +               /* we are done, get out of here */
26369 +               con->file_finished = 1;
26370 +
26371 +               /* close the chunk-queue with a empty chunk */
26372 +
26373 +               return 1;
26374 +       default:
26375 +               /* oops */
26376                 return -1;
26377         }
26378  
26379 +       /* looks like we got some content
26380 +       *
26381 +       * split off the header from the incoming stream
26382 +       */
26383  
26384 -       if (p->conf.debug) {
26385 -               log_error_write(srv, __FILE__, __LINE__, "sd",
26386 -                              "proxy - have to read:", b);
26387 -       }
26388 +       if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
26389 +               size_t i;
26390 +               int have_content_length = 0;
26391  
26392 -       if (b > 0) {
26393 -               if (hctx->response->used == 0) {
26394 -                       /* avoid too small buffer */
26395 -                       buffer_prepare_append(hctx->response, b + 1);
26396 -                       hctx->response->used = 1;
26397 -               } else {
26398 -                       buffer_prepare_append(hctx->response, hctx->response->used + b);
26399 -               }
26400 -               
26401 -               if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
26402 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
26403 -                                       "unexpected end-of-file (perhaps the proxy process died):",
26404 -                                       proxy_fd, strerror(errno));
26405 -                       return -1;
26406 -               }
26407 -               
26408 -               /* this should be catched by the b > 0 above */
26409 -               assert(r);
26410 -               
26411 -               hctx->response->used += r;
26412 -               hctx->response->ptr[hctx->response->used - 1] = '\0';
26413 -
26414 -#if 0
26415 -               log_error_write(srv, __FILE__, __LINE__, "sdsbs", 
26416 -                               "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
26417 -#endif
26418 +               http_response_reset(p->resp);
26419  
26420 -               if (0 == con->got_response) {
26421 -                       con->got_response = 1;
26422 -                       buffer_prepare_copy(hctx->response_header, 128);
26423 -               }
26424 -                               
26425 -               if (0 == con->file_started) {
26426 -                       char *c;
26427 -                               
26428 -                       /* search for the \r\n\r\n in the string */
26429 -                       if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
26430 -                               size_t hlen = c - hctx->response->ptr + 4;
26431 -                               size_t blen = hctx->response->used - hlen - 1;
26432 -                               /* found */
26433 -                               
26434 -                               buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
26435 -#if 0
26436 -                               log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
26437 -#endif
26438 -                               /* parse the response header */
26439 -                               proxy_response_parse(srv, con, p, hctx->response_header);
26440 -                                       
26441 -                               /* enable chunked-transfer-encoding */
26442 -                               if (con->request.http_version == HTTP_VERSION_1_1 &&
26443 -                                   !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
26444 -                                       con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26445 +               /* the response header is not fully received yet,
26446 +               *
26447 +               * extract the http-response header from the rb-cq
26448 +               */
26449 +               switch (http_response_parse_cq(hctx->rb, p->resp)) {
26450 +               case PARSE_ERROR:
26451 +                       /* parsing failed */
26452 +
26453 +                       con->http_status = 502; /* Bad Gateway */
26454 +                       return 1;
26455 +               case PARSE_NEED_MORE:
26456 +                       return 0;
26457 +               case PARSE_SUCCESS:
26458 +                       con->http_status = p->resp->status;
26459 +
26460 +                       chunkqueue_remove_finished_chunks(hctx->rb);
26461 +
26462 +                       /* copy the http-headers */
26463 +                       for (i = 0; i < p->resp->headers->used; i++) {
26464 +                               const char *ign[] = { "Status", "Connection", NULL };
26465 +                               size_t j;
26466 +                               data_string *ds;
26467 +
26468 +                               data_string *header = (data_string *)p->resp->headers->data[i];
26469 +
26470 +                               /* some headers are ignored by default */
26471 +                               for (j = 0; ign[j]; j++) {
26472 +                                       if (0 == strcasecmp(ign[j], header->key->ptr)) break;
26473                                 }
26474 -                                       
26475 -                               con->file_started = 1;
26476 -                               if (blen) {
26477 -                                       http_chunk_append_mem(srv, con, c + 4, blen + 1);
26478 -                                       joblist_append(srv, con);
26479 +                               if (ign[j]) continue;
26480 +
26481 +                               if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
26482 +                                       /* CGI/1.1 rev 03 - 7.2.1.2 */
26483 +                                       if (con->http_status == 0) con->http_status = 302;
26484 +                               } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
26485 +                                       have_content_length = 1;
26486                                 }
26487 -                               hctx->response->used = 0;
26488 +                               
26489 +                               if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26490 +                                       ds = data_response_init();
26491 +                               }
26492 +                               buffer_copy_string_buffer(ds->key, header->key);
26493 +                               buffer_copy_string_buffer(ds->value, header->value);
26494 +
26495 +                               array_insert_unique(con->response.headers, (data_unset *)ds);
26496                         }
26497 -               } else {
26498 -                       http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
26499 -                       joblist_append(srv, con);
26500 -                       hctx->response->used = 0;
26501 +
26502 +                       con->file_started = 1;
26503 +
26504 +                       if (con->request.http_version == HTTP_VERSION_1_1 &&
26505 +                           !have_content_length) {
26506 +                               con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26507 +                       }
26508 +
26509 +                       hctx->state = PROXY_STATE_RESPONSE_CONTENT;
26510 +                       break;
26511                 }
26512 -               
26513 -       } else {
26514 -               /* reading from upstream done */
26515 -               con->file_finished = 1;
26516 -               
26517 -               http_chunk_append_mem(srv, con, NULL, 0);
26518 -               joblist_append(srv, con);
26519 -               
26520 -               fin = 1;
26521         }
26522 -       
26523 -       return fin;
26524 +
26525 +       /* FIXME: pass the response-header to the other plugins to
26526 +       * setup the filter-queue
26527 +       *
26528 +       * - use next-queue instead of con->write_queue
26529 +       */
26530 +
26531 +       next_queue = con->write_queue;
26532 +
26533 +       assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
26534 +
26535 +       /* FIXME: if we have a content-length or chunked-encoding
26536 +       * handle it.
26537 +       *
26538 +       * for now we wait for EOF on the socket */
26539 +
26540 +       /* copy the content to the next cq */
26541 +       for (c = hctx->rb->first; c; c = c->next) {
26542 +               http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
26543 +
26544 +               c->offset = c->mem->used - 1;
26545 +       }
26546 +
26547 +       chunkqueue_remove_finished_chunks(hctx->rb);
26548 +       joblist_append(srv, con);
26549 +
26550 +       return 0;
26551  }
26552  
26553  
26554 @@ -731,12 +712,12 @@
26555         data_proxy *host= hctx->host;
26556         plugin_data *p    = hctx->plugin_data;
26557         connection *con   = hctx->remote_conn;
26558 -       
26559 +
26560         int ret;
26561 -       
26562 -       if (!host || 
26563 -           (!host->host->used || !host->port)) return -1;
26564 -       
26565 +
26566 +       if (!host ||
26567 +               (!host->host->used || !host->port)) return -1;
26568 +
26569         switch(hctx->state) {
26570         case PROXY_STATE_INIT:
26571                 if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
26572 @@ -744,19 +725,19 @@
26573                         return HANDLER_ERROR;
26574                 }
26575                 hctx->fde_ndx = -1;
26576 -               
26577 +
26578                 srv->cur_fds++;
26579 -               
26580 +
26581                 fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
26582 -               
26583 +
26584                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
26585                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
26586 -                       
26587 +
26588                         return HANDLER_ERROR;
26589                 }
26590 -               
26591 +
26592                 /* fall through */
26593 -               
26594 +
26595         case PROXY_STATE_CONNECT:
26596                 /* try to finish the connect() */
26597                 if (hctx->state == PROXY_STATE_INIT) {
26598 @@ -764,16 +745,16 @@
26599                         switch (proxy_establish_connection(srv, hctx)) {
26600                         case 1:
26601                                 proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
26602 -                               
26603 +
26604                                 /* connection is in progress, wait for an event and call getsockopt() below */
26605 -                               
26606 +
26607                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26608 -                               
26609 +
26610                                 return HANDLER_WAIT_FOR_EVENT;
26611                         case -1:
26612                                 /* if ECONNREFUSED choose another connection -> FIXME */
26613                                 hctx->fde_ndx = -1;
26614 -                               
26615 +
26616                                 return HANDLER_ERROR;
26617                         default:
26618                                 /* everything is ok, go on */
26619 @@ -782,152 +763,152 @@
26620                 } else {
26621                         int socket_error;
26622                         socklen_t socket_error_len = sizeof(socket_error);
26623 -               
26624 -                       /* we don't need it anymore */  
26625 +
26626 +                       /* we don't need it anymore */
26627                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26628  
26629                         /* try to finish the connect() */
26630                         if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
26631 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
26632 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
26633                                                 "getsockopt failed:", strerror(errno));
26634 -                               
26635 +
26636                                 return HANDLER_ERROR;
26637                         }
26638                         if (socket_error != 0) {
26639                                 log_error_write(srv, __FILE__, __LINE__, "ss",
26640 -                                               "establishing connection failed:", strerror(socket_error), 
26641 +                                               "establishing connection failed:", strerror(socket_error),
26642                                                 "port:", hctx->host->port);
26643 -                               
26644 +
26645                                 return HANDLER_ERROR;
26646                         }
26647                         if (p->conf.debug) {
26648 -                               log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - connect - delayed success"); 
26649 +                               log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - connect - delayed success");
26650                         }
26651                 }
26652 -               
26653 +
26654                 proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
26655                 /* fall through */
26656         case PROXY_STATE_PREPARE_WRITE:
26657                 proxy_create_env(srv, hctx);
26658 -               
26659 +
26660                 proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
26661 -               
26662 +
26663                 /* fall through */
26664         case PROXY_STATE_WRITE:;
26665 -               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); 
26666 +               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
26667  
26668                 chunkqueue_remove_finished_chunks(hctx->wb);
26669  
26670 -               if (-1 == ret) {
26671 -                       if (errno != EAGAIN &&
26672 -                           errno != EINTR) {
26673 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26674 -                               
26675 -                               return HANDLER_ERROR;
26676 -                       } else {
26677 -                               fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26678 +               switch(ret) {
26679 +               case NETWORK_STATUS_FATAL_ERROR:
26680 +                       log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26681  
26682 -                               return HANDLER_WAIT_FOR_EVENT;
26683 -                       }
26684 +                       return HANDLER_ERROR;
26685 +               case NETWORK_STATUS_WAIT_FOR_EVENT:
26686 +
26687 +                       fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26688 +
26689 +                       return HANDLER_WAIT_FOR_EVENT;
26690                 }
26691  
26692                 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
26693 -                       proxy_set_state(srv, hctx, PROXY_STATE_READ);
26694 +                       proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
26695  
26696                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26697                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
26698                 } else {
26699                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26700 -                               
26701 +
26702                         return HANDLER_WAIT_FOR_EVENT;
26703                 }
26704 -               
26705 +
26706                 return HANDLER_WAIT_FOR_EVENT;
26707 -       case PROXY_STATE_READ:
26708 +       case PROXY_STATE_RESPONSE_CONTENT:
26709 +       case PROXY_STATE_RESPONSE_HEADER:
26710                 /* waiting for a response */
26711 +
26712                 return HANDLER_WAIT_FOR_EVENT;
26713         default:
26714                 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
26715                 return HANDLER_ERROR;
26716         }
26717 -       
26718 +
26719         return HANDLER_GO_ON;
26720  }
26721  
26722 -#define PATCH(x) \
26723 -       p->conf.x = s->x;
26724  static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
26725         size_t i, j;
26726         plugin_config *s = p->config_storage[0];
26727 -       
26728 -       PATCH(extensions);
26729 -       PATCH(debug);
26730 -       PATCH(balance);
26731 -       
26732 +
26733 +       PATCH_OPTION(extensions);
26734 +       PATCH_OPTION(debug);
26735 +       PATCH_OPTION(balance);
26736 +       PATCH_OPTION(last_used_backends);
26737 +
26738         /* skip the first, the global context */
26739         for (i = 1; i < srv->config_context->used; i++) {
26740                 data_config *dc = (data_config *)srv->config_context->data[i];
26741                 s = p->config_storage[i];
26742 -               
26743 +
26744                 /* condition didn't match */
26745                 if (!config_check_cond(srv, con, dc)) continue;
26746 -               
26747 +
26748                 /* merge config */
26749                 for (j = 0; j < dc->value->used; j++) {
26750                         data_unset *du = dc->value->data[j];
26751 -                       
26752 +
26753                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
26754 -                               PATCH(extensions);
26755 +                               PATCH_OPTION(extensions);
26756                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
26757 -                               PATCH(debug);
26758 +                               PATCH_OPTION(debug);
26759                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
26760 -                               PATCH(balance);
26761 +                               PATCH_OPTION(balance);
26762 +                               PATCH_OPTION(last_used_backends);
26763                         }
26764                 }
26765         }
26766 -       
26767 +
26768         return 0;
26769  }
26770 -#undef PATCH
26771  
26772  SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
26773         plugin_data *p = p_d;
26774 -       
26775 +
26776         handler_ctx *hctx = con->plugin_ctx[p->id];
26777         data_proxy *host;
26778 -       
26779 +
26780         if (NULL == hctx) return HANDLER_GO_ON;
26781  
26782         mod_proxy_patch_connection(srv, con, p);
26783 -       
26784 +
26785         host = hctx->host;
26786 -       
26787 +
26788         /* not my job */
26789         if (con->mode != p->id) return HANDLER_GO_ON;
26790 -       
26791 +
26792         /* ok, create the request */
26793         switch(proxy_write_request(srv, hctx)) {
26794         case HANDLER_ERROR:
26795 -               log_error_write(srv, __FILE__, __LINE__,  "sbdd", "proxy-server disabled:", 
26796 +               log_error_write(srv, __FILE__, __LINE__,  "sbdd", "proxy-server disabled:",
26797                                 host->host,
26798                                 host->port,
26799                                 hctx->fd);
26800 -               
26801 +
26802                 /* disable this server */
26803                 host->is_disabled = 1;
26804                 host->disable_ts = srv->cur_ts;
26805 -               
26806 +
26807                 proxy_connection_close(srv, hctx);
26808 -       
26809 -               /* reset the enviroment and restart the sub-request */  
26810 +
26811 +               /* reset the enviroment and restart the sub-request */
26812                 buffer_reset(con->physical.path);
26813                 con->mode = DIRECT;
26814  
26815                 joblist_append(srv, con);
26816  
26817 -               /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop 
26818 -                * and hope that the childs will be restarted 
26819 -                * 
26820 +               /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26821 +                * and hope that the childs will be restarted
26822 +                *
26823                  */
26824  
26825                 return HANDLER_WAIT_FOR_FD;
26826 @@ -938,7 +919,7 @@
26827         default:
26828                 break;
26829         }
26830 -       
26831 +
26832         if (con->file_started == 1) {
26833                 return HANDLER_FINISHED;
26834         } else {
26835 @@ -951,13 +932,14 @@
26836         handler_ctx *hctx = ctx;
26837         connection  *con  = hctx->remote_conn;
26838         plugin_data *p    = hctx->plugin_data;
26839 -       
26840 -       
26841 +
26842 +
26843         if ((revents & FDEVENT_IN) &&
26844 -           hctx->state == PROXY_STATE_READ) {
26845 +           (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
26846 +            hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
26847  
26848                 if (p->conf.debug) {
26849 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
26850 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
26851                                         "proxy: fdevent-in", hctx->state);
26852                 }
26853  
26854 @@ -965,11 +947,15 @@
26855                 case 0:
26856                         break;
26857                 case 1:
26858 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
26859 +                                       "proxy: request done", hctx->fd);
26860                         hctx->host->usage--;
26861 -                       
26862 +
26863 +                       http_chunk_append_mem(srv, con, NULL, 0);
26864 +
26865                         /* we are done */
26866                         proxy_connection_close(srv, hctx);
26867 -                       
26868 +
26869                         joblist_append(srv, con);
26870                         return HANDLER_FINISHED;
26871                 case -1:
26872 @@ -982,53 +968,53 @@
26873                                 /* response might have been already started, kill the connection */
26874                                 connection_set_state(srv, con, CON_STATE_ERROR);
26875                         }
26876 -                       
26877 +
26878                         joblist_append(srv, con);
26879                         return HANDLER_FINISHED;
26880                 }
26881         }
26882 -       
26883 +
26884         if (revents & FDEVENT_OUT) {
26885                 if (p->conf.debug) {
26886 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
26887 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
26888                                         "proxy: fdevent-out", hctx->state);
26889                 }
26890  
26891                 if (hctx->state == PROXY_STATE_CONNECT ||
26892                     hctx->state == PROXY_STATE_WRITE) {
26893                         /* we are allowed to send something out
26894 -                        * 
26895 +                        *
26896                          * 1. in a unfinished connect() call
26897                          * 2. in a unfinished write() call (long POST request)
26898                          */
26899                         return mod_proxy_handle_subrequest(srv, con, p);
26900                 } else {
26901 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
26902 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
26903                                         "proxy: out", hctx->state);
26904                 }
26905         }
26906 -       
26907 +
26908         /* perhaps this issue is already handled */
26909         if (revents & FDEVENT_HUP) {
26910                 if (p->conf.debug) {
26911 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
26912 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
26913                                         "proxy: fdevent-hup", hctx->state);
26914                 }
26915 -               
26916 +
26917                 if (hctx->state == PROXY_STATE_CONNECT) {
26918                         /* connect() -> EINPROGRESS -> HUP */
26919 -                       
26920 +
26921                         /**
26922 -                        * what is proxy is doing if it can't reach the next hop ? 
26923 -                        * 
26924 +                        * what is proxy is doing if it can't reach the next hop ?
26925 +                        *
26926                          */
26927 -                       
26928 +
26929                         proxy_connection_close(srv, hctx);
26930                         joblist_append(srv, con);
26931 -                       
26932 +
26933                         con->http_status = 503;
26934                         con->mode = DIRECT;
26935 -                       
26936 +
26937                         return HANDLER_FINISHED;
26938                 }
26939  
26940 @@ -1038,13 +1024,13 @@
26941                 joblist_append(srv, con);
26942         } else if (revents & FDEVENT_ERR) {
26943                 /* kill all connections to the proxy process */
26944 -               
26945 +
26946                 log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
26947  
26948                 joblist_append(srv, con);
26949                 proxy_connection_close(srv, hctx);
26950         }
26951 -       
26952 +
26953         return HANDLER_FINISHED;
26954  }
26955  
26956 @@ -1058,44 +1044,48 @@
26957         buffer *fn;
26958         data_array *extension = NULL;
26959         size_t path_info_offset;
26960 -       
26961 +       data_integer *last_used_backend;
26962 +       data_proxy *host = NULL;
26963 +       handler_ctx *hctx = NULL;
26964 +
26965 +       array *backends = NULL;
26966 +
26967         /* Possibly, we processed already this request */
26968         if (con->file_started == 1) return HANDLER_GO_ON;
26969 -       
26970 +
26971         mod_proxy_patch_connection(srv, con, p);
26972 -       
26973 +
26974         fn = con->uri.path;
26975  
26976         if (fn->used == 0) {
26977                 return HANDLER_ERROR;
26978         }
26979 -       
26980 +
26981         s_len = fn->used - 1;
26982 -       
26983 -       
26984 +
26985         path_info_offset = 0;
26986  
26987 -       if (p->conf.debug) {    
26988 +       if (p->conf.debug) {
26989                 log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - start");
26990         }
26991  
26992         /* check if extension matches */
26993         for (k = 0; k < p->conf.extensions->used; k++) {
26994                 size_t ct_len;
26995 -               
26996 +
26997                 extension = (data_array *)p->conf.extensions->data[k];
26998 -               
26999 +
27000                 if (extension->key->used == 0) continue;
27001 -               
27002 +
27003                 ct_len = extension->key->used - 1;
27004 -               
27005 +
27006                 if (s_len < ct_len) continue;
27007 -               
27008 +
27009                 /* check extension in the form "/proxy_pattern" */
27010                 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
27011                         if (s_len > ct_len + 1) {
27012                                 char *pi_offset;
27013 -                               
27014 +
27015                                 if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
27016                                         path_info_offset = pi_offset - fn->ptr;
27017                                 }
27018 @@ -1106,12 +1096,14 @@
27019                         break;
27020                 }
27021         }
27022 -       
27023 +
27024         if (k == p->conf.extensions->used) {
27025                 return HANDLER_GO_ON;
27026         }
27027  
27028 -       if (p->conf.debug) {    
27029 +       backends = extension->value;
27030 +
27031 +       if (p->conf.debug) {
27032                 log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - ext found");
27033         }
27034  
27035 @@ -1120,34 +1112,34 @@
27036                 /* hash balancing */
27037  
27038                 if (p->conf.debug) {
27039 -                       log_error_write(srv, __FILE__, __LINE__,  "sd", 
27040 -                                       "proxy - used hash balancing, hosts:", extension->value->used);
27041 +                       log_error_write(srv, __FILE__, __LINE__,  "sd",
27042 +                                       "proxy - used hash balancing, hosts:", backends->used);
27043                 }
27044  
27045 -               for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
27046 -                       data_proxy *host = (data_proxy *)extension->value->data[k];
27047 +               for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
27048                         unsigned long cur_max;
27049  
27050 -                       if (host->is_disabled) continue;
27051 -                       
27052 +                       data_proxy *cur = (data_proxy *)backends->data[k];
27053 +
27054 +                       if (cur->is_disabled) continue;
27055 +
27056                         cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
27057 -                               generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
27058 +                               generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
27059                                 generate_crc32c(CONST_BUF_LEN(con->uri.authority));
27060 -                       
27061 +
27062                         if (p->conf.debug) {
27063 -                               log_error_write(srv, __FILE__, __LINE__,  "sbbbd", 
27064 +                               log_error_write(srv, __FILE__, __LINE__,  "sbbbd",
27065                                                 "proxy - election:",
27066                                                 con->uri.path,
27067 -                                               host->host,
27068 +                                               cur->host,
27069                                                 con->uri.authority,
27070                                                 cur_max);
27071                         }
27072  
27073 -                       if ((last_max == ULONG_MAX) || /* first round */
27074 -                           (cur_max > last_max)) {
27075 +                       if (host == NULL || (cur_max > last_max)) {
27076                                 last_max = cur_max;
27077  
27078 -                               ndx = k;
27079 +                               host = cur;
27080                         }
27081                 }
27082  
27083 @@ -1155,19 +1147,20 @@
27084         case PROXY_BALANCE_FAIR:
27085                 /* fair balancing */
27086                 if (p->conf.debug) {
27087 -                       log_error_write(srv, __FILE__, __LINE__,  "s", 
27088 +                       log_error_write(srv, __FILE__, __LINE__,  "s",
27089                                         "proxy - used fair balancing");
27090                 }
27091  
27092 -               for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27093 -                       data_proxy *host = (data_proxy *)extension->value->data[k];
27094 -               
27095 -                       if (host->is_disabled) continue;
27096 -
27097 -                       if (host->usage < max_usage) {
27098 -                               max_usage = host->usage;
27099 -                       
27100 -                               ndx = k;
27101 +               /* try to find the host with the lowest load */
27102 +               for (k = 0, max_usage = 0; k < backends->used; k++) {
27103 +                       data_proxy *cur = (data_proxy *)backends->data[k];
27104 +
27105 +                       if (cur->is_disabled) continue;
27106 +
27107 +                       if (NULL == host || cur->usage < max_usage) {
27108 +                               max_usage = cur->usage;
27109 +
27110 +                               host = cur;
27111                         }
27112                 }
27113  
27114 @@ -1175,89 +1168,100 @@
27115         case PROXY_BALANCE_RR:
27116                 /* round robin */
27117                 if (p->conf.debug) {
27118 -                       log_error_write(srv, __FILE__, __LINE__,  "s", 
27119 +                       log_error_write(srv, __FILE__, __LINE__,  "s",
27120                                         "proxy - used round-robin balancing");
27121                 }
27122  
27123                 /* just to be sure */
27124 -               assert(extension->value->used < INT_MAX);
27125 -               
27126 -               for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27127 -                       data_proxy *host = (data_proxy *)extension->value->data[k];
27128 -               
27129 -                       if (host->is_disabled) continue;
27130 -
27131 -                       /* first usable ndx */
27132 -                       if (max_usage == INT_MAX) {
27133 -                               max_usage = k;
27134 -                       }
27135 +               assert(backends->used < INT_MAX);
27136  
27137 -                       /* get next ndx */
27138 -                       if ((int)k > host->last_used_ndx) {
27139 -                               ndx = k;
27140 -                               host->last_used_ndx = k;
27141 +               /* send each request to another host:
27142 +                *
27143 +                * e.g.:
27144 +                *
27145 +                * if we have three hosts it is
27146 +                *
27147 +                * 1 .. 2 .. 3 .. 1 .. 2 .. 3
27148 +                *
27149 +                **/
27150  
27151 -                               break;
27152 -                       }
27153 +               /* walk through the list */
27154 +               last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
27155 +
27156 +               if (NULL == last_used_backend) {
27157 +                       last_used_backend = data_integer_init();
27158 +
27159 +                       buffer_copy_string_buffer(last_used_backend->key, extension->key);
27160 +                       last_used_backend->value = 0;
27161 +
27162 +                       array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
27163 +               }
27164 +
27165 +               /* scan all but the last host to see if they are up
27166 +                * take the first running host */
27167 +               for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
27168 +                       data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
27169 +
27170 +                       if (cur->is_disabled) continue;
27171 +
27172 +                       host = cur;
27173 +
27174 +                       last_used_backend->value = k;
27175 +
27176 +                       break;
27177                 }
27178 -               
27179 -               /* didn't found a higher id, wrap to the start */
27180 -               if (ndx != -1 && max_usage != INT_MAX) {
27181 -                       ndx = max_usage;
27182 +
27183 +               if (NULL == host) {
27184 +                       /* we found nothing better, fallback to the last used backend
27185 +                        * and check if it is still up */
27186 +                       host = (data_proxy *)backends->data[last_used_backend->value];
27187 +
27188 +                       if (host->is_disabled) host = NULL;
27189                 }
27190  
27191                 break;
27192         default:
27193                 break;
27194         }
27195 -       
27196 -       /* found a server */
27197 -       if (ndx != -1) {
27198 -               data_proxy *host = (data_proxy *)extension->value->data[ndx];
27199 -               
27200 -               /* 
27201 -                * if check-local is disabled, use the uri.path handler 
27202 -                * 
27203 -                */
27204 -               
27205 -               /* init handler-context */
27206 -               handler_ctx *hctx;
27207 -               hctx = handler_ctx_init();
27208 -                               
27209 -               hctx->path_info_offset = path_info_offset;
27210 -               hctx->remote_conn      = con;
27211 -               hctx->plugin_data      = p;
27212 -               hctx->host             = host;
27213 -                               
27214 -               con->plugin_ctx[p->id] = hctx;
27215 -               
27216 -               host->usage++;
27217 -               
27218 -               con->mode = p->id;
27219 -               
27220 -               if (p->conf.debug) {
27221 -                       log_error_write(srv, __FILE__, __LINE__,  "sbd", 
27222 -                                       "proxy - found a host",
27223 -                                       host->host, host->port);
27224 -               }
27225  
27226 -               return HANDLER_GO_ON;
27227 -       } else {
27228 -               /* no handler found */
27229 +       /* we havn't found a host */
27230 +       if (NULL == host) {
27231                 con->http_status = 500;
27232 -               
27233 -               log_error_write(srv, __FILE__, __LINE__,  "sb", 
27234 -                               "no proxy-handler found for:", 
27235 +
27236 +               log_error_write(srv, __FILE__, __LINE__,  "sb",
27237 +                               "no proxy-handler found for:",
27238                                 fn);
27239 -               
27240 +
27241                 return HANDLER_FINISHED;
27242         }
27243 +
27244 +       /* init handler-context */
27245 +       hctx = handler_ctx_init();
27246 +
27247 +       hctx->path_info_offset = path_info_offset;
27248 +       hctx->remote_conn      = con;
27249 +       hctx->plugin_data      = p;
27250 +       hctx->host             = host;
27251 +
27252 +       con->plugin_ctx[p->id] = hctx;
27253 +
27254 +       host->usage++;
27255 +
27256 +       /* we handle this request */
27257 +       con->mode = p->id;
27258 +
27259 +       if (p->conf.debug) {
27260 +               log_error_write(srv, __FILE__, __LINE__,  "sbd",
27261 +                               "proxy - found a host",
27262 +                               host->host, host->port);
27263 +       }
27264 +
27265         return HANDLER_GO_ON;
27266  }
27267  
27268  static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
27269         plugin_data *p = p_d;
27270 -       
27271 +
27272         proxy_connection_close(srv, con->plugin_ctx[p->id]);
27273  
27274         return HANDLER_GO_ON;
27275 @@ -1276,11 +1280,11 @@
27276                 size_t i, n, k;
27277                 for (i = 0; i < srv->config_context->used; i++) {
27278                         plugin_config *s = p->config_storage[i];
27279 -                       
27280 -                       if (!s) continue; 
27281 +
27282 +                       if (!s) continue;
27283  
27284                         /* get the extensions for all configs */
27285 -                       
27286 +
27287                         for (k = 0; k < s->extensions->used; k++) {
27288                                 data_array *extension = (data_array *)s->extensions->data[k];
27289  
27290 @@ -1290,8 +1294,8 @@
27291  
27292                                         if (!host->is_disabled ||
27293                                             srv->cur_ts - host->disable_ts < 5) continue;
27294 -                       
27295 -                                       log_error_write(srv, __FILE__, __LINE__,  "sbd", 
27296 +
27297 +                                       log_error_write(srv, __FILE__, __LINE__,  "sbd",
27298                                                         "proxy - re-enabled:",
27299                                                         host->host, host->port);
27300  
27301 @@ -1317,8 +1321,8 @@
27302         p->handle_uri_clean        = mod_proxy_check_extension;
27303         p->handle_subrequest       = mod_proxy_handle_subrequest;
27304         p->handle_trigger          = mod_proxy_trigger;
27305 -       
27306 +
27307         p->data         = NULL;
27308 -       
27309 +
27310         return 0;
27311  }
27312 --- ../lighttpd-1.4.11/src/mod_redirect.c       2006-02-08 15:38:06.000000000 +0200
27313 +++ lighttpd-1.4.12/src/mod_redirect.c  2006-07-11 22:07:52.000000000 +0300
27314 @@ -22,35 +22,35 @@
27315         PLUGIN_DATA;
27316         buffer *match_buf;
27317         buffer *location;
27318 -       
27319 +
27320         plugin_config **config_storage;
27321 -       
27322 -       plugin_config conf; 
27323 +
27324 +       plugin_config conf;
27325  } plugin_data;
27326  
27327  INIT_FUNC(mod_redirect_init) {
27328         plugin_data *p;
27329 -       
27330 +
27331         p = calloc(1, sizeof(*p));
27332 -       
27333 +
27334         p->match_buf = buffer_init();
27335         p->location = buffer_init();
27336 -       
27337 +
27338         return p;
27339  }
27340  
27341  FREE_FUNC(mod_redirect_free) {
27342         plugin_data *p = p_d;
27343 -       
27344 +
27345         if (!p) return HANDLER_GO_ON;
27346  
27347         if (p->config_storage) {
27348                 size_t i;
27349                 for (i = 0; i < srv->config_context->used; i++) {
27350                         plugin_config *s = p->config_storage[i];
27351 -                       
27352 +
27353                         pcre_keyvalue_buffer_free(s->redirect);
27354 -                       
27355 +
27356                         free(s);
27357                 }
27358                 free(p->config_storage);
27359 @@ -59,9 +59,9 @@
27360  
27361         buffer_free(p->match_buf);
27362         buffer_free(p->location);
27363 -       
27364 +
27365         free(p);
27366 -       
27367 +
27368         return HANDLER_GO_ON;
27369  }
27370  
27371 @@ -69,195 +69,137 @@
27372         plugin_data *p = p_d;
27373         data_unset *du;
27374         size_t i = 0;
27375 -       
27376 -       config_values_t cv[] = { 
27377 +
27378 +       config_values_t cv[] = {
27379                 { "url.redirect",               NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27380                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27381         };
27382 -       
27383 +
27384         if (!p) return HANDLER_ERROR;
27385 -       
27386 +
27387         /* 0 */
27388         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27389 -       
27390 +
27391         for (i = 0; i < srv->config_context->used; i++) {
27392                 plugin_config *s;
27393                 size_t j;
27394                 array *ca;
27395                 data_array *da = (data_array *)du;
27396 -               
27397 +
27398                 s = calloc(1, sizeof(plugin_config));
27399                 s->redirect   = pcre_keyvalue_buffer_init();
27400 -               
27401 +
27402                 cv[0].destination = s->redirect;
27403 -               
27404 +
27405                 p->config_storage[i] = s;
27406                 ca = ((data_config *)srv->config_context->data[i])->value;
27407 -       
27408 +
27409                 if (0 != config_insert_values_global(srv, ca, cv)) {
27410                         return HANDLER_ERROR;
27411                 }
27412 -               
27413 +
27414                 if (NULL == (du = array_get_element(ca, "url.redirect"))) {
27415                         /* no url.redirect defined */
27416                         continue;
27417                 }
27418 -               
27419 +
27420                 if (du->type != TYPE_ARRAY) {
27421 -                       log_error_write(srv, __FILE__, __LINE__, "sss", 
27422 +                       log_error_write(srv, __FILE__, __LINE__, "sss",
27423                                         "unexpected type for key: ", "url.redirect", "array of strings");
27424 -                       
27425 +
27426                         return HANDLER_ERROR;
27427                 }
27428 -               
27429 +
27430                 da = (data_array *)du;
27431 -                               
27432 +
27433                 for (j = 0; j < da->value->used; j++) {
27434                         if (da->value->data[j]->type != TYPE_STRING) {
27435 -                               log_error_write(srv, __FILE__, __LINE__, "sssbs", 
27436 -                                               "unexpected type for key: ", 
27437 -                                               "url.redirect", 
27438 +                               log_error_write(srv, __FILE__, __LINE__, "sssbs",
27439 +                                               "unexpected type for key: ",
27440 +                                               "url.redirect",
27441                                                 "[", da->value->data[j]->key, "](string)");
27442 -                               
27443 +
27444                                 return HANDLER_ERROR;
27445                         }
27446 -                               
27447 -                       if (0 != pcre_keyvalue_buffer_append(s->redirect, 
27448 +
27449 +                       if (0 != pcre_keyvalue_buffer_append(s->redirect,
27450                                                              ((data_string *)(da->value->data[j]))->key->ptr,
27451                                                              ((data_string *)(da->value->data[j]))->value->ptr)) {
27452 -                                       
27453 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
27454 +
27455 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
27456                                                 "pcre-compile failed for", da->value->data[j]->key);
27457                         }
27458                 }
27459         }
27460 -       
27461 +
27462         return HANDLER_GO_ON;
27463  }
27464  #ifdef HAVE_PCRE_H
27465  static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
27466         size_t i, j;
27467         plugin_config *s = p->config_storage[0];
27468 -       
27469 +
27470         p->conf.redirect = s->redirect;
27471 -       
27472 +
27473         /* skip the first, the global context */
27474         for (i = 1; i < srv->config_context->used; i++) {
27475                 data_config *dc = (data_config *)srv->config_context->data[i];
27476                 s = p->config_storage[i];
27477 -               
27478 +
27479                 /* condition didn't match */
27480                 if (!config_check_cond(srv, con, dc)) continue;
27481 -               
27482 +
27483                 /* merge config */
27484                 for (j = 0; j < dc->value->used; j++) {
27485                         data_unset *du = dc->value->data[j];
27486 -                       
27487 +
27488                         if (0 == strcmp(du->key->ptr, "url.redirect")) {
27489                                 p->conf.redirect = s->redirect;
27490                                 p->conf.context = dc;
27491                         }
27492                 }
27493         }
27494 -       
27495 +
27496         return 0;
27497  }
27498  #endif
27499  static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
27500  #ifdef HAVE_PCRE_H
27501         plugin_data *p = p_data;
27502 -       size_t i;
27503 +       int i;
27504  
27505 -       /* 
27506 +       /*
27507          * REWRITE URL
27508 -        * 
27509 +        *
27510          * e.g. redirect /base/ to /index.php?section=base
27511 -        * 
27512 +        *
27513          */
27514 -       
27515 +
27516         mod_redirect_patch_connection(srv, con, p);
27517 -       
27518 +
27519         buffer_copy_string_buffer(p->match_buf, con->request.uri);
27520 -       
27521 -       for (i = 0; i < p->conf.redirect->used; i++) {
27522 -               pcre *match;
27523 -               pcre_extra *extra;
27524 -               const char *pattern;
27525 -               size_t pattern_len;
27526 -               int n;
27527 -               pcre_keyvalue *kv = p->conf.redirect->kv[i];
27528 -# define N 10
27529 -               int ovec[N * 3];
27530 -               
27531 -               match       = kv->key;
27532 -               extra       = kv->key_extra;
27533 -               pattern     = kv->value->ptr;
27534 -               pattern_len = kv->value->used - 1;
27535 -               
27536 -               if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
27537 -                       if (n != PCRE_ERROR_NOMATCH) {
27538 -                               log_error_write(srv, __FILE__, __LINE__, "sd",
27539 -                                               "execution error while matching: ", n);
27540 -                               return HANDLER_ERROR;
27541 -                       }
27542 -               } else {
27543 -                       const char **list;
27544 -                       size_t start, end;
27545 -                       size_t k;
27546 -                       
27547 -                       /* it matched */
27548 -                       pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
27549 -                       
27550 -                       /* search for $[0-9] */
27551 -                       
27552 -                       buffer_reset(p->location);
27553 -                       
27554 -                       start = 0; end = pattern_len;
27555 -                       for (k = 0; k < pattern_len; k++) {
27556 -                               if ((pattern[k] == '$' || pattern[k] == '%') &&
27557 -                                   isdigit((unsigned char)pattern[k + 1])) {
27558 -                                       /* got one */
27559 -                                       
27560 -                                       size_t num = pattern[k + 1] - '0';
27561 -                                       
27562 -                                       end = k;
27563 -                                       
27564 -                                       buffer_append_string_len(p->location, pattern + start, end - start);
27565 -                                       
27566 -                                       if (pattern[k] == '$') {
27567 -                                               /* n is always > 0 */
27568 -                                               if (num < (size_t)n) {
27569 -                                                       buffer_append_string(p->location, list[num]);
27570 -                                               }
27571 -                                       } else {
27572 -                                               config_append_cond_match_buffer(con, p->conf.context, p->location, num);
27573 -                                       }
27574 -                                       
27575 -                                       k++;
27576 -                                       start = k + 1;
27577 -                               } 
27578 -                       }
27579 -                       
27580 -                       buffer_append_string_len(p->location, pattern + start, pattern_len - start);
27581 -                       
27582 -                       pcre_free(list);
27583 -                       
27584 -                       response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27585 -                       
27586 -                       con->http_status = 301;
27587 -                       con->file_finished = 1;
27588 -                       
27589 -                       return HANDLER_FINISHED;
27590 -               }
27591 +       i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
27592 +
27593 +       if (i >= 0) {
27594 +               response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27595 +
27596 +               con->http_status = 301;
27597 +               con->file_finished = 1;
27598 +
27599 +               return HANDLER_FINISHED;
27600 +       }
27601 +       else if (i != PCRE_ERROR_NOMATCH) {
27602 +               log_error_write(srv, __FILE__, __LINE__, "s",
27603 +                               "execution error while matching", i);
27604         }
27605  #undef N
27606 -               
27607 +
27608  #else
27609         UNUSED(srv);
27610         UNUSED(con);
27611         UNUSED(p_data);
27612  #endif
27613 -       
27614 +
27615         return HANDLER_GO_ON;
27616  }
27617  
27618 @@ -265,13 +207,13 @@
27619  int mod_redirect_plugin_init(plugin *p) {
27620         p->version     = LIGHTTPD_VERSION_ID;
27621         p->name        = buffer_init_string("redirect");
27622 -       
27623 +
27624         p->init        = mod_redirect_init;
27625         p->handle_uri_clean  = mod_redirect_uri_handler;
27626         p->set_defaults  = mod_redirect_set_defaults;
27627         p->cleanup     = mod_redirect_free;
27628 -       
27629 +
27630         p->data        = NULL;
27631 -       
27632 +
27633         return 0;
27634  }
27635 --- ../lighttpd-1.4.11/src/mod_rewrite.c        2005-09-29 20:59:10.000000000 +0300
27636 +++ lighttpd-1.4.12/src/mod_rewrite.c   2006-07-11 22:07:51.000000000 +0300
27637 @@ -13,24 +13,8 @@
27638  #endif
27639  
27640  typedef struct {
27641 -#ifdef HAVE_PCRE_H
27642 -       pcre *key;
27643 -#endif
27644 -       
27645 -       buffer *value;
27646 -       
27647 -       int once;
27648 -} rewrite_rule;
27649 -
27650 -typedef struct {
27651 -       rewrite_rule **ptr;
27652 -       
27653 -       size_t used;
27654 -       size_t size;
27655 -} rewrite_rule_buffer;
27656 -
27657 -typedef struct {
27658 -       rewrite_rule_buffer *rewrite;
27659 +       pcre_keyvalue_buffer *rewrite;
27660 +       buffer *once;
27661         data_config *context; /* to which apply me */
27662  } plugin_config;
27663  
27664 @@ -42,20 +26,20 @@
27665  typedef struct {
27666         PLUGIN_DATA;
27667         buffer *match_buf;
27668 -       
27669 +
27670         plugin_config **config_storage;
27671 -       
27672 -       plugin_config conf; 
27673 +
27674 +       plugin_config conf;
27675  } plugin_data;
27676  
27677  static handler_ctx * handler_ctx_init() {
27678         handler_ctx * hctx;
27679 -       
27680 +
27681         hctx = calloc(1, sizeof(*hctx));
27682 -       
27683 +
27684         hctx->state = REWRITE_STATE_UNSET;
27685         hctx->loops = 0;
27686 -       
27687 +
27688         return hctx;
27689  }
27690  
27691 @@ -63,207 +47,136 @@
27692         free(hctx);
27693  }
27694  
27695 -rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
27696 -       rewrite_rule_buffer *kvb;
27697 -       
27698 -       kvb = calloc(1, sizeof(*kvb));
27699 -       
27700 -       return kvb;
27701 -}
27702 -
27703 -int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
27704 -#ifdef HAVE_PCRE_H
27705 -       size_t i;
27706 -       const char *errptr;
27707 -       int erroff;
27708 -       
27709 -       if (!key) return -1;
27710 -
27711 -       if (kvb->size == 0) {
27712 -               kvb->size = 4;
27713 -               kvb->used = 0;
27714 -               
27715 -               kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
27716 -               
27717 -               for(i = 0; i < kvb->size; i++) {
27718 -                       kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27719 -               }
27720 -       } else if (kvb->used == kvb->size) {
27721 -               kvb->size += 4;
27722 -               
27723 -               kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
27724 -               
27725 -               for(i = kvb->used; i < kvb->size; i++) {
27726 -                       kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27727 -               }
27728 -       }
27729 -       
27730 -       if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
27731 -                                                           0, &errptr, &erroff, NULL))) {
27732 -               
27733 -               return -1;
27734 -       }
27735 -       
27736 -       kvb->ptr[kvb->used]->value = buffer_init();
27737 -       buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
27738 -       kvb->ptr[kvb->used]->once = once;
27739 -       
27740 -       kvb->used++;
27741 -       
27742 -       return 0;
27743 -#else
27744 -       UNUSED(kvb);
27745 -       UNUSED(value);
27746 -       UNUSED(once);
27747 -       UNUSED(key);
27748 -
27749 -       return -1;
27750 -#endif
27751 -}
27752 -
27753 -void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
27754 -#ifdef HAVE_PCRE_H
27755 -       size_t i;
27756 -
27757 -       for (i = 0; i < kvb->size; i++) {
27758 -               if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
27759 -               if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
27760 -               free(kvb->ptr[i]);
27761 -       }
27762 -       
27763 -       if (kvb->ptr) free(kvb->ptr);
27764 -#endif
27765 -       
27766 -       free(kvb);
27767 -}
27768 -
27769  
27770  INIT_FUNC(mod_rewrite_init) {
27771         plugin_data *p;
27772 -       
27773 +
27774         p = calloc(1, sizeof(*p));
27775 -       
27776 +
27777         p->match_buf = buffer_init();
27778 -       
27779 +
27780         return p;
27781  }
27782  
27783  FREE_FUNC(mod_rewrite_free) {
27784         plugin_data *p = p_d;
27785 -       
27786 +
27787         UNUSED(srv);
27788  
27789         if (!p) return HANDLER_GO_ON;
27790 -       
27791 +
27792         buffer_free(p->match_buf);
27793         if (p->config_storage) {
27794                 size_t i;
27795                 for (i = 0; i < srv->config_context->used; i++) {
27796                         plugin_config *s = p->config_storage[i];
27797 -                       rewrite_rule_buffer_free(s->rewrite);
27798 -                       
27799 +                       pcre_keyvalue_buffer_free(s->rewrite);
27800 +                       buffer_free(s->once);
27801 +
27802                         free(s);
27803                 }
27804                 free(p->config_storage);
27805         }
27806 -       
27807 +
27808         free(p);
27809 -       
27810 +
27811         return HANDLER_GO_ON;
27812  }
27813  
27814  static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
27815         data_unset *du;
27816 -       
27817 +
27818         if (NULL != (du = array_get_element(ca, option))) {
27819                 data_array *da = (data_array *)du;
27820                 size_t j;
27821 -               
27822 +
27823                 if (du->type != TYPE_ARRAY) {
27824 -                       log_error_write(srv, __FILE__, __LINE__, "sss", 
27825 +                       log_error_write(srv, __FILE__, __LINE__, "sss",
27826                                         "unexpected type for key: ", option, "array of strings");
27827 -                       
27828 +
27829                         return HANDLER_ERROR;
27830                 }
27831 -               
27832 +
27833                 da = (data_array *)du;
27834 -               
27835 +
27836                 for (j = 0; j < da->value->used; j++) {
27837                         if (da->value->data[j]->type != TYPE_STRING) {
27838 -                               log_error_write(srv, __FILE__, __LINE__, "sssbs", 
27839 -                                               "unexpected type for key: ", 
27840 -                                               option, 
27841 +                               log_error_write(srv, __FILE__, __LINE__, "sssbs",
27842 +                                               "unexpected type for key: ",
27843 +                                               option,
27844                                                 "[", da->value->data[j]->key, "](string)");
27845 -                               
27846 +
27847                                 return HANDLER_ERROR;
27848                         }
27849 -                       
27850 -                       if (0 != rewrite_rule_buffer_append(s->rewrite, 
27851 -                                                           ((data_string *)(da->value->data[j]))->key,
27852 -                                                           ((data_string *)(da->value->data[j]))->value,
27853 -                                                           once)) {
27854 +
27855 +                       if (0 != pcre_keyvalue_buffer_append(s->rewrite,
27856 +                                                           ((data_string *)(da->value->data[j]))->key->ptr,
27857 +                                                           ((data_string *)(da->value->data[j]))->value->ptr)) {
27858  #ifdef HAVE_PCRE_H
27859 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
27860 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
27861                                                 "pcre-compile failed for", da->value->data[j]->key);
27862  #else
27863 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
27864 +                               log_error_write(srv, __FILE__, __LINE__, "s",
27865                                                 "pcre support is missing, please install libpcre and the headers");
27866  #endif
27867                         }
27868 +
27869 +                       if (once) {
27870 +                               buffer_append_string_len(s->once, CONST_STR_LEN("1"));
27871 +                       } else {
27872 +                               buffer_append_string_len(s->once, CONST_STR_LEN("0"));
27873 +                       }
27874                 }
27875         }
27876 -       
27877 +
27878         return 0;
27879  }
27880  
27881  SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
27882         plugin_data *p = p_d;
27883         size_t i = 0;
27884 -       
27885 -       config_values_t cv[] = { 
27886 +
27887 +       config_values_t cv[] = {
27888                 { "url.rewrite-repeat",        NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27889                 { "url.rewrite-once",          NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
27890 -               
27891 -               /* old names, still supported 
27892 -                * 
27893 +
27894 +               /* old names, still supported
27895 +                *
27896                  * url.rewrite remapped to url.rewrite-once
27897                  * url.rewrite-final    is url.rewrite-once
27898 -                * 
27899 +                *
27900                  */
27901                 { "url.rewrite",               NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
27902                 { "url.rewrite-final",         NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
27903                 { NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27904         };
27905 -       
27906 +
27907         if (!p) return HANDLER_ERROR;
27908 -       
27909 +
27910         /* 0 */
27911         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27912 -       
27913 +
27914         for (i = 0; i < srv->config_context->used; i++) {
27915                 plugin_config *s;
27916                 array *ca;
27917 -               
27918 +
27919                 s = calloc(1, sizeof(plugin_config));
27920 -               s->rewrite   = rewrite_rule_buffer_init();
27921 -               
27922 -               cv[0].destination = s->rewrite;
27923 -               cv[1].destination = s->rewrite;
27924 -               cv[2].destination = s->rewrite;
27925 -               
27926 +               s->rewrite   = pcre_keyvalue_buffer_init();
27927 +               s->once      = buffer_init();
27928 +
27929                 p->config_storage[i] = s;
27930                 ca = ((data_config *)srv->config_context->data[i])->value;
27931 -       
27932 +
27933                 if (0 != config_insert_values_global(srv, ca, cv)) {
27934                         return HANDLER_ERROR;
27935                 }
27936 -               
27937 +
27938                 parse_config_entry(srv, s, ca, "url.rewrite-once",   1);
27939                 parse_config_entry(srv, s, ca, "url.rewrite-final",  1);
27940                 parse_config_entry(srv, s, ca, "url.rewrite",        1);
27941                 parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
27942         }
27943 -       
27944 +
27945         return HANDLER_GO_ON;
27946  }
27947  #ifdef HAVE_PCRE_H
27948 @@ -271,157 +184,107 @@
27949         size_t i, j;
27950         plugin_config *s = p->config_storage[0];
27951         p->conf.rewrite = s->rewrite;
27952 -       
27953 +       p->conf.once    = s->once;
27954 +
27955         /* skip the first, the global context */
27956         for (i = 1; i < srv->config_context->used; i++) {
27957                 data_config *dc = (data_config *)srv->config_context->data[i];
27958                 s = p->config_storage[i];
27959 -               
27960 +
27961                 if (COMP_HTTP_URL == dc->comp) continue;
27962 -               
27963 +
27964                 /* condition didn't match */
27965                 if (!config_check_cond(srv, con, dc)) continue;
27966 -               
27967 +
27968                 /* merge config */
27969                 for (j = 0; j < dc->value->used; j++) {
27970                         data_unset *du = dc->value->data[j];
27971 -                       
27972 +
27973                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
27974                                 p->conf.rewrite = s->rewrite;
27975 +                               p->conf.once    = s->once;
27976                                 p->conf.context = dc;
27977                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
27978                                 p->conf.rewrite = s->rewrite;
27979 +                               p->conf.once    = s->once;
27980                                 p->conf.context = dc;
27981                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
27982                                 p->conf.rewrite = s->rewrite;
27983 +                               p->conf.once    = s->once;
27984                                 p->conf.context = dc;
27985                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
27986                                 p->conf.rewrite = s->rewrite;
27987 +                               p->conf.once    = s->once;
27988                                 p->conf.context = dc;
27989                         }
27990                 }
27991         }
27992 -       
27993 +
27994         return 0;
27995  }
27996  #endif
27997  URIHANDLER_FUNC(mod_rewrite_con_reset) {
27998         plugin_data *p = p_d;
27999 -       
28000 +
28001         UNUSED(srv);
28002 -       
28003 +
28004         if (con->plugin_ctx[p->id]) {
28005                 handler_ctx_free(con->plugin_ctx[p->id]);
28006                 con->plugin_ctx[p->id] = NULL;
28007         }
28008 -       
28009 +
28010         return HANDLER_GO_ON;
28011  }
28012  
28013  URIHANDLER_FUNC(mod_rewrite_uri_handler) {
28014  #ifdef HAVE_PCRE_H
28015         plugin_data *p = p_d;
28016 -       size_t i;
28017 +       int i;
28018         handler_ctx *hctx;
28019  
28020 -       /* 
28021 +       /*
28022          * REWRITE URL
28023 -        * 
28024 +        *
28025          * e.g. rewrite /base/ to /index.php?section=base
28026 -        * 
28027 +        *
28028          */
28029 -       
28030 +
28031         if (con->plugin_ctx[p->id]) {
28032                 hctx = con->plugin_ctx[p->id];
28033 -               
28034 +
28035                 if (hctx->loops++ > 100) {
28036 -                       log_error_write(srv, __FILE__, __LINE__,  "s",  
28037 +                       log_error_write(srv, __FILE__, __LINE__,  "s",
28038                                         "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
28039 -                       
28040 +
28041                         return HANDLER_ERROR;
28042                 }
28043 -               
28044 +
28045                 if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
28046         }
28047 -       
28048 +
28049         mod_rewrite_patch_connection(srv, con, p);
28050  
28051         if (!p->conf.rewrite) return HANDLER_GO_ON;
28052 -       
28053 +
28054         buffer_copy_string_buffer(p->match_buf, con->request.uri);
28055 -       
28056 -       for (i = 0; i < p->conf.rewrite->used; i++) {
28057 -               pcre *match;
28058 -               const char *pattern;
28059 -               size_t pattern_len;
28060 -               int n;
28061 -               rewrite_rule *rule = p->conf.rewrite->ptr[i];
28062 -# define N 10
28063 -               int ovec[N * 3];
28064 -               
28065 -               match       = rule->key;
28066 -               pattern     = rule->value->ptr;
28067 -               pattern_len = rule->value->used - 1;
28068 -               
28069 -               if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
28070 -                       if (n != PCRE_ERROR_NOMATCH) {
28071 -                               log_error_write(srv, __FILE__, __LINE__, "sd",
28072 -                                               "execution error while matching: ", n);
28073 -                               return HANDLER_ERROR;
28074 -                       }
28075 -               } else {
28076 -                       const char **list;
28077 -                       size_t start, end;
28078 -                       size_t k;
28079 -                       
28080 -                       /* it matched */
28081 -                       pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
28082 -                       
28083 -                       /* search for $[0-9] */
28084 -                       
28085 -                       buffer_reset(con->request.uri);
28086 -                       
28087 -                       start = 0; end = pattern_len;
28088 -                       for (k = 0; k < pattern_len; k++) {
28089 -                               if ((pattern[k] == '$' || pattern[k] == '%') &&
28090 -                                   isdigit((unsigned char)pattern[k + 1])) {
28091 -                                       /* got one */
28092 -                                       
28093 -                                       size_t num = pattern[k + 1] - '0';
28094 -                                       
28095 -                                       end = k;
28096 -                                       
28097 -                                       buffer_append_string_len(con->request.uri, pattern + start, end - start);
28098 -                                       
28099 -                                       if (pattern[k] == '$') {
28100 -                                               /* n is always > 0 */
28101 -                                               if (num < (size_t)n) {
28102 -                                                       buffer_append_string(con->request.uri, list[num]);
28103 -                                               }
28104 -                                       } else {
28105 -                                               config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
28106 -                                       }
28107 -                                       
28108 -                                       k++;
28109 -                                       start = k + 1;
28110 -                               } 
28111 -                       }
28112 -                       
28113 -                       buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
28114 -                       
28115 -                       pcre_free(list);
28116 -                       
28117 -                       hctx = handler_ctx_init();
28118 -                               
28119 -                       con->plugin_ctx[p->id] = hctx;
28120 -                       
28121 -                       if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
28122 -                       
28123 -                       return HANDLER_COMEBACK;
28124 -               }
28125 +       i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
28126 +
28127 +       if (i >= 0) {
28128 +               hctx = handler_ctx_init();
28129 +
28130 +               con->plugin_ctx[p->id] = hctx;
28131 +
28132 +               if (p->conf.once->ptr[i] == '1')
28133 +                       hctx->state = REWRITE_STATE_FINISHED;
28134 +
28135 +               return HANDLER_COMEBACK;
28136 +       }
28137 +       else if (i != PCRE_ERROR_NOMATCH) {
28138 +               log_error_write(srv, __FILE__, __LINE__, "s",
28139 +                               "execution error while matching", i);
28140         }
28141  #undef N
28142 -               
28143 +
28144  #else
28145         UNUSED(srv);
28146         UNUSED(con);
28147 @@ -434,17 +297,17 @@
28148  int mod_rewrite_plugin_init(plugin *p) {
28149         p->version     = LIGHTTPD_VERSION_ID;
28150         p->name        = buffer_init_string("rewrite");
28151 -       
28152 +
28153         p->init        = mod_rewrite_init;
28154         /* it has to stay _raw as we are matching on uri + querystring
28155          */
28156 -       
28157 +
28158         p->handle_uri_raw = mod_rewrite_uri_handler;
28159         p->set_defaults = mod_rewrite_set_defaults;
28160         p->cleanup     = mod_rewrite_free;
28161         p->connection_reset = mod_rewrite_con_reset;
28162 -       
28163 +
28164         p->data        = NULL;
28165 -       
28166 +
28167         return 0;
28168  }
28169 --- ../lighttpd-1.4.11/src/mod_rrdtool.c        2005-08-22 01:52:24.000000000 +0300
28170 +++ lighttpd-1.4.12/src/mod_rrdtool.c   2006-07-11 22:07:52.000000000 +0300
28171 @@ -5,7 +5,6 @@
28172  #include <stdlib.h>
28173  #include <stdio.h>
28174  #include <string.h>
28175 -#include <unistd.h>
28176  #include <errno.h>
28177  #include <time.h>
28178  
28179 @@ -20,10 +19,14 @@
28180  /* no need for waitpid if we don't have fork */
28181  #include <sys/wait.h>
28182  #endif
28183 +
28184 +#include "sys-files.h"
28185 +#include "sys-process.h"
28186 +
28187  typedef struct {
28188         buffer *path_rrdtool_bin;
28189         buffer *path_rrd;
28190 -       
28191 +
28192         double requests, *requests_ptr;
28193         double bytes_written, *bytes_written_ptr;
28194         double bytes_read, *bytes_read_ptr;
28195 @@ -31,84 +34,84 @@
28196  
28197  typedef struct {
28198         PLUGIN_DATA;
28199 -       
28200 +
28201         buffer *cmd;
28202         buffer *resp;
28203 -       
28204 +
28205         int read_fd, write_fd;
28206         pid_t rrdtool_pid;
28207 -       
28208 +
28209         int rrdtool_running;
28210 -       
28211 +
28212         plugin_config **config_storage;
28213         plugin_config conf;
28214  } plugin_data;
28215  
28216  INIT_FUNC(mod_rrd_init) {
28217         plugin_data *p;
28218 -       
28219 +
28220         p = calloc(1, sizeof(*p));
28221 -       
28222 +
28223         p->resp = buffer_init();
28224         p->cmd = buffer_init();
28225 -       
28226 +
28227         return p;
28228  }
28229  
28230  FREE_FUNC(mod_rrd_free) {
28231         plugin_data *p = p_d;
28232         size_t i;
28233 -       
28234 +
28235         if (!p) return HANDLER_GO_ON;
28236 -       
28237 +
28238         if (p->config_storage) {
28239                 for (i = 0; i < srv->config_context->used; i++) {
28240                         plugin_config *s = p->config_storage[i];
28241 -                       
28242 +
28243                         buffer_free(s->path_rrdtool_bin);
28244                         buffer_free(s->path_rrd);
28245 -                       
28246 +
28247                         free(s);
28248                 }
28249         }
28250         buffer_free(p->cmd);
28251         buffer_free(p->resp);
28252 -       
28253 +
28254         free(p->config_storage);
28255 -       
28256 +
28257         if (p->rrdtool_pid) {
28258                 int status;
28259                 close(p->read_fd);
28260                 close(p->write_fd);
28261 -#ifdef HAVE_FORK       
28262 +#ifdef HAVE_FORK
28263                 /* collect status */
28264                 waitpid(p->rrdtool_pid, &status, 0);
28265  #endif
28266         }
28267 -       
28268 +
28269         free(p);
28270 -       
28271 +
28272         return HANDLER_GO_ON;
28273  }
28274  
28275  int mod_rrd_create_pipe(server *srv, plugin_data *p) {
28276         pid_t pid;
28277 -       
28278 +
28279         int to_rrdtool_fds[2];
28280         int from_rrdtool_fds[2];
28281 -#ifdef HAVE_FORK       
28282 +#ifdef HAVE_FORK
28283         if (pipe(to_rrdtool_fds)) {
28284 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
28285 +               log_error_write(srv, __FILE__, __LINE__, "ss",
28286                                 "pipe failed: ", strerror(errno));
28287                 return -1;
28288         }
28289 -       
28290 +
28291         if (pipe(from_rrdtool_fds)) {
28292 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
28293 +               log_error_write(srv, __FILE__, __LINE__, "ss",
28294                                 "pipe failed: ", strerror(errno));
28295                 return -1;
28296         }
28297 -       
28298 +
28299         /* fork, execve */
28300         switch (pid = fork()) {
28301         case 0: {
28302 @@ -117,33 +120,33 @@
28303                 int argc;
28304                 int i = 0;
28305                 char *dash = "-";
28306 -               
28307 +
28308                 /* move stdout to from_rrdtool_fd[1] */
28309                 close(STDOUT_FILENO);
28310                 dup2(from_rrdtool_fds[1], STDOUT_FILENO);
28311                 close(from_rrdtool_fds[1]);
28312                 /* not needed */
28313                 close(from_rrdtool_fds[0]);
28314 -               
28315 +
28316                 /* move the stdin to to_rrdtool_fd[0] */
28317                 close(STDIN_FILENO);
28318                 dup2(to_rrdtool_fds[0], STDIN_FILENO);
28319                 close(to_rrdtool_fds[0]);
28320                 /* not needed */
28321                 close(to_rrdtool_fds[1]);
28322 -               
28323 +
28324                 close(STDERR_FILENO);
28325 -               
28326 +
28327                 if (srv->errorlog_mode == ERRORLOG_FILE) {
28328                         dup2(srv->errorlog_fd, STDERR_FILENO);
28329                         close(srv->errorlog_fd);
28330                 }
28331 -               
28332 +
28333                 /* set up args */
28334                 argc = 3;
28335                 args = malloc(sizeof(*args) * argc);
28336                 i = 0;
28337 -               
28338 +
28339                 args[i++] = p->conf.path_rrdtool_bin->ptr;
28340                 args[i++] = dash;
28341                 args[i++] = NULL;
28342 @@ -152,12 +155,12 @@
28343                 for (i = 3; i < 256; i++) {
28344                         close(i);
28345                 }
28346 -               
28347 +
28348                 /* exec the cgi */
28349                 execv(args[0], args);
28350 -               
28351 +
28352                 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
28353 -               
28354 +
28355                 /* */
28356                 SEGFAULT();
28357                 break;
28358 @@ -168,19 +171,19 @@
28359                 break;
28360         default: {
28361                 /* father */
28362 -               
28363 +
28364                 close(from_rrdtool_fds[1]);
28365                 close(to_rrdtool_fds[0]);
28366 -               
28367 +
28368                 /* register PID and wait for them asyncronously */
28369                 p->write_fd = to_rrdtool_fds[1];
28370                 p->read_fd = from_rrdtool_fds[0];
28371                 p->rrdtool_pid = pid;
28372 -               
28373 +
28374                 break;
28375         }
28376         }
28377 -       
28378 +
28379         return 0;
28380  #else
28381         return -1;
28382 @@ -189,19 +192,19 @@
28383  
28384  static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
28385         struct stat st;
28386 -       
28387 +
28388         /* check if DB already exists */
28389         if (0 == stat(s->path_rrd->ptr, &st)) {
28390                 /* check if it is plain file */
28391                 if (!S_ISREG(st.st_mode)) {
28392 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
28393 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
28394                                         "not a regular file:", s->path_rrd);
28395                         return HANDLER_ERROR;
28396                 }
28397         } else {
28398                 int r ;
28399                 /* create a new one */
28400 -               
28401 +
28402                 BUFFER_COPY_STRING_CONST(p->cmd, "create ");
28403                 buffer_append_string_buffer(p->cmd, s->path_rrd);
28404                 buffer_append_string(p->cmd, " --step 60 ");
28405 @@ -220,158 +223,155 @@
28406                 buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
28407                 buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
28408                 buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
28409 -               
28410 +
28411                 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28412 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28413 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28414                                 "rrdtool-write: failed", strerror(errno));
28415 -                       
28416 +
28417                         return HANDLER_ERROR;
28418                 }
28419 -               
28420 +
28421                 buffer_prepare_copy(p->resp, 4096);
28422                 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28423 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28424 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28425                                 "rrdtool-read: failed", strerror(errno));
28426 -                       
28427 +
28428                         return HANDLER_ERROR;
28429                 }
28430 -               
28431 +
28432                 p->resp->used = r;
28433 -               
28434 +
28435                 if (p->resp->ptr[0] != 'O' ||
28436                     p->resp->ptr[1] != 'K') {
28437 -                       log_error_write(srv, __FILE__, __LINE__, "sbb", 
28438 +                       log_error_write(srv, __FILE__, __LINE__, "sbb",
28439                                 "rrdtool-response:", p->cmd, p->resp);
28440 -                       
28441 +
28442                         return HANDLER_ERROR;
28443                 }
28444         }
28445 -       
28446 +
28447         return HANDLER_GO_ON;
28448  }
28449  
28450 -#define PATCH(x) \
28451 -       p->conf.x = s->x;
28452  static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
28453         size_t i, j;
28454         plugin_config *s = p->config_storage[0];
28455 -       
28456 -       PATCH(path_rrdtool_bin);
28457 -       PATCH(path_rrd);
28458 -       
28459 +
28460 +       PATCH_OPTION(path_rrdtool_bin);
28461 +       PATCH_OPTION(path_rrd);
28462 +
28463         p->conf.bytes_written_ptr = &(s->bytes_written);
28464         p->conf.bytes_read_ptr = &(s->bytes_read);
28465         p->conf.requests_ptr = &(s->requests);
28466 -       
28467 +
28468         /* skip the first, the global context */
28469         for (i = 1; i < srv->config_context->used; i++) {
28470                 data_config *dc = (data_config *)srv->config_context->data[i];
28471                 s = p->config_storage[i];
28472 -               
28473 +
28474                 /* condition didn't match */
28475                 if (!config_check_cond(srv, con, dc)) continue;
28476 -               
28477 +
28478                 /* merge config */
28479                 for (j = 0; j < dc->value->used; j++) {
28480                         data_unset *du = dc->value->data[j];
28481 -                       
28482 +
28483                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
28484 -                               PATCH(path_rrd);
28485 +                               PATCH_OPTION(path_rrd);
28486                                 /* get pointers to double values */
28487 -                               
28488 +
28489                                 p->conf.bytes_written_ptr = &(s->bytes_written);
28490                                 p->conf.bytes_read_ptr = &(s->bytes_read);
28491                                 p->conf.requests_ptr = &(s->requests);
28492                         }
28493                 }
28494         }
28495 -       
28496 +
28497         return 0;
28498  }
28499 -#undef PATCH
28500  
28501  SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
28502         plugin_data *p = p_d;
28503         size_t i;
28504 -       
28505 -       config_values_t cv[] = { 
28506 +
28507 +       config_values_t cv[] = {
28508                 { "rrdtool.binary",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
28509                 { "rrdtool.db-name",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
28510                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
28511         };
28512 -       
28513 +
28514         if (!p) return HANDLER_ERROR;
28515 -       
28516 +
28517         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28518 -       
28519 +
28520         for (i = 0; i < srv->config_context->used; i++) {
28521                 plugin_config *s;
28522 -               
28523 +
28524                 s = calloc(1, sizeof(plugin_config));
28525                 s->path_rrdtool_bin = buffer_init();
28526                 s->path_rrd = buffer_init();
28527                 s->requests = 0;
28528                 s->bytes_written = 0;
28529                 s->bytes_read = 0;
28530 -               
28531 +
28532                 cv[0].destination = s->path_rrdtool_bin;
28533                 cv[1].destination = s->path_rrd;
28534 -               
28535 +
28536                 p->config_storage[i] = s;
28537 -       
28538 +
28539                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
28540                         return HANDLER_ERROR;
28541                 }
28542 -               
28543 +
28544                 if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
28545                         /* path_rrdtool_bin is a global option */
28546 -                       
28547 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
28548 +
28549 +                       log_error_write(srv, __FILE__, __LINE__, "s",
28550                                         "rrdtool.binary can only be set as a global option.");
28551 -                       
28552 +
28553                         return HANDLER_ERROR;
28554                 }
28555 -               
28556 +
28557         }
28558 -       
28559 +
28560         p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
28561         p->rrdtool_running = 0;
28562 -       
28563 +
28564         /* check for dir */
28565 -       
28566 +
28567         if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
28568 -               log_error_write(srv, __FILE__, __LINE__, "s", 
28569 +               log_error_write(srv, __FILE__, __LINE__, "s",
28570                                 "rrdtool.binary has to be set");
28571                 return HANDLER_ERROR;
28572         }
28573 -       
28574 +
28575         /* open the pipe to rrdtool */
28576         if (mod_rrd_create_pipe(srv, p)) {
28577                 return HANDLER_ERROR;
28578         }
28579 -       
28580 +
28581         p->rrdtool_running = 1;
28582 -               
28583 +
28584         return HANDLER_GO_ON;
28585  }
28586  
28587  TRIGGER_FUNC(mod_rrd_trigger) {
28588         plugin_data *p = p_d;
28589         size_t i;
28590 -       
28591 +
28592         if (!p->rrdtool_running) return HANDLER_GO_ON;
28593         if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
28594 -       
28595 +
28596         for (i = 0; i < srv->config_context->used; i++) {
28597                 plugin_config *s = p->config_storage[i];
28598                 int r;
28599 -               
28600 +
28601                 if (buffer_is_empty(s->path_rrd)) continue;
28602 -       
28603 +
28604                 /* write the data down every minute */
28605 -               
28606 +
28607                 if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
28608 -               
28609 +
28610                 BUFFER_COPY_STRING_CONST(p->cmd, "update ");
28611                 buffer_append_string_buffer(p->cmd, s->path_rrd);
28612                 BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
28613 @@ -381,69 +381,69 @@
28614                 BUFFER_APPEND_STRING_CONST(p->cmd, ":");
28615                 buffer_append_long(p->cmd, s->requests);
28616                 BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
28617 -               
28618 +
28619                 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28620                         p->rrdtool_running = 0;
28621 -                       
28622 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28623 +
28624 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28625                                         "rrdtool-write: failed", strerror(errno));
28626 -                       
28627 +
28628                         return HANDLER_ERROR;
28629                 }
28630 -               
28631 +
28632                 buffer_prepare_copy(p->resp, 4096);
28633                 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28634                         p->rrdtool_running = 0;
28635 -                       
28636 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28637 +
28638 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28639                                         "rrdtool-read: failed", strerror(errno));
28640 -                       
28641 +
28642                         return HANDLER_ERROR;
28643                 }
28644 -               
28645 +
28646                 p->resp->used = r;
28647 -               
28648 +
28649                 if (p->resp->ptr[0] != 'O' ||
28650                     p->resp->ptr[1] != 'K') {
28651                         p->rrdtool_running = 0;
28652 -                       
28653 -                       log_error_write(srv, __FILE__, __LINE__, "sbb", 
28654 +
28655 +                       log_error_write(srv, __FILE__, __LINE__, "sbb",
28656                                         "rrdtool-response:", p->cmd, p->resp);
28657 -                       
28658 +
28659                         return HANDLER_ERROR;
28660                 }
28661                 s->requests = 0;
28662                 s->bytes_written = 0;
28663                 s->bytes_read = 0;
28664         }
28665 -       
28666 +
28667         return HANDLER_GO_ON;
28668  }
28669  
28670  REQUESTDONE_FUNC(mod_rrd_account) {
28671         plugin_data *p = p_d;
28672 -       
28673 +
28674         mod_rrd_patch_connection(srv, con, p);
28675 -       
28676 +
28677         *(p->conf.requests_ptr)      += 1;
28678         *(p->conf.bytes_written_ptr) += con->bytes_written;
28679         *(p->conf.bytes_read_ptr)    += con->bytes_read;
28680 -       
28681 +
28682         return HANDLER_GO_ON;
28683  }
28684  
28685  int mod_rrdtool_plugin_init(plugin *p) {
28686         p->version     = LIGHTTPD_VERSION_ID;
28687         p->name        = buffer_init_string("rrd");
28688 -       
28689 +
28690         p->init        = mod_rrd_init;
28691         p->cleanup     = mod_rrd_free;
28692         p->set_defaults= mod_rrd_set_defaults;
28693 -       
28694 +
28695         p->handle_trigger      = mod_rrd_trigger;
28696         p->handle_request_done = mod_rrd_account;
28697 -       
28698 +
28699         p->data        = NULL;
28700 -       
28701 +
28702         return 0;
28703  }
28704 --- ../lighttpd-1.4.11/src/mod_scgi.c   2006-03-04 17:15:26.000000000 +0200
28705 +++ lighttpd-1.4.12/src/mod_scgi.c      2006-07-11 22:07:51.000000000 +0300
28706 @@ -1,5 +1,4 @@
28707  #include <sys/types.h>
28708 -#include <unistd.h>
28709  #include <errno.h>
28710  #include <fcntl.h>
28711  #include <string.h>
28712 @@ -30,7 +29,9 @@
28713  #endif
28714  
28715  #include "sys-socket.h"
28716 -
28717 +#include "sys-files.h"
28718 +#include "sys-strings.h"
28719 +#include "sys-process.h"
28720  
28721  #ifndef UNIX_PATH_MAX
28722  # define UNIX_PATH_MAX 108
28723 @@ -46,30 +47,29 @@
28724  enum {EOL_UNSET, EOL_N, EOL_RN};
28725  
28726  /*
28727 - * 
28728 + *
28729   * TODO:
28730 - * 
28731 + *
28732   * - add timeout for a connect to a non-scgi process
28733   *   (use state_timestamp + state)
28734 - * 
28735 + *
28736   */
28737  
28738  typedef struct scgi_proc {
28739         size_t id; /* id will be between 1 and max_procs */
28740         buffer *socket; /* config.socket + "-" + id */
28741         unsigned port;  /* config.port + pno */
28742 -       
28743 -       pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
28744  
28745 +       pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
28746  
28747         size_t load; /* number of requests waiting on this process */
28748  
28749         time_t last_used; /* see idle_timeout */
28750         size_t requests;  /* see max_requests */
28751         struct scgi_proc *prev, *next; /* see first */
28752 -       
28753 +
28754         time_t disable_ts; /* replace by host->something */
28755 -       
28756 +
28757         int is_local;
28758  
28759         enum { PROC_STATE_UNSET,            /* init-phase */
28760 @@ -78,7 +78,7 @@
28761                         PROC_STATE_KILLED,  /* was killed as we don't have the load anymore */
28762                         PROC_STATE_DIED,    /* marked as dead, should be restarted */
28763                         PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
28764 -       } state; 
28765 +       } state;
28766  } scgi_proc;
28767  
28768  typedef struct {
28769 @@ -86,20 +86,20 @@
28770          * sorted by lowest load
28771          *
28772          * whenever a job is done move it up in the list
28773 -        * until it is sorted, move it down as soon as the 
28774 +        * until it is sorted, move it down as soon as the
28775          * job is started
28776          */
28777 -       scgi_proc *first; 
28778 -       scgi_proc *unused_procs; 
28779 +       scgi_proc *first;
28780 +       scgi_proc *unused_procs;
28781  
28782 -       /* 
28783 +       /*
28784          * spawn at least min_procs, at max_procs.
28785          *
28786 -        * as soon as the load of the first entry 
28787 +        * as soon as the load of the first entry
28788          * is max_load_per_proc we spawn a new one
28789 -        * and add it to the first entry and give it 
28790 +        * and add it to the first entry and give it
28791          * the load
28792 -        * 
28793 +        *
28794          */
28795  
28796         unsigned short min_procs;
28797 @@ -111,44 +111,44 @@
28798  
28799         /*
28800          * kick the process from the list if it was not
28801 -        * used for idle_timeout until min_procs is 
28802 +        * used for idle_timeout until min_procs is
28803          * reached. this helps to get the processlist
28804          * small again we had a small peak load.
28805          *
28806          */
28807 -       
28808 +
28809         unsigned short idle_timeout;
28810 -       
28811 +
28812         /*
28813          * time after a disabled remote connection is tried to be re-enabled
28814 -        * 
28815 -        * 
28816 +        *
28817 +        *
28818          */
28819 -       
28820 +
28821         unsigned short disable_time;
28822  
28823         /*
28824          * same scgi processes get a little bit larger
28825 -        * than wanted. max_requests_per_proc kills a 
28826 +        * than wanted. max_requests_per_proc kills a
28827          * process after a number of handled requests.
28828          *
28829          */
28830         size_t max_requests_per_proc;
28831 -       
28832 +
28833  
28834         /* config */
28835  
28836 -       /* 
28837 -        * host:port 
28838 +       /*
28839 +        * host:port
28840          *
28841 -        * if host is one of the local IP adresses the 
28842 +        * if host is one of the local IP adresses the
28843          * whole connection is local
28844          *
28845          * if tcp/ip should be used host AND port have
28846 -        * to be specified 
28847 -        * 
28848 -        */ 
28849 -       buffer *host; 
28850 +        * to be specified
28851 +        *
28852 +        */
28853 +       buffer *host;
28854         unsigned short port;
28855  
28856         /*
28857 @@ -161,7 +161,7 @@
28858          */
28859         buffer *unixsocket;
28860  
28861 -       /* if socket is local we can start the scgi 
28862 +       /* if socket is local we can start the scgi
28863          * process ourself
28864          *
28865          * bin-path is the path to the binary
28866 @@ -169,19 +169,19 @@
28867          * check min_procs and max_procs for the number
28868          * of process to start-up
28869          */
28870 -       buffer *bin_path; 
28871 -       
28872 -       /* bin-path is set bin-environment is taken to 
28873 +       buffer *bin_path;
28874 +
28875 +       /* bin-path is set bin-environment is taken to
28876          * create the environement before starting the
28877          * FastCGI process
28878 -        * 
28879 +        *
28880          */
28881         array *bin_env;
28882 -       
28883 +
28884         array *bin_env_copy;
28885 -       
28886 +
28887         /*
28888 -        * docroot-translation between URL->phys and the 
28889 +        * docroot-translation between URL->phys and the
28890          * remote host
28891          *
28892          * reasons:
28893 @@ -192,7 +192,7 @@
28894         buffer *docroot;
28895  
28896         /*
28897 -        * check_local tell you if the phys file is stat()ed 
28898 +        * check_local tell you if the phys file is stat()ed
28899          * or not. FastCGI doesn't care if the service is
28900          * remote. If the web-server side doesn't contain
28901          * the scgi-files we should not stat() for them
28902 @@ -202,33 +202,33 @@
28903  
28904         /*
28905          * append PATH_INFO to SCRIPT_FILENAME
28906 -        * 
28907 +        *
28908          * php needs this if cgi.fix_pathinfo is provied
28909 -        * 
28910 +        *
28911          */
28912 -       
28913 +
28914         ssize_t load; /* replace by host->load */
28915  
28916         size_t max_id; /* corresponds most of the time to
28917         num_procs.
28918 -       
28919 +
28920         only if a process is killed max_id waits for the process itself
28921         to die and decrements its afterwards */
28922  } scgi_extension_host;
28923  
28924  /*
28925   * one extension can have multiple hosts assigned
28926 - * one host can spawn additional processes on the same 
28927 + * one host can spawn additional processes on the same
28928   *   socket (if we control it)
28929   *
28930   * ext -> host -> procs
28931   *    1:n     1:n
28932   *
28933 - * if the scgi process is remote that whole goes down 
28934 + * if the scgi process is remote that whole goes down
28935   * to
28936   *
28937   * ext -> host -> procs
28938 - *    1:n     1:1 
28939 + *    1:n     1:1
28940   *
28941   * in case of PHP and FCGI_CHILDREN we have again a procs
28942   * but we don't control it directly.
28943 @@ -239,7 +239,7 @@
28944         buffer *key; /* like .php */
28945  
28946         scgi_extension_host **hosts;
28947 -       
28948 +
28949         size_t used;
28950         size_t size;
28951  } scgi_extension;
28952 @@ -253,14 +253,14 @@
28953  
28954  
28955  typedef struct {
28956 -       scgi_exts *exts; 
28957 -       
28958 +       scgi_exts *exts;
28959 +
28960         int debug;
28961  } plugin_config;
28962  
28963  typedef struct {
28964         char **ptr;
28965 -       
28966 +
28967         size_t size;
28968         size_t used;
28969  } char_array;
28970 @@ -268,52 +268,51 @@
28971  /* generic plugin data, shared between all connections */
28972  typedef struct {
28973         PLUGIN_DATA;
28974 -       
28975 +
28976         buffer *scgi_env;
28977 -       
28978 +
28979         buffer *path;
28980         buffer *parse_response;
28981 -       
28982 +
28983         plugin_config **config_storage;
28984 -       
28985 +
28986         plugin_config conf; /* this is only used as long as no handler_ctx is setup */
28987  } plugin_data;
28988  
28989  /* connection specific data */
28990 -typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE, 
28991 -               FCGI_STATE_WRITE, FCGI_STATE_READ 
28992 +typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
28993 +               FCGI_STATE_WRITE, FCGI_STATE_READ
28994  } scgi_connection_state_t;
28995  
28996  typedef struct {
28997 -       buffer  *response; 
28998 +       buffer  *response;
28999         size_t   response_len;
29000         int      response_type;
29001         int      response_padding;
29002 -       
29003 +
29004         scgi_proc *proc;
29005         scgi_extension_host *host;
29006 -       
29007 +
29008         scgi_connection_state_t state;
29009         time_t   state_timestamp;
29010 -       
29011 +
29012         int      reconnects; /* number of reconnect attempts */
29013 -       
29014 +
29015         read_buffer *rb;
29016         chunkqueue *wb;
29017 -       
29018 +
29019         buffer   *response_header;
29020 -       
29021 +
29022         int       delayed;   /* flag to mark that the connect() is delayed */
29023 -       
29024 +
29025         size_t    request_id;
29026         int       fd;        /* fd to the scgi process */
29027         int       fde_ndx;   /* index into the fd-event buffer */
29028 -
29029         pid_t     pid;
29030         int       got_proc;
29031 -       
29032 +
29033         plugin_config conf;
29034 -       
29035 +
29036         connection *remote_conn;  /* dumb pointer */
29037         plugin_data *plugin_data; /* dumb pointer */
29038  } handler_ctx;
29039 @@ -328,28 +327,28 @@
29040  
29041  static handler_ctx * handler_ctx_init() {
29042         handler_ctx * hctx;
29043 -       
29044 +
29045         hctx = calloc(1, sizeof(*hctx));
29046         assert(hctx);
29047 -       
29048 +
29049         hctx->fde_ndx = -1;
29050 -       
29051 +
29052         hctx->response = buffer_init();
29053         hctx->response_header = buffer_init();
29054 -       
29055 +
29056         hctx->request_id = 0;
29057         hctx->state = FCGI_STATE_INIT;
29058         hctx->proc = NULL;
29059 -       
29060 +
29061         hctx->response_len = 0;
29062         hctx->response_type = 0;
29063         hctx->response_padding = 0;
29064         hctx->fd = -1;
29065 -       
29066 +
29067         hctx->reconnects = 0;
29068  
29069         hctx->wb = chunkqueue_init();
29070 -       
29071 +
29072         return hctx;
29073  }
29074  
29075 @@ -358,12 +357,12 @@
29076         buffer_free(hctx->response_header);
29077  
29078         chunkqueue_free(hctx->wb);
29079 -       
29080 +
29081         if (hctx->rb) {
29082                 if (hctx->rb->ptr) free(hctx->rb->ptr);
29083                 free(hctx->rb);
29084         }
29085 -       
29086 +
29087         free(hctx);
29088  }
29089  
29090 @@ -372,20 +371,20 @@
29091  
29092         f = calloc(1, sizeof(*f));
29093         f->socket = buffer_init();
29094 -       
29095 +
29096         f->prev = NULL;
29097         f->next = NULL;
29098 -       
29099 +
29100         return f;
29101  }
29102  
29103  void scgi_process_free(scgi_proc *f) {
29104         if (!f) return;
29105 -       
29106 +
29107         scgi_process_free(f->next);
29108 -       
29109 +
29110         buffer_free(f->socket);
29111 -       
29112 +
29113         free(f);
29114  }
29115  
29116 @@ -400,62 +399,62 @@
29117         f->bin_path = buffer_init();
29118         f->bin_env = array_init();
29119         f->bin_env_copy = array_init();
29120 -       
29121 +
29122         return f;
29123  }
29124  
29125  void scgi_host_free(scgi_extension_host *h) {
29126         if (!h) return;
29127 -       
29128 +
29129         buffer_free(h->host);
29130         buffer_free(h->unixsocket);
29131         buffer_free(h->docroot);
29132         buffer_free(h->bin_path);
29133         array_free(h->bin_env);
29134         array_free(h->bin_env_copy);
29135 -       
29136 +
29137         scgi_process_free(h->first);
29138         scgi_process_free(h->unused_procs);
29139 -       
29140 +
29141         free(h);
29142 -       
29143 +
29144  }
29145  
29146  scgi_exts *scgi_extensions_init() {
29147         scgi_exts *f;
29148  
29149         f = calloc(1, sizeof(*f));
29150 -       
29151 +
29152         return f;
29153  }
29154  
29155  void scgi_extensions_free(scgi_exts *f) {
29156         size_t i;
29157 -       
29158 +
29159         if (!f) return;
29160 -       
29161 +
29162         for (i = 0; i < f->used; i++) {
29163                 scgi_extension *fe;
29164                 size_t j;
29165 -               
29166 +
29167                 fe = f->exts[i];
29168 -               
29169 +
29170                 for (j = 0; j < fe->used; j++) {
29171                         scgi_extension_host *h;
29172 -                       
29173 +
29174                         h = fe->hosts[j];
29175 -                       
29176 +
29177                         scgi_host_free(h);
29178                 }
29179 -               
29180 +
29181                 buffer_free(fe->key);
29182                 free(fe->hosts);
29183 -               
29184 +
29185                 free(fe);
29186         }
29187 -       
29188 +
29189         free(f->exts);
29190 -       
29191 +
29192         free(f);
29193  }
29194  
29195 @@ -504,99 +503,103 @@
29196                 assert(fe->hosts);
29197         }
29198  
29199 -       fe->hosts[fe->used++] = fh; 
29200 +       fe->hosts[fe->used++] = fh;
29201  
29202         return 0;
29203 -       
29204 +
29205  }
29206  
29207  INIT_FUNC(mod_scgi_init) {
29208         plugin_data *p;
29209 -       
29210 +
29211         p = calloc(1, sizeof(*p));
29212 -       
29213 +
29214         p->scgi_env = buffer_init();
29215 -       
29216 +
29217         p->path = buffer_init();
29218         p->parse_response = buffer_init();
29219 -       
29220 +
29221         return p;
29222  }
29223  
29224  
29225  FREE_FUNC(mod_scgi_free) {
29226         plugin_data *p = p_d;
29227 -       
29228 +
29229         UNUSED(srv);
29230  
29231         buffer_free(p->scgi_env);
29232         buffer_free(p->path);
29233         buffer_free(p->parse_response);
29234 -       
29235 +
29236         if (p->config_storage) {
29237                 size_t i, j, n;
29238                 for (i = 0; i < srv->config_context->used; i++) {
29239                         plugin_config *s = p->config_storage[i];
29240                         scgi_exts *exts;
29241 -                       
29242 +
29243                         if (!s) continue;
29244 -                       
29245 +
29246                         exts = s->exts;
29247  
29248                         for (j = 0; j < exts->used; j++) {
29249                                 scgi_extension *ex;
29250 -                               
29251 +
29252                                 ex = exts->exts[j];
29253 -                               
29254 +
29255                                 for (n = 0; n < ex->used; n++) {
29256                                         scgi_proc *proc;
29257                                         scgi_extension_host *host;
29258 -                                       
29259 +
29260                                         host = ex->hosts[n];
29261 -                                       
29262 +
29263                                         for (proc = host->first; proc; proc = proc->next) {
29264 +#ifndef _WIN32
29265                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29266 -                                               
29267 -                                               if (proc->is_local && 
29268 +#endif
29269 +
29270 +                                               if (proc->is_local &&
29271                                                     !buffer_is_empty(proc->socket)) {
29272                                                         unlink(proc->socket->ptr);
29273                                                 }
29274                                         }
29275 -                                       
29276 +
29277                                         for (proc = host->unused_procs; proc; proc = proc->next) {
29278 +#ifndef _WIN32
29279                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29280 -                                               
29281 -                                               if (proc->is_local && 
29282 +#endif
29283 +
29284 +                                               if (proc->is_local &&
29285                                                     !buffer_is_empty(proc->socket)) {
29286                                                         unlink(proc->socket->ptr);
29287                                                 }
29288                                         }
29289                                 }
29290                         }
29291 -                       
29292 +
29293                         scgi_extensions_free(s->exts);
29294 -                       
29295 +
29296                         free(s);
29297                 }
29298                 free(p->config_storage);
29299         }
29300 -       
29301 +
29302         free(p);
29303 -       
29304 +
29305         return HANDLER_GO_ON;
29306  }
29307  
29308  static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
29309         char *dst;
29310 -       
29311 +
29312         if (!key || !val) return -1;
29313 -       
29314 +
29315         dst = malloc(key_len + val_len + 3);
29316         memcpy(dst, key, key_len);
29317         dst[key_len] = '=';
29318         /* add the \0 from the value */
29319         memcpy(dst + key_len + 1, val, val_len + 1);
29320 -       
29321 +
29322         if (env->size == 0) {
29323                 env->size = 16;
29324                 env->ptr = malloc(env->size * sizeof(*env->ptr));
29325 @@ -604,13 +607,13 @@
29326                 env->size += 16;
29327                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
29328         }
29329 -       
29330 +
29331         env->ptr[env->used++] = dst;
29332 -       
29333 +
29334         return 0;
29335  }
29336  
29337 -static int scgi_spawn_connection(server *srv, 
29338 +static int scgi_spawn_connection(server *srv,
29339                                  plugin_data *p,
29340                                  scgi_extension_host *host,
29341                                  scgi_proc *proc) {
29342 @@ -622,31 +625,27 @@
29343  #endif
29344         struct sockaddr_in scgi_addr_in;
29345         struct sockaddr *scgi_addr;
29346 -       
29347 +
29348         socklen_t servlen;
29349 -       
29350 +
29351  #ifndef HAVE_FORK
29352         return -1;
29353  #endif
29354 -       
29355 +
29356         if (p->conf.debug) {
29357                 log_error_write(srv, __FILE__, __LINE__, "sdb",
29358                                 "new proc, socket:", proc->port, proc->socket);
29359         }
29360 -               
29361 +
29362         if (!buffer_is_empty(proc->socket)) {
29363                 memset(&scgi_addr, 0, sizeof(scgi_addr));
29364 -               
29365 +
29366  #ifdef HAVE_SYS_UN_H
29367                 scgi_addr_un.sun_family = AF_UNIX;
29368                 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
29369 -               
29370 -#ifdef SUN_LEN
29371 +
29372                 servlen = SUN_LEN(&scgi_addr_un);
29373 -#else
29374 -               /* stevens says: */
29375 -               servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
29376 -#endif
29377 +
29378                 socket_type = AF_UNIX;
29379                 scgi_addr = (struct sockaddr *) &scgi_addr_un;
29380  #else
29381 @@ -656,115 +655,115 @@
29382  #endif
29383         } else {
29384                 scgi_addr_in.sin_family = AF_INET;
29385 -               
29386 +
29387                 if (buffer_is_empty(host->host)) {
29388                         scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29389                 } else {
29390                         struct hostent *he;
29391 -                       
29392 +
29393                         /* set a usefull default */
29394                         scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29395 -                       
29396 -                       
29397 +
29398 +
29399                         if (NULL == (he = gethostbyname(host->host->ptr))) {
29400 -                               log_error_write(srv, __FILE__, __LINE__, 
29401 -                                               "sdb", "gethostbyname failed: ", 
29402 +                               log_error_write(srv, __FILE__, __LINE__,
29403 +                                               "sdb", "gethostbyname failed: ",
29404                                                 h_errno, host->host);
29405                                 return -1;
29406                         }
29407 -                       
29408 +
29409                         if (he->h_addrtype != AF_INET) {
29410                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
29411                                 return -1;
29412                         }
29413 -                       
29414 +
29415                         if (he->h_length != sizeof(struct in_addr)) {
29416                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
29417                                 return -1;
29418                         }
29419 -                       
29420 +
29421                         memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
29422 -                       
29423 +
29424                 }
29425                 scgi_addr_in.sin_port = htons(proc->port);
29426                 servlen = sizeof(scgi_addr_in);
29427 -               
29428 +
29429                 socket_type = AF_INET;
29430                 scgi_addr = (struct sockaddr *) &scgi_addr_in;
29431         }
29432 -       
29433 +
29434         if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29435 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
29436 +               log_error_write(srv, __FILE__, __LINE__, "ss",
29437                                 "failed:", strerror(errno));
29438                 return -1;
29439         }
29440 -       
29441 +
29442         if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
29443                 /* server is not up, spawn in  */
29444                 pid_t child;
29445                 int val;
29446 -               
29447 +
29448                 if (!buffer_is_empty(proc->socket)) {
29449                         unlink(proc->socket->ptr);
29450                 }
29451 -               
29452 +
29453                 close(scgi_fd);
29454 -               
29455 +
29456                 /* reopen socket */
29457                 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29458 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
29459 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
29460                                 "socket failed:", strerror(errno));
29461                         return -1;
29462                 }
29463 -               
29464 +
29465                 val = 1;
29466                 if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
29467 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
29468 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
29469                                         "socketsockopt failed:", strerror(errno));
29470                         return -1;
29471                 }
29472 -               
29473 +
29474                 /* create socket */
29475                 if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
29476 -                       log_error_write(srv, __FILE__, __LINE__, "sbds", 
29477 -                               "bind failed for:", 
29478 -                               proc->socket, 
29479 -                               proc->port, 
29480 +                       log_error_write(srv, __FILE__, __LINE__, "sbds",
29481 +                               "bind failed for:",
29482 +                               proc->socket,
29483 +                               proc->port,
29484                                 strerror(errno));
29485                         return -1;
29486                 }
29487 -               
29488 +
29489                 if (-1 == listen(scgi_fd, 1024)) {
29490 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
29491 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
29492                                 "listen failed:", strerror(errno));
29493                         return -1;
29494                 }
29495 -               
29496 -#ifdef HAVE_FORK       
29497 +
29498 +#ifdef HAVE_FORK
29499                 switch ((child = fork())) {
29500                 case 0: {
29501                         buffer *b;
29502                         size_t i = 0;
29503                         int fd = 0;
29504                         char_array env;
29505 -                       
29506 -                       
29507 +
29508 +
29509                         /* create environment */
29510                         env.ptr = NULL;
29511                         env.size = 0;
29512                         env.used = 0;
29513 -                       
29514 +
29515                         /* we don't need the client socket */
29516                         for (fd = 3; fd < 256; fd++) {
29517                                 if (fd != 2 && fd != scgi_fd) close(fd);
29518                         }
29519 -                       
29520 +
29521                         /* build clean environment */
29522                         if (host->bin_env_copy->used) {
29523                                 for (i = 0; i < host->bin_env_copy->used; i++) {
29524                                         data_string *ds = (data_string *)host->bin_env_copy->data[i];
29525                                         char *ge;
29526 -                                       
29527 +
29528                                         if (NULL != (ge = getenv(ds->value->ptr))) {
29529                                                 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
29530                                         }
29531 @@ -772,44 +771,44 @@
29532                         } else {
29533                                 for (i = 0; environ[i]; i++) {
29534                                         char *eq;
29535 -                                       
29536 +
29537                                         if (NULL != (eq = strchr(environ[i], '='))) {
29538                                                 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
29539                                         }
29540                                 }
29541                         }
29542 -                       
29543 +
29544                         /* create environment */
29545                         for (i = 0; i < host->bin_env->used; i++) {
29546                                 data_string *ds = (data_string *)host->bin_env->data[i];
29547 -                               
29548 +
29549                                 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
29550                         }
29551 -                       
29552 +
29553                         for (i = 0; i < env.used; i++) {
29554                                 /* search for PHP_FCGI_CHILDREN */
29555                                 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
29556                         }
29557 -                       
29558 +
29559                         /* not found, add a default */
29560                         if (i == env.used) {
29561                                 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
29562                         }
29563 -                       
29564 +
29565                         env.ptr[env.used] = NULL;
29566 -                       
29567 +
29568                         b = buffer_init();
29569                         buffer_copy_string(b, "exec ");
29570                         buffer_append_string_buffer(b, host->bin_path);
29571 -                       
29572 +
29573                         /* exec the cgi */
29574                         execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
29575 -                       
29576 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
29577 +
29578 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
29579                                         "execl failed for:", host->bin_path, strerror(errno));
29580 -                       
29581 +
29582                         exit(errno);
29583 -                       
29584 +
29585                         break;
29586                 }
29587                 case -1:
29588 @@ -817,32 +816,32 @@
29589                         break;
29590                 default:
29591                         /* father */
29592 -                       
29593 +
29594                         /* wait */
29595                         select(0, NULL, NULL, NULL, &tv);
29596 -                       
29597 +
29598                         switch (waitpid(child, &status, WNOHANG)) {
29599                         case 0:
29600                                 /* child still running after timeout, good */
29601                                 break;
29602                         case -1:
29603                                 /* no PID found ? should never happen */
29604 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
29605 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
29606                                                 "pid not found:", strerror(errno));
29607                                 return -1;
29608                         default:
29609                                 /* the child should not terminate at all */
29610                                 if (WIFEXITED(status)) {
29611 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
29612 -                                                       "child exited (is this a SCGI binary ?):", 
29613 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
29614 +                                                       "child exited (is this a SCGI binary ?):",
29615                                                         WEXITSTATUS(status));
29616                                 } else if (WIFSIGNALED(status)) {
29617 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
29618 -                                                       "child signaled:", 
29619 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
29620 +                                                       "child signaled:",
29621                                                         WTERMSIG(status));
29622                                 } else {
29623 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
29624 -                                                       "child died somehow:", 
29625 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
29626 +                                                       "child died somehow:",
29627                                                         status);
29628                                 }
29629                                 return -1;
29630 @@ -852,26 +851,26 @@
29631                         proc->pid = child;
29632                         proc->last_used = srv->cur_ts;
29633                         proc->is_local = 1;
29634 -                                               
29635 +
29636                         break;
29637                 }
29638  #endif
29639         } else {
29640                 proc->is_local = 0;
29641                 proc->pid = 0;
29642 -               
29643 +
29644                 if (p->conf.debug) {
29645                         log_error_write(srv, __FILE__, __LINE__, "sb",
29646                                         "(debug) socket is already used, won't spawn:",
29647                                         proc->socket);
29648                 }
29649         }
29650 -       
29651 +
29652         proc->state = PROC_STATE_RUNNING;
29653         host->active_procs++;
29654 -       
29655 +
29656         close(scgi_fd);
29657 -       
29658 +
29659         return 0;
29660  }
29661  
29662 @@ -880,89 +879,89 @@
29663         plugin_data *p = p_d;
29664         data_unset *du;
29665         size_t i = 0;
29666 -       
29667 -       config_values_t cv[] = { 
29668 +
29669 +       config_values_t cv[] = {
29670                 { "scgi.server",              NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
29671                 { "scgi.debug",               NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
29672                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29673         };
29674 -       
29675 +
29676         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
29677 -       
29678 +
29679         for (i = 0; i < srv->config_context->used; i++) {
29680                 plugin_config *s;
29681                 array *ca;
29682 -               
29683 +
29684                 s = malloc(sizeof(plugin_config));
29685                 s->exts          = scgi_extensions_init();
29686                 s->debug         = 0;
29687 -               
29688 +
29689                 cv[0].destination = s->exts;
29690                 cv[1].destination = &(s->debug);
29691 -               
29692 +
29693                 p->config_storage[i] = s;
29694                 ca = ((data_config *)srv->config_context->data[i])->value;
29695 -       
29696 +
29697                 if (0 != config_insert_values_global(srv, ca, cv)) {
29698                         return HANDLER_ERROR;
29699                 }
29700 -               
29701 -               /* 
29702 +
29703 +               /*
29704                  * <key> = ( ... )
29705                  */
29706 -               
29707 +
29708                 if (NULL != (du = array_get_element(ca, "scgi.server"))) {
29709                         size_t j;
29710                         data_array *da = (data_array *)du;
29711 -                       
29712 +
29713                         if (du->type != TYPE_ARRAY) {
29714 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
29715 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
29716                                                 "unexpected type for key: ", "scgi.server", "array of strings");
29717 -                               
29718 +
29719                                 return HANDLER_ERROR;
29720                         }
29721 -                       
29722 -                       
29723 -                       /* 
29724 -                        * scgi.server = ( "<ext>" => ( ... ), 
29725 +
29726 +
29727 +                       /*
29728 +                        * scgi.server = ( "<ext>" => ( ... ),
29729                          *                    "<ext>" => ( ... ) )
29730                          */
29731 -                       
29732 +
29733                         for (j = 0; j < da->value->used; j++) {
29734                                 size_t n;
29735                                 data_array *da_ext = (data_array *)da->value->data[j];
29736 -                               
29737 +
29738                                 if (da->value->data[j]->type != TYPE_ARRAY) {
29739 -                                       log_error_write(srv, __FILE__, __LINE__, "sssbs", 
29740 -                                                       "unexpected type for key: ", "scgi.server", 
29741 +                                       log_error_write(srv, __FILE__, __LINE__, "sssbs",
29742 +                                                       "unexpected type for key: ", "scgi.server",
29743                                                         "[", da->value->data[j]->key, "](string)");
29744 -                                       
29745 +
29746                                         return HANDLER_ERROR;
29747                                 }
29748 -                               
29749 -                               /* 
29750 -                                * da_ext->key == name of the extension 
29751 +
29752 +                               /*
29753 +                                * da_ext->key == name of the extension
29754                                  */
29755 -                               
29756 -                               /* 
29757 -                                * scgi.server = ( "<ext>" => 
29758 -                                *                     ( "<host>" => ( ... ), 
29759 +
29760 +                               /*
29761 +                                * scgi.server = ( "<ext>" =>
29762 +                                *                     ( "<host>" => ( ... ),
29763                                  *                       "<host>" => ( ... )
29764 -                                *                     ), 
29765 +                                *                     ),
29766                                  *                    "<ext>" => ... )
29767                                  */
29768 -                                       
29769 +
29770                                 for (n = 0; n < da_ext->value->used; n++) {
29771                                         data_array *da_host = (data_array *)da_ext->value->data[n];
29772 -                                       
29773 +
29774                                         scgi_extension_host *df;
29775 -                                       
29776 -                                       config_values_t fcv[] = { 
29777 +
29778 +                                       config_values_t fcv[] = {
29779                                                 { "host",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
29780                                                 { "docroot",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
29781                                                 { "socket",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
29782                                                 { "bin-path",          NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
29783 -                                               
29784 +
29785                                                 { "check-local",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 4 */
29786                                                 { "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 5 */
29787                                                 { "min-procs-not-working",         NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 7 this is broken for now */
29788 @@ -970,37 +969,37 @@
29789                                                 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 8 */
29790                                                 { "idle-timeout",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 9 */
29791                                                 { "disable-time",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 10 */
29792 -                                               
29793 +
29794                                                 { "bin-environment",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 11 */
29795                                                 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },     /* 12 */
29796 -                                               
29797 -                                               
29798 +
29799 +
29800                                                 { NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29801                                         };
29802 -                                       
29803 +
29804                                         if (da_host->type != TYPE_ARRAY) {
29805 -                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS", 
29806 -                                                               "unexpected type for key:", 
29807 -                                                               "scgi.server", 
29808 +                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29809 +                                                               "unexpected type for key:",
29810 +                                                               "scgi.server",
29811                                                                 "[", da_host->key, "](string)");
29812 -                                               
29813 +
29814                                                 return HANDLER_ERROR;
29815                                         }
29816 -                                       
29817 +
29818                                         df = scgi_host_init();
29819 -                                       
29820 +
29821                                         df->check_local  = 1;
29822                                         df->min_procs    = 4;
29823                                         df->max_procs    = 4;
29824                                         df->max_load_per_proc = 1;
29825                                         df->idle_timeout = 60;
29826                                         df->disable_time = 60;
29827 -                                       
29828 +
29829                                         fcv[0].destination = df->host;
29830                                         fcv[1].destination = df->docroot;
29831                                         fcv[2].destination = df->unixsocket;
29832                                         fcv[3].destination = df->bin_path;
29833 -                                       
29834 +
29835                                         fcv[4].destination = &(df->check_local);
29836                                         fcv[5].destination = &(df->port);
29837                                         fcv[6].destination = &(df->min_procs);
29838 @@ -1008,47 +1007,47 @@
29839                                         fcv[8].destination = &(df->max_load_per_proc);
29840                                         fcv[9].destination = &(df->idle_timeout);
29841                                         fcv[10].destination = &(df->disable_time);
29842 -                                       
29843 +
29844                                         fcv[11].destination = df->bin_env;
29845                                         fcv[12].destination = df->bin_env_copy;
29846 -                                       
29847 -                                       
29848 +
29849 +
29850                                         if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
29851                                                 return HANDLER_ERROR;
29852                                         }
29853 -                                                       
29854 -                                       if ((!buffer_is_empty(df->host) || df->port) && 
29855 +
29856 +                                       if ((!buffer_is_empty(df->host) || df->port) &&
29857                                             !buffer_is_empty(df->unixsocket)) {
29858 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
29859 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
29860                                                                 "either host+port or socket");
29861 -                                               
29862 +
29863                                                 return HANDLER_ERROR;
29864                                         }
29865 -                                       
29866 +
29867                                         if (!buffer_is_empty(df->unixsocket)) {
29868                                                 /* unix domain socket */
29869 -                                               
29870 +
29871                                                 if (df->unixsocket->used > UNIX_PATH_MAX - 2) {
29872 -                                                       log_error_write(srv, __FILE__, __LINE__, "s", 
29873 +                                                       log_error_write(srv, __FILE__, __LINE__, "s",
29874                                                                         "path of the unixdomain socket is too large");
29875                                                         return HANDLER_ERROR;
29876                                                 }
29877                                         } else {
29878                                                 /* tcp/ip */
29879 -                                               
29880 -                                               if (buffer_is_empty(df->host) && 
29881 +
29882 +                                               if (buffer_is_empty(df->host) &&
29883                                                     buffer_is_empty(df->bin_path)) {
29884 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs", 
29885 -                                                                       "missing key (string):", 
29886 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29887 +                                                                       "missing key (string):",
29888                                                                         da->key,
29889                                                                         da_ext->key,
29890                                                                         da_host->key,
29891                                                                         "host");
29892 -                                                       
29893 +
29894                                                         return HANDLER_ERROR;
29895                                                 } else if (df->port == 0) {
29896 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs", 
29897 -                                                                       "missing key (short):", 
29898 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29899 +                                                                       "missing key (short):",
29900                                                                         da->key,
29901                                                                         da_ext->key,
29902                                                                         da_host->key,
29903 @@ -1056,14 +1055,14 @@
29904                                                         return HANDLER_ERROR;
29905                                                 }
29906                                         }
29907 -                                               
29908 -                                       if (!buffer_is_empty(df->bin_path)) { 
29909 +
29910 +                                       if (!buffer_is_empty(df->bin_path)) {
29911                                                 /* a local socket + self spawning */
29912                                                 size_t pno;
29913 -                                               
29914 +
29915                                                 if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
29916                                                 if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
29917 -                                               
29918 +
29919                                                 if (s->debug) {
29920                                                         log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
29921                                                                         "--- scgi spawning local",
29922 @@ -1073,7 +1072,7 @@
29923                                                                         "\n\tmin-procs:", df->min_procs,
29924                                                                         "\n\tmax-procs:", df->max_procs);
29925                                                 }
29926 -                                               
29927 +
29928                                                 for (pno = 0; pno < df->min_procs; pno++) {
29929                                                         scgi_proc *proc;
29930  
29931 @@ -1088,7 +1087,7 @@
29932                                                                 buffer_append_string(proc->socket, "-");
29933                                                                 buffer_append_long(proc->socket, pno);
29934                                                         }
29935 -                                                       
29936 +
29937                                                         if (s->debug) {
29938                                                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
29939                                                                                 "--- scgi spawning",
29940 @@ -1096,53 +1095,53 @@
29941                                                                                 "\n\tsocket", df->unixsocket,
29942                                                                                 "\n\tcurrent:", pno, "/", df->min_procs);
29943                                                         }
29944 -                                                       
29945 +
29946                                                         if (scgi_spawn_connection(srv, p, df, proc)) {
29947                                                                 log_error_write(srv, __FILE__, __LINE__, "s",
29948                                                                                 "[ERROR]: spawning fcgi failed.");
29949                                                                 return HANDLER_ERROR;
29950                                                         }
29951 -                                                       
29952 +
29953                                                         proc->next = df->first;
29954                                                         if (df->first)  df->first->prev = proc;
29955 -                                                       
29956 +
29957                                                         df->first = proc;
29958                                                 }
29959                                         } else {
29960                                                 scgi_proc *fp;
29961 -                                               
29962 +
29963                                                 fp = scgi_process_init();
29964                                                 fp->id = df->num_procs++;
29965                                                 df->max_id++;
29966                                                 df->active_procs++;
29967                                                 fp->state = PROC_STATE_RUNNING;
29968 -                                               
29969 +
29970                                                 if (buffer_is_empty(df->unixsocket)) {
29971                                                         fp->port = df->port;
29972                                                 } else {
29973                                                         buffer_copy_string_buffer(fp->socket, df->unixsocket);
29974                                                 }
29975 -                                               
29976 +
29977                                                 df->first = fp;
29978 -                                               
29979 +
29980                                                 df->min_procs = 1;
29981                                                 df->max_procs = 1;
29982                                         }
29983 -                                       
29984 +
29985                                         /* if extension already exists, take it */
29986                                         scgi_extension_insert(s->exts, da_ext->key, df);
29987                                 }
29988                         }
29989                 }
29990         }
29991 -       
29992 +
29993         return HANDLER_GO_ON;
29994  }
29995  
29996  static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) {
29997         hctx->state = state;
29998         hctx->state_timestamp = srv->cur_ts;
29999 -       
30000 +
30001         return 0;
30002  }
30003  
30004 @@ -1150,34 +1149,34 @@
30005  void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
30006         plugin_data *p;
30007         connection  *con;
30008 -       
30009 +
30010         if (NULL == hctx) return;
30011 -       
30012 +
30013         p    = hctx->plugin_data;
30014         con  = hctx->remote_conn;
30015 -       
30016 +
30017         if (con->mode != p->id) {
30018                 WP();
30019                 return;
30020         }
30021 -       
30022 +
30023         if (hctx->fd != -1) {
30024                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30025                 fdevent_unregister(srv->ev, hctx->fd);
30026                 close(hctx->fd);
30027                 srv->cur_fds--;
30028         }
30029 -       
30030 +
30031         if (hctx->host && hctx->proc) {
30032                 hctx->host->load--;
30033 -               
30034 +
30035                 if (hctx->got_proc) {
30036                         /* after the connect the process gets a load */
30037                         hctx->proc->load--;
30038 -                       
30039 +
30040                         if (p->conf.debug) {
30041                                 log_error_write(srv, __FILE__, __LINE__, "sddb",
30042 -                                               "release proc:", 
30043 +                                               "release proc:",
30044                                                 hctx->fd,
30045                                                 hctx->proc->pid, hctx->proc->socket);
30046                         }
30047 @@ -1186,87 +1185,87 @@
30048                 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30049         }
30050  
30051 -       
30052 +
30053         handler_ctx_free(hctx);
30054 -       con->plugin_ctx[p->id] = NULL;  
30055 +       con->plugin_ctx[p->id] = NULL;
30056  }
30057  
30058  static int scgi_reconnect(server *srv, handler_ctx *hctx) {
30059         plugin_data *p    = hctx->plugin_data;
30060 -       
30061 -       /* child died 
30062 -        * 
30063 -        * 1. 
30064 -        * 
30065 +
30066 +       /* child died
30067 +        *
30068 +        * 1.
30069 +        *
30070          * connect was ok, connection was accepted
30071          * but the php accept loop checks after the accept if it should die or not.
30072 -        * 
30073 -        * if yes we can only detect it at a write() 
30074 -        * 
30075 +        *
30076 +        * if yes we can only detect it at a write()
30077 +        *
30078          * next step is resetting this attemp and setup a connection again
30079 -        * 
30080 +        *
30081          * if we have more then 5 reconnects for the same request, die
30082 -        * 
30083 -        * 2. 
30084 -        * 
30085 +        *
30086 +        * 2.
30087 +        *
30088          * we have a connection but the child died by some other reason
30089 -        * 
30090 +        *
30091          */
30092 -       
30093 +
30094         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30095         fdevent_unregister(srv->ev, hctx->fd);
30096         close(hctx->fd);
30097         srv->cur_fds--;
30098 -       
30099 +
30100         scgi_set_state(srv, hctx, FCGI_STATE_INIT);
30101 -       
30102 +
30103         hctx->request_id = 0;
30104         hctx->reconnects++;
30105 -       
30106 +
30107         if (p->conf.debug) {
30108                 log_error_write(srv, __FILE__, __LINE__, "sddb",
30109 -                               "release proc:", 
30110 +                               "release proc:",
30111                                 hctx->fd,
30112                                 hctx->proc->pid, hctx->proc->socket);
30113         }
30114 -       
30115 +
30116         hctx->proc->load--;
30117         scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30118 -       
30119 +
30120         return 0;
30121  }
30122  
30123  
30124  static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
30125         plugin_data *p = p_d;
30126 -       
30127 +
30128         scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
30129 -       
30130 +
30131         return HANDLER_GO_ON;
30132  }
30133  
30134  
30135  static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
30136         size_t len;
30137 -       
30138 +
30139         if (!key || !val) return -1;
30140 -       
30141 +
30142         len = key_len + val_len + 2;
30143 -       
30144 +
30145         buffer_prepare_append(env, len);
30146  
30147 -       /* include the NUL */   
30148 +       /* include the NUL */
30149         memcpy(env->ptr + env->used, key, key_len + 1);
30150         env->used += key_len + 1;
30151         memcpy(env->ptr + env->used, val, val_len + 1);
30152         env->used += val_len + 1;
30153 -       
30154 +
30155         return 0;
30156  }
30157  
30158  
30159  /**
30160 - * 
30161 + *
30162   * returns
30163   *   -1 error
30164   *    0 connected
30165 @@ -1280,24 +1279,21 @@
30166         struct sockaddr_un scgi_addr_un;
30167  #endif
30168         socklen_t servlen;
30169 -       
30170 +
30171         scgi_extension_host *host = hctx->host;
30172         scgi_proc *proc   = hctx->proc;
30173         int scgi_fd       = hctx->fd;
30174 -       
30175 +
30176         memset(&scgi_addr, 0, sizeof(scgi_addr));
30177 -       
30178 +
30179         if (!buffer_is_empty(proc->socket)) {
30180  #ifdef HAVE_SYS_UN_H
30181                 /* use the unix domain socket */
30182                 scgi_addr_un.sun_family = AF_UNIX;
30183                 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
30184 -#ifdef SUN_LEN
30185 +               
30186                 servlen = SUN_LEN(&scgi_addr_un);
30187 -#else
30188 -               /* stevens says: */
30189 -               servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
30190 -#endif
30191 +
30192                 scgi_addr = (struct sockaddr *) &scgi_addr_un;
30193  #else
30194                 return -1;
30195 @@ -1305,105 +1301,105 @@
30196         } else {
30197                 scgi_addr_in.sin_family = AF_INET;
30198                 if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) {
30199 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
30200 -                                       "converting IP-adress failed for", host->host, 
30201 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
30202 +                                       "converting IP-adress failed for", host->host,
30203                                         "\nBe sure to specify an IP address here");
30204 -                       
30205 +
30206                         return -1;
30207                 }
30208                 scgi_addr_in.sin_port = htons(proc->port);
30209                 servlen = sizeof(scgi_addr_in);
30210 -               
30211 +
30212                 scgi_addr = (struct sockaddr *) &scgi_addr_in;
30213         }
30214 -       
30215 +
30216         if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
30217 -               if (errno == EINPROGRESS || 
30218 +               if (errno == EINPROGRESS ||
30219                     errno == EALREADY ||
30220                     errno == EINTR) {
30221                         if (hctx->conf.debug) {
30222 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
30223 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
30224                                                 "connect delayed, will continue later:", scgi_fd);
30225                         }
30226 -                       
30227 +
30228                         return 1;
30229                 } else {
30230 -                       log_error_write(srv, __FILE__, __LINE__, "sdsddb", 
30231 -                                       "connect failed:", scgi_fd, 
30232 +                       log_error_write(srv, __FILE__, __LINE__, "sdsddb",
30233 +                                       "connect failed:", scgi_fd,
30234                                         strerror(errno), errno,
30235                                         proc->port, proc->socket);
30236  
30237                         if (errno == EAGAIN) {
30238                                 /* this is Linux only */
30239 -                               
30240 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
30241 +
30242 +                               log_error_write(srv, __FILE__, __LINE__, "s",
30243                                                 "If this happend on Linux: You have been run out of local ports. "
30244                                                 "Check the manual, section Performance how to handle this.");
30245 -                       } 
30246 -                       
30247 +                       }
30248 +
30249                         return -1;
30250                 }
30251         }
30252         if (hctx->conf.debug > 1) {
30253 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
30254 +               log_error_write(srv, __FILE__, __LINE__, "sd",
30255                                 "connect succeeded: ", scgi_fd);
30256         }
30257  
30258  
30259 -       
30260 +
30261         return 0;
30262  }
30263  
30264  static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
30265         size_t i;
30266 -       
30267 +
30268         for (i = 0; i < con->request.headers->used; i++) {
30269                 data_string *ds;
30270 -               
30271 +
30272                 ds = (data_string *)con->request.headers->data[i];
30273 -               
30274 +
30275                 if (ds->value->used && ds->key->used) {
30276                         size_t j;
30277                         buffer_reset(srv->tmp_buf);
30278 -                       
30279 +
30280                         if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
30281                                 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
30282                                 srv->tmp_buf->used--;
30283                         }
30284 -                       
30285 +
30286                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30287                         for (j = 0; j < ds->key->used - 1; j++) {
30288 -                               srv->tmp_buf->ptr[srv->tmp_buf->used++] = 
30289 -                                       light_isalpha(ds->key->ptr[j]) ? 
30290 +                               srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30291 +                                       light_isalpha(ds->key->ptr[j]) ?
30292                                         ds->key->ptr[j] & ~32 : '_';
30293                         }
30294                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30295 -                       
30296 +
30297                         scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30298                 }
30299         }
30300 -       
30301 +
30302         for (i = 0; i < con->environment->used; i++) {
30303                 data_string *ds;
30304 -               
30305 +
30306                 ds = (data_string *)con->environment->data[i];
30307 -               
30308 +
30309                 if (ds->value->used && ds->key->used) {
30310                         size_t j;
30311                         buffer_reset(srv->tmp_buf);
30312 -                       
30313 +
30314                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30315                         for (j = 0; j < ds->key->used - 1; j++) {
30316 -                               srv->tmp_buf->ptr[srv->tmp_buf->used++] = 
30317 -                                       isalpha((unsigned char)ds->key->ptr[j]) ? 
30318 +                               srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30319 +                                       isalpha((unsigned char)ds->key->ptr[j]) ?
30320                                         toupper((unsigned char)ds->key->ptr[j]) : '_';
30321                         }
30322                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30323 -                       
30324 +
30325                         scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30326                 }
30327         }
30328 -       
30329 +
30330         return 0;
30331  }
30332  
30333 @@ -1415,20 +1411,20 @@
30334         char b2[INET6_ADDRSTRLEN + 1];
30335  #endif
30336         buffer *b;
30337 -       
30338 +
30339         plugin_data *p    = hctx->plugin_data;
30340         scgi_extension_host *host= hctx->host;
30341  
30342         connection *con   = hctx->remote_conn;
30343         server_socket *srv_sock = con->srv_socket;
30344 -       
30345 +
30346         sock_addr our_addr;
30347         socklen_t our_addr_len;
30348 -       
30349 +
30350         buffer_prepare_copy(p->scgi_env, 1024);
30351  
30352         /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
30353 -               
30354 +
30355         /* request.content_length < SSIZE_MAX, see request.c */
30356         ltostr(buf, con->request.content_length);
30357         scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
30358 @@ -1436,13 +1432,13 @@
30359  
30360  
30361         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
30362 -       
30363 +
30364         if (con->server_name->used) {
30365                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
30366         } else {
30367  #ifdef HAVE_IPV6
30368 -               s = inet_ntop(srv_sock->addr.plain.sa_family, 
30369 -                             srv_sock->addr.plain.sa_family == AF_INET6 ? 
30370 +               s = inet_ntop(srv_sock->addr.plain.sa_family,
30371 +                             srv_sock->addr.plain.sa_family == AF_INET6 ?
30372                               (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
30373                               (const void *) &(srv_sock->addr.ipv4.sin_addr),
30374                               b2, sizeof(b2)-1);
30375 @@ -1451,47 +1447,47 @@
30376  #endif
30377                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
30378         }
30379 -       
30380 +
30381         scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
30382 -       
30383 -       ltostr(buf, 
30384 +
30385 +       ltostr(buf,
30386  #ifdef HAVE_IPV6
30387                ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
30388  #else
30389                ntohs(srv_sock->addr.ipv4.sin_port)
30390  #endif
30391                );
30392 -       
30393 +
30394         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
30395 -       
30396 +
30397         /* get the server-side of the connection to the client */
30398         our_addr_len = sizeof(our_addr);
30399 -       
30400 +
30401         if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
30402                 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
30403         } else {
30404                 s = inet_ntop_cache_get_ip(srv, &(our_addr));
30405         }
30406         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
30407 -       
30408 -       ltostr(buf, 
30409 +
30410 +       ltostr(buf,
30411  #ifdef HAVE_IPV6
30412                ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
30413  #else
30414                ntohs(con->dst_addr.ipv4.sin_port)
30415  #endif
30416                );
30417 -       
30418 +
30419         scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
30420 -       
30421 +
30422         s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
30423         scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
30424 -       
30425 +
30426         if (!buffer_is_empty(con->authed_user)) {
30427                 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
30428                              CONST_BUF_LEN(con->authed_user));
30429         }
30430 -       
30431 +
30432  
30433         /*
30434          * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
30435 @@ -1500,12 +1496,12 @@
30436          */
30437  
30438         scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
30439 -               
30440 +
30441         if (!buffer_is_empty(con->request.pathinfo)) {
30442                 scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
30443 -               
30444 +
30445                 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
30446 -               
30447 +
30448                 if (!buffer_is_empty(host->docroot)) {
30449                         buffer_copy_string_buffer(p->path, host->docroot);
30450                 } else {
30451 @@ -1526,19 +1522,19 @@
30452          */
30453  
30454         if (!buffer_is_empty(host->docroot)) {
30455 -               /* 
30456 -                * rewrite SCRIPT_FILENAME 
30457 -                * 
30458 +               /*
30459 +                * rewrite SCRIPT_FILENAME
30460 +                *
30461                  */
30462 -               
30463 +
30464                 buffer_copy_string_buffer(p->path, host->docroot);
30465                 buffer_append_string_buffer(p->path, con->uri.path);
30466 -               
30467 +
30468                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30469                 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
30470         } else {
30471                 buffer_copy_string_buffer(p->path, con->physical.path);
30472 -               
30473 +
30474                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30475                 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
30476         }
30477 @@ -1551,30 +1547,30 @@
30478         } else {
30479                 scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
30480         }
30481 -       
30482 +
30483         s = get_http_method_name(con->request.http_method);
30484         scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
30485         scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
30486         s = get_http_version_name(con->request.http_version);
30487         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
30488 -       
30489 +
30490  #ifdef USE_OPENSSL
30491         if (srv_sock->is_ssl) {
30492                 scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
30493         }
30494  #endif
30495 -       
30496 +
30497         scgi_env_add_request_headers(srv, con, p);
30498  
30499         b = chunkqueue_get_append_buffer(hctx->wb);
30500 -       
30501 +
30502         buffer_append_long(b, p->scgi_env->used);
30503         buffer_append_string_len(b, CONST_STR_LEN(":"));
30504         buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used);
30505         buffer_append_string_len(b, CONST_STR_LEN(","));
30506  
30507         hctx->wb->bytes_in += b->used - 1;
30508 -       
30509 +
30510         if (con->request.content_length) {
30511                 chunkqueue *req_cq = con->request_content_queue;
30512                 chunk *req_c;
30513 @@ -1587,7 +1583,7 @@
30514  
30515                         /* we announce toWrite octects
30516                          * now take all the request_content chunk that we need to fill this request
30517 -                        * */   
30518 +                        * */
30519  
30520                         switch (req_c->type) {
30521                         case FILE_CHUNK:
30522 @@ -1615,32 +1611,32 @@
30523  
30524                                 req_c->offset += weHave;
30525                                 req_cq->bytes_out += weHave;
30526 -                               
30527 +
30528                                 hctx->wb->bytes_in += weHave;
30529  
30530                                 break;
30531                         default:
30532                                 break;
30533                         }
30534 -                       
30535 +
30536                         offset += weHave;
30537                 }
30538         }
30539 -       
30540 +
30541  #if 0
30542         for (i = 0; i < hctx->write_buffer->used; i++) {
30543                 fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]);
30544                 if ((i+1) % 16 == 0) {
30545                         size_t j;
30546                         for (j = i-15; j <= i; j++) {
30547 -                               fprintf(stderr, "%c", 
30548 +                               fprintf(stderr, "%c",
30549                                         isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
30550                         }
30551                         fprintf(stderr, "\n");
30552                 }
30553         }
30554  #endif
30555 -       
30556 +
30557         return 0;
30558  }
30559  
30560 @@ -1648,32 +1644,32 @@
30561         char *ns;
30562         const char *s;
30563         int line = 0;
30564 -       
30565 +
30566         UNUSED(srv);
30567 -       
30568 +
30569         buffer_copy_string_buffer(p->parse_response, in);
30570 -       
30571 -       for (s = p->parse_response->ptr; 
30572 -            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); 
30573 +
30574 +       for (s = p->parse_response->ptr;
30575 +            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
30576              s = ns + (eol == EOL_RN ? 2 : 1), line++) {
30577                 const char *key, *value;
30578                 int key_len;
30579                 data_string *ds;
30580 -               
30581 +
30582                 ns[0] = '\0';
30583 -               
30584 -               if (line == 0 && 
30585 +
30586 +               if (line == 0 &&
30587                     0 == strncmp(s, "HTTP/1.", 7)) {
30588                         /* non-parsed header ... we parse them anyway */
30589 -                       
30590 +
30591                         if ((s[7] == '1' ||
30592                              s[7] == '0') &&
30593                             s[8] == ' ') {
30594                                 int status;
30595                                 /* after the space should be a status code for us */
30596 -                               
30597 +
30598                                 status = strtol(s+9, NULL, 10);
30599 -                               
30600 +
30601                                 if (con->http_status >= 100 &&
30602                                     con->http_status < 1000) {
30603                                         /* we expected 3 digits and didn't got them */
30604 @@ -1682,27 +1678,27 @@
30605                                 }
30606                         }
30607                 } else {
30608 -               
30609 +
30610                         key = s;
30611                         if (NULL == (value = strchr(s, ':'))) {
30612                                 /* we expect: "<key>: <value>\r\n" */
30613                                 continue;
30614                         }
30615 -                       
30616 +
30617                         key_len = value - key;
30618                         value += 1;
30619 -                       
30620 +
30621                         /* skip LWS */
30622                         while (*value == ' ' || *value == '\t') value++;
30623 -                       
30624 +
30625                         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
30626                                 ds = data_response_init();
30627                         }
30628                         buffer_copy_string_len(ds->key, key, key_len);
30629                         buffer_copy_string(ds->value, value);
30630 -                       
30631 +
30632                         array_insert_unique(con->response.headers, (data_unset *)ds);
30633 -                       
30634 +
30635                         switch(key_len) {
30636                         case 4:
30637                                 if (0 == strncasecmp(key, "Date", key_len)) {
30638 @@ -1737,13 +1733,13 @@
30639                         }
30640                 }
30641         }
30642 -       
30643 +
30644         /* CGI/1.1 rev 03 - 7.2.1.2 */
30645         if ((con->parsed_response & HTTP_LOCATION) &&
30646             !(con->parsed_response & HTTP_STATUS)) {
30647                 con->http_status = 302;
30648         }
30649 -       
30650 +
30651         return 0;
30652  }
30653  
30654 @@ -1751,10 +1747,10 @@
30655  static int scgi_demux_response(server *srv, handler_ctx *hctx) {
30656         plugin_data *p    = hctx->plugin_data;
30657         connection  *con  = hctx->remote_conn;
30658 -       
30659 +
30660         while(1) {
30661                 int n;
30662 -               
30663 +
30664                 buffer_prepare_copy(hctx->response, 1024);
30665                 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
30666                         if (errno == EAGAIN || errno == EINTR) {
30667 @@ -1765,143 +1761,143 @@
30668                         log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
30669                         return -1;
30670                 }
30671 -               
30672 +
30673                 if (n == 0) {
30674                         /* read finished */
30675 -                       
30676 +
30677                         con->file_finished = 1;
30678 -                       
30679 +
30680                         /* send final chunk */
30681                         http_chunk_append_mem(srv, con, NULL, 0);
30682                         joblist_append(srv, con);
30683 -                       
30684 +
30685                         return 1;
30686                 }
30687 -               
30688 +
30689                 hctx->response->ptr[n] = '\0';
30690                 hctx->response->used = n+1;
30691 -               
30692 +
30693                 /* split header from body */
30694 -               
30695 +
30696                 if (con->file_started == 0) {
30697                         char *c;
30698                         int in_header = 0;
30699                         int header_end = 0;
30700                         int cp, eol = EOL_UNSET;
30701                         size_t used = 0;
30702 -                       
30703 +
30704                         buffer_append_string_buffer(hctx->response_header, hctx->response);
30705 -                       
30706 +
30707                         /* nph (non-parsed headers) */
30708                         if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
30709 -                       
30710 +
30711                         /* search for the \r\n\r\n or \n\n in the string */
30712                         for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
30713                                 if (*c == ':') in_header = 1;
30714                                 else if (*c == '\n') {
30715                                         if (in_header == 0) {
30716                                                 /* got a response without a response header */
30717 -                                               
30718 +
30719                                                 c = NULL;
30720                                                 header_end = 1;
30721                                                 break;
30722                                         }
30723 -                                       
30724 +
30725                                         if (eol == EOL_UNSET) eol = EOL_N;
30726 -                                       
30727 +
30728                                         if (*(c+1) == '\n') {
30729                                                 header_end = 1;
30730                                                 break;
30731                                         }
30732 -                                       
30733 +
30734                                 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
30735                                         if (in_header == 0) {
30736                                                 /* got a response without a response header */
30737 -                                               
30738 +
30739                                                 c = NULL;
30740                                                 header_end = 1;
30741                                                 break;
30742                                         }
30743 -                                       
30744 +
30745                                         if (eol == EOL_UNSET) eol = EOL_RN;
30746 -                                       
30747 +
30748                                         if (used > 3 &&
30749 -                                           *(c+2) == '\r' && 
30750 +                                           *(c+2) == '\r' &&
30751                                             *(c+3) == '\n') {
30752                                                 header_end = 1;
30753                                                 break;
30754                                         }
30755 -                                       
30756 +
30757                                         /* skip the \n */
30758                                         c++;
30759                                         cp++;
30760                                         used--;
30761                                 }
30762                         }
30763 -                       
30764 +
30765                         if (header_end) {
30766                                 if (c == NULL) {
30767                                         /* no header, but a body */
30768 -                                       
30769 +
30770                                         if (con->request.http_version == HTTP_VERSION_1_1) {
30771                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30772                                         }
30773 -                                       
30774 +
30775                                         http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
30776                                         joblist_append(srv, con);
30777                                 } else {
30778                                         size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
30779                                         size_t blen = hctx->response_header->used - hlen - 1;
30780 -                               
30781 +
30782                                         /* a small hack: terminate after at the second \r */
30783                                         hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
30784                                         hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
30785 -                               
30786 +
30787                                         /* parse the response header */
30788                                         scgi_response_parse(srv, con, p, hctx->response_header, eol);
30789 -                                       
30790 +
30791                                         /* enable chunked-transfer-encoding */
30792                                         if (con->request.http_version == HTTP_VERSION_1_1 &&
30793                                             !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
30794                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30795                                         }
30796 -                                       
30797 +
30798                                         if ((hctx->response->used != hlen) && blen > 0) {
30799                                                 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
30800                                                 joblist_append(srv, con);
30801                                         }
30802                                 }
30803 -                               
30804 +
30805                                 con->file_started = 1;
30806                         }
30807                 } else {
30808                         http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
30809                         joblist_append(srv, con);
30810                 }
30811 -               
30812 -#if 0          
30813 +
30814 +#if 0
30815                 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
30816  #endif
30817         }
30818 -       
30819 +
30820         return 0;
30821  }
30822  
30823  
30824  int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30825         scgi_proc *p;
30826 -       
30827 +
30828         UNUSED(srv);
30829 -       
30830 -       /* we have been the smallest of the current list 
30831 -        * and we want to insert the node sorted as soon 
30832 +
30833 +       /* we have been the smallest of the current list
30834 +        * and we want to insert the node sorted as soon
30835          * possible
30836          *
30837 -        * 1 0 0 0 1 1 1 
30838 -        * |      ^ 
30839 +        * 1 0 0 0 1 1 1
30840 +        * |      ^
30841          * |      |
30842          * +------+
30843 -        * 
30844 +        *
30845          */
30846  
30847         /* nothing to sort, only one element */
30848 @@ -1909,9 +1905,9 @@
30849  
30850         for (p = proc; p->next && p->next->load < proc->load; p = p->next);
30851  
30852 -       /* no need to move something 
30853 +       /* no need to move something
30854          *
30855 -        * 1 2 2 2 3 3 3 
30856 +        * 1 2 2 2 3 3 3
30857          * ^
30858          * |
30859          * +
30860 @@ -1930,16 +1926,16 @@
30861  
30862         if (proc->prev) proc->prev->next = proc->next;
30863         if (proc->next) proc->next->prev = proc->prev;
30864 -       
30865 +
30866         /* proc should be right of p */
30867 -       
30868 +
30869         proc->next = p->next;
30870         proc->prev = p;
30871         if (p->next) p->next->prev = proc;
30872         p->next = proc;
30873  #if 0
30874         for(p = host->first; p; p = p->next) {
30875 -               log_error_write(srv, __FILE__, __LINE__, "dd", 
30876 +               log_error_write(srv, __FILE__, __LINE__, "dd",
30877                                 p->pid, p->load);
30878         }
30879  #else
30880 @@ -1951,21 +1947,21 @@
30881  
30882  int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30883         scgi_proc *p;
30884 -       
30885 +
30886         UNUSED(srv);
30887 -       
30888 -       /* we have been the smallest of the current list 
30889 -        * and we want to insert the node sorted as soon 
30890 +
30891 +       /* we have been the smallest of the current list
30892 +        * and we want to insert the node sorted as soon
30893          * possible
30894          *
30895 -        *  0 0 0 0 1 0 1 
30896 +        *  0 0 0 0 1 0 1
30897          * ^          |
30898          * |          |
30899          * +----------+
30900          *
30901          *
30902          * the basic is idea is:
30903 -        * - the last active scgi process should be still 
30904 +        * - the last active scgi process should be still
30905          *   in ram and is not swapped out yet
30906          * - processes that are not reused will be killed
30907          *   after some time by the trigger-handler
30908 @@ -1975,7 +1971,7 @@
30909          *   ice-cold processes are propably unused since more
30910          *   than 'unused-timeout', are swaped out and won't be
30911          *   reused in the next seconds anyway.
30912 -        * 
30913 +        *
30914          */
30915  
30916         /* nothing to sort, only one element */
30917 @@ -1984,16 +1980,16 @@
30918         for (p = host->first; p != proc && p->load < proc->load; p = p->next);
30919  
30920  
30921 -       /* no need to move something 
30922 +       /* no need to move something
30923          *
30924 -        * 1 2 2 2 3 3 3 
30925 +        * 1 2 2 2 3 3 3
30926          * ^
30927          * |
30928          * +
30929          *
30930          */
30931         if (p == proc) return 0;
30932 -       
30933 +
30934         /* we have to move left. If we are already the first element
30935          * we are done */
30936         if (host->first == proc) return 0;
30937 @@ -2009,9 +2005,9 @@
30938         p->prev = proc;
30939  
30940         if (proc->prev == NULL) host->first = proc;
30941 -#if 0  
30942 +#if 0
30943         for(p = host->first; p; p = p->next) {
30944 -               log_error_write(srv, __FILE__, __LINE__, "dd", 
30945 +               log_error_write(srv, __FILE__, __LINE__, "dd",
30946                                 p->pid, p->load);
30947         }
30948  #else
30949 @@ -2023,41 +2019,42 @@
30950  
30951  static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
30952         scgi_proc *proc;
30953 -       
30954 +
30955         for (proc = host->first; proc; proc = proc->next) {
30956                 if (p->conf.debug) {
30957 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdbdddd", 
30958 -                                       "proc:", 
30959 -                                       host->host, proc->port, 
30960 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdbdddd",
30961 +                                       "proc:",
30962 +                                       host->host, proc->port,
30963                                         proc->socket,
30964                                         proc->state,
30965                                         proc->is_local,
30966                                         proc->load,
30967                                         proc->pid);
30968                 }
30969 -               
30970 +
30971                 if (0 == proc->is_local) {
30972 -                       /* 
30973 -                        * external servers might get disabled 
30974 -                        * 
30975 -                        * enable the server again, perhaps it is back again 
30976 +                       /*
30977 +                        * external servers might get disabled
30978 +                        *
30979 +                        * enable the server again, perhaps it is back again
30980                          */
30981 -                       
30982 +
30983                         if ((proc->state == PROC_STATE_DISABLED) &&
30984                             (srv->cur_ts - proc->disable_ts > host->disable_time)) {
30985                                 proc->state = PROC_STATE_RUNNING;
30986                                 host->active_procs++;
30987 -                               
30988 -                               log_error_write(srv, __FILE__, __LINE__,  "sbdb", 
30989 -                                               "fcgi-server re-enabled:", 
30990 -                                               host->host, host->port, 
30991 +
30992 +                               log_error_write(srv, __FILE__, __LINE__,  "sbdb",
30993 +                                               "fcgi-server re-enabled:",
30994 +                                               host->host, host->port,
30995                                                 host->unixsocket);
30996                         }
30997                 } else {
30998                         /* the child should not terminate at all */
30999                         int status;
31000 -                       
31001 +
31002                         if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
31003 +#ifndef _WIN32
31004                                 switch(waitpid(proc->pid, &status, WNOHANG)) {
31005                                 case 0:
31006                                         /* child is still alive */
31007 @@ -2067,33 +2064,34 @@
31008                                 default:
31009                                         if (WIFEXITED(status)) {
31010  #if 0
31011 -                                               log_error_write(srv, __FILE__, __LINE__, "sdsd", 
31012 +                                               log_error_write(srv, __FILE__, __LINE__, "sdsd",
31013                                                                 "child exited, pid:", proc->pid,
31014                                                                 "status:", WEXITSTATUS(status));
31015  #endif
31016                                         } else if (WIFSIGNALED(status)) {
31017 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31018 -                                                               "child signaled:", 
31019 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31020 +                                                               "child signaled:",
31021                                                                 WTERMSIG(status));
31022                                         } else {
31023 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31024 -                                                               "child died somehow:", 
31025 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31026 +                                                               "child died somehow:",
31027                                                                 status);
31028                                         }
31029 -                                       
31030 +
31031                                         proc->state = PROC_STATE_DIED;
31032                                         break;
31033                                 }
31034 +#endif
31035                         }
31036 -                       
31037 -                       /* 
31038 +
31039 +                       /*
31040                          * local servers might died, but we restart them
31041 -                        * 
31042 +                        *
31043                          */
31044                         if (proc->state == PROC_STATE_DIED &&
31045                             proc->load == 0) {
31046                                 /* restart the child */
31047 -                               
31048 +
31049                                 if (p->conf.debug) {
31050                                         log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31051                                                         "--- scgi spawning",
31052 @@ -2101,18 +2099,18 @@
31053                                                         "\n\tsocket", host->unixsocket,
31054                                                         "\n\tcurrent:", 1, "/", host->min_procs);
31055                                 }
31056 -                               
31057 +
31058                                 if (scgi_spawn_connection(srv, p, host, proc)) {
31059                                         log_error_write(srv, __FILE__, __LINE__, "s",
31060                                                         "ERROR: spawning fcgi failed.");
31061                                         return HANDLER_ERROR;
31062                                 }
31063 -                               
31064 +
31065                                 scgi_proclist_sort_down(srv, host, proc);
31066                         }
31067                 }
31068         }
31069 -       
31070 +
31071         return 0;
31072  }
31073  
31074 @@ -2121,13 +2119,13 @@
31075         plugin_data *p    = hctx->plugin_data;
31076         scgi_extension_host *host= hctx->host;
31077         connection *con   = hctx->remote_conn;
31078 -       
31079 +
31080         int ret;
31081  
31082 -       /* sanity check */      
31083 +       /* sanity check */
31084         if (!host ||
31085             ((!host->host->used || !host->port) && !host->unixsocket->used)) {
31086 -               log_error_write(srv, __FILE__, __LINE__, "sxddd", 
31087 +               log_error_write(srv, __FILE__, __LINE__, "sxddd",
31088                                 "write-req: error",
31089                                 host,
31090                                 host->host->used,
31091 @@ -2135,179 +2133,180 @@
31092                                 host->unixsocket->used);
31093                 return HANDLER_ERROR;
31094         }
31095 -       
31096 +
31097  
31098         switch(hctx->state) {
31099         case FCGI_STATE_INIT:
31100                 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
31101 -               
31102 +
31103                 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
31104                         if (errno == EMFILE ||
31105                             errno == EINTR) {
31106 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31107 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
31108                                                 "wait for fd at connection:", con->fd);
31109 -                               
31110 +
31111                                 return HANDLER_WAIT_FOR_FD;
31112                         }
31113 -                       
31114 -                       log_error_write(srv, __FILE__, __LINE__, "ssdd", 
31115 +
31116 +                       log_error_write(srv, __FILE__, __LINE__, "ssdd",
31117                                         "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
31118                         return HANDLER_ERROR;
31119                 }
31120                 hctx->fde_ndx = -1;
31121 -               
31122 +
31123                 srv->cur_fds++;
31124 -               
31125 +
31126                 fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
31127 -               
31128 +
31129                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
31130 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
31131 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
31132                                         "fcntl failed: ", strerror(errno));
31133 -                       
31134 +
31135                         return HANDLER_ERROR;
31136                 }
31137 -               
31138 +
31139                 /* fall through */
31140         case FCGI_STATE_CONNECT:
31141                 if (hctx->state == FCGI_STATE_INIT) {
31142 -                       for (hctx->proc = hctx->host->first; 
31143 -                            hctx->proc && hctx->proc->state != PROC_STATE_RUNNING; 
31144 +                       for (hctx->proc = hctx->host->first;
31145 +                            hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
31146                              hctx->proc = hctx->proc->next);
31147 -                       
31148 +
31149                         /* all childs are dead */
31150                         if (hctx->proc == NULL) {
31151                                 hctx->fde_ndx = -1;
31152 -                               
31153 +
31154                                 return HANDLER_ERROR;
31155                         }
31156 -                       
31157 +
31158                         if (hctx->proc->is_local) {
31159                                 hctx->pid = hctx->proc->pid;
31160                         }
31161 -                       
31162 +
31163                         switch (scgi_establish_connection(srv, hctx)) {
31164                         case 1:
31165                                 scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
31166 -                               
31167 +
31168                                 /* connection is in progress, wait for an event and call getsockopt() below */
31169 -                               
31170 +
31171                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31172 -                               
31173 +
31174                                 return HANDLER_WAIT_FOR_EVENT;
31175                         case -1:
31176                                 /* if ECONNREFUSED choose another connection -> FIXME */
31177                                 hctx->fde_ndx = -1;
31178 -                               
31179 +
31180                                 return HANDLER_ERROR;
31181                         default:
31182                                 /* everything is ok, go on */
31183                                 break;
31184                         }
31185  
31186 -                       
31187 +
31188                 } else {
31189                         int socket_error;
31190                         socklen_t socket_error_len = sizeof(socket_error);
31191 -                       
31192 +
31193                         /* try to finish the connect() */
31194                         if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
31195 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
31196 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
31197                                                 "getsockopt failed:", strerror(errno));
31198 -                               
31199 +
31200                                 return HANDLER_ERROR;
31201                         }
31202                         if (socket_error != 0) {
31203                                 if (!hctx->proc->is_local || p->conf.debug) {
31204                                         /* local procs get restarted */
31205 -                                       
31206 +
31207                                         log_error_write(srv, __FILE__, __LINE__, "ss",
31208 -                                                       "establishing connection failed:", strerror(socket_error), 
31209 +                                                       "establishing connection failed:", strerror(socket_error),
31210                                                         "port:", hctx->proc->port);
31211                                 }
31212 -                               
31213 +
31214                                 return HANDLER_ERROR;
31215                         }
31216                 }
31217 -               
31218 +
31219                 /* ok, we have the connection */
31220 -               
31221 +
31222                 hctx->proc->load++;
31223                 hctx->proc->last_used = srv->cur_ts;
31224                 hctx->got_proc = 1;
31225 -               
31226 +
31227                 if (p->conf.debug) {
31228                         log_error_write(srv, __FILE__, __LINE__, "sddbdd",
31229 -                                       "got proc:", 
31230 +                                       "got proc:",
31231                                         hctx->fd,
31232 -                                       hctx->proc->pid, 
31233 -                                       hctx->proc->socket, 
31234 +                                       hctx->proc->pid,
31235 +                                       hctx->proc->socket,
31236                                         hctx->proc->port,
31237                                         hctx->proc->load);
31238                 }
31239  
31240                 /* move the proc-list entry down the list */
31241                 scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
31242 -               
31243 +
31244                 scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
31245                 /* fall through */
31246         case FCGI_STATE_PREPARE_WRITE:
31247                 scgi_create_env(srv, hctx);
31248 -               
31249 +
31250                 scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
31251 -               
31252 +
31253                 /* fall through */
31254         case FCGI_STATE_WRITE:
31255 -               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); 
31256 +               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
31257  
31258                 chunkqueue_remove_finished_chunks(hctx->wb);
31259 -       
31260 +
31261                 if (-1 == ret) {
31262                         if (errno == ENOTCONN) {
31263 -                               /* the connection got dropped after accept() 
31264 -                                * 
31265 -                                * this is most of the time a PHP which dies 
31266 +                               /* the connection got dropped after accept()
31267 +                                *
31268 +                                * this is most of the time a PHP which dies
31269                                  * after PHP_FCGI_MAX_REQUESTS
31270 -                                * 
31271 -                                */ 
31272 +                                *
31273 +                                */
31274                                 if (hctx->wb->bytes_out == 0 &&
31275                                     hctx->reconnects < 5) {
31276 -                                       usleep(10000); /* take away the load of the webserver 
31277 -                                                       * to let the php a chance to restart 
31278 +#ifndef _WIN32
31279 +                                       usleep(10000); /* take away the load of the webserver
31280 +                                                       * to let the php a chance to restart
31281                                                         */
31282 -                                       
31283 +#endif
31284                                         scgi_reconnect(srv, hctx);
31285 -                               
31286 +
31287                                         return HANDLER_WAIT_FOR_FD;
31288                                 }
31289 -                               
31290 +
31291                                 /* not reconnected ... why
31292 -                                * 
31293 +                                *
31294                                  * far@#lighttpd report this for FreeBSD
31295 -                                * 
31296 +                                *
31297                                  */
31298 -                               
31299 -                               log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
31300 +
31301 +                               log_error_write(srv, __FILE__, __LINE__, "ssosd",
31302                                                 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
31303                                                 "write-offset:", hctx->wb->bytes_out,
31304                                                 "reconnect attempts:", hctx->reconnects);
31305 -                               
31306 +
31307                                 return HANDLER_ERROR;
31308                         }
31309 -                       
31310 +
31311                         if ((errno != EAGAIN) &&
31312                             (errno != EINTR)) {
31313 -                               
31314 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", 
31315 +
31316 +                               log_error_write(srv, __FILE__, __LINE__, "ssd",
31317                                                 "write failed:", strerror(errno), errno);
31318 -                               
31319 +
31320                                 return HANDLER_ERROR;
31321                         } else {
31322                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31323 -                               
31324 +
31325                                 return HANDLER_WAIT_FOR_EVENT;
31326                         }
31327                 }
31328 -               
31329 +
31330                 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
31331                         /* we don't need the out event anymore */
31332                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
31333 @@ -2315,10 +2314,10 @@
31334                         scgi_set_state(srv, hctx, FCGI_STATE_READ);
31335                 } else {
31336                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31337 -                       
31338 +
31339                         return HANDLER_WAIT_FOR_EVENT;
31340                 }
31341 -               
31342 +
31343                 break;
31344         case FCGI_STATE_READ:
31345                 /* waiting for a response */
31346 @@ -2327,67 +2326,67 @@
31347                 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
31348                 return HANDLER_ERROR;
31349         }
31350 -       
31351 +
31352         return HANDLER_WAIT_FOR_EVENT;
31353  }
31354  
31355  SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
31356         plugin_data *p = p_d;
31357 -       
31358 +
31359         handler_ctx *hctx = con->plugin_ctx[p->id];
31360         scgi_proc *proc;
31361         scgi_extension_host *host;
31362 -       
31363 +
31364         if (NULL == hctx) return HANDLER_GO_ON;
31365 -       
31366 +
31367         /* not my job */
31368         if (con->mode != p->id) return HANDLER_GO_ON;
31369 -       
31370 +
31371         /* ok, create the request */
31372         switch(scgi_write_request(srv, hctx)) {
31373         case HANDLER_ERROR:
31374                 proc = hctx->proc;
31375                 host = hctx->host;
31376 -               
31377 -               if (proc && 
31378 +
31379 +               if (proc &&
31380                     0 == proc->is_local &&
31381                     proc->state != PROC_STATE_DISABLED) {
31382                         /* only disable remote servers as we don't manage them*/
31383 -                       
31384 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "fcgi-server disabled:", 
31385 +
31386 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "fcgi-server disabled:",
31387                                         host->host,
31388                                         proc->port,
31389                                         proc->socket);
31390 -                       
31391 +
31392                         /* disable this server */
31393                         proc->disable_ts = srv->cur_ts;
31394                         proc->state = PROC_STATE_DISABLED;
31395                         host->active_procs--;
31396                 }
31397 -               
31398 +
31399                 if (hctx->state == FCGI_STATE_INIT ||
31400                     hctx->state == FCGI_STATE_CONNECT) {
31401 -                       /* connect() or getsockopt() failed, 
31402 -                        * restart the request-handling 
31403 +                       /* connect() or getsockopt() failed,
31404 +                        * restart the request-handling
31405                          */
31406                         if (proc && proc->is_local) {
31407  
31408                                 if (p->conf.debug) {
31409 -                                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "connect() to scgi failed, restarting the request-handling:", 
31410 +                                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "connect() to scgi failed, restarting the request-handling:",
31411                                                         host->host,
31412                                                         proc->port,
31413                                                         proc->socket);
31414                                 }
31415  
31416 -                               /* 
31417 +                               /*
31418                                  * several hctx might reference the same proc
31419 -                                * 
31420 +                                *
31421                                  * Only one of them should mark the proc as dead all the other
31422                                  * ones should just take a new one.
31423 -                                * 
31424 +                                *
31425                                  * If a new proc was started with the old struct this might lead
31426                                  * the mark a perfect proc as dead otherwise
31427 -                                * 
31428 +                                *
31429                                  */
31430                                 if (proc->state == PROC_STATE_RUNNING &&
31431                                     hctx->pid == proc->pid) {
31432 @@ -2395,25 +2394,25 @@
31433                                 }
31434                         }
31435                         scgi_restart_dead_procs(srv, p, host);
31436 -                       
31437 +
31438                         scgi_connection_cleanup(srv, hctx);
31439 -                       
31440 +
31441                         buffer_reset(con->physical.path);
31442                         con->mode = DIRECT;
31443                         joblist_append(srv, con);
31444 -                       
31445 -                       /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop 
31446 -                        * and hope that the childs will be restarted 
31447 -                        * 
31448 +
31449 +                       /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31450 +                        * and hope that the childs will be restarted
31451 +                        *
31452                          */
31453                         return HANDLER_WAIT_FOR_FD;
31454                 } else {
31455                         scgi_connection_cleanup(srv, hctx);
31456 -                       
31457 +
31458                         buffer_reset(con->physical.path);
31459                         con->mode = DIRECT;
31460                         con->http_status = 503;
31461 -                       
31462 +
31463                         return HANDLER_FINISHED;
31464                 }
31465         case HANDLER_WAIT_FOR_EVENT:
31466 @@ -2433,23 +2432,23 @@
31467  static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
31468         plugin_data *p;
31469         connection  *con;
31470 -       
31471 +
31472         if (NULL == hctx) return HANDLER_GO_ON;
31473 -       
31474 +
31475         p    = hctx->plugin_data;
31476         con  = hctx->remote_conn;
31477 -       
31478 +
31479         if (con->mode != p->id) return HANDLER_GO_ON;
31480 -       
31481 -       log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
31482 -                       "emergency exit: scgi:", 
31483 +
31484 +       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31485 +                       "emergency exit: scgi:",
31486                         "connection-fd:", con->fd,
31487                         "fcgi-fd:", hctx->fd);
31488 -       
31489 -       
31490 -       
31491 +
31492 +
31493 +
31494         scgi_connection_cleanup(srv, hctx);
31495 -       
31496 +
31497         return HANDLER_FINISHED;
31498  }
31499  
31500 @@ -2459,7 +2458,7 @@
31501         handler_ctx *hctx = ctx;
31502         connection  *con  = hctx->remote_conn;
31503         plugin_data *p    = hctx->plugin_data;
31504 -       
31505 +
31506         scgi_proc *proc   = hctx->proc;
31507         scgi_extension_host *host= hctx->host;
31508  
31509 @@ -2471,15 +2470,15 @@
31510                 case 1:
31511                         /* we are done */
31512                         scgi_connection_cleanup(srv, hctx);
31513 -                       
31514 +
31515                         joblist_append(srv, con);
31516                         return HANDLER_FINISHED;
31517                 case -1:
31518                         if (proc->pid && proc->state != PROC_STATE_DIED) {
31519                                 int status;
31520 -                               
31521 +
31522                                 /* only fetch the zombie if it is not already done */
31523 -                               
31524 +#ifndef _WIN32
31525                                 switch(waitpid(proc->pid, &status, WNOHANG)) {
31526                                 case 0:
31527                                         /* child is still alive */
31528 @@ -2489,19 +2488,19 @@
31529                                 default:
31530                                         /* the child should not terminate at all */
31531                                         if (WIFEXITED(status)) {
31532 -                                               log_error_write(srv, __FILE__, __LINE__, "sdsd", 
31533 +                                               log_error_write(srv, __FILE__, __LINE__, "sdsd",
31534                                                                 "child exited, pid:", proc->pid,
31535                                                                 "status:", WEXITSTATUS(status));
31536                                         } else if (WIFSIGNALED(status)) {
31537 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31538 -                                                               "child signaled:", 
31539 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31540 +                                                               "child signaled:",
31541                                                                 WTERMSIG(status));
31542                                         } else {
31543 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31544 -                                                               "child died somehow:", 
31545 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31546 +                                                               "child died somehow:",
31547                                                                 status);
31548                                         }
31549 -                                       
31550 +
31551                                         if (p->conf.debug) {
31552                                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31553                                                                 "--- scgi spawning",
31554 @@ -2509,40 +2508,41 @@
31555                                                                 "\n\tsocket", host->unixsocket,
31556                                                                 "\n\tcurrent:", 1, "/", host->min_procs);
31557                                         }
31558 -                                       
31559 +
31560                                         if (scgi_spawn_connection(srv, p, host, proc)) {
31561                                                 /* child died */
31562                                                 proc->state = PROC_STATE_DIED;
31563                                         } else {
31564                                                 scgi_proclist_sort_down(srv, host, proc);
31565                                         }
31566 -                                       
31567 +
31568                                         break;
31569                                 }
31570 +#endif
31571                         }
31572  
31573                         if (con->file_started == 0) {
31574                                 /* nothing has been send out yet, try to use another child */
31575 -                               
31576 +
31577                                 if (hctx->wb->bytes_out == 0 &&
31578                                     hctx->reconnects < 5) {
31579                                         scgi_reconnect(srv, hctx);
31580 -                                       
31581 -                                       log_error_write(srv, __FILE__, __LINE__, "sdsdsd", 
31582 +
31583 +                                       log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31584                                                 "response not sent, request not sent, reconnection.",
31585                                                 "connection-fd:", con->fd,
31586                                                 "fcgi-fd:", hctx->fd);
31587 -                                       
31588 +
31589                                         return HANDLER_WAIT_FOR_FD;
31590                                 }
31591 -                               
31592 -                               log_error_write(srv, __FILE__, __LINE__, "sdsdsd", 
31593 +
31594 +                               log_error_write(srv, __FILE__, __LINE__, "sosdsd",
31595                                                 "response not sent, request sent:", hctx->wb->bytes_out,
31596                                                 "connection-fd:", con->fd,
31597                                                 "fcgi-fd:", hctx->fd);
31598 -                               
31599 +
31600                                 scgi_connection_cleanup(srv, hctx);
31601 -                               
31602 +
31603                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
31604                                 buffer_reset(con->physical.path);
31605                                 con->http_status = 500;
31606 @@ -2550,76 +2550,76 @@
31607                         } else {
31608                                 /* response might have been already started, kill the connection */
31609                                 scgi_connection_cleanup(srv, hctx);
31610 -                               
31611 -                               log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
31612 +
31613 +                               log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31614                                                 "response already sent out, termination connection",
31615                                                 "connection-fd:", con->fd,
31616                                                 "fcgi-fd:", hctx->fd);
31617 -                               
31618 +
31619                                 connection_set_state(srv, con, CON_STATE_ERROR);
31620                         }
31621  
31622                         /* */
31623 -                       
31624 -                       
31625 +
31626 +
31627                         joblist_append(srv, con);
31628                         return HANDLER_FINISHED;
31629                 }
31630         }
31631 -       
31632 +
31633         if (revents & FDEVENT_OUT) {
31634                 if (hctx->state == FCGI_STATE_CONNECT ||
31635                     hctx->state == FCGI_STATE_WRITE) {
31636                         /* we are allowed to send something out
31637 -                        * 
31638 +                        *
31639                          * 1. in a unfinished connect() call
31640                          * 2. in a unfinished write() call (long POST request)
31641                          */
31642                         return mod_scgi_handle_subrequest(srv, con, p);
31643                 } else {
31644 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
31645 -                                       "got a FDEVENT_OUT and didn't know why:", 
31646 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
31647 +                                       "got a FDEVENT_OUT and didn't know why:",
31648                                         hctx->state);
31649                 }
31650         }
31651 -       
31652 +
31653         /* perhaps this issue is already handled */
31654         if (revents & FDEVENT_HUP) {
31655                 if (hctx->state == FCGI_STATE_CONNECT) {
31656                         /* getoptsock will catch this one (right ?)
31657 -                        * 
31658 -                        * if we are in connect we might get a EINPROGRESS 
31659 -                        * in the first call and a FDEVENT_HUP in the 
31660 +                        *
31661 +                        * if we are in connect we might get a EINPROGRESS
31662 +                        * in the first call and a FDEVENT_HUP in the
31663                          * second round
31664 -                        * 
31665 +                        *
31666                          * FIXME: as it is a bit ugly.
31667 -                        * 
31668 +                        *
31669                          */
31670                         return mod_scgi_handle_subrequest(srv, con, p);
31671                 } else if (hctx->state == FCGI_STATE_READ &&
31672                            hctx->proc->port == 0) {
31673                         /* FIXME:
31674 -                        * 
31675 +                        *
31676                          * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
31677                          * even if the FCGI_FIN packet is not received yet
31678                          */
31679                 } else {
31680 -                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", 
31681 -                                       "error: unexpected close of scgi connection for", 
31682 +                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
31683 +                                       "error: unexpected close of scgi connection for",
31684                                         con->uri.path,
31685 -                                       "(no scgi process on host: ", 
31686 +                                       "(no scgi process on host: ",
31687                                         host->host,
31688 -                                       ", port: ", 
31689 +                                       ", port: ",
31690                                         host->port,
31691                                         " ?)",
31692                                         hctx->state);
31693 -                       
31694 +
31695                         connection_set_state(srv, con, CON_STATE_ERROR);
31696                         scgi_connection_close(srv, hctx);
31697                         joblist_append(srv, con);
31698                 }
31699         } else if (revents & FDEVENT_ERR) {
31700 -               log_error_write(srv, __FILE__, __LINE__, "s", 
31701 +               log_error_write(srv, __FILE__, __LINE__, "s",
31702                                 "fcgi: got a FDEVENT_ERR. Don't know why.");
31703                 /* kill all connections to the scgi process */
31704  
31705 @@ -2628,42 +2628,39 @@
31706                 scgi_connection_close(srv, hctx);
31707                 joblist_append(srv, con);
31708         }
31709 -       
31710 +
31711         return HANDLER_FINISHED;
31712  }
31713 -#define PATCH(x) \
31714 -       p->conf.x = s->x;
31715 +
31716  static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
31717         size_t i, j;
31718         plugin_config *s = p->config_storage[0];
31719 -       
31720 -       PATCH(exts);
31721 -       PATCH(debug);
31722 -       
31723 +
31724 +       PATCH_OPTION(exts);
31725 +       PATCH_OPTION(debug);
31726 +
31727         /* skip the first, the global context */
31728         for (i = 1; i < srv->config_context->used; i++) {
31729                 data_config *dc = (data_config *)srv->config_context->data[i];
31730                 s = p->config_storage[i];
31731 -               
31732 +
31733                 /* condition didn't match */
31734                 if (!config_check_cond(srv, con, dc)) continue;
31735 -               
31736 +
31737                 /* merge config */
31738                 for (j = 0; j < dc->value->used; j++) {
31739                         data_unset *du = dc->value->data[j];
31740 -                       
31741 +
31742                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
31743 -                               PATCH(exts);
31744 +                               PATCH_OPTION(exts);
31745                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
31746 -                               PATCH(debug);
31747 +                               PATCH_OPTION(debug);
31748                         }
31749                 }
31750         }
31751 -       
31752 +
31753         return 0;
31754  }
31755 -#undef PATCH
31756 -
31757  
31758  static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
31759         plugin_data *p = p_d;
31760 @@ -2673,30 +2670,30 @@
31761         size_t k;
31762         buffer *fn;
31763         scgi_extension *extension = NULL;
31764 -       
31765 +
31766         /* Possibly, we processed already this request */
31767         if (con->file_started == 1) return HANDLER_GO_ON;
31768 -       
31769 +
31770         fn = uri_path_handler ? con->uri.path : con->physical.path;
31771  
31772         if (buffer_is_empty(fn)) return HANDLER_GO_ON;
31773  
31774         s_len = fn->used - 1;
31775 -       
31776 +
31777         scgi_patch_connection(srv, con, p);
31778  
31779         /* check if extension matches */
31780         for (k = 0; k < p->conf.exts->used; k++) {
31781                 size_t ct_len;
31782 -               
31783 +
31784                 extension = p->conf.exts->exts[k];
31785 -               
31786 +
31787                 if (extension->key->used == 0) continue;
31788 -               
31789 +
31790                 ct_len = extension->key->used - 1;
31791 -               
31792 +
31793                 if (s_len < ct_len) continue;
31794 -               
31795 +
31796                 /* check extension in the form "/scgi_pattern" */
31797                 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
31798                         break;
31799 @@ -2710,17 +2707,17 @@
31800         if (k == p->conf.exts->used) {
31801                 return HANDLER_GO_ON;
31802         }
31803 -       
31804 +
31805         /* get best server */
31806         for (k = 0, ndx = -1; k < extension->used; k++) {
31807                 scgi_extension_host *host = extension->hosts[k];
31808 -               
31809 +
31810                 /* we should have at least one proc that can do somthing */
31811                 if (host->active_procs == 0) continue;
31812  
31813                 if (used == -1 || host->load < used) {
31814                         used = host->load;
31815 -                       
31816 +
31817                         ndx = k;
31818                 }
31819         }
31820 @@ -2728,12 +2725,12 @@
31821         /* found a server */
31822         if (ndx != -1) {
31823                 scgi_extension_host *host = extension->hosts[ndx];
31824 -               
31825 -               /* 
31826 -                * if check-local is disabled, use the uri.path handler 
31827 -                * 
31828 +
31829 +               /*
31830 +                * if check-local is disabled, use the uri.path handler
31831 +                *
31832                  */
31833 -               
31834 +
31835                 /* init handler-context */
31836                 if (uri_path_handler) {
31837                         if (host->check_local == 0) {
31838 @@ -2741,7 +2738,7 @@
31839                                 char *pathinfo;
31840  
31841                                 hctx = handler_ctx_init();
31842 -                               
31843 +
31844                                 hctx->remote_conn      = con;
31845                                 hctx->plugin_data      = p;
31846                                 hctx->host             = host;
31847 @@ -2749,45 +2746,45 @@
31848  
31849                                 hctx->conf.exts        = p->conf.exts;
31850                                 hctx->conf.debug       = p->conf.debug;
31851 -                               
31852 +
31853                                 con->plugin_ctx[p->id] = hctx;
31854 -                               
31855 +
31856                                 host->load++;
31857 -                               
31858 +
31859                                 con->mode = p->id;
31860  
31861                                 if (con->conf.log_request_handling) {
31862                                         log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
31863                                 }
31864  
31865 -                               /* the prefix is the SCRIPT_NAME, 
31866 +                               /* the prefix is the SCRIPT_NAME,
31867                                  * everthing from start to the next slash
31868                                  * this is important for check-local = "disable"
31869 -                                * 
31870 +                                *
31871                                  * if prefix = /admin.fcgi
31872 -                                * 
31873 +                                *
31874                                  * /admin.fcgi/foo/bar
31875 -                                * 
31876 +                                *
31877                                  * SCRIPT_NAME = /admin.fcgi
31878                                  * PATH_INFO   = /foo/bar
31879 -                                * 
31880 +                                *
31881                                  * if prefix = /fcgi-bin/
31882 -                                * 
31883 +                                *
31884                                  * /fcgi-bin/foo/bar
31885 -                                * 
31886 +                                *
31887                                  * SCRIPT_NAME = /fcgi-bin/foo
31888                                  * PATH_INFO   = /bar
31889 -                                * 
31890 +                                *
31891                                  */
31892 -                               
31893 +
31894                                 /* the rewrite is only done for /prefix/? matches */
31895                                 if (extension->key->ptr[0] == '/' &&
31896                                     con->uri.path->used > extension->key->used &&
31897                                     NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
31898 -                                       /* rewrite uri.path and pathinfo */ 
31899 -                                       
31900 +                                       /* rewrite uri.path and pathinfo */
31901 +
31902                                         buffer_copy_string(con->request.pathinfo, pathinfo);
31903 -                                       
31904 +
31905                                         con->uri.path->used -= con->request.pathinfo->used - 1;
31906                                         con->uri.path->ptr[con->uri.path->used - 1] = '\0';
31907                                 }
31908 @@ -2796,21 +2793,21 @@
31909                 } else {
31910                         handler_ctx *hctx;
31911                         hctx = handler_ctx_init();
31912 -                       
31913 +
31914                         hctx->remote_conn      = con;
31915                         hctx->plugin_data      = p;
31916                         hctx->host             = host;
31917                         hctx->proc             = NULL;
31918 -                       
31919 +
31920                         hctx->conf.exts        = p->conf.exts;
31921                         hctx->conf.debug       = p->conf.debug;
31922 -                       
31923 +
31924                         con->plugin_ctx[p->id] = hctx;
31925 -                       
31926 +
31927                         host->load++;
31928 -                       
31929 +
31930                         con->mode = p->id;
31931 -                       
31932 +
31933                         if (con->conf.log_request_handling) {
31934                                 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
31935                         }
31936 @@ -2821,11 +2818,11 @@
31937                 /* no handler found */
31938                 buffer_reset(con->physical.path);
31939                 con->http_status = 500;
31940 -               
31941 -               log_error_write(srv, __FILE__, __LINE__,  "sb", 
31942 -                               "no fcgi-handler found for:", 
31943 +
31944 +               log_error_write(srv, __FILE__, __LINE__,  "sb",
31945 +                               "no fcgi-handler found for:",
31946                                 fn);
31947 -               
31948 +
31949                 return HANDLER_FINISHED;
31950         }
31951         return HANDLER_GO_ON;
31952 @@ -2844,19 +2841,19 @@
31953  JOBLIST_FUNC(mod_scgi_handle_joblist) {
31954         plugin_data *p = p_d;
31955         handler_ctx *hctx = con->plugin_ctx[p->id];
31956 -       
31957 +
31958         if (hctx == NULL) return HANDLER_GO_ON;
31959  
31960         if (hctx->fd != -1) {
31961                 switch (hctx->state) {
31962                 case FCGI_STATE_READ:
31963                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
31964 -                       
31965 +
31966                         break;
31967                 case FCGI_STATE_CONNECT:
31968                 case FCGI_STATE_WRITE:
31969                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31970 -                       
31971 +
31972                         break;
31973                 case FCGI_STATE_INIT:
31974                         /* at reconnect */
31975 @@ -2873,21 +2870,21 @@
31976  
31977  static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
31978         plugin_data *p = p_d;
31979 -       
31980 +
31981         return scgi_connection_close(srv, con->plugin_ctx[p->id]);
31982  }
31983  
31984  TRIGGER_FUNC(mod_scgi_handle_trigger) {
31985         plugin_data *p = p_d;
31986         size_t i, j, n;
31987 -       
31988 -       
31989 +
31990 +
31991         /* perhaps we should kill a connect attempt after 10-15 seconds
31992 -        * 
31993 +        *
31994          * currently we wait for the TCP timeout which is on Linux 180 seconds
31995 -        * 
31996 -        * 
31997 -        * 
31998 +        *
31999 +        *
32000 +        *
32001          */
32002  
32003         /* check all childs if they are still up */
32004 @@ -2904,47 +2901,47 @@
32005                         scgi_extension *ex;
32006  
32007                         ex = exts->exts[j];
32008 -                       
32009 +
32010                         for (n = 0; n < ex->used; n++) {
32011 -                               
32012 +
32013                                 scgi_proc *proc;
32014                                 unsigned long sum_load = 0;
32015                                 scgi_extension_host *host;
32016 -                               
32017 +
32018                                 host = ex->hosts[n];
32019 -                               
32020 +
32021                                 scgi_restart_dead_procs(srv, p, host);
32022 -                               
32023 +
32024                                 for (proc = host->first; proc; proc = proc->next) {
32025                                         sum_load += proc->load;
32026                                 }
32027 -                               
32028 +
32029                                 if (host->num_procs &&
32030                                     host->num_procs < host->max_procs &&
32031                                     (sum_load / host->num_procs) > host->max_load_per_proc) {
32032                                         /* overload, spawn new child */
32033                                         scgi_proc *fp = NULL;
32034 -                                       
32035 +
32036                                         if (p->conf.debug) {
32037 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
32038 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
32039                                                                 "overload detected, spawning a new child");
32040                                         }
32041 -                                       
32042 +
32043                                         for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
32044 -                                       
32045 +
32046                                         if (fp) {
32047                                                 if (fp == host->unused_procs) host->unused_procs = fp->next;
32048 -                                               
32049 +
32050                                                 if (fp->next) fp->next->prev = NULL;
32051 -                                               
32052 +
32053                                                 host->max_id++;
32054                                         } else {
32055                                                 fp = scgi_process_init();
32056                                                 fp->id = host->max_id++;
32057                                         }
32058 -                                       
32059 +
32060                                         host->num_procs++;
32061 -                                       
32062 +
32063                                         if (buffer_is_empty(host->unixsocket)) {
32064                                                 fp->port = host->port + fp->id;
32065                                         } else {
32066 @@ -2952,13 +2949,13 @@
32067                                                 buffer_append_string(fp->socket, "-");
32068                                                 buffer_append_long(fp->socket, fp->id);
32069                                         }
32070 -                                       
32071 +
32072                                         if (scgi_spawn_connection(srv, p, host, fp)) {
32073                                                 log_error_write(srv, __FILE__, __LINE__, "s",
32074                                                                 "ERROR: spawning fcgi failed.");
32075                                                 return HANDLER_ERROR;
32076                                         }
32077 -                                       
32078 +
32079                                         fp->prev = NULL;
32080                                         fp->next = host->first;
32081                                         if (host->first) {
32082 @@ -2966,56 +2963,57 @@
32083                                         }
32084                                         host->first = fp;
32085                                 }
32086 -                               
32087 +
32088                                 for (proc = host->first; proc; proc = proc->next) {
32089                                         if (proc->load != 0) break;
32090                                         if (host->num_procs <= host->min_procs) break;
32091                                         if (proc->pid == 0) continue;
32092 -                                       
32093 +#ifndef _WIN32
32094                                         if (srv->cur_ts - proc->last_used > host->idle_timeout) {
32095                                                 /* a proc is idling for a long time now,
32096                                                  * terminated it */
32097 -                                               
32098 +
32099                                                 if (p->conf.debug) {
32100 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
32101 -                                                                       "idle-timeout reached, terminating child:", 
32102 -                                                                       "socket:", proc->socket, 
32103 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32104 +                                                                       "idle-timeout reached, terminating child:",
32105 +                                                                       "socket:", proc->socket,
32106                                                                         "pid", proc->pid);
32107                                                 }
32108 -                                               
32109 -                                               
32110 +
32111 +
32112                                                 if (proc->next) proc->next->prev = proc->prev;
32113                                                 if (proc->prev) proc->prev->next = proc->next;
32114 -                                               
32115 +
32116                                                 if (proc->prev == NULL) host->first = proc->next;
32117 -                                               
32118 +
32119                                                 proc->prev = NULL;
32120                                                 proc->next = host->unused_procs;
32121 -                                               
32122 +
32123                                                 if (host->unused_procs) host->unused_procs->prev = proc;
32124                                                 host->unused_procs = proc;
32125 -                                               
32126 +
32127                                                 kill(proc->pid, SIGTERM);
32128 -                                               
32129 +
32130                                                 proc->state = PROC_STATE_KILLED;
32131 -                                               
32132 -                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
32133 -                                                                       "killed:", 
32134 -                                                                       "socket:", proc->socket, 
32135 +
32136 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32137 +                                                                       "killed:",
32138 +                                                                       "socket:", proc->socket,
32139                                                                         "pid", proc->pid);
32140 -                                               
32141 +
32142                                                 host->num_procs--;
32143 -                                               
32144 +
32145                                                 /* proc is now in unused, let the next second handle the next process */
32146                                                 break;
32147 -                                       }       
32148 +                                       }
32149 +#endif
32150                                 }
32151 -                               
32152 +
32153                                 for (proc = host->unused_procs; proc; proc = proc->next) {
32154                                         int status;
32155 -                                       
32156 +
32157                                         if (proc->pid == 0) continue;
32158 -                                       
32159 +#ifndef _WIN32
32160                                         switch (waitpid(proc->pid, &status, WNOHANG)) {
32161                                         case 0:
32162                                                 /* child still running after timeout, good */
32163 @@ -3023,10 +3021,10 @@
32164                                         case -1:
32165                                                 if (errno != EINTR) {
32166                                                         /* no PID found ? should never happen */
32167 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddss", 
32168 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddss",
32169                                                                         "pid ", proc->pid, proc->state,
32170                                                                         "not found:", strerror(errno));
32171 -                                                       
32172 +
32173  #if 0
32174                                                         if (errno == ECHILD) {
32175                                                                 /* someone else has cleaned up for us */
32176 @@ -3040,25 +3038,26 @@
32177                                                 /* the child should not terminate at all */
32178                                                 if (WIFEXITED(status)) {
32179                                                         if (proc->state != PROC_STATE_KILLED) {
32180 -                                                               log_error_write(srv, __FILE__, __LINE__, "sdb", 
32181 -                                                                               "child exited:", 
32182 +                                                               log_error_write(srv, __FILE__, __LINE__, "sdb",
32183 +                                                                               "child exited:",
32184                                                                                 WEXITSTATUS(status), proc->socket);
32185                                                         }
32186                                                 } else if (WIFSIGNALED(status)) {
32187                                                         if (WTERMSIG(status) != SIGTERM) {
32188 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
32189 -                                                                               "child signaled:", 
32190 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
32191 +                                                                               "child signaled:",
32192                                                                                 WTERMSIG(status));
32193                                                         }
32194                                                 } else {
32195 -                                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
32196 -                                                                       "child died somehow:", 
32197 +                                                       log_error_write(srv, __FILE__, __LINE__, "sd",
32198 +                                                                       "child died somehow:",
32199                                                                         status);
32200                                                 }
32201                                                 proc->pid = 0;
32202                                                 proc->state = PROC_STATE_UNSET;
32203                                                 host->max_id--;
32204                                         }
32205 +#endif
32206                                 }
32207                         }
32208                 }
32209 @@ -3082,8 +3081,8 @@
32210         p->handle_subrequest       = mod_scgi_handle_subrequest;
32211         p->handle_joblist          = mod_scgi_handle_joblist;
32212         p->handle_trigger          = mod_scgi_handle_trigger;
32213 -       
32214 +
32215         p->data         = NULL;
32216 -       
32217 +
32218         return 0;
32219  }
32220 --- ../lighttpd-1.4.11/src/mod_secure_download.c        2005-12-14 14:37:29.000000000 +0200
32221 +++ lighttpd-1.4.12/src/mod_secure_download.c   2006-07-11 22:07:51.000000000 +0300
32222 @@ -25,7 +25,7 @@
32223  #ifdef USE_OPENSSL
32224  #define IN const
32225  #else
32226 -#define IN 
32227 +#define IN
32228  #endif
32229  #define OUT
32230  
32231 @@ -36,28 +36,28 @@
32232         buffer *doc_root;
32233         buffer *secret;
32234         buffer *uri_prefix;
32235 -       
32236 +
32237         unsigned short timeout;
32238  } plugin_config;
32239  
32240  typedef struct {
32241         PLUGIN_DATA;
32242 -       
32243 +
32244         buffer *md5;
32245 -       
32246 +
32247         plugin_config **config_storage;
32248 -       
32249 -       plugin_config conf; 
32250 +
32251 +       plugin_config conf;
32252  } plugin_data;
32253  
32254  /* init the plugin data */
32255  INIT_FUNC(mod_secdownload_init) {
32256         plugin_data *p;
32257 -       
32258 +
32259         p = calloc(1, sizeof(*p));
32260 -       
32261 +
32262         p->md5 = buffer_init();
32263 -       
32264 +
32265         return p;
32266  }
32267  
32268 @@ -65,27 +65,27 @@
32269  FREE_FUNC(mod_secdownload_free) {
32270         plugin_data *p = p_d;
32271         UNUSED(srv);
32272 -       
32273 +
32274         if (!p) return HANDLER_GO_ON;
32275 -       
32276 +
32277         if (p->config_storage) {
32278                 size_t i;
32279                 for (i = 0; i < srv->config_context->used; i++) {
32280                         plugin_config *s = p->config_storage[i];
32281 -                       
32282 +
32283                         buffer_free(s->secret);
32284                         buffer_free(s->doc_root);
32285                         buffer_free(s->uri_prefix);
32286 -                       
32287 +
32288                         free(s);
32289                 }
32290                 free(p->config_storage);
32291         }
32292 -       
32293 +
32294         buffer_free(p->md5);
32295 -       
32296 +
32297         free(p);
32298 -       
32299 +
32300         return HANDLER_GO_ON;
32301  }
32302  
32303 @@ -94,107 +94,103 @@
32304  SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
32305         plugin_data *p = p_d;
32306         size_t i = 0;
32307 -       
32308 -       config_values_t cv[] = { 
32309 +
32310 +       config_values_t cv[] = {
32311                 { "secdownload.secret",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
32312                 { "secdownload.document-root",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
32313                 { "secdownload.uri-prefix",        NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
32314                 { "secdownload.timeout",           NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 3 */
32315                 { NULL,                            NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32316         };
32317 -       
32318 +
32319         if (!p) return HANDLER_ERROR;
32320 -       
32321 +
32322         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32323 -       
32324 +
32325         for (i = 0; i < srv->config_context->used; i++) {
32326                 plugin_config *s;
32327 -               
32328 +
32329                 s = calloc(1, sizeof(plugin_config));
32330                 s->secret        = buffer_init();
32331                 s->doc_root      = buffer_init();
32332                 s->uri_prefix    = buffer_init();
32333                 s->timeout       = 60;
32334 -               
32335 +
32336                 cv[0].destination = s->secret;
32337                 cv[1].destination = s->doc_root;
32338                 cv[2].destination = s->uri_prefix;
32339                 cv[3].destination = &(s->timeout);
32340 -               
32341 +
32342                 p->config_storage[i] = s;
32343 -       
32344 +
32345                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32346                         return HANDLER_ERROR;
32347                 }
32348         }
32349 -       
32350 +
32351         return HANDLER_GO_ON;
32352  }
32353  
32354  /**
32355   * checks if the supplied string is a MD5 string
32356 - * 
32357 + *
32358   * @param str a possible MD5 string
32359   * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
32360   */
32361  
32362  int is_hex_len(const char *str, size_t len) {
32363         size_t i;
32364 -       
32365 +
32366         if (NULL == str) return 0;
32367 -       
32368 +
32369         for (i = 0; i < len && *str; i++, str++) {
32370                 /* illegal characters */
32371                 if (!((*str >= '0' && *str <= '9') ||
32372                       (*str >= 'a' && *str <= 'f') ||
32373 -                     (*str >= 'A' && *str <= 'F')) 
32374 +                     (*str >= 'A' && *str <= 'F'))
32375                     ) {
32376                         return 0;
32377                 }
32378         }
32379 -       
32380 +
32381         return i == len;
32382  }
32383  
32384 -#define PATCH(x) \
32385 -       p->conf.x = s->x;
32386  static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
32387         size_t i, j;
32388         plugin_config *s = p->config_storage[0];
32389 -       
32390 -       PATCH(secret);
32391 -       PATCH(doc_root);
32392 -       PATCH(uri_prefix);
32393 -       PATCH(timeout);
32394 -       
32395 +
32396 +       PATCH_OPTION(secret);
32397 +       PATCH_OPTION(doc_root);
32398 +       PATCH_OPTION(uri_prefix);
32399 +       PATCH_OPTION(timeout);
32400 +
32401         /* skip the first, the global context */
32402         for (i = 1; i < srv->config_context->used; i++) {
32403                 data_config *dc = (data_config *)srv->config_context->data[i];
32404                 s = p->config_storage[i];
32405 -               
32406 +
32407                 /* condition didn't match */
32408                 if (!config_check_cond(srv, con, dc)) continue;
32409 -               
32410 +
32411                 /* merge config */
32412                 for (j = 0; j < dc->value->used; j++) {
32413                         data_unset *du = dc->value->data[j];
32414 -                       
32415 +
32416                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
32417 -                               PATCH(secret);
32418 +                               PATCH_OPTION(secret);
32419                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
32420 -                               PATCH(doc_root);
32421 +                               PATCH_OPTION(doc_root);
32422                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
32423 -                               PATCH(uri_prefix);
32424 +                               PATCH_OPTION(uri_prefix);
32425                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
32426 -                               PATCH(timeout);
32427 +                               PATCH_OPTION(timeout);
32428                         }
32429                 }
32430         }
32431 -       
32432 +
32433         return 0;
32434  }
32435 -#undef PATCH
32436 -
32437  
32438  URIHANDLER_FUNC(mod_secdownload_uri_handler) {
32439         plugin_data *p = p_d;
32440 @@ -203,88 +199,88 @@
32441         const char *rel_uri, *ts_str, *md5_str;
32442         time_t ts = 0;
32443         size_t i;
32444 -       
32445 +
32446         if (con->uri.path->used == 0) return HANDLER_GO_ON;
32447 -       
32448 +
32449         mod_secdownload_patch_connection(srv, con, p);
32450  
32451         if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
32452 -       
32453 +
32454         if (buffer_is_empty(p->conf.secret)) {
32455                 log_error_write(srv, __FILE__, __LINE__, "s",
32456                                 "secdownload.secret has to be set");
32457                 return HANDLER_ERROR;
32458         }
32459 -       
32460 +
32461         if (buffer_is_empty(p->conf.doc_root)) {
32462                 log_error_write(srv, __FILE__, __LINE__, "s",
32463                                 "secdownload.document-root has to be set");
32464                 return HANDLER_ERROR;
32465         }
32466 -       
32467 -       /* 
32468 +
32469 +       /*
32470          *  /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
32471          */
32472 -       
32473 +
32474         if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
32475 -       
32476 +
32477         md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
32478 -       
32479 +
32480         if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
32481         if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
32482 -       
32483 +
32484         ts_str = md5_str + 32 + 1;
32485 -       
32486 +
32487         if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
32488         if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
32489 -       
32490 +
32491         for (i = 0; i < 8; i++) {
32492                 ts = (ts << 4) + hex2int(*(ts_str + i));
32493         }
32494 -       
32495 +
32496         /* timed-out */
32497 -       if (srv->cur_ts - ts > p->conf.timeout || 
32498 +       if (srv->cur_ts - ts > p->conf.timeout ||
32499             srv->cur_ts - ts < -p->conf.timeout) {
32500                 con->http_status = 408;
32501 -               
32502 +
32503                 return HANDLER_FINISHED;
32504         }
32505 -       
32506 +
32507         rel_uri = ts_str + 8;
32508 -       
32509 -       /* checking MD5 
32510 -        * 
32511 +
32512 +       /* checking MD5
32513 +        *
32514          * <secret><rel-path><timestamp-hex>
32515          */
32516 -       
32517 +
32518         buffer_copy_string_buffer(p->md5, p->conf.secret);
32519         buffer_append_string(p->md5, rel_uri);
32520         buffer_append_string_len(p->md5, ts_str, 8);
32521 -       
32522 +
32523         MD5_Init(&Md5Ctx);
32524         MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
32525         MD5_Final(HA1, &Md5Ctx);
32526 -       
32527 +
32528         buffer_copy_string_hex(p->md5, (char *)HA1, 16);
32529 -       
32530 +
32531         if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
32532                 con->http_status = 403;
32533 -               
32534 -               log_error_write(srv, __FILE__, __LINE__, "sss", 
32535 +
32536 +               log_error_write(srv, __FILE__, __LINE__, "sss",
32537                                 "md5 invalid:",
32538                                 md5_str, p->md5->ptr);
32539 -               
32540 +
32541                 return HANDLER_FINISHED;
32542         }
32543 -       
32544 +
32545         /* starting with the last / we should have relative-path to the docroot
32546          */
32547 -       
32548 +
32549         buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
32550         buffer_copy_string(con->physical.rel_path, rel_uri);
32551         buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
32552         buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
32553 -       
32554 +
32555         return HANDLER_GO_ON;
32556  }
32557  
32558 @@ -293,13 +289,13 @@
32559  int mod_secdownload_plugin_init(plugin *p) {
32560         p->version     = LIGHTTPD_VERSION_ID;
32561         p->name        = buffer_init_string("secdownload");
32562 -       
32563 +
32564         p->init        = mod_secdownload_init;
32565         p->handle_physical  = mod_secdownload_uri_handler;
32566         p->set_defaults  = mod_secdownload_set_defaults;
32567         p->cleanup     = mod_secdownload_free;
32568 -       
32569 +
32570         p->data        = NULL;
32571 -       
32572 +
32573         return 0;
32574  }
32575 --- ../lighttpd-1.4.11/src/mod_setenv.c 2006-01-14 20:33:12.000000000 +0200
32576 +++ lighttpd-1.4.12/src/mod_setenv.c    2006-07-11 22:07:53.000000000 +0300
32577 @@ -18,25 +18,25 @@
32578  typedef struct {
32579         array *request_header;
32580         array *response_header;
32581 -       
32582 +
32583         array *environment;
32584  } plugin_config;
32585  
32586  typedef struct {
32587         PLUGIN_DATA;
32588 -       
32589 +
32590         plugin_config **config_storage;
32591 -       
32592 -       plugin_config conf; 
32593 +
32594 +       plugin_config conf;
32595  } plugin_data;
32596  
32597  static handler_ctx * handler_ctx_init() {
32598         handler_ctx * hctx;
32599 -       
32600 +
32601         hctx = calloc(1, sizeof(*hctx));
32602 -       
32603 +
32604         hctx->handled = 0;
32605 -       
32606 +
32607         return hctx;
32608  }
32609  
32610 @@ -48,36 +48,36 @@
32611  /* init the plugin data */
32612  INIT_FUNC(mod_setenv_init) {
32613         plugin_data *p;
32614 -       
32615 +
32616         p = calloc(1, sizeof(*p));
32617 -       
32618 +
32619         return p;
32620  }
32621  
32622  /* detroy the plugin data */
32623  FREE_FUNC(mod_setenv_free) {
32624         plugin_data *p = p_d;
32625 -       
32626 +
32627         UNUSED(srv);
32628  
32629         if (!p) return HANDLER_GO_ON;
32630 -       
32631 +
32632         if (p->config_storage) {
32633                 size_t i;
32634                 for (i = 0; i < srv->config_context->used; i++) {
32635                         plugin_config *s = p->config_storage[i];
32636 -                       
32637 +
32638                         array_free(s->request_header);
32639                         array_free(s->response_header);
32640                         array_free(s->environment);
32641 -                       
32642 +
32643                         free(s);
32644                 }
32645                 free(p->config_storage);
32646         }
32647 -       
32648 +
32649         free(p);
32650 -       
32651 +
32652         return HANDLER_GO_ON;
32653  }
32654  
32655 @@ -86,86 +86,83 @@
32656  SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
32657         plugin_data *p = p_d;
32658         size_t i = 0;
32659 -       
32660 -       config_values_t cv[] = { 
32661 +
32662 +       config_values_t cv[] = {
32663                 { "setenv.add-request-header",  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
32664                 { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
32665                 { "setenv.add-environment",     NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
32666                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32667         };
32668 -       
32669 +
32670         if (!p) return HANDLER_ERROR;
32671 -       
32672 +
32673         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32674 -       
32675 +
32676         for (i = 0; i < srv->config_context->used; i++) {
32677                 plugin_config *s;
32678 -               
32679 +
32680                 s = calloc(1, sizeof(plugin_config));
32681                 s->request_header   = array_init();
32682                 s->response_header  = array_init();
32683                 s->environment      = array_init();
32684 -               
32685 +
32686                 cv[0].destination = s->request_header;
32687                 cv[1].destination = s->response_header;
32688                 cv[2].destination = s->environment;
32689 -               
32690 +
32691                 p->config_storage[i] = s;
32692 -       
32693 +
32694                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32695                         return HANDLER_ERROR;
32696                 }
32697         }
32698 -       
32699 +
32700         return HANDLER_GO_ON;
32701  }
32702  
32703 -#define PATCH(x) \
32704 -       p->conf.x = s->x;
32705  static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
32706         size_t i, j;
32707         plugin_config *s = p->config_storage[0];
32708 -       
32709 -       PATCH(request_header);
32710 -       PATCH(response_header);
32711 -       PATCH(environment);
32712 -       
32713 +
32714 +       PATCH_OPTION(request_header);
32715 +       PATCH_OPTION(response_header);
32716 +       PATCH_OPTION(environment);
32717 +
32718         /* skip the first, the global context */
32719         for (i = 1; i < srv->config_context->used; i++) {
32720                 data_config *dc = (data_config *)srv->config_context->data[i];
32721                 s = p->config_storage[i];
32722 -               
32723 +
32724                 /* condition didn't match */
32725                 if (!config_check_cond(srv, con, dc)) continue;
32726 -               
32727 +
32728                 /* merge config */
32729                 for (j = 0; j < dc->value->used; j++) {
32730                         data_unset *du = dc->value->data[j];
32731 -                       
32732 +
32733                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
32734 -                               PATCH(request_header);
32735 +                               PATCH_OPTION(request_header);
32736                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
32737 -                               PATCH(response_header);
32738 +                               PATCH_OPTION(response_header);
32739                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
32740 -                               PATCH(environment);
32741 +                               PATCH_OPTION(environment);
32742                         }
32743                 }
32744         }
32745 -       
32746 +
32747         return 0;
32748  }
32749 -#undef PATCH
32750  
32751  URIHANDLER_FUNC(mod_setenv_uri_handler) {
32752         plugin_data *p = p_d;
32753         size_t k;
32754         handler_ctx *hctx;
32755 -       
32756 +
32757         if (con->plugin_ctx[p->id]) {
32758                 hctx = con->plugin_ctx[p->id];
32759         } else {
32760                 hctx = handler_ctx_init();
32761 -                               
32762 +
32763                 con->plugin_ctx[p->id] = hctx;
32764         }
32765  
32766 @@ -180,52 +177,52 @@
32767         for (k = 0; k < p->conf.request_header->used; k++) {
32768                 data_string *ds = (data_string *)p->conf.request_header->data[k];
32769                 data_string *ds_dst;
32770 -               
32771 +
32772                 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
32773                         ds_dst = data_string_init();
32774                 }
32775 -               
32776 +
32777                 buffer_copy_string_buffer(ds_dst->key, ds->key);
32778                 buffer_copy_string_buffer(ds_dst->value, ds->value);
32779 -               
32780 +
32781                 array_insert_unique(con->request.headers, (data_unset *)ds_dst);
32782         }
32783 -       
32784 +
32785         for (k = 0; k < p->conf.environment->used; k++) {
32786                 data_string *ds = (data_string *)p->conf.environment->data[k];
32787                 data_string *ds_dst;
32788 -               
32789 +
32790                 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
32791                         ds_dst = data_string_init();
32792                 }
32793 -               
32794 +
32795                 buffer_copy_string_buffer(ds_dst->key, ds->key);
32796                 buffer_copy_string_buffer(ds_dst->value, ds->value);
32797 -               
32798 +
32799                 array_insert_unique(con->environment, (data_unset *)ds_dst);
32800         }
32801 -       
32802 +
32803         for (k = 0; k < p->conf.response_header->used; k++) {
32804                 data_string *ds = (data_string *)p->conf.response_header->data[k];
32805 -               
32806 +
32807                 response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
32808         }
32809 -       
32810 +
32811         /* not found */
32812         return HANDLER_GO_ON;
32813  }
32814  
32815  REQUESTDONE_FUNC(mod_setenv_reset) {
32816         plugin_data *p = p_d;
32817 -       
32818 +
32819         UNUSED(srv);
32820 -       
32821 +
32822         if (con->plugin_ctx[p->id]) {
32823                 handler_ctx_free(con->plugin_ctx[p->id]);
32824                 con->plugin_ctx[p->id] = NULL;
32825         }
32826  
32827 -       return HANDLER_GO_ON;   
32828 +       return HANDLER_GO_ON;
32829  }
32830  
32831  /* this function is called at dlopen() time and inits the callbacks */
32832 @@ -233,15 +230,15 @@
32833  int mod_setenv_plugin_init(plugin *p) {
32834         p->version     = LIGHTTPD_VERSION_ID;
32835         p->name        = buffer_init_string("setenv");
32836 -       
32837 +
32838         p->init        = mod_setenv_init;
32839         p->handle_uri_clean  = mod_setenv_uri_handler;
32840         p->set_defaults  = mod_setenv_set_defaults;
32841         p->cleanup     = mod_setenv_free;
32842 -       
32843 +
32844         p->handle_request_done  = mod_setenv_reset;
32845  
32846         p->data        = NULL;
32847 -       
32848 +
32849         return 0;
32850  }
32851 --- ../lighttpd-1.4.11/src/mod_simple_vhost.c   2005-11-18 15:16:13.000000000 +0200
32852 +++ lighttpd-1.4.12/src/mod_simple_vhost.c      2006-07-11 22:07:52.000000000 +0300
32853 @@ -10,6 +10,8 @@
32854  
32855  #include "plugin.h"
32856  
32857 +#include "sys-files.h"
32858 +
32859  #ifdef HAVE_CONFIG_H
32860  #include "config.h"
32861  #endif
32862 @@ -18,7 +20,7 @@
32863         buffer *server_root;
32864         buffer *default_host;
32865         buffer *document_root;
32866 -       
32867 +
32868         buffer *docroot_cache_key;
32869         buffer *docroot_cache_value;
32870         buffer *docroot_cache_servername;
32871 @@ -28,138 +30,138 @@
32872  
32873  typedef struct {
32874         PLUGIN_DATA;
32875 -       
32876 +
32877         buffer *doc_root;
32878 -       
32879 +
32880         plugin_config **config_storage;
32881 -       plugin_config conf; 
32882 +       plugin_config conf;
32883  } plugin_data;
32884  
32885  INIT_FUNC(mod_simple_vhost_init) {
32886         plugin_data *p;
32887 -       
32888 +
32889         p = calloc(1, sizeof(*p));
32890 -       
32891 +
32892         p->doc_root = buffer_init();
32893 -       
32894 +
32895         return p;
32896  }
32897  
32898  FREE_FUNC(mod_simple_vhost_free) {
32899         plugin_data *p = p_d;
32900 -       
32901 +
32902         UNUSED(srv);
32903  
32904         if (!p) return HANDLER_GO_ON;
32905 -       
32906 +
32907         if (p->config_storage) {
32908                 size_t i;
32909                 for (i = 0; i < srv->config_context->used; i++) {
32910                         plugin_config *s = p->config_storage[i];
32911 -                       
32912 +
32913                         buffer_free(s->document_root);
32914                         buffer_free(s->default_host);
32915                         buffer_free(s->server_root);
32916 -                       
32917 +
32918                         buffer_free(s->docroot_cache_key);
32919                         buffer_free(s->docroot_cache_value);
32920                         buffer_free(s->docroot_cache_servername);
32921 -                       
32922 +
32923                         free(s);
32924                 }
32925 -       
32926 +
32927                 free(p->config_storage);
32928         }
32929 -       
32930 +
32931         buffer_free(p->doc_root);
32932 -       
32933 +
32934         free(p);
32935 -       
32936 +
32937         return HANDLER_GO_ON;
32938  }
32939  
32940  SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
32941         plugin_data *p = p_d;
32942         size_t i;
32943 -       
32944 -       config_values_t cv[] = { 
32945 +
32946 +       config_values_t cv[] = {
32947                 { "simple-vhost.server-root",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
32948                 { "simple-vhost.default-host",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
32949                 { "simple-vhost.document-root",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
32950                 { "simple-vhost.debug",             NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
32951                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32952         };
32953 -       
32954 +
32955         if (!p) return HANDLER_ERROR;
32956 -       
32957 +
32958         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32959 -       
32960 +
32961         for (i = 0; i < srv->config_context->used; i++) {
32962                 plugin_config *s;
32963 -               
32964 +
32965                 s = calloc(1, sizeof(plugin_config));
32966 -               
32967 +
32968                 s->server_root = buffer_init();
32969                 s->default_host = buffer_init();
32970                 s->document_root = buffer_init();
32971 -               
32972 +
32973                 s->docroot_cache_key = buffer_init();
32974                 s->docroot_cache_value = buffer_init();
32975                 s->docroot_cache_servername = buffer_init();
32976  
32977                 s->debug = 0;
32978 -               
32979 +
32980                 cv[0].destination = s->server_root;
32981                 cv[1].destination = s->default_host;
32982                 cv[2].destination = s->document_root;
32983                 cv[3].destination = &(s->debug);
32984 -               
32985 -               
32986 +
32987 +
32988                 p->config_storage[i] = s;
32989 -               
32990 +
32991                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32992                         return HANDLER_ERROR;
32993                 }
32994         }
32995 -       
32996 +
32997         return HANDLER_GO_ON;
32998  }
32999  
33000  static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
33001         stat_cache_entry *sce = NULL;
33002 -       
33003 +
33004         buffer_prepare_copy(out, 128);
33005  
33006         if (p->conf.server_root->used) {
33007                 buffer_copy_string_buffer(out, p->conf.server_root);
33008 -               
33009 +
33010                 if (host->used) {
33011                         /* a hostname has to start with a alpha-numerical character
33012                          * and must not contain a slash "/"
33013                          */
33014                         char *dp;
33015 -                       
33016 -                       BUFFER_APPEND_SLASH(out);
33017 -                       
33018 +
33019 +                       PATHNAME_APPEND_SLASH(out);
33020 +
33021                         if (NULL == (dp = strchr(host->ptr, ':'))) {
33022                                 buffer_append_string_buffer(out, host);
33023                         } else {
33024                                 buffer_append_string_len(out, host->ptr, dp - host->ptr);
33025                         }
33026                 }
33027 -               BUFFER_APPEND_SLASH(out);
33028 -               
33029 +               PATHNAME_APPEND_SLASH(out);
33030 +
33031                 if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
33032                         buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
33033                 } else {
33034                         buffer_append_string_buffer(out, p->conf.document_root);
33035 -                       BUFFER_APPEND_SLASH(out);
33036 +                       PATHNAME_APPEND_SLASH(out);
33037                 }
33038         } else {
33039                 buffer_copy_string_buffer(out, con->conf.document_root);
33040 -               BUFFER_APPEND_SLASH(out);
33041 +               PATHNAME_APPEND_SLASH(out);
33042         }
33043 -       
33044 +
33045         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
33046                 if (p->conf.debug) {
33047                         log_error_write(srv, __FILE__, __LINE__, "sb",
33048 @@ -169,57 +171,53 @@
33049         } else if (!S_ISDIR(sce->st.st_mode)) {
33050                 return -1;
33051         }
33052 -       
33053 +
33054         return 0;
33055  }
33056  
33057 -
33058 -#define PATCH(x) \
33059 -       p->conf.x = s->x;
33060  static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
33061         size_t i, j;
33062         plugin_config *s = p->config_storage[0];
33063 -       
33064 -       PATCH(server_root);
33065 -       PATCH(default_host);
33066 -       PATCH(document_root);
33067 -       
33068 -       PATCH(docroot_cache_key);
33069 -       PATCH(docroot_cache_value);
33070 -       PATCH(docroot_cache_servername);
33071  
33072 -       PATCH(debug);
33073 -       
33074 +       PATCH_OPTION(server_root);
33075 +       PATCH_OPTION(default_host);
33076 +       PATCH_OPTION(document_root);
33077 +
33078 +       PATCH_OPTION(docroot_cache_key);
33079 +       PATCH_OPTION(docroot_cache_value);
33080 +       PATCH_OPTION(docroot_cache_servername);
33081 +
33082 +       PATCH_OPTION(debug);
33083 +
33084         /* skip the first, the global context */
33085         for (i = 1; i < srv->config_context->used; i++) {
33086                 data_config *dc = (data_config *)srv->config_context->data[i];
33087                 s = p->config_storage[i];
33088 -               
33089 +
33090                 /* condition didn't match */
33091                 if (!config_check_cond(srv, con, dc)) continue;
33092 -               
33093 +
33094                 /* merge config */
33095                 for (j = 0; j < dc->value->used; j++) {
33096                         data_unset *du = dc->value->data[j];
33097 -                       
33098 +
33099                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
33100 -                               PATCH(server_root);
33101 -                               PATCH(docroot_cache_key);
33102 -                               PATCH(docroot_cache_value);
33103 -                               PATCH(docroot_cache_servername);
33104 +                               PATCH_OPTION(server_root);
33105 +                               PATCH_OPTION(docroot_cache_key);
33106 +                               PATCH_OPTION(docroot_cache_value);
33107 +                               PATCH_OPTION(docroot_cache_servername);
33108                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
33109 -                               PATCH(default_host);
33110 +                               PATCH_OPTION(default_host);
33111                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
33112 -                               PATCH(document_root);
33113 +                               PATCH_OPTION(document_root);
33114                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
33115 -                               PATCH(debug);
33116 +                               PATCH_OPTION(debug);
33117                         }
33118                 }
33119         }
33120 -       
33121 +
33122         return 0;
33123  }
33124 -#undef PATCH
33125  
33126  static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
33127         plugin_data *p = p_data;
33128 @@ -227,12 +225,12 @@
33129         /*
33130          * cache the last successfull translation from hostname (authority) to docroot
33131          * - this saves us a stat() call
33132 -        * 
33133 +        *
33134          */
33135 -       
33136 +
33137         mod_simple_vhost_patch_connection(srv, con, p);
33138 -       
33139 -       if (p->conf.docroot_cache_key->used && 
33140 +
33141 +       if (p->conf.docroot_cache_key->used &&
33142             con->uri.authority->used &&
33143             buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
33144                 /* cache hit */
33145 @@ -243,8 +241,8 @@
33146                 if ((con->uri.authority->used == 0) ||
33147                     build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
33148                         /* not found, fallback the default-host */
33149 -                       if (build_doc_root(srv, con, p, 
33150 -                                          p->doc_root, 
33151 +                       if (build_doc_root(srv, con, p,
33152 +                                          p->doc_root,
33153                                            p->conf.default_host)) {
33154                                 return HANDLER_GO_ON;
33155                         } else {
33156 @@ -253,15 +251,15 @@
33157                 } else {
33158                         buffer_copy_string_buffer(con->server_name, con->uri.authority);
33159                 }
33160 -               
33161 +
33162                 /* copy to cache */
33163                 buffer_copy_string_buffer(p->conf.docroot_cache_key,        con->uri.authority);
33164                 buffer_copy_string_buffer(p->conf.docroot_cache_value,      p->doc_root);
33165                 buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
33166 -               
33167 +
33168                 buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
33169         }
33170 -       
33171 +
33172         return HANDLER_GO_ON;
33173  }
33174  
33175 @@ -269,13 +267,13 @@
33176  int mod_simple_vhost_plugin_init(plugin *p) {
33177         p->version     = LIGHTTPD_VERSION_ID;
33178         p->name        = buffer_init_string("simple_vhost");
33179 -       
33180 +
33181         p->init        = mod_simple_vhost_init;
33182         p->set_defaults = mod_simple_vhost_set_defaults;
33183         p->handle_docroot  = mod_simple_vhost_docroot;
33184         p->cleanup     = mod_simple_vhost_free;
33185 -       
33186 +
33187         p->data        = NULL;
33188 -       
33189 +
33190         return 0;
33191  }
33192 --- ../lighttpd-1.4.11/src/mod_skeleton.c       2005-10-02 18:30:51.000000000 +0300
33193 +++ lighttpd-1.4.12/src/mod_skeleton.c  2006-07-11 22:07:51.000000000 +0300
33194 @@ -14,13 +14,13 @@
33195  
33196  /**
33197   * this is a skeleton for a lighttpd plugin
33198 - * 
33199 + *
33200   * just replaces every occurance of 'skeleton' by your plugin name
33201 - * 
33202 + *
33203   * e.g. in vim:
33204 - * 
33205 + *
33206   *   :%s/skeleton/myhandler/
33207 - * 
33208 + *
33209   */
33210  
33211  
33212 @@ -33,12 +33,12 @@
33213  
33214  typedef struct {
33215         PLUGIN_DATA;
33216 -       
33217 +
33218         buffer *match_buf;
33219 -       
33220 +
33221         plugin_config **config_storage;
33222 -       
33223 -       plugin_config conf; 
33224 +
33225 +       plugin_config conf;
33226  } plugin_data;
33227  
33228  typedef struct {
33229 @@ -47,36 +47,36 @@
33230  
33231  static handler_ctx * handler_ctx_init() {
33232         handler_ctx * hctx;
33233 -       
33234 +
33235         hctx = calloc(1, sizeof(*hctx));
33236 -       
33237 +
33238         return hctx;
33239  }
33240  
33241  static void handler_ctx_free(handler_ctx *hctx) {
33242 -       
33243 +
33244         free(hctx);
33245  }
33246  
33247  /* init the plugin data */
33248  INIT_FUNC(mod_skeleton_init) {
33249         plugin_data *p;
33250 -       
33251 +
33252         p = calloc(1, sizeof(*p));
33253 -       
33254 +
33255         p->match_buf = buffer_init();
33256 -       
33257 +
33258         return p;
33259  }
33260  
33261  /* detroy the plugin data */
33262  FREE_FUNC(mod_skeleton_free) {
33263         plugin_data *p = p_d;
33264 -       
33265 +
33266         UNUSED(srv);
33267  
33268         if (!p) return HANDLER_GO_ON;
33269 -       
33270 +
33271         if (p->config_storage) {
33272                 size_t i;
33273  
33274 @@ -84,18 +84,18 @@
33275                         plugin_config *s = p->config_storage[i];
33276  
33277                         if (!s) continue;
33278 -                       
33279 +
33280                         array_free(s->match);
33281 -                       
33282 +
33283                         free(s);
33284                 }
33285                 free(p->config_storage);
33286         }
33287 -       
33288 +
33289         buffer_free(p->match_buf);
33290 -       
33291 +
33292         free(p);
33293 -       
33294 +
33295         return HANDLER_GO_ON;
33296  }
33297  
33298 @@ -104,91 +104,88 @@
33299  SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
33300         plugin_data *p = p_d;
33301         size_t i = 0;
33302 -       
33303 -       config_values_t cv[] = { 
33304 +
33305 +       config_values_t cv[] = {
33306                 { "skeleton.array",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
33307                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33308         };
33309 -       
33310 +
33311         if (!p) return HANDLER_ERROR;
33312 -       
33313 +
33314         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33315 -       
33316 +
33317         for (i = 0; i < srv->config_context->used; i++) {
33318                 plugin_config *s;
33319 -               
33320 +
33321                 s = calloc(1, sizeof(plugin_config));
33322                 s->match    = array_init();
33323 -               
33324 +
33325                 cv[0].destination = s->match;
33326 -               
33327 +
33328                 p->config_storage[i] = s;
33329 -       
33330 +
33331                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33332                         return HANDLER_ERROR;
33333                 }
33334         }
33335 -       
33336 +
33337         return HANDLER_GO_ON;
33338  }
33339  
33340 -#define PATCH(x) \
33341 -       p->conf.x = s->x;
33342  static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
33343         size_t i, j;
33344         plugin_config *s = p->config_storage[0];
33345 -       
33346 -       PATCH(match);
33347 -       
33348 +
33349 +       PATCH_OPTION(match);
33350 +
33351         /* skip the first, the global context */
33352         for (i = 1; i < srv->config_context->used; i++) {
33353                 data_config *dc = (data_config *)srv->config_context->data[i];
33354                 s = p->config_storage[i];
33355 -               
33356 +
33357                 /* condition didn't match */
33358                 if (!config_check_cond(srv, con, dc)) continue;
33359 -               
33360 +
33361                 /* merge config */
33362                 for (j = 0; j < dc->value->used; j++) {
33363                         data_unset *du = dc->value->data[j];
33364 -                       
33365 +
33366                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
33367 -                               PATCH(match);
33368 +                               PATCH_OPTION(match);
33369                         }
33370                 }
33371         }
33372 -       
33373 +
33374         return 0;
33375  }
33376 -#undef PATCH
33377  
33378  URIHANDLER_FUNC(mod_skeleton_uri_handler) {
33379         plugin_data *p = p_d;
33380         int s_len;
33381         size_t k, i;
33382 -       
33383 +
33384         UNUSED(srv);
33385  
33386         if (con->uri.path->used == 0) return HANDLER_GO_ON;
33387 -       
33388 +
33389         mod_skeleton_patch_connection(srv, con, p);
33390  
33391         s_len = con->uri.path->used - 1;
33392 -       
33393 +
33394         for (k = 0; k < p->conf.match->used; k++) {
33395                 data_string *ds = (data_string *)p->conf.match->data[k];
33396                 int ct_len = ds->value->used - 1;
33397 -               
33398 +
33399                 if (ct_len > s_len) continue;
33400                 if (ds->value->used == 0) continue;
33401 -               
33402 +
33403                 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
33404                         con->http_status = 403;
33405 -       
33406 +
33407                         return HANDLER_FINISHED;
33408                 }
33409         }
33410 -       
33411 +
33412         /* not found */
33413         return HANDLER_GO_ON;
33414  }
33415 @@ -198,13 +195,13 @@
33416  int mod_skeleton_plugin_init(plugin *p) {
33417         p->version     = LIGHTTPD_VERSION_ID;
33418         p->name        = buffer_init_string("skeleton");
33419 -       
33420 +
33421         p->init        = mod_skeleton_init;
33422         p->handle_uri_clean  = mod_skeleton_uri_handler;
33423         p->set_defaults  = mod_skeleton_set_defaults;
33424         p->cleanup     = mod_skeleton_free;
33425 -       
33426 +
33427         p->data        = NULL;
33428 -       
33429 +
33430         return 0;
33431  }
33432 --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.c 1970-01-01 03:00:00.000000000 +0300
33433 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.c    2006-07-11 22:07:53.000000000 +0300
33434 @@ -0,0 +1,209 @@
33435 +#include <stdio.h>
33436 +#include <errno.h>
33437 +#include <fcntl.h>
33438 +#include <string.h>
33439 +
33440 +#ifdef HAVE_CONFIG_H
33441 +#include "config.h"
33442 +#endif
33443 +
33444 +#include "plugin.h"
33445 +#include "log.h"
33446 +
33447 +#include "stat_cache.h"
33448 +
33449 +#include "mod_sql_vhost_core.h"
33450 +
33451 +#define plugin_data mod_sql_vhost_core_plugin_data
33452 +#define plugin_config mod_sql_vhost_core_plugin_config
33453 +
33454 +/* init the plugin data */
33455 +INIT_FUNC(mod_sql_vhost_core_init) {
33456 +       plugin_data *p;
33457 +
33458 +       p = calloc(1, sizeof(*p));
33459 +
33460 +       p->docroot = buffer_init();
33461 +       p->host = buffer_init();
33462 +
33463 +       return p;
33464 +}
33465 +
33466 +/* cleanup the plugin data */
33467 +SERVER_FUNC(mod_sql_vhost_core_cleanup) {
33468 +       plugin_data *p = p_d;
33469 +
33470 +       UNUSED(srv);
33471 +
33472 +       if (!p) return HANDLER_GO_ON;
33473 +
33474 +       if (p->config_storage) {
33475 +               size_t i;
33476 +               for (i = 0; i < srv->config_context->used; i++) {
33477 +                       plugin_config *s = p->config_storage[i];
33478 +
33479 +                       if (!s) continue;
33480 +
33481 +                       buffer_free(s->db);
33482 +                       buffer_free(s->user);
33483 +                       buffer_free(s->pass);
33484 +                       buffer_free(s->sock);
33485 +                       buffer_free(s->backend);
33486 +
33487 +                       free(s);
33488 +               }
33489 +               free(p->config_storage);
33490 +       }
33491 +       buffer_free(p->docroot);
33492 +       buffer_free(p->host);
33493 +
33494 +       free(p);
33495 +
33496 +       return HANDLER_GO_ON;
33497 +}
33498 +
33499 +/* set configuration values */
33500 +SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
33501 +       plugin_data *p = p_d;
33502 +
33503 +       size_t i = 0;
33504 +
33505 +       config_values_t cv[] = {
33506 +               { "sql-vhost.db",       NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
33507 +               { "sql-vhost.user",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
33508 +               { "sql-vhost.pass",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
33509 +               { "sql-vhost.sock",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
33510 +               { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING,      T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
33511 +               { "sql-vhost.hostname", NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
33512 +               { "sql-vhost.port",     NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
33513 +               { "sql-vhost.backend",  NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
33514 +
33515 +               /* backward compat */
33516 +               { "mysql-vhost.db",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
33517 +               { "mysql-vhost.user",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
33518 +               { "mysql-vhost.pass",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
33519 +               { "mysql-vhost.sock",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
33520 +               { "mysql-vhost.sql",    NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
33521 +               { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
33522 +               { "mysql-vhost.port",   NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
33523 +
33524 +                { NULL,                        NULL, T_CONFIG_UNSET,   T_CONFIG_SCOPE_UNSET }
33525 +        };
33526 +
33527 +       p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33528 +
33529 +       for (i = 0; i < srv->config_context->used; i++) {
33530 +               plugin_config *s;
33531 +
33532 +               s = calloc(1, sizeof(plugin_config));
33533 +               s->db = buffer_init();
33534 +               s->user = buffer_init();
33535 +               s->pass = buffer_init();
33536 +               s->sock = buffer_init();
33537 +               s->hostname = buffer_init();
33538 +               s->backend = buffer_init();
33539 +               s->port   = 0;               /* default port for mysql */
33540 +               s->select_vhost = buffer_init();
33541 +               s->backend_data = NULL;
33542 +
33543 +               cv[0].destination = s->db;
33544 +               cv[1].destination = s->user;
33545 +               cv[2].destination = s->pass;
33546 +               cv[3].destination = s->sock;
33547 +               cv[4].destination = s->select_vhost;
33548 +               cv[5].destination = s->hostname;
33549 +               cv[6].destination = &(s->port);
33550 +               cv[7].destination = s->backend;
33551 +
33552 +               /* backend compat */
33553 +               cv[8].destination = cv[0].destination;
33554 +               cv[9].destination = cv[1].destination;
33555 +               cv[10].destination = cv[2].destination;
33556 +               cv[11].destination = cv[3].destination;
33557 +               cv[12].destination = cv[4].destination;
33558 +               cv[13].destination = cv[5].destination;
33559 +               cv[14].destination = cv[6].destination;
33560 +
33561 +               p->config_storage[i] = s;
33562 +
33563 +               if (config_insert_values_global(srv,
33564 +                       ((data_config *)srv->config_context->data[i])->value,
33565 +                       cv)) return HANDLER_ERROR;
33566 +
33567 +               /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
33568 +       }
33569 +
33570 +        return HANDLER_GO_ON;
33571 +}
33572 +
33573 +static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
33574 +       size_t i;
33575 +       plugin_config *s = p->config_storage[0];
33576 +
33577 +       PATCH_OPTION(backend_data);
33578 +       PATCH_OPTION(get_vhost);
33579 +
33580 +       /* skip the first, the global context */
33581 +       for (i = 1; i < srv->config_context->used; i++) {
33582 +               data_config *dc = (data_config *)srv->config_context->data[i];
33583 +               s = p->config_storage[i];
33584 +
33585 +               /* condition didn't match */
33586 +               if (!config_check_cond(srv, con, dc)) continue;
33587 +
33588 +               if (s->backend_data) {
33589 +                       PATCH_OPTION(backend_data);
33590 +                       PATCH_OPTION(get_vhost);
33591 +               }
33592 +       }
33593 +
33594 +       return 0;
33595 +}
33596 +
33597 +/* handle document root request */
33598 +CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
33599 +       plugin_data *p = p_d;
33600 +       stat_cache_entry *sce;
33601 +
33602 +       /* no host specified? */
33603 +       if (!con->uri.authority->used) return HANDLER_GO_ON;
33604 +
33605 +       mod_sql_vhost_core_patch_connection(srv, con, p);
33606 +
33607 +       /* do we have backend ? */
33608 +       if (!p->conf.get_vhost) return HANDLER_GO_ON;
33609 +
33610 +       /* ask the backend for the data */
33611 +       if (0 != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
33612 +               return HANDLER_GO_ON;
33613 +       }
33614 +
33615 +       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
33616 +               log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->docroot);
33617 +               return HANDLER_GO_ON;
33618 +       }
33619 +        if (!S_ISDIR(sce->st.st_mode)) {
33620 +               log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->docroot);
33621 +               return HANDLER_GO_ON;
33622 +       }
33623 +
33624 +       buffer_copy_string_buffer(con->server_name, p->host);
33625 +       buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
33626 +
33627 +       return HANDLER_GO_ON;
33628 +}
33629 +
33630 +/* this function is called at dlopen() time and inits the callbacks */
33631 +int mod_sql_vhost_core_plugin_init(plugin *p) {
33632 +       p->version     = LIGHTTPD_VERSION_ID;
33633 +       p->name                         = buffer_init_string("mod_sql_vhost_core");
33634 +
33635 +       p->init                         = mod_sql_vhost_core_init;
33636 +       p->cleanup                      = mod_sql_vhost_core_cleanup;
33637 +
33638 +       p->set_defaults                 = mod_sql_vhost_core_set_defaults;
33639 +       p->handle_docroot               = mod_sql_vhost_core_handle_docroot;
33640 +
33641 +       return 0;
33642 +}
33643 +
33644 --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.h 1970-01-01 03:00:00.000000000 +0300
33645 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.h    2006-07-11 22:07:53.000000000 +0300
33646 @@ -0,0 +1,49 @@
33647 +#ifndef _MOD_SQL_VHOST_CORE_H_
33648 +#define _MOD_SQL_VHOST_CORE_H_
33649 +
33650 +#include "buffer.h"
33651 +#include "plugin.h"
33652 +
33653 +#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
33654 +       (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
33655 +
33656 +#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
33657 +
33658 +#define SQLVHOST_BACKEND_GETVHOST(name) \
33659 +       SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
33660 +
33661 +#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
33662 +       SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
33663 +
33664 +typedef struct {
33665 +       buffer  *db;
33666 +       buffer  *user;
33667 +       buffer  *pass;
33668 +       buffer  *sock;
33669 +
33670 +       buffer  *hostname;
33671 +       unsigned short port;
33672 +
33673 +       buffer  *backend;
33674 +       void *backend_data;
33675 +
33676 +       buffer *select_vhost;
33677 +
33678 +       SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
33679 +} mod_sql_vhost_core_plugin_config;
33680 +
33681 +/* global plugin data */
33682 +typedef struct {
33683 +       PLUGIN_DATA;
33684 +
33685 +       buffer  *docroot;
33686 +       buffer  *host;
33687 +
33688 +       mod_sql_vhost_core_plugin_config **config_storage;
33689 +
33690 +       mod_sql_vhost_core_plugin_config conf;
33691 +} mod_sql_vhost_core_plugin_data;
33692 +
33693 +
33694 +
33695 +#endif
33696 --- ../lighttpd-1.4.11/src/mod_ssi.c    2006-03-04 17:09:48.000000000 +0200
33697 +++ lighttpd-1.4.12/src/mod_ssi.c       2006-07-11 22:07:53.000000000 +0300
33698 @@ -6,7 +6,6 @@
33699  #include <string.h>
33700  #include <errno.h>
33701  #include <time.h>
33702 -#include <unistd.h>
33703  
33704  #include "base.h"
33705  #include "log.h"
33706 @@ -23,6 +22,8 @@
33707  #include "inet_ntop_cache.h"
33708  
33709  #include "sys-socket.h"
33710 +#include "sys-strings.h"
33711 +#include "sys-files.h"
33712  
33713  #ifdef HAVE_PWD_H
33714  #include <pwd.h>
33715 @@ -39,15 +40,15 @@
33716  /* init the plugin data */
33717  INIT_FUNC(mod_ssi_init) {
33718         plugin_data *p;
33719 -       
33720 +
33721         p = calloc(1, sizeof(*p));
33722 -       
33723 +
33724         p->timefmt = buffer_init();
33725         p->stat_fn = buffer_init();
33726 -       
33727 +
33728         p->ssi_vars = array_init();
33729         p->ssi_cgi_env = array_init();
33730 -       
33731 +
33732         return p;
33733  }
33734  
33735 @@ -55,21 +56,21 @@
33736  FREE_FUNC(mod_ssi_free) {
33737         plugin_data *p = p_d;
33738         UNUSED(srv);
33739 -       
33740 +
33741         if (!p) return HANDLER_GO_ON;
33742 -       
33743 +
33744         if (p->config_storage) {
33745                 size_t i;
33746                 for (i = 0; i < srv->config_context->used; i++) {
33747                         plugin_config *s = p->config_storage[i];
33748 -                       
33749 +
33750                         array_free(s->ssi_extension);
33751 -                       
33752 +
33753                         free(s);
33754                 }
33755                 free(p->config_storage);
33756         }
33757 -       
33758 +
33759         array_free(p->ssi_vars);
33760         array_free(p->ssi_cgi_env);
33761  #ifdef HAVE_PCRE_H
33762 @@ -77,9 +78,9 @@
33763  #endif
33764         buffer_free(p->timefmt);
33765         buffer_free(p->stat_fn);
33766 -       
33767 +
33768         free(p);
33769 -       
33770 +
33771         return HANDLER_GO_ON;
33772  }
33773  
33774 @@ -92,36 +93,36 @@
33775         const char *errptr;
33776         int erroff;
33777  #endif
33778 -       
33779 -       config_values_t cv[] = { 
33780 +
33781 +       config_values_t cv[] = {
33782                 { "ssi.extension",              NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
33783                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33784         };
33785 -       
33786 +
33787         if (!p) return HANDLER_ERROR;
33788 -       
33789 +
33790         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33791 -       
33792 +
33793         for (i = 0; i < srv->config_context->used; i++) {
33794                 plugin_config *s;
33795 -               
33796 +
33797                 s = calloc(1, sizeof(plugin_config));
33798                 s->ssi_extension  = array_init();
33799 -               
33800 +
33801                 cv[0].destination = s->ssi_extension;
33802 -               
33803 +
33804                 p->config_storage[i] = s;
33805 -       
33806 +
33807                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33808                         return HANDLER_ERROR;
33809                 }
33810         }
33811 -       
33812 +
33813  #ifdef HAVE_PCRE_H
33814         /* allow 2 params */
33815         if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
33816                 log_error_write(srv, __FILE__, __LINE__, "sds",
33817 -                               "ssi: pcre ", 
33818 +                               "ssi: pcre ",
33819                                 erroff, errptr);
33820                 return HANDLER_ERROR;
33821         }
33822 @@ -130,52 +131,52 @@
33823                         "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
33824         return HANDLER_ERROR;
33825  #endif
33826 -       
33827 +
33828         return HANDLER_GO_ON;
33829  }
33830  
33831  int ssi_env_add(array *env, const char *key, const char *val) {
33832         data_string *ds;
33833 -                       
33834 +
33835         if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
33836                 ds = data_string_init();
33837         }
33838         buffer_copy_string(ds->key,   key);
33839         buffer_copy_string(ds->value, val);
33840 -       
33841 +
33842         array_insert_unique(env, (data_unset *)ds);
33843 -       
33844 +
33845         return 0;
33846  }
33847  
33848  /**
33849   *
33850   *  the next two functions are take from fcgi.c
33851 - * 
33852 + *
33853   */
33854  
33855  static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
33856         size_t i;
33857 -       
33858 +
33859         for (i = 0; i < con->request.headers->used; i++) {
33860                 data_string *ds;
33861 -               
33862 +
33863                 ds = (data_string *)con->request.headers->data[i];
33864 -               
33865 +
33866                 if (ds->value->used && ds->key->used) {
33867                         size_t j;
33868                         buffer_reset(srv->tmp_buf);
33869 -                       
33870 +
33871                         /* don't forward the Authorization: Header */
33872                         if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
33873                                 continue;
33874                         }
33875 -                       
33876 +
33877                         if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
33878                                 buffer_copy_string(srv->tmp_buf, "HTTP_");
33879                                 srv->tmp_buf->used--;
33880                         }
33881 -                       
33882 +
33883                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
33884                         for (j = 0; j < ds->key->used - 1; j++) {
33885                                 char c = '_';
33886 @@ -189,33 +190,33 @@
33887                                 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
33888                         }
33889                         srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
33890 -                       
33891 +
33892                         ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
33893                 }
33894         }
33895 -       
33896 +
33897         return 0;
33898  }
33899  
33900  static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
33901         char buf[32];
33902 -       
33903 +
33904         server_socket *srv_sock = con->srv_socket;
33905 -       
33906 +
33907  #ifdef HAVE_IPV6
33908         char b2[INET6_ADDRSTRLEN + 1];
33909  #endif
33910  
33911  #define CONST_STRING(x) \
33912                 x
33913 -       
33914 +
33915         array_reset(p->ssi_cgi_env);
33916 -       
33917 +
33918         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
33919         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
33920  #ifdef HAVE_IPV6
33921 -                    inet_ntop(srv_sock->addr.plain.sa_family, 
33922 -                              srv_sock->addr.plain.sa_family == AF_INET6 ? 
33923 +                    inet_ntop(srv_sock->addr.plain.sa_family,
33924 +                              srv_sock->addr.plain.sa_family == AF_INET6 ?
33925                                (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
33926                                (const void *) &(srv_sock->addr.ipv4.sin_addr),
33927                                b2, sizeof(b2)-1)
33928 @@ -224,28 +225,28 @@
33929  #endif
33930                      );
33931         ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
33932 -               
33933 -       ltostr(buf, 
33934 +
33935 +       ltostr(buf,
33936  #ifdef HAVE_IPV6
33937                ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
33938  #else
33939                ntohs(srv_sock->addr.ipv4.sin_port)
33940  #endif
33941                );
33942 -       
33943 +
33944         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
33945 -       
33946 +
33947         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
33948                     inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
33949 -       
33950 +
33951         if (con->authed_user->used) {
33952                 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
33953                              con->authed_user->ptr);
33954         }
33955 -       
33956 +
33957         if (con->request.content_length > 0) {
33958                 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
33959 -               
33960 +
33961                 /* request.content_length < SSIZE_MAX, see request.c */
33962                 ltostr(buf, con->request.content_length);
33963                 ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
33964 @@ -271,30 +272,30 @@
33965         if (con->request.pathinfo->used) {
33966                 ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
33967         }
33968 -               
33969 +
33970         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
33971         ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
33972 -       
33973 +
33974         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
33975         ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
33976         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
33977         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
33978         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
33979 -       
33980 +
33981         ssi_env_add_request_headers(srv, con, p);
33982 -       
33983 +
33984         return 0;
33985  }
33986  
33987 -static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, 
33988 +static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
33989                             const char **l, size_t n) {
33990         size_t i, ssicmd = 0;
33991         char buf[255];
33992         buffer *b = NULL;
33993 -       
33994 -       struct { 
33995 +
33996 +       struct {
33997                 const char *var;
33998 -               enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD, 
33999 +               enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
34000                                 SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
34001                                 SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
34002         } ssicmds[] = {
34003 @@ -310,27 +311,27 @@
34004                 { "endif",    SSI_ENDIF },
34005                 { "else",     SSI_ELSE },
34006                 { "exec",     SSI_EXEC },
34007 -               
34008 +
34009                 { NULL, SSI_UNSET }
34010         };
34011 -       
34012 +
34013         for (i = 0; ssicmds[i].var; i++) {
34014                 if (0 == strcmp(l[1], ssicmds[i].var)) {
34015                         ssicmd = ssicmds[i].type;
34016                         break;
34017                 }
34018         }
34019 -       
34020 +
34021         switch(ssicmd) {
34022         case SSI_ECHO: {
34023                 /* echo */
34024                 int var = 0, enc = 0;
34025                 const char *var_val = NULL;
34026                 stat_cache_entry *sce = NULL;
34027 -               
34028 -               struct { 
34029 +
34030 +               struct {
34031                         const char *var;
34032 -                       enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI, 
34033 +                       enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
34034                                         SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
34035                 } echovars[] = {
34036                         { "DATE_GMT",      SSI_ECHO_DATE_GMT },
34037 @@ -339,27 +340,27 @@
34038                         { "DOCUMENT_URI",  SSI_ECHO_DOCUMENT_URI },
34039                         { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
34040                         { "USER_NAME",     SSI_ECHO_USER_NAME },
34041 -                       
34042 +
34043                         { NULL, SSI_ECHO_UNSET }
34044                 };
34045 -               
34046 -               struct { 
34047 +
34048 +               struct {
34049                         const char *var;
34050                         enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
34051                 } encvars[] = {
34052                         { "url",          SSI_ENC_URL },
34053                         { "none",         SSI_ENC_NONE },
34054                         { "entity",       SSI_ENC_ENTITY },
34055 -                       
34056 +
34057                         { NULL, SSI_ENC_UNSET }
34058                 };
34059 -               
34060 +
34061                 for (i = 2; i < n; i += 2) {
34062                         if (0 == strcmp(l[i], "var")) {
34063                                 int j;
34064 -                               
34065 +
34066                                 var_val = l[i+1];
34067 -                               
34068 +
34069                                 for (j = 0; echovars[j].var; j++) {
34070                                         if (0 == strcmp(l[i+1], echovars[j].var)) {
34071                                                 var = echovars[j].type;
34072 @@ -368,7 +369,7 @@
34073                                 }
34074                         } else if (0 == strcmp(l[i], "encoding")) {
34075                                 int j;
34076 -                               
34077 +
34078                                 for (j = 0; encvars[j].var; j++) {
34079                                         if (0 == strcmp(l[i+1], encvars[j].var)) {
34080                                                 enc = encvars[j].type;
34081 @@ -377,26 +378,26 @@
34082                                 }
34083                         } else {
34084                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34085 -                                               "ssi: unknow attribute for ", 
34086 +                                               "ssi: unknow attribute for ",
34087                                                 l[1], l[i]);
34088                         }
34089                 }
34090 -               
34091 +
34092                 if (p->if_is_false) break;
34093 -               
34094 +
34095                 if (!var_val) {
34096                         log_error_write(srv, __FILE__, __LINE__, "sss",
34097 -                                       "ssi: ", 
34098 +                                       "ssi: ",
34099                                         l[1], "var is missing");
34100                         break;
34101                 }
34102  
34103                 stat_cache_get_entry(srv, con, con->physical.path, &sce);
34104 -               
34105 +
34106                 switch(var) {
34107                 case SSI_ECHO_USER_NAME: {
34108                         struct passwd *pw;
34109 -                       
34110 +
34111                         b = chunkqueue_get_append_buffer(con->write_queue);
34112  #ifdef HAVE_PWD_H
34113                         if (NULL == (pw = getpwuid(sce->st.st_uid))) {
34114 @@ -411,7 +412,7 @@
34115                 }
34116                 case SSI_ECHO_LAST_MODIFIED:    {
34117                         time_t t = sce->st.st_mtime;
34118 -                       
34119 +
34120                         b = chunkqueue_get_append_buffer(con->write_queue);
34121                         if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34122                                 buffer_copy_string(b, "(none)");
34123 @@ -422,7 +423,7 @@
34124                 }
34125                 case SSI_ECHO_DATE_LOCAL: {
34126                         time_t t = time(NULL);
34127 -                       
34128 +
34129                         b = chunkqueue_get_append_buffer(con->write_queue);
34130                         if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34131                                 buffer_copy_string(b, "(none)");
34132 @@ -433,7 +434,7 @@
34133                 }
34134                 case SSI_ECHO_DATE_GMT: {
34135                         time_t t = time(NULL);
34136 -                       
34137 +
34138                         b = chunkqueue_get_append_buffer(con->write_queue);
34139                         if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
34140                                 buffer_copy_string(b, "(none)");
34141 @@ -444,7 +445,7 @@
34142                 }
34143                 case SSI_ECHO_DOCUMENT_NAME: {
34144                         char *sl;
34145 -                       
34146 +
34147                         b = chunkqueue_get_append_buffer(con->write_queue);
34148                         if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34149                                 buffer_copy_string_buffer(b, con->physical.path);
34150 @@ -461,15 +462,15 @@
34151                 default: {
34152                         data_string *ds;
34153                         /* check if it is a cgi-var */
34154 -                       
34155 +
34156                         b = chunkqueue_get_append_buffer(con->write_queue);
34157 -                       
34158 +
34159                         if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
34160                                 buffer_copy_string_buffer(b, ds->value);
34161                         } else {
34162                                 buffer_copy_string(b, "(none)");
34163                         }
34164 -                       
34165 +
34166                         break;
34167                 }
34168                 }
34169 @@ -481,7 +482,7 @@
34170                 const char * file_path = NULL, *virt_path = NULL;
34171                 struct stat st;
34172                 char *sl;
34173 -               
34174 +
34175                 for (i = 2; i < n; i += 2) {
34176                         if (0 == strcmp(l[i], "file")) {
34177                                 file_path = l[i+1];
34178 @@ -489,28 +490,28 @@
34179                                 virt_path = l[i+1];
34180                         } else {
34181                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34182 -                                               "ssi: unknow attribute for ", 
34183 +                                               "ssi: unknow attribute for ",
34184                                                 l[1], l[i]);
34185                         }
34186                 }
34187 -               
34188 +
34189                 if (!file_path && !virt_path) {
34190                         log_error_write(srv, __FILE__, __LINE__, "sss",
34191 -                                       "ssi: ", 
34192 +                                       "ssi: ",
34193                                         l[1], "file or virtual are missing");
34194                         break;
34195                 }
34196 -               
34197 +
34198                 if (file_path && virt_path) {
34199                         log_error_write(srv, __FILE__, __LINE__, "sss",
34200 -                                       "ssi: ", 
34201 +                                       "ssi: ",
34202                                         l[1], "only one of file and virtual is allowed here");
34203                         break;
34204                 }
34205 -               
34206 -               
34207 +
34208 +
34209                 if (p->if_is_false) break;
34210 -               
34211 +
34212                 if (file_path) {
34213                         /* current doc-root */
34214                         if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34215 @@ -519,46 +520,46 @@
34216                                 buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
34217                         }
34218  
34219 -                       buffer_copy_string(srv->tmp_buf, file_path); 
34220 +                       buffer_copy_string(srv->tmp_buf, file_path);
34221                         buffer_urldecode_path(srv->tmp_buf);
34222 -                       buffer_path_simplify(srv->tmp_buf, srv->tmp_buf); 
34223 -                       buffer_append_string_buffer(p->stat_fn, srv->tmp_buf); 
34224 +                       buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
34225 +                       buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34226                 } else {
34227                         /* virtual */
34228 -                       
34229 +
34230                         if (virt_path[0] == '/') {
34231                                 buffer_copy_string(p->stat_fn, virt_path);
34232                         } else {
34233                                 /* there is always a / */
34234                                 sl = strrchr(con->uri.path->ptr, '/');
34235 -                               
34236 +
34237                                 buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
34238                                 buffer_append_string(p->stat_fn, virt_path);
34239                         }
34240 -                       
34241 +
34242                         buffer_urldecode_path(p->stat_fn);
34243                         buffer_path_simplify(srv->tmp_buf, p->stat_fn);
34244 -                       
34245 +
34246                         /* we have an uri */
34247 -                       
34248 +
34249                         buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
34250                         buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34251                 }
34252 -               
34253 +
34254                 if (0 == stat(p->stat_fn->ptr, &st)) {
34255                         time_t t = st.st_mtime;
34256 -                       
34257 +
34258                         switch (ssicmd) {
34259                         case SSI_FSIZE:
34260                                 b = chunkqueue_get_append_buffer(con->write_queue);
34261                                 if (p->sizefmt) {
34262                                         int j = 0;
34263                                         const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
34264 -                                       
34265 +
34266                                         off_t s = st.st_size;
34267 -                                       
34268 +
34269                                         for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
34270 -                                       
34271 +
34272                                         buffer_copy_off_t(b, s);
34273                                         buffer_append_string(b, abr[j]);
34274                                 } else {
34275 @@ -579,7 +580,7 @@
34276                         }
34277                 } else {
34278                         log_error_write(srv, __FILE__, __LINE__, "sbs",
34279 -                                       "ssi: stating failed ", 
34280 +                                       "ssi: stating failed ",
34281                                         p->stat_fn, strerror(errno));
34282                 }
34283                 break;
34284 @@ -593,33 +594,33 @@
34285                                 val = l[i+1];
34286                         } else {
34287                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34288 -                                               "ssi: unknow attribute for ", 
34289 +                                               "ssi: unknow attribute for ",
34290                                                 l[1], l[i]);
34291                         }
34292                 }
34293 -               
34294 +
34295                 if (p->if_is_false) break;
34296 -               
34297 +
34298                 if (key && val) {
34299                         data_string *ds;
34300 -                       
34301 +
34302                         if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
34303                                 ds = data_string_init();
34304                         }
34305                         buffer_copy_string(ds->key,   key);
34306                         buffer_copy_string(ds->value, val);
34307 -                       
34308 +
34309                         array_insert_unique(p->ssi_vars, (data_unset *)ds);
34310                 } else {
34311                         log_error_write(srv, __FILE__, __LINE__, "sss",
34312 -                                       "ssi: var and value have to be set in", 
34313 +                                       "ssi: var and value have to be set in",
34314                                         l[0], l[1]);
34315                 }
34316                 break;
34317         }
34318 -       case SSI_CONFIG: 
34319 +       case SSI_CONFIG:
34320                 if (p->if_is_false) break;
34321 -               
34322 +
34323                 for (i = 2; i < n; i += 2) {
34324                         if (0 == strcmp(l[i], "timefmt")) {
34325                                 buffer_copy_string(p->timefmt, l[i+1]);
34326 @@ -632,63 +633,65 @@
34327                                         log_error_write(srv, __FILE__, __LINE__, "sssss",
34328                                                         "ssi: unknow value for attribute '",
34329                                                         l[i],
34330 -                                                       "' for ", 
34331 +                                                       "' for ",
34332                                                         l[1], l[i+1]);
34333                                 }
34334                         } else {
34335                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34336 -                                               "ssi: unknow attribute for ", 
34337 +                                               "ssi: unknow attribute for ",
34338                                                 l[1], l[i]);
34339                         }
34340                 }
34341                 break;
34342         case SSI_PRINTENV:
34343                 if (p->if_is_false) break;
34344 -               
34345 +
34346                 b = chunkqueue_get_append_buffer(con->write_queue);
34347                 buffer_copy_string(b, "<pre>");
34348                 for (i = 0; i < p->ssi_vars->used; i++) {
34349                         data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
34350 -                       
34351 +
34352                         buffer_append_string_buffer(b, ds->key);
34353                         buffer_append_string(b, ": ");
34354                         buffer_append_string_buffer(b, ds->value);
34355                         buffer_append_string(b, "<br />");
34356 -                                       
34357 +
34358                 }
34359                 buffer_append_string(b, "</pre>");
34360 -               
34361 +
34362                 break;
34363         case SSI_EXEC: {
34364 +#ifndef _WIN32
34365 +
34366                 const char *cmd = NULL;
34367                 pid_t pid;
34368                 int from_exec_fds[2];
34369 -               
34370 +
34371                 for (i = 2; i < n; i += 2) {
34372                         if (0 == strcmp(l[i], "cmd")) {
34373                                 cmd = l[i+1];
34374                         } else {
34375                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34376 -                                               "ssi: unknow attribute for ", 
34377 +                                               "ssi: unknow attribute for ",
34378                                                 l[1], l[i]);
34379                         }
34380                 }
34381 -               
34382 +
34383                 if (p->if_is_false) break;
34384 -               
34385 +
34386                 /* create a return pipe and send output to the html-page
34387 -                * 
34388 -                * as exec is assumed evil it is implemented synchronously 
34389 +                *
34390 +                * as exec is assumed evil it is implemented synchronously
34391                  */
34392 -               
34393 +
34394                 if (!cmd) break;
34395 -#ifdef HAVE_FORK       
34396 +
34397                 if (pipe(from_exec_fds)) {
34398 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
34399 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
34400                                         "pipe failed: ", strerror(errno));
34401                         return -1;
34402                 }
34403 -       
34404 +
34405                 /* fork, execve */
34406                 switch (pid = fork()) {
34407                 case 0: {
34408 @@ -698,14 +701,14 @@
34409                         close(from_exec_fds[1]);
34410                         /* not needed */
34411                         close(from_exec_fds[0]);
34412 -                       
34413 +
34414                         /* close stdin */
34415                         close(STDIN_FILENO);
34416 -               
34417 +
34418                         execl("/bin/sh", "sh", "-c", cmd, NULL);
34419 -                       
34420 +
34421                         log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
34422 -               
34423 +
34424                         /* */
34425                         SEGFAULT();
34426                         break;
34427 @@ -718,9 +721,9 @@
34428                         /* father */
34429                         int status;
34430                         ssize_t r;
34431 -                       
34432 +
34433                         close(from_exec_fds[1]);
34434 -                       
34435 +
34436                         /* wait for the client to end */
34437                         if (-1 == waitpid(pid, &status, 0)) {
34438                                 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
34439 @@ -730,7 +733,7 @@
34440  
34441                                 while(1) {
34442                                         if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
34443 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
34444 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
34445                                                         "unexpected end-of-file (perhaps the ssi-exec process died)");
34446                                                 return -1;
34447                                         }
34448 @@ -738,10 +741,10 @@
34449                                         if (toread > 0) {
34450                                                 b = chunkqueue_get_append_buffer(con->write_queue);
34451  
34452 -                                               buffer_prepare_copy(b, toread + 1); 
34453 +                                               buffer_prepare_copy(b, toread + 1);
34454  
34455                                                 if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
34456 -                                                       /* read failed */ 
34457 +                                                       /* read failed */
34458                                                         break;
34459                                                 } else {
34460                                                         b->used = r;
34461 @@ -755,59 +758,58 @@
34462                                 log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
34463                         }
34464                         close(from_exec_fds[0]);
34465 -                       
34466 +
34467                         break;
34468                 }
34469                 }
34470  #else
34471 -
34472                 return -1;
34473  #endif
34474 -               
34475 +
34476                 break;
34477         }
34478         case SSI_IF: {
34479                 const char *expr = NULL;
34480 -               
34481 +
34482                 for (i = 2; i < n; i += 2) {
34483                         if (0 == strcmp(l[i], "expr")) {
34484                                 expr = l[i+1];
34485                         } else {
34486                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34487 -                                               "ssi: unknow attribute for ", 
34488 +                                               "ssi: unknow attribute for ",
34489                                                 l[1], l[i]);
34490                         }
34491                 }
34492 -               
34493 +
34494                 if (!expr) {
34495                         log_error_write(srv, __FILE__, __LINE__, "sss",
34496 -                                       "ssi: ", 
34497 +                                       "ssi: ",
34498                                         l[1], "expr missing");
34499                         break;
34500                 }
34501 -               
34502 +
34503                 if ((!p->if_is_false) &&
34504 -                   ((p->if_is_false_level == 0) || 
34505 +                   ((p->if_is_false_level == 0) ||
34506                      (p->if_level < p->if_is_false_level))) {
34507                         switch (ssi_eval_expr(srv, con, p, expr)) {
34508                         case -1:
34509 -                       case 0: 
34510 -                               p->if_is_false = 1; 
34511 +                       case 0:
34512 +                               p->if_is_false = 1;
34513                                 p->if_is_false_level = p->if_level;
34514                                 break;
34515 -                       case 1: 
34516 -                               p->if_is_false = 0; 
34517 +                       case 1:
34518 +                               p->if_is_false = 0;
34519                                 break;
34520                         }
34521                 }
34522 -               
34523 +
34524                 p->if_level++;
34525 -               
34526 +
34527                 break;
34528         }
34529         case SSI_ELSE:
34530                 p->if_level--;
34531 -               
34532 +
34533                 if (p->if_is_false) {
34534                         if ((p->if_level == p->if_is_false_level) &&
34535                             (p->if_is_false_endif == 0)) {
34536 @@ -815,11 +817,11 @@
34537                         }
34538                 } else {
34539                         p->if_is_false = 1;
34540 -                       
34541 +
34542                         p->if_is_false_level = p->if_level;
34543                 }
34544                 p->if_level++;
34545 -               
34546 +
34547                 break;
34548         case SSI_ELIF: {
34549                 const char *expr = NULL;
34550 @@ -828,52 +830,52 @@
34551                                 expr = l[i+1];
34552                         } else {
34553                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34554 -                                               "ssi: unknow attribute for ", 
34555 +                                               "ssi: unknow attribute for ",
34556                                                 l[1], l[i]);
34557                         }
34558                 }
34559 -               
34560 +
34561                 if (!expr) {
34562                         log_error_write(srv, __FILE__, __LINE__, "sss",
34563 -                                       "ssi: ", 
34564 +                                       "ssi: ",
34565                                         l[1], "expr missing");
34566                         break;
34567                 }
34568 -               
34569 +
34570                 p->if_level--;
34571 -               
34572 +
34573                 if (p->if_level == p->if_is_false_level) {
34574                         if ((p->if_is_false) &&
34575                             (p->if_is_false_endif == 0)) {
34576                                 switch (ssi_eval_expr(srv, con, p, expr)) {
34577                                 case -1:
34578 -                               case 0: 
34579 -                                       p->if_is_false = 1; 
34580 +                               case 0:
34581 +                                       p->if_is_false = 1;
34582                                         p->if_is_false_level = p->if_level;
34583                                         break;
34584 -                               case 1: 
34585 -                                       p->if_is_false = 0; 
34586 +                               case 1:
34587 +                                       p->if_is_false = 0;
34588                                         break;
34589                                 }
34590                         } else {
34591 -                               p->if_is_false = 1; 
34592 +                               p->if_is_false = 1;
34593                                 p->if_is_false_level = p->if_level;
34594                                 p->if_is_false_endif = 1;
34595                         }
34596                 }
34597 -               
34598 +
34599                 p->if_level++;
34600 -               
34601 +
34602                 break;
34603         }
34604         case SSI_ENDIF:
34605                 p->if_level--;
34606 -               
34607 +
34608                 if (p->if_level == p->if_is_false_level) {
34609                         p->if_is_false = 0;
34610                         p->if_is_false_endif = 0;
34611                 }
34612 -                       
34613 +
34614                 break;
34615         default:
34616                 log_error_write(srv, __FILE__, __LINE__, "ss",
34617 @@ -881,41 +883,41 @@
34618                                 l[1]);
34619                 break;
34620         }
34621 -       
34622 +
34623         return 0;
34624 -       
34625 +
34626  }
34627  
34628  static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
34629         stream s;
34630  #ifdef  HAVE_PCRE_H
34631         int i, n;
34632 -       
34633 +
34634  #define N 10
34635         int ovec[N * 3];
34636  #endif
34637 -       
34638 +
34639         /* get a stream to the file */
34640 -       
34641 +
34642         array_reset(p->ssi_vars);
34643         array_reset(p->ssi_cgi_env);
34644         buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z");
34645         p->sizefmt = 0;
34646         build_ssi_cgi_vars(srv, con, p);
34647         p->if_is_false = 0;
34648 -       
34649 +
34650         if (-1 == stream_open(&s, con->physical.path)) {
34651                 log_error_write(srv, __FILE__, __LINE__, "sb",
34652                                 "stream-open: ", con->physical.path);
34653                 return -1;
34654         }
34655 -       
34656 -       
34657 +
34658 +
34659         /**
34660 -        * <!--#element attribute=value attribute=value ... --> 
34661 -        * 
34662 +        * <!--#element attribute=value attribute=value ... -->
34663 +        *
34664          * config       DONE
34665 -        *   errmsg     -- missing 
34666 +        *   errmsg     -- missing
34667          *   sizefmt    DONE
34668          *   timefmt    DONE
34669          * echo         DONE
34670 @@ -937,13 +939,13 @@
34671          * set          DONE
34672          *   var        DONE
34673          *   value      DONE
34674 -        * 
34675 +        *
34676          * if           DONE
34677          * elif         DONE
34678          * else         DONE
34679          * endif        DONE
34680 -        * 
34681 -        * 
34682 +        *
34683 +        *
34684          * expressions
34685          * AND, OR      DONE
34686          * comp         DONE
34687 @@ -951,118 +953,115 @@
34688          * $...         DONE
34689          * '...'        DONE
34690          * ( ... )      DONE
34691 -        * 
34692 -        * 
34693 -        * 
34694 +        *
34695 +        *
34696 +        *
34697          * ** all DONE **
34698 -        * DATE_GMT 
34699 -        *   The current date in Greenwich Mean Time. 
34700 -        * DATE_LOCAL 
34701 -        *   The current date in the local time zone. 
34702 -        * DOCUMENT_NAME 
34703 -        *   The filename (excluding directories) of the document requested by the user. 
34704 -        * DOCUMENT_URI 
34705 -        *   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. 
34706 -        * LAST_MODIFIED 
34707 -        *   The last modification date of the document requested by the user. 
34708 -        * USER_NAME 
34709 +        * DATE_GMT
34710 +        *   The current date in Greenwich Mean Time.
34711 +        * DATE_LOCAL
34712 +        *   The current date in the local time zone.
34713 +        * DOCUMENT_NAME
34714 +        *   The filename (excluding directories) of the document requested by the user.
34715 +        * DOCUMENT_URI
34716 +        *   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.
34717 +        * LAST_MODIFIED
34718 +        *   The last modification date of the document requested by the user.
34719 +        * USER_NAME
34720          *   Contains the owner of the file which included it.
34721 -        * 
34722 +        *
34723          */
34724 -#ifdef HAVE_PCRE_H     
34725 +#ifdef HAVE_PCRE_H
34726         for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
34727                 const char **l;
34728                 /* take everything from last offset to current match pos */
34729 -               
34730 +
34731                 if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
34732 -               
34733 +
34734                 pcre_get_substring_list(s.start, ovec, n, &l);
34735                 process_ssi_stmt(srv, con, p, l, n);
34736                 pcre_free_substring_list(l);
34737         }
34738 -       
34739 +
34740         switch(n) {
34741         case PCRE_ERROR_NOMATCH:
34742                 /* copy everything/the rest */
34743                 chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
34744 -               
34745 +
34746                 break;
34747         default:
34748                 log_error_write(srv, __FILE__, __LINE__, "sd",
34749                                 "execution error while matching: ", n);
34750                 break;
34751         }
34752 -#endif 
34753 -       
34754 -       
34755 +#endif
34756 +
34757 +
34758         stream_close(&s);
34759 -       
34760 +
34761         con->file_started  = 1;
34762         con->file_finished = 1;
34763 -       
34764 +
34765         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
34766 -       
34767 +
34768         /* reset physical.path */
34769         buffer_reset(con->physical.path);
34770 -       
34771 +
34772         return 0;
34773  }
34774  
34775 -#define PATCH(x) \
34776 -       p->conf.x = s->x;
34777  static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
34778         size_t i, j;
34779         plugin_config *s = p->config_storage[0];
34780 -       
34781 -       PATCH(ssi_extension);
34782 -       
34783 +
34784 +       PATCH_OPTION(ssi_extension);
34785 +
34786         /* skip the first, the global context */
34787         for (i = 1; i < srv->config_context->used; i++) {
34788                 data_config *dc = (data_config *)srv->config_context->data[i];
34789                 s = p->config_storage[i];
34790 -               
34791 +
34792                 /* condition didn't match */
34793                 if (!config_check_cond(srv, con, dc)) continue;
34794 -               
34795 +
34796                 /* merge config */
34797                 for (j = 0; j < dc->value->used; j++) {
34798                         data_unset *du = dc->value->data[j];
34799 -                       
34800 +
34801                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
34802 -                               PATCH(ssi_extension);
34803 +                               PATCH_OPTION(ssi_extension);
34804                         }
34805                 }
34806         }
34807 -       
34808 +
34809         return 0;
34810  }
34811 -#undef PATCH
34812  
34813  URIHANDLER_FUNC(mod_ssi_physical_path) {
34814         plugin_data *p = p_d;
34815         size_t k;
34816 -       
34817 +
34818         if (con->physical.path->used == 0) return HANDLER_GO_ON;
34819 -       
34820 +
34821         mod_ssi_patch_connection(srv, con, p);
34822 -       
34823 +
34824         for (k = 0; k < p->conf.ssi_extension->used; k++) {
34825                 data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
34826 -               
34827 +
34828                 if (ds->value->used == 0) continue;
34829 -               
34830 +
34831                 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
34832                         /* handle ssi-request */
34833 -                       
34834 +
34835                         if (mod_ssi_handle_request(srv, con, p)) {
34836                                 /* on error */
34837                                 con->http_status = 500;
34838                         }
34839 -                       
34840 +
34841                         return HANDLER_FINISHED;
34842                 }
34843         }
34844 -       
34845 +
34846         /* not found */
34847         return HANDLER_GO_ON;
34848  }
34849 @@ -1072,13 +1071,13 @@
34850  int mod_ssi_plugin_init(plugin *p) {
34851         p->version     = LIGHTTPD_VERSION_ID;
34852         p->name        = buffer_init_string("ssi");
34853 -       
34854 +
34855         p->init        = mod_ssi_init;
34856         p->handle_subrequest_start = mod_ssi_physical_path;
34857         p->set_defaults  = mod_ssi_set_defaults;
34858         p->cleanup     = mod_ssi_free;
34859 -       
34860 +
34861         p->data        = NULL;
34862 -       
34863 +
34864         return 0;
34865  }
34866 --- ../lighttpd-1.4.11/src/mod_ssi.h    2005-08-11 01:26:39.000000000 +0300
34867 +++ lighttpd-1.4.12/src/mod_ssi.h       2006-07-11 22:07:53.000000000 +0300
34868 @@ -19,23 +19,23 @@
34869  
34870  typedef struct {
34871         PLUGIN_DATA;
34872 -       
34873 -#ifdef HAVE_PCRE_H     
34874 +
34875 +#ifdef HAVE_PCRE_H
34876         pcre *ssi_regex;
34877 -#endif 
34878 +#endif
34879         buffer *timefmt;
34880         int sizefmt;
34881 -       
34882 +
34883         buffer *stat_fn;
34884 -       
34885 +
34886         array *ssi_vars;
34887         array *ssi_cgi_env;
34888 -       
34889 +
34890         int if_level, if_is_false_level, if_is_false, if_is_false_endif;
34891 -       
34892 +
34893         plugin_config **config_storage;
34894 -       
34895 -       plugin_config conf; 
34896 +
34897 +       plugin_config conf;
34898  } plugin_data;
34899  
34900  int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
34901 --- ../lighttpd-1.4.11/src/mod_ssi_expr.c       2005-08-11 01:26:48.000000000 +0300
34902 +++ lighttpd-1.4.12/src/mod_ssi_expr.c  2006-07-11 22:07:52.000000000 +0300
34903 @@ -11,9 +11,9 @@
34904         const char *input;
34905         size_t offset;
34906         size_t size;
34907 -       
34908 +
34909         int line_pos;
34910 -       
34911 +
34912         int in_key;
34913         int in_brace;
34914         int in_cond;
34915 @@ -21,15 +21,15 @@
34916  
34917  ssi_val_t *ssi_val_init() {
34918         ssi_val_t *s;
34919 -       
34920 +
34921         s = calloc(1, sizeof(*s));
34922 -       
34923 +
34924         return s;
34925  }
34926  
34927  void ssi_val_free(ssi_val_t *s) {
34928         if (s->str) buffer_free(s->str);
34929 -       
34930 +
34931         free(s);
34932  }
34933  
34934 @@ -45,175 +45,175 @@
34935                               ssi_tokenizer_t *t, int *token_id, buffer *token) {
34936         int tid = 0;
34937         size_t i;
34938 -       
34939 +
34940         UNUSED(con);
34941  
34942         for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
34943                 char c = t->input[t->offset];
34944                 data_string *ds;
34945 -               
34946 +
34947                 switch (c) {
34948 -               case '=': 
34949 +               case '=':
34950                         tid = TK_EQ;
34951 -                       
34952 +
34953                         t->offset++;
34954                         t->line_pos++;
34955 -                       
34956 +
34957                         buffer_copy_string(token, "(=)");
34958 -                       
34959 +
34960                         break;
34961                 case '>':
34962                         if (t->input[t->offset + 1] == '=') {
34963                                 t->offset += 2;
34964                                 t->line_pos += 2;
34965 -                               
34966 +
34967                                 tid = TK_GE;
34968 -                               
34969 +
34970                                 buffer_copy_string(token, "(>=)");
34971                         } else {
34972                                 t->offset += 1;
34973                                 t->line_pos += 1;
34974 -                               
34975 +
34976                                 tid = TK_GT;
34977 -                               
34978 +
34979                                 buffer_copy_string(token, "(>)");
34980                         }
34981 -                       
34982 +
34983                         break;
34984                 case '<':
34985                         if (t->input[t->offset + 1] == '=') {
34986                                 t->offset += 2;
34987                                 t->line_pos += 2;
34988 -                               
34989 +
34990                                 tid = TK_LE;
34991 -                               
34992 +
34993                                 buffer_copy_string(token, "(<=)");
34994                         } else {
34995                                 t->offset += 1;
34996                                 t->line_pos += 1;
34997 -                               
34998 +
34999                                 tid = TK_LT;
35000 -                               
35001 +
35002                                 buffer_copy_string(token, "(<)");
35003                         }
35004 -                       
35005 +
35006                         break;
35007 -                       
35008 +
35009                 case '!':
35010                         if (t->input[t->offset + 1] == '=') {
35011                                 t->offset += 2;
35012                                 t->line_pos += 2;
35013 -                               
35014 +
35015                                 tid = TK_NE;
35016 -                               
35017 +
35018                                 buffer_copy_string(token, "(!=)");
35019                         } else {
35020                                 t->offset += 1;
35021                                 t->line_pos += 1;
35022 -                               
35023 +
35024                                 tid = TK_NOT;
35025 -                               
35026 +
35027                                 buffer_copy_string(token, "(!)");
35028                         }
35029 -                       
35030 +
35031                         break;
35032                 case '&':
35033                         if (t->input[t->offset + 1] == '&') {
35034                                 t->offset += 2;
35035                                 t->line_pos += 2;
35036 -                               
35037 +
35038                                 tid = TK_AND;
35039 -                               
35040 +
35041                                 buffer_copy_string(token, "(&&)");
35042                         } else {
35043 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
35044 -                                               "pos:", t->line_pos, 
35045 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
35046 +                                               "pos:", t->line_pos,
35047                                                 "missing second &");
35048                                 return -1;
35049                         }
35050 -                       
35051 +
35052                         break;
35053                 case '|':
35054                         if (t->input[t->offset + 1] == '|') {
35055                                 t->offset += 2;
35056                                 t->line_pos += 2;
35057 -                               
35058 +
35059                                 tid = TK_OR;
35060 -                               
35061 +
35062                                 buffer_copy_string(token, "(||)");
35063                         } else {
35064 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
35065 -                                               "pos:", t->line_pos, 
35066 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
35067 +                                               "pos:", t->line_pos,
35068                                                 "missing second |");
35069                                 return -1;
35070                         }
35071 -                       
35072 +
35073                         break;
35074                 case '\t':
35075                 case ' ':
35076                         t->offset++;
35077                         t->line_pos++;
35078                         break;
35079 -                       
35080 +
35081                 case '\'':
35082                         /* search for the terminating " */
35083                         for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\'';  i++);
35084 -                       
35085 +
35086                         if (t->input[t->offset + i]) {
35087                                 tid = TK_VALUE;
35088 -                               
35089 +
35090                                 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35091 -                               
35092 +
35093                                 t->offset += i + 1;
35094                                 t->line_pos += i + 1;
35095                         } else {
35096                                 /* ERROR */
35097 -                               
35098 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
35099 -                                               "pos:", t->line_pos, 
35100 +
35101 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
35102 +                                               "pos:", t->line_pos,
35103                                                 "missing closing quote");
35104 -                               
35105 +
35106                                 return -1;
35107                         }
35108 -                       
35109 +
35110                         break;
35111                 case '(':
35112                         t->offset++;
35113                         t->in_brace++;
35114 -                               
35115 +
35116                         tid = TK_LPARAN;
35117 -                               
35118 +
35119                         buffer_copy_string(token, "(");
35120                         break;
35121                 case ')':
35122                         t->offset++;
35123                         t->in_brace--;
35124 -                               
35125 +
35126                         tid = TK_RPARAN;
35127 -                               
35128 +
35129                         buffer_copy_string(token, ")");
35130                         break;
35131                 case '$':
35132                         if (t->input[t->offset + 1] == '{') {
35133                                 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}';  i++);
35134 -                               
35135 +
35136                                 if (t->input[t->offset + i] != '}') {
35137 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", 
35138 -                                                       "pos:", t->line_pos, 
35139 +                                       log_error_write(srv, __FILE__, __LINE__, "sds",
35140 +                                                       "pos:", t->line_pos,
35141                                                         "missing closing quote");
35142 -                                       
35143 +
35144                                         return -1;
35145                                 }
35146 -                               
35147 +
35148                                 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
35149                         } else {
35150                                 for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_';  i++);
35151 -                               
35152 +
35153                                 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35154                         }
35155 -                       
35156 +
35157                         tid = TK_VALUE;
35158 -                       
35159 +
35160                         if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
35161                                 buffer_copy_string_buffer(token, ds->value);
35162                         } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
35163 @@ -221,16 +221,16 @@
35164                         } else {
35165                                 buffer_copy_string(token, "");
35166                         }
35167 -                               
35168 +
35169                         t->offset += i;
35170                         t->line_pos += i;
35171 -                       
35172 +
35173                         break;
35174                 default:
35175                         for (i = 0; isgraph(t->input[t->offset + i]);  i++) {
35176                                 char d = t->input[t->offset + i];
35177                                 switch(d) {
35178 -                               case ' ': 
35179 +                               case ' ':
35180                                 case '\t':
35181                                 case ')':
35182                                 case '(':
35183 @@ -244,25 +244,25 @@
35184                                         break;
35185                                 }
35186                         }
35187 -                       
35188 +
35189                         tid = TK_VALUE;
35190 -                               
35191 +
35192                         buffer_copy_string_len(token, t->input + t->offset, i);
35193 -                               
35194 +
35195                         t->offset += i;
35196                         t->line_pos += i;
35197 -                       
35198 +
35199                         break;
35200                 }
35201         }
35202 -                       
35203 +
35204         if (tid) {
35205                 *token_id = tid;
35206 -               
35207 +
35208                 return 1;
35209         } else if (t->offset < t->size) {
35210 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
35211 -                               "pos:", t->line_pos, 
35212 +               log_error_write(srv, __FILE__, __LINE__, "sds",
35213 +                               "pos:", t->line_pos,
35214                                 "foobar");
35215         }
35216         return 0;
35217 @@ -275,50 +275,50 @@
35218         buffer *token;
35219         ssi_ctx_t context;
35220         int ret;
35221 -       
35222 +
35223         t.input = expr;
35224         t.offset = 0;
35225         t.size = strlen(expr);
35226         t.line_pos = 1;
35227 -       
35228 +
35229         t.in_key = 1;
35230         t.in_brace = 0;
35231         t.in_cond = 0;
35232 -       
35233 +
35234         context.ok = 1;
35235         context.srv = srv;
35236 -       
35237 +
35238         /* default context */
35239 -       
35240 +
35241         pParser = ssiexprparserAlloc( malloc );
35242         token = buffer_init();
35243         while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
35244                 ssiexprparser(pParser, token_id, token, &context);
35245 -               
35246 +
35247                 token = buffer_init();
35248         }
35249         ssiexprparser(pParser, 0, token, &context);
35250         ssiexprparserFree(pParser, free );
35251 -       
35252 +
35253         buffer_free(token);
35254 -       
35255 +
35256         if (ret == -1) {
35257 -               log_error_write(srv, __FILE__, __LINE__, "s", 
35258 +               log_error_write(srv, __FILE__, __LINE__, "s",
35259                                 "expr parser failed");
35260                 return -1;
35261         }
35262 -       
35263 +
35264         if (context.ok == 0) {
35265 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
35266 -                               "pos:", t.line_pos, 
35267 +               log_error_write(srv, __FILE__, __LINE__, "sds",
35268 +                               "pos:", t.line_pos,
35269                                 "parser failed somehow near here");
35270                 return -1;
35271         }
35272  #if 0
35273 -       log_error_write(srv, __FILE__, __LINE__, "ssd", 
35274 +       log_error_write(srv, __FILE__, __LINE__, "ssd",
35275                         "expr: ",
35276                         expr,
35277                         context.val.bo);
35278 -#endif 
35279 +#endif
35280         return context.val.bo;
35281  }
35282 --- ../lighttpd-1.4.11/src/mod_ssi_expr.h       2005-08-11 01:26:48.000000000 +0300
35283 +++ lighttpd-1.4.12/src/mod_ssi_expr.h  2006-07-11 22:07:52.000000000 +0300
35284 @@ -5,16 +5,16 @@
35285  
35286  typedef struct {
35287         enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
35288 -       
35289 +
35290         buffer *str;
35291         int     bo;
35292  } ssi_val_t;
35293  
35294  typedef struct {
35295         int     ok;
35296 -       
35297 +
35298         ssi_val_t val;
35299 -       
35300 +
35301         void   *srv;
35302  } ssi_ctx_t;
35303  
35304 --- ../lighttpd-1.4.11/src/mod_ssi_exprparser.c 2005-10-03 00:40:25.000000000 +0300
35305 +++ lighttpd-1.4.12/src/mod_ssi_exprparser.c    2006-07-11 22:08:02.000000000 +0300
35306 @@ -18,10 +18,10 @@
35307  /* Next is all token values, in a form suitable for use by makeheaders.
35308  ** This section will be null unless lemon is run with the -m switch.
35309  */
35310 -/* 
35311 +/*
35312  ** These constants (all generated automatically by the parser generator)
35313  ** specify the various kinds of tokens (terminals) that the parser
35314 -** understands. 
35315 +** understands.
35316  **
35317  ** Each symbol here is a terminal symbol in the grammar.
35318  */
35319 @@ -38,7 +38,7 @@
35320  **                       and nonterminals.  "int" is used otherwise.
35321  **    YYNOCODE           is a number of type YYCODETYPE which corresponds
35322  **                       to no legal terminal or nonterminal number.  This
35323 -**                       number is used to fill in empty slots of the hash 
35324 +**                       number is used to fill in empty slots of the hash
35325  **                       table.
35326  **    YYFALLBACK         If defined, this indicates that one or more tokens
35327  **                       have fall-back values which should be used if the
35328 @@ -47,7 +47,7 @@
35329  **                       and nonterminal numbers.  "unsigned char" is
35330  **                       used if there are fewer than 250 rules and
35331  **                       states combined.  "int" is used otherwise.
35332 -**    ssiexprparserTOKENTYPE     is the data type used for minor tokens given 
35333 +**    ssiexprparserTOKENTYPE     is the data type used for minor tokens given
35334  **                       directly to the parser from the tokenizer.
35335  **    YYMINORTYPE        is the data type used for all minor tokens.
35336  **                       This is typically a union of many types, one of
35337 @@ -91,7 +91,7 @@
35338  /* Next are that tables used to determine what action to take based on the
35339  ** current state and lookahead token.  These tables are used to implement
35340  ** functions that take a state number and lookahead value and return an
35341 -** action integer.  
35342 +** action integer.
35343  **
35344  ** Suppose the action integer is N.  Then the action is determined as
35345  ** follows
35346 @@ -116,7 +116,7 @@
35347  ** If the index value yy_shift_ofst[S]+X is out of range or if the value
35348  ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
35349  ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
35350 -** and that yy_default[S] should be used instead.  
35351 +** and that yy_default[S] should be used instead.
35352  **
35353  ** The formula above is for computing the action when the lookahead is
35354  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
35355 @@ -168,7 +168,7 @@
35356  
35357  /* The next table maps tokens into fallback tokens.  If a construct
35358  ** like the following:
35359 -** 
35360 +**
35361  **      %fallback ID X Y Z.
35362  **
35363  ** appears in the grammer, then ID becomes a fallback token for X, Y,
35364 @@ -219,10 +219,10 @@
35365  #endif /* NDEBUG */
35366  
35367  #ifndef NDEBUG
35368 -/* 
35369 +/*
35370  ** Turn parser tracing on by giving a stream to which to write the trace
35371  ** and a prompt to preface each trace message.  Tracing is turned off
35372 -** by making either argument NULL 
35373 +** by making either argument NULL
35374  **
35375  ** Inputs:
35376  ** <ul>
35377 @@ -247,7 +247,7 @@
35378  #ifndef NDEBUG
35379  /* For tracing shifts, the names of all terminals and nonterminals
35380  ** are required.  The following table supplies these names */
35381 -static const char *yyTokenName[] = { 
35382 +static const char *yyTokenName[] = {
35383    "$",             "AND",           "OR",            "EQ",          
35384    "NE",            "GT",            "GE",            "LT",          
35385    "LE",            "NOT",           "LPARAN",        "RPARAN",      
35386 @@ -295,7 +295,7 @@
35387  #endif
35388  }
35389  
35390 -/* 
35391 +/*
35392  ** This function allocates a new parser.
35393  ** The only argument is a pointer to a function which works like
35394  ** malloc.
35395 @@ -326,7 +326,7 @@
35396      /* Here is inserted the actions which take place when a
35397      ** terminal or non-terminal is destroyed.  This can happen
35398      ** when the symbol is popped from the stack during a
35399 -    ** reduce or during error processing or when a parser is 
35400 +    ** reduce or during error processing or when a parser is
35401      ** being destroyed before it is finished parsing.
35402      **
35403      ** Note: during a reduce, the only symbols destroyed are those
35404 @@ -379,7 +379,7 @@
35405    return yymajor;
35406  }
35407  
35408 -/* 
35409 +/*
35410  ** Deallocate and destroy a parser.  Destructors are all called for
35411  ** all stack elements before shutting the parser down.
35412  **
35413 @@ -415,7 +415,7 @@
35414  ){
35415    int i;
35416    int stateno = pParser->yystack[pParser->yyidx].stateno;
35417
35418 +
35419    /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
35420    i = yy_shift_ofst[stateno];
35421    if( i==YY_SHIFT_USE_DFLT ){
35422 @@ -459,7 +459,7 @@
35423  ){
35424    int i;
35425    int stateno = pParser->yystack[pParser->yyidx].stateno;
35426
35427 +
35428    i = yy_reduce_ofst[stateno];
35429    if( i==YY_REDUCE_USE_DFLT ){
35430      return yy_default[stateno];
35431 @@ -559,7 +559,7 @@
35432    ssiexprparserARG_FETCH;
35433    yymsp = &yypParser->yystack[yypParser->yyidx];
35434  #ifndef NDEBUG
35435 -  if( yyTraceFILE && yyruleno>=0 
35436 +  if( yyTraceFILE && yyruleno>=0
35437          && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
35438      fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
35439        yyRuleName[yyruleno]);
35440 @@ -872,7 +872,7 @@
35441  #ifdef YYERRORSYMBOL
35442        /* A syntax error has occurred.
35443        ** The response to an error depends upon whether or not the
35444 -      ** grammar defines an error token "ERROR".  
35445 +      ** grammar defines an error token "ERROR".
35446        **
35447        ** This is what we do if the grammar does define ERROR:
35448        **
35449 --- ../lighttpd-1.4.11/src/mod_staticfile.c     2006-02-15 14:31:14.000000000 +0200
35450 +++ lighttpd-1.4.12/src/mod_staticfile.c        2006-07-11 22:07:51.000000000 +0300
35451 @@ -14,9 +14,11 @@
35452  #include "http_chunk.h"
35453  #include "response.h"
35454  
35455 +#include "sys-files.h"
35456 +#include "sys-strings.h"
35457  /**
35458   * this is a staticfile for a lighttpd plugin
35459 - * 
35460 + *
35461   */
35462  
35463  
35464 @@ -29,48 +31,48 @@
35465  
35466  typedef struct {
35467         PLUGIN_DATA;
35468 -       
35469 +
35470         buffer *range_buf;
35471 -       
35472 +
35473         plugin_config **config_storage;
35474 -       
35475 -       plugin_config conf; 
35476 +
35477 +       plugin_config conf;
35478  } plugin_data;
35479  
35480  /* init the plugin data */
35481  INIT_FUNC(mod_staticfile_init) {
35482         plugin_data *p;
35483 -       
35484 +
35485         p = calloc(1, sizeof(*p));
35486 -       
35487 +
35488         p->range_buf = buffer_init();
35489 -       
35490 +
35491         return p;
35492  }
35493  
35494 -/* detroy the plugin data */
35495 +/* destroy the plugin data */
35496  FREE_FUNC(mod_staticfile_free) {
35497         plugin_data *p = p_d;
35498 -       
35499 +
35500         UNUSED(srv);
35501  
35502         if (!p) return HANDLER_GO_ON;
35503 -       
35504 +
35505         if (p->config_storage) {
35506                 size_t i;
35507                 for (i = 0; i < srv->config_context->used; i++) {
35508                         plugin_config *s = p->config_storage[i];
35509 -                       
35510 +
35511                         array_free(s->exclude_ext);
35512 -                       
35513 +
35514                         free(s);
35515                 }
35516                 free(p->config_storage);
35517         }
35518         buffer_free(p->range_buf);
35519 -       
35520 +
35521         free(p);
35522 -       
35523 +
35524         return HANDLER_GO_ON;
35525  }
35526  
35527 @@ -79,63 +81,60 @@
35528  SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
35529         plugin_data *p = p_d;
35530         size_t i = 0;
35531 -       
35532 -       config_values_t cv[] = { 
35533 +
35534 +       config_values_t cv[] = {
35535                 { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
35536                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
35537         };
35538 -       
35539 +
35540         if (!p) return HANDLER_ERROR;
35541 -       
35542 +
35543         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
35544 -       
35545 +
35546         for (i = 0; i < srv->config_context->used; i++) {
35547                 plugin_config *s;
35548 -               
35549 +
35550                 s = calloc(1, sizeof(plugin_config));
35551                 s->exclude_ext    = array_init();
35552 -               
35553 +
35554                 cv[0].destination = s->exclude_ext;
35555 -               
35556 +
35557                 p->config_storage[i] = s;
35558 -       
35559 +
35560                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
35561                         return HANDLER_ERROR;
35562                 }
35563         }
35564 -       
35565 +
35566         return HANDLER_GO_ON;
35567  }
35568  
35569 -#define PATCH(x) \
35570 -       p->conf.x = s->x;
35571  static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
35572         size_t i, j;
35573         plugin_config *s = p->config_storage[0];
35574 -       
35575 -       PATCH(exclude_ext);
35576 -       
35577 +
35578 +       PATCH_OPTION(exclude_ext);
35579 +
35580         /* skip the first, the global context */
35581         for (i = 1; i < srv->config_context->used; i++) {
35582                 data_config *dc = (data_config *)srv->config_context->data[i];
35583                 s = p->config_storage[i];
35584 -               
35585 +
35586                 /* condition didn't match */
35587                 if (!config_check_cond(srv, con, dc)) continue;
35588 -               
35589 +
35590                 /* merge config */
35591                 for (j = 0; j < dc->value->used; j++) {
35592                         data_unset *du = dc->value->data[j];
35593 -                       
35594 +
35595                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
35596 -                               PATCH(exclude_ext);
35597 +                               PATCH_OPTION(exclude_ext);
35598                         }
35599                 }
35600         }
35601 -       
35602 +
35603         return 0;
35604  }
35605 -#undef PATCH
35606  
35607  static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
35608         int multipart = 0;
35609 @@ -146,69 +145,69 @@
35610         data_string *ds;
35611         stat_cache_entry *sce = NULL;
35612         buffer *content_type = NULL;
35613 -       
35614 +
35615         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35616                 SEGFAULT();
35617         }
35618 -       
35619 +
35620         start = 0;
35621         end = sce->st.st_size - 1;
35622 -       
35623 +
35624         con->response.content_length = 0;
35625 -       
35626 +
35627         if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
35628                 content_type = ds->value;
35629         }
35630 -       
35631 +
35632         for (s = con->request.http_range, error = 0;
35633              !error && *s && NULL != (minus = strchr(s, '-')); ) {
35634                 char *err;
35635                 off_t la, le;
35636 -               
35637 +
35638                 if (s == minus) {
35639                         /* -<stop> */
35640 -                       
35641 +
35642                         le = strtoll(s, &err, 10);
35643 -                       
35644 +
35645                         if (le == 0) {
35646                                 /* RFC 2616 - 14.35.1 */
35647 -                               
35648 +
35649                                 con->http_status = 416;
35650                                 error = 1;
35651                         } else if (*err == '\0') {
35652                                 /* end */
35653                                 s = err;
35654 -                               
35655 +
35656                                 end = sce->st.st_size - 1;
35657                                 start = sce->st.st_size + le;
35658                         } else if (*err == ',') {
35659                                 multipart = 1;
35660                                 s = err + 1;
35661 -                               
35662 +
35663                                 end = sce->st.st_size - 1;
35664                                 start = sce->st.st_size + le;
35665                         } else {
35666                                 error = 1;
35667                         }
35668 -                       
35669 +
35670                 } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
35671                         /* <start>- */
35672 -                       
35673 +
35674                         la = strtoll(s, &err, 10);
35675 -                       
35676 +
35677                         if (err == minus) {
35678                                 /* ok */
35679 -                               
35680 +
35681                                 if (*(err + 1) == '\0') {
35682                                         s = err + 1;
35683 -                                       
35684 +
35685                                         end = sce->st.st_size - 1;
35686                                         start = la;
35687 -                                       
35688 +
35689                                 } else if (*(err + 1) == ',') {
35690                                         multipart = 1;
35691                                         s = err + 2;
35692 -                                       
35693 +
35694                                         end = sce->st.st_size - 1;
35695                                         start = la;
35696                                 } else {
35697 @@ -220,64 +219,64 @@
35698                         }
35699                 } else {
35700                         /* <start>-<stop> */
35701 -                       
35702 +
35703                         la = strtoll(s, &err, 10);
35704 -                       
35705 +
35706                         if (err == minus) {
35707                                 le = strtoll(minus+1, &err, 10);
35708 -                               
35709 +
35710                                 /* RFC 2616 - 14.35.1 */
35711                                 if (la > le) {
35712                                         error = 1;
35713                                 }
35714 -                                       
35715 +
35716                                 if (*err == '\0') {
35717                                         /* ok, end*/
35718                                         s = err;
35719 -                                       
35720 +
35721                                         end = le;
35722                                         start = la;
35723                                 } else if (*err == ',') {
35724                                         multipart = 1;
35725                                         s = err + 1;
35726 -                                       
35727 +
35728                                         end = le;
35729                                         start = la;
35730                                 } else {
35731                                         /* error */
35732 -                                       
35733 +
35734                                         error = 1;
35735                                 }
35736                         } else {
35737                                 /* error */
35738 -                               
35739 +
35740                                 error = 1;
35741                         }
35742                 }
35743 -               
35744 +
35745                 if (!error) {
35746                         if (start < 0) start = 0;
35747 -                       
35748 +
35749                         /* RFC 2616 - 14.35.1 */
35750                         if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
35751 -                       
35752 +
35753                         if (start > sce->st.st_size - 1) {
35754                                 error = 1;
35755 -                               
35756 +
35757                                 con->http_status = 416;
35758                         }
35759                 }
35760 -               
35761 +
35762                 if (!error) {
35763                         if (multipart) {
35764                                 /* write boundary-header */
35765                                 buffer *b;
35766 -                               
35767 +
35768                                 b = chunkqueue_get_append_buffer(con->write_queue);
35769 -                               
35770 +
35771                                 buffer_copy_string(b, "\r\n--");
35772                                 buffer_append_string(b, boundary);
35773 -                               
35774 +
35775                                 /* write Content-Range */
35776                                 buffer_append_string(b, "\r\nContent-Range: bytes ");
35777                                 buffer_append_off_t(b, start);
35778 @@ -285,54 +284,54 @@
35779                                 buffer_append_off_t(b, end);
35780                                 buffer_append_string(b, "/");
35781                                 buffer_append_off_t(b, sce->st.st_size);
35782 -                               
35783 +
35784                                 buffer_append_string(b, "\r\nContent-Type: ");
35785                                 buffer_append_string_buffer(b, content_type);
35786 -                               
35787 +
35788                                 /* write END-OF-HEADER */
35789                                 buffer_append_string(b, "\r\n\r\n");
35790 -                               
35791 +
35792                                 con->response.content_length += b->used - 1;
35793 -                               
35794 +
35795                         }
35796 -                       
35797 +
35798                         chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
35799                         con->response.content_length += end - start + 1;
35800                 }
35801         }
35802 -       
35803 +
35804         /* something went wrong */
35805         if (error) return -1;
35806 -       
35807 +
35808         if (multipart) {
35809                 /* add boundary end */
35810                 buffer *b;
35811 -               
35812 +
35813                 b = chunkqueue_get_append_buffer(con->write_queue);
35814 -               
35815 +
35816                 buffer_copy_string_len(b, "\r\n--", 4);
35817                 buffer_append_string(b, boundary);
35818                 buffer_append_string_len(b, "--\r\n", 4);
35819 -               
35820 +
35821                 con->response.content_length += b->used - 1;
35822 -               
35823 +
35824                 /* set header-fields */
35825 -               
35826 +
35827                 buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
35828                 buffer_append_string(p->range_buf, boundary);
35829 -               
35830 +
35831                 /* overwrite content-type */
35832                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
35833         } else {
35834                 /* add Content-Range-header */
35835 -               
35836 +
35837                 buffer_copy_string(p->range_buf, "bytes ");
35838                 buffer_append_off_t(p->range_buf, start);
35839                 buffer_append_string(p->range_buf, "-");
35840                 buffer_append_off_t(p->range_buf, end);
35841                 buffer_append_string(p->range_buf, "/");
35842                 buffer_append_off_t(p->range_buf, sce->st.st_size);
35843 -               
35844 +
35845                 response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
35846         }
35847  
35848 @@ -347,12 +346,12 @@
35849         stat_cache_entry *sce = NULL;
35850         buffer *mtime;
35851         data_string *ds;
35852 -       
35853 +
35854         /* someone else has done a decision for us */
35855         if (con->http_status != 0) return HANDLER_GO_ON;
35856         if (con->uri.path->used == 0) return HANDLER_GO_ON;
35857         if (con->physical.path->used == 0) return HANDLER_GO_ON;
35858 -       
35859 +
35860         /* someone else has handled this request */
35861         if (con->mode != DIRECT) return HANDLER_GO_ON;
35862  
35863 @@ -365,52 +364,52 @@
35864         default:
35865                 return HANDLER_GO_ON;
35866         }
35867 -       
35868 +
35869         mod_staticfile_patch_connection(srv, con, p);
35870 -       
35871 +
35872         s_len = con->uri.path->used - 1;
35873 -       
35874 +
35875         /* ignore certain extensions */
35876         for (k = 0; k < p->conf.exclude_ext->used; k++) {
35877 -               ds = (data_string *)p->conf.exclude_ext->data[k]; 
35878 -               
35879 +               ds = (data_string *)p->conf.exclude_ext->data[k];
35880 +
35881                 if (ds->value->used == 0) continue;
35882  
35883                 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
35884                         return HANDLER_GO_ON;
35885                 }
35886         }
35887 -       
35888 +
35889  
35890         if (con->conf.log_request_handling) {
35891                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling file as static file");
35892         }
35893 -       
35894 +
35895         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35896                 con->http_status = 403;
35897 -               
35898 +
35899                 log_error_write(srv, __FILE__, __LINE__, "sbsb",
35900                                 "not a regular file:", con->uri.path,
35901                                 "->", con->physical.path);
35902 -               
35903 +
35904                 return HANDLER_FINISHED;
35905         }
35906 -       
35907 -       /* we only handline regular files */
35908 +
35909 +       /* we only handle regular files */
35910         if (!S_ISREG(sce->st.st_mode)) {
35911                 con->http_status = 404;
35912 -               
35913 +
35914                 if (con->conf.log_file_not_found) {
35915                         log_error_write(srv, __FILE__, __LINE__, "sbsb",
35916                                         "not a regular file:", con->uri.path,
35917                                         "->", sce->name);
35918                 }
35919 -               
35920 +
35921                 return HANDLER_FINISHED;
35922         }
35923  
35924 -       /* mod_compress might set several data directly, don't overwrite them */
35925 -       
35926 +       /* mod_compress might set several parameters directly; don't overwrite them */
35927 +
35928         /* set response content-type, if not set already */
35929  
35930         if (NULL == array_get_element(con->response.headers, "Content-Type")) {
35931 @@ -420,15 +419,15 @@
35932                         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
35933                 }
35934         }
35935 -       
35936 +
35937         if (NULL == array_get_element(con->response.headers, "ETag")) {
35938                 /* generate e-tag */
35939                 etag_mutate(con->physical.etag, sce->etag);
35940 -       
35941 +
35942                 response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
35943         }
35944         response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
35945 -       
35946 +
35947         /* prepare header */
35948         if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
35949                 mtime = strftime_cache_get(srv, sce->st.st_mtime);
35950 @@ -444,34 +443,34 @@
35951                 /* check if we have a conditional GET */
35952  
35953                 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) {
35954 -                       /* if the value is the same as our ETag, we do a Range-request, 
35955 +                       /* if the value is the same as our ETag, we do a Range-request,
35956                          * otherwise a full 200 */
35957  
35958                         if (!buffer_is_equal(ds->value, con->physical.etag)) {
35959                                 do_range_request = 0;
35960                         }
35961                 }
35962 -       
35963 +
35964                 if (do_range_request) {
35965                         /* content prepared, I'm done */
35966                         con->file_finished = 1;
35967 -               
35968 +
35969                         if (0 == http_response_parse_range(srv, con, p)) {
35970                                 con->http_status = 206;
35971                         }
35972                         return HANDLER_FINISHED;
35973                 }
35974         }
35975 -       
35976 +
35977         /* if we are still here, prepare body */
35978 -       
35979 -       /* we add it here for all requests 
35980 -        * the HEAD request will drop it afterwards again 
35981 +
35982 +       /* we add it here for all requests
35983 +        * the HEAD request will drop it afterwards again
35984          */
35985         http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
35986 -       
35987 +
35988         con->file_finished = 1;
35989 -       
35990 +
35991         return HANDLER_FINISHED;
35992  }
35993  
35994 @@ -480,13 +479,13 @@
35995  int mod_staticfile_plugin_init(plugin *p) {
35996         p->version     = LIGHTTPD_VERSION_ID;
35997         p->name        = buffer_init_string("staticfile");
35998 -       
35999 +
36000         p->init        = mod_staticfile_init;
36001         p->handle_subrequest_start = mod_staticfile_subrequest;
36002         p->set_defaults  = mod_staticfile_set_defaults;
36003         p->cleanup     = mod_staticfile_free;
36004 -       
36005 +
36006         p->data        = NULL;
36007 -       
36008 +
36009         return 0;
36010  }
36011 --- ../lighttpd-1.4.11/src/mod_status.c 2006-01-10 21:45:32.000000000 +0200
36012 +++ lighttpd-1.4.12/src/mod_status.c    2006-07-11 22:07:53.000000000 +0300
36013 @@ -4,7 +4,6 @@
36014  #include <fcntl.h>
36015  #include <stdlib.h>
36016  #include <string.h>
36017 -#include <unistd.h>
36018  #include <errno.h>
36019  #include <time.h>
36020  #include <stdio.h>
36021 @@ -29,114 +28,114 @@
36022  
36023  typedef struct {
36024         PLUGIN_DATA;
36025 -       
36026 +
36027         double traffic_out;
36028         double requests;
36029 -       
36030 +
36031         double mod_5s_traffic_out[5];
36032         double mod_5s_requests[5];
36033         size_t mod_5s_ndx;
36034 -       
36035 +
36036         double rel_traffic_out;
36037         double rel_requests;
36038 -       
36039 +
36040         double abs_traffic_out;
36041         double abs_requests;
36042 -       
36043 +
36044         double bytes_written;
36045 -       
36046 +
36047         buffer *module_list;
36048 -       
36049 +
36050         plugin_config **config_storage;
36051 -       
36052 -       plugin_config conf; 
36053 +
36054 +       plugin_config conf;
36055  } plugin_data;
36056  
36057  INIT_FUNC(mod_status_init) {
36058         plugin_data *p;
36059         size_t i;
36060 -       
36061 +
36062         p = calloc(1, sizeof(*p));
36063 -       
36064 +
36065         p->traffic_out = p->requests = 0;
36066         p->rel_traffic_out = p->rel_requests = 0;
36067         p->abs_traffic_out = p->abs_requests = 0;
36068         p->bytes_written = 0;
36069         p->module_list = buffer_init();
36070 -       
36071 +
36072         for (i = 0; i < 5; i++) {
36073                 p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
36074         }
36075 -       
36076 +
36077         return p;
36078  }
36079  
36080  FREE_FUNC(mod_status_free) {
36081         plugin_data *p = p_d;
36082 -       
36083 +
36084         UNUSED(srv);
36085  
36086         if (!p) return HANDLER_GO_ON;
36087 -       
36088 +
36089         buffer_free(p->module_list);
36090 -       
36091 +
36092         if (p->config_storage) {
36093                 size_t i;
36094                 for (i = 0; i < srv->config_context->used; i++) {
36095                         plugin_config *s = p->config_storage[i];
36096 -                       
36097 +
36098                         buffer_free(s->status_url);
36099                         buffer_free(s->statistics_url);
36100                         buffer_free(s->config_url);
36101 -                       
36102 +
36103                         free(s);
36104                 }
36105                 free(p->config_storage);
36106         }
36107 -       
36108 -       
36109 +
36110 +
36111         free(p);
36112 -       
36113 +
36114         return HANDLER_GO_ON;
36115  }
36116  
36117  SETDEFAULTS_FUNC(mod_status_set_defaults) {
36118         plugin_data *p = p_d;
36119         size_t i;
36120 -       
36121 -       config_values_t cv[] = { 
36122 +
36123 +       config_values_t cv[] = {
36124                 { "status.status-url",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36125                 { "status.config-url",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36126                 { "status.enable-sort",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
36127                 { "status.statistics-url",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36128                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36129         };
36130 -       
36131 +
36132         if (!p) return HANDLER_ERROR;
36133 -       
36134 +
36135         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36136 -       
36137 +
36138         for (i = 0; i < srv->config_context->used; i++) {
36139                 plugin_config *s;
36140 -               
36141 +
36142                 s = calloc(1, sizeof(plugin_config));
36143                 s->config_url    = buffer_init();
36144                 s->status_url    = buffer_init();
36145                 s->sort          = 1;
36146                 s->statistics_url    = buffer_init();
36147 -               
36148 +
36149                 cv[0].destination = s->status_url;
36150                 cv[1].destination = s->config_url;
36151                 cv[2].destination = &(s->sort);
36152                 cv[3].destination = s->statistics_url;
36153 -               
36154 +
36155                 p->config_storage[i] = s;
36156 -       
36157 +
36158                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36159                         return HANDLER_ERROR;
36160                 }
36161         }
36162 -       
36163 +
36164         return HANDLER_GO_ON;
36165  }
36166  
36167 @@ -151,7 +150,7 @@
36168         buffer_append_string(b, value);
36169         BUFFER_APPEND_STRING_CONST(b, "</td>\n");
36170         BUFFER_APPEND_STRING_CONST(b, "   </tr>\n");
36171 -       
36172 +
36173         return 0;
36174  }
36175  
36176 @@ -161,13 +160,13 @@
36177         buffer_append_string(b, key);
36178         BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36179         BUFFER_APPEND_STRING_CONST(b, "   </tr>\n");
36180 -       
36181 +
36182         return 0;
36183  }
36184  
36185  static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
36186         plugin_data *p = p_d;
36187 -       
36188 +
36189         if (p->conf.sort) {
36190                 BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">");
36191                 buffer_append_string(b, key);
36192 @@ -177,13 +176,13 @@
36193                 buffer_append_string(b, key);
36194                 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36195         }
36196 -       
36197 +
36198         return 0;
36199  }
36200  
36201  static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
36202         *multiplier = ' ';
36203 -       
36204 +
36205         if (*avg > size) { *avg /= size; *multiplier = 'k'; }
36206         if (*avg > size) { *avg /= size; *multiplier = 'M'; }
36207         if (*avg > size) { *avg /= size; *multiplier = 'G'; }
36208 @@ -202,21 +201,21 @@
36209         size_t j;
36210         double avg;
36211         char multiplier = '\0';
36212 -       char buf[32];
36213 +       char buf[128];
36214         time_t ts;
36215 -       
36216 +
36217         int days, hours, mins, seconds;
36218 -       
36219 +
36220         b = chunkqueue_get_append_buffer(con->write_queue);
36221  
36222 -       BUFFER_COPY_STRING_CONST(b, 
36223 +       BUFFER_COPY_STRING_CONST(b,
36224                                  "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36225                                  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36226                                  "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36227                                  "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
36228                                  " <head>\n"
36229                                  "  <title>Status</title>\n");
36230 -       
36231 +
36232         BUFFER_APPEND_STRING_CONST(b,
36233                                    "  <style type=\"text/css\">\n"
36234                                    "    table.status { border: black solid thin; }\n"
36235 @@ -226,14 +225,14 @@
36236                                    "    a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
36237                                    "    span.sortarrow { color: white; text-decoration: none; }\n"
36238                                    "  </style>\n");
36239 -       
36240 +
36241         if (p->conf.sort) {
36242                 BUFFER_APPEND_STRING_CONST(b,
36243                                            "<script type=\"text/javascript\">\n"
36244                                            "// <!--\n"
36245                                            "var sort_column;\n"
36246                                            "var prev_span = null;\n");
36247 -               
36248 +
36249                 BUFFER_APPEND_STRING_CONST(b,
36250                                            "function get_inner_text(el) {\n"
36251                                            " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
36252 @@ -251,7 +250,7 @@
36253                                            " }\n"
36254                                            " return str;\n"
36255                                            "}\n");
36256 -               
36257 +
36258                 BUFFER_APPEND_STRING_CONST(b,
36259                                            "function sortfn(a,b) {\n"
36260                                            " var at = get_inner_text(a.cells[sort_column]);\n"
36261 @@ -266,7 +265,7 @@
36262                                            "  else return 1;\n"
36263                                            " }\n"
36264                                            "}\n");
36265 -               
36266 +
36267                 BUFFER_APPEND_STRING_CONST(b,
36268                                            "function resort(lnk) {\n"
36269                                            " var span = lnk.childNodes[1];\n"
36270 @@ -276,7 +275,7 @@
36271                                            "  rows[j-1] = table.rows[j];\n"
36272                                            " sort_column = lnk.parentNode.cellIndex;\n"
36273                                            " rows.sort(sortfn);\n");
36274 -               
36275 +
36276                 BUFFER_APPEND_STRING_CONST(b,
36277                                            " if (prev_span != null) prev_span.innerHTML = '';\n"
36278                                            " if (span.getAttribute('sortdir')=='down') {\n"
36279 @@ -294,175 +293,175 @@
36280                                            "// -->\n"
36281                                            "</script>\n");
36282         }
36283 -       
36284 -       BUFFER_APPEND_STRING_CONST(b, 
36285 +
36286 +       BUFFER_APPEND_STRING_CONST(b,
36287                                  " </head>\n"
36288                                  " <body>\n");
36289 -       
36290 -       
36291 -       
36292 +
36293 +
36294 +
36295         /* connection listing */
36296         BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
36297 -       
36298 -       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
36299 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
36300 +
36301 +       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
36302 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
36303         buffer_append_string_buffer(b, con->uri.authority);
36304 -       BUFFER_APPEND_STRING_CONST(b, " (");
36305 +       BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
36306         buffer_append_string_buffer(b, con->server_name);
36307 -       BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
36308 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
36309 -       
36310 +       BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
36311 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
36312 +
36313         ts = srv->cur_ts - srv->startup_ts;
36314 -       
36315 +
36316         days = ts / (60 * 60 * 24);
36317         ts %= (60 * 60 * 24);
36318 -       
36319 +
36320         hours = ts / (60 * 60);
36321         ts %= (60 * 60);
36322 -       
36323 +
36324         mins = ts / (60);
36325         ts %= (60);
36326 -       
36327 +
36328         seconds = ts;
36329 -       
36330 +
36331         if (days) {
36332                 buffer_append_long(b, days);
36333                 BUFFER_APPEND_STRING_CONST(b, " days ");
36334         }
36335 -       
36336 +
36337         if (hours) {
36338                 buffer_append_long(b, hours);
36339                 BUFFER_APPEND_STRING_CONST(b, " hours ");
36340         }
36341 -       
36342 +
36343         if (mins) {
36344                 buffer_append_long(b, mins);
36345                 BUFFER_APPEND_STRING_CONST(b, " min ");
36346         }
36347 -       
36348 +
36349         buffer_append_long(b, seconds);
36350         BUFFER_APPEND_STRING_CONST(b, " s");
36351 -       
36352 +
36353         BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36354         BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
36355 -       
36356 +
36357         ts = srv->startup_ts;
36358 -       
36359 -       strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
36360 +
36361 +       strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
36362         buffer_append_string(b, buf);
36363         BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36364 -       
36365 -       
36366 +
36367 +
36368         BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
36369 -       
36370 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36371 +
36372 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
36373         avg = p->abs_requests;
36374  
36375         mod_status_get_multiplier(&avg, &multiplier, 1000);
36376 -       
36377 +
36378         buffer_append_long(b, avg);
36379 -       BUFFER_APPEND_STRING_CONST(b, " ");
36380 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
36381         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36382 -       BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
36383 -       
36384 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36385 +       BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
36386 +
36387 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
36388         avg = p->abs_traffic_out;
36389  
36390         mod_status_get_multiplier(&avg, &multiplier, 1024);
36391  
36392         sprintf(buf, "%.2f", avg);
36393         buffer_append_string(b, buf);
36394 -       BUFFER_APPEND_STRING_CONST(b, " ");
36395 +       BUFFER_APPEND_STRING_CONST(b, "</span>  <span id=\"traffic_mult\">");
36396         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36397 -       BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
36398 +       BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
36399  
36400  
36401  
36402         BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
36403 -       
36404 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36405 +
36406 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
36407         avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
36408  
36409         mod_status_get_multiplier(&avg, &multiplier, 1000);
36410  
36411         buffer_append_long(b, avg);
36412 -       BUFFER_APPEND_STRING_CONST(b, " ");
36413 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
36414         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36415 -       BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36416 -       
36417 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36418 +       BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36419 +
36420 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
36421         avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
36422  
36423         mod_status_get_multiplier(&avg, &multiplier, 1024);
36424  
36425         sprintf(buf, "%.2f", avg);
36426         buffer_append_string(b, buf);
36427 -       BUFFER_APPEND_STRING_CONST(b, " ");
36428 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
36429         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36430 -       BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36431 +       BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36432 +
36433 +
36434  
36435 -       
36436 -       
36437         BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n");
36438         for (j = 0, avg = 0; j < 5; j++) {
36439                 avg += p->mod_5s_requests[j];
36440         }
36441 -       
36442 +
36443         avg /= 5;
36444 -       
36445 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36446 +
36447 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
36448  
36449         mod_status_get_multiplier(&avg, &multiplier, 1000);
36450  
36451         buffer_append_long(b, avg);
36452 -       BUFFER_APPEND_STRING_CONST(b, " ");
36453 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
36454         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36455 -       
36456 -       BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36457 -       
36458 +
36459 +       BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36460 +
36461         for (j = 0, avg = 0; j < 5; j++) {
36462                 avg += p->mod_5s_traffic_out[j];
36463         }
36464 -       
36465 +
36466         avg /= 5;
36467 -       
36468 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36469 +
36470 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
36471  
36472         mod_status_get_multiplier(&avg, &multiplier, 1024);
36473  
36474         sprintf(buf, "%.2f", avg);
36475         buffer_append_string(b, buf);
36476 -       BUFFER_APPEND_STRING_CONST(b, " ");
36477 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
36478         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36479 -       BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36480 -       
36481 +       BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36482 +
36483         BUFFER_APPEND_STRING_CONST(b, "</table>\n");
36484 -       
36485 -       
36486 +
36487 +
36488         BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n");
36489         BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n");
36490         BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n");
36491         BUFFER_APPEND_STRING_CONST(b, "q = request-start,  Q = request-end\n");
36492         BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
36493 -       
36494 -       BUFFER_APPEND_STRING_CONST(b, "<b>");
36495 +
36496 +       BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
36497         buffer_append_long(b, srv->conns->used);
36498 -       BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
36499 -       
36500 +       BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
36501 +
36502         for (j = 0; j < srv->conns->used; j++) {
36503                 connection *c = srv->conns->ptr[j];
36504                 const char *state = connection_get_short_state(c->state);
36505 -               
36506 +
36507                 buffer_append_string_len(b, state, 1);
36508 -               
36509 +
36510                 if (((j + 1) % 50) == 0) {
36511                         BUFFER_APPEND_STRING_CONST(b, "\n");
36512                 }
36513         }
36514 -       
36515 +
36516         BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
36517 -       
36518 -       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
36519 +
36520 +       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
36521         BUFFER_APPEND_STRING_CONST(b, "<tr>");
36522         mod_status_header_append_sort(b, p_d, "Client IP");
36523         mod_status_header_append_sort(b, p_d, "Read");
36524 @@ -473,16 +472,16 @@
36525         mod_status_header_append_sort(b, p_d, "URI");
36526         mod_status_header_append_sort(b, p_d, "File");
36527         BUFFER_APPEND_STRING_CONST(b, "</tr>\n");
36528 -       
36529 +
36530         for (j = 0; j < srv->conns->used; j++) {
36531                 connection *c = srv->conns->ptr[j];
36532 -               
36533 -               BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
36534 -               
36535 +
36536 +               BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
36537 +
36538                 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
36539 -               
36540 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36541 -               
36542 +
36543 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
36544 +
36545                 if (con->request.content_length) {
36546                         buffer_append_long(b, c->request_content_queue->bytes_in);
36547                         BUFFER_APPEND_STRING_CONST(b, "/");
36548 @@ -490,55 +489,55 @@
36549                 } else {
36550                         BUFFER_APPEND_STRING_CONST(b, "0/0");
36551                 }
36552 -       
36553 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36554 -               
36555 +
36556 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
36557 +
36558                 buffer_append_off_t(b, chunkqueue_written(c->write_queue));
36559                 BUFFER_APPEND_STRING_CONST(b, "/");
36560                 buffer_append_off_t(b, chunkqueue_length(c->write_queue));
36561 -               
36562 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36563 -               
36564 +
36565 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
36566 +
36567                 buffer_append_string(b, connection_get_state(c->state));
36568 -               
36569 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36570 -               
36571 +
36572 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
36573 +
36574                 buffer_append_long(b, srv->cur_ts - c->request_start);
36575 -               
36576 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36577 -               
36578 +
36579 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
36580 +
36581                 if (buffer_is_empty(c->server_name)) {
36582                         buffer_append_string_buffer(b, c->uri.authority);
36583                 }
36584                 else {
36585                         buffer_append_string_buffer(b, c->server_name);
36586                 }
36587 -               
36588 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36589 -               
36590 +
36591 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
36592 +
36593                 if (!buffer_is_empty(c->uri.path)) {
36594                         buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
36595                 }
36596 -               
36597 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36598 -               
36599 +
36600 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
36601 +
36602                 buffer_append_string_buffer(b, c->physical.path);
36603 -               
36604 +
36605                 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36606         }
36607 -       
36608 -       
36609 -       BUFFER_APPEND_STRING_CONST(b, 
36610 +
36611 +
36612 +       BUFFER_APPEND_STRING_CONST(b,
36613                       "</table>\n");
36614 -       
36615 -       
36616 -       BUFFER_APPEND_STRING_CONST(b, 
36617 +
36618 +
36619 +       BUFFER_APPEND_STRING_CONST(b,
36620                       " </body>\n"
36621                       "</html>\n"
36622                       );
36623 -       
36624 +
36625         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36626 -       
36627 +
36628         return 0;
36629  }
36630  
36631 @@ -548,7 +547,7 @@
36632         buffer *b;
36633         double avg;
36634         time_t ts;
36635 -       
36636 +
36637         b = chunkqueue_get_append_buffer(con->write_queue);
36638  
36639         /* output total number of requests */
36640 @@ -556,19 +555,19 @@
36641         avg = p->abs_requests;
36642         buffer_append_long(b, avg);
36643         BUFFER_APPEND_STRING_CONST(b, "\n");
36644 -       
36645 +
36646         /* output total traffic out in kbytes */
36647         BUFFER_APPEND_STRING_CONST(b, "Total kBytes: ");
36648         avg = p->abs_traffic_out / 1024;
36649         buffer_append_long(b, avg);
36650         BUFFER_APPEND_STRING_CONST(b, "\n");
36651 -       
36652 +
36653         /* output uptime */
36654         BUFFER_APPEND_STRING_CONST(b, "Uptime: ");
36655         ts = srv->cur_ts - srv->startup_ts;
36656         buffer_append_long(b, ts);
36657         BUFFER_APPEND_STRING_CONST(b, "\n");
36658 -       
36659 +
36660         /* output busy servers */
36661         BUFFER_APPEND_STRING_CONST(b, "BusyServers: ");
36662         buffer_append_long(b, srv->conns->used);
36663 @@ -577,7 +576,7 @@
36664         /* set text/plain output */
36665  
36666         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36667 -       
36668 +
36669         return 0;
36670  }
36671  
36672 @@ -591,10 +590,10 @@
36673                 /* we have nothing to send */
36674                 con->http_status = 204;
36675                 con->file_finished = 1;
36676 -       
36677 +
36678                 return HANDLER_FINISHED;
36679         }
36680 -       
36681 +
36682         b = chunkqueue_get_append_buffer(con->write_queue);
36683  
36684         for (i = 0; i < st->used; i++) {
36685 @@ -605,27 +604,27 @@
36686                 buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
36687                 buffer_append_string(b, "\n");
36688         }
36689 -       
36690 +
36691         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36692 -       
36693 +
36694         con->http_status = 200;
36695         con->file_finished = 1;
36696 -       
36697 +
36698         return HANDLER_FINISHED;
36699  }
36700  
36701  
36702  static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
36703 -       
36704 +
36705         if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
36706                 mod_status_handle_server_status_text(srv, con, p_d);
36707         } else {
36708                 mod_status_handle_server_status_html(srv, con, p_d);
36709         }
36710 -       
36711 +
36712         con->http_status = 200;
36713         con->file_finished = 1;
36714 -       
36715 +
36716         return HANDLER_FINISHED;
36717  }
36718  
36719 @@ -634,9 +633,9 @@
36720         plugin_data *p = p_d;
36721         buffer *b, *m = p->module_list;
36722         size_t i;
36723 -       
36724 -       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = 
36725 -       { 
36726 +
36727 +       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36728 +       {
36729                 /* - poll is most reliable
36730                  * - select works everywhere
36731                  * - linux-* are experimental
36732 @@ -661,10 +660,10 @@
36733  #endif
36734                 { FDEVENT_HANDLER_UNSET,          NULL }
36735         };
36736 -       
36737 +
36738         b = chunkqueue_get_append_buffer(con->write_queue);
36739 -       
36740 -       BUFFER_COPY_STRING_CONST(b, 
36741 +
36742 +       BUFFER_COPY_STRING_CONST(b,
36743                            "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36744                            "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36745                            "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36746 @@ -675,7 +674,7 @@
36747                            " <body>\n"
36748                            "  <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
36749                            "  <table border=\"1\">\n");
36750 -       
36751 +
36752         mod_status_header_append(b, "Server-Features");
36753  #ifdef HAVE_PCRE_H
36754         mod_status_row_append(b, "RegEx Conditionals", "enabled");
36755 @@ -683,21 +682,21 @@
36756         mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
36757  #endif
36758         mod_status_header_append(b, "Network Engine");
36759 -       
36760 +
36761         for (i = 0; event_handlers[i].name; i++) {
36762                 if (event_handlers[i].et == srv->event_handler) {
36763                         mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
36764                         break;
36765                 }
36766         }
36767 -       
36768 +
36769         mod_status_header_append(b, "Config-File-Settings");
36770 -       
36771 +
36772         for (i = 0; i < srv->plugins.used; i++) {
36773                 plugin **ps = srv->plugins.ptr;
36774 -               
36775 +
36776                 plugin *pl = ps[i];
36777 -       
36778 +
36779                 if (i == 0) {
36780                         buffer_copy_string_buffer(m, pl->name);
36781                 } else {
36782 @@ -705,137 +704,135 @@
36783                         buffer_append_string_buffer(m, pl->name);
36784                 }
36785         }
36786 -       
36787 +
36788         mod_status_row_append(b, "Loaded Modules", m->ptr);
36789 -       
36790 +
36791         BUFFER_APPEND_STRING_CONST(b, "  </table>\n");
36792 -       
36793 -       BUFFER_APPEND_STRING_CONST(b, 
36794 +
36795 +       BUFFER_APPEND_STRING_CONST(b,
36796                       " </body>\n"
36797                       "</html>\n"
36798                       );
36799 -       
36800 +
36801         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36802 -       
36803 +
36804         con->http_status = 200;
36805         con->file_finished = 1;
36806 -       
36807 +
36808         return HANDLER_FINISHED;
36809  }
36810  
36811 -#define PATCH(x) \
36812 -       p->conf.x = s->x;
36813  static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
36814         size_t i, j;
36815         plugin_config *s = p->config_storage[0];
36816 -       
36817 -       PATCH(status_url);
36818 -       PATCH(config_url);
36819 -       PATCH(sort);
36820 -       PATCH(statistics_url);
36821 -       
36822 +
36823 +       PATCH_OPTION(status_url);
36824 +       PATCH_OPTION(config_url);
36825 +       PATCH_OPTION(sort);
36826 +       PATCH_OPTION(statistics_url);
36827 +
36828         /* skip the first, the global context */
36829         for (i = 1; i < srv->config_context->used; i++) {
36830                 data_config *dc = (data_config *)srv->config_context->data[i];
36831                 s = p->config_storage[i];
36832 -               
36833 +
36834                 /* condition didn't match */
36835                 if (!config_check_cond(srv, con, dc)) continue;
36836 -               
36837 +
36838                 /* merge config */
36839                 for (j = 0; j < dc->value->used; j++) {
36840                         data_unset *du = dc->value->data[j];
36841 -                       
36842 +
36843                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
36844 -                               PATCH(status_url);
36845 +                               PATCH_OPTION(status_url);
36846                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
36847 -                               PATCH(config_url);
36848 +                               PATCH_OPTION(config_url);
36849                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
36850 -                               PATCH(sort);
36851 +                               PATCH_OPTION(sort);
36852                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
36853 -                               PATCH(statistics_url);
36854 -                       } 
36855 +                               PATCH_OPTION(statistics_url);
36856 +                       }
36857                 }
36858         }
36859 -       
36860 +
36861         return 0;
36862  }
36863  
36864  static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
36865         plugin_data *p = p_d;
36866 -       
36867 +
36868         mod_status_patch_connection(srv, con, p);
36869 -       
36870 -       if (!buffer_is_empty(p->conf.status_url) && 
36871 +
36872 +       if (!buffer_is_empty(p->conf.status_url) &&
36873             buffer_is_equal(p->conf.status_url, con->uri.path)) {
36874                 return mod_status_handle_server_status(srv, con, p_d);
36875 -       } else if (!buffer_is_empty(p->conf.config_url) && 
36876 +       } else if (!buffer_is_empty(p->conf.config_url) &&
36877             buffer_is_equal(p->conf.config_url, con->uri.path)) {
36878                 return mod_status_handle_server_config(srv, con, p_d);
36879 -       } else if (!buffer_is_empty(p->conf.statistics_url) && 
36880 +       } else if (!buffer_is_empty(p->conf.statistics_url) &&
36881             buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
36882                 return mod_status_handle_server_statistics(srv, con, p_d);
36883         }
36884 -       
36885 +
36886         return HANDLER_GO_ON;
36887  }
36888  
36889  TRIGGER_FUNC(mod_status_trigger) {
36890         plugin_data *p = p_d;
36891         size_t i;
36892 -       
36893 +
36894         /* check all connections */
36895         for (i = 0; i < srv->conns->used; i++) {
36896                 connection *c = srv->conns->ptr[i];
36897 -               
36898 +
36899                 p->bytes_written += c->bytes_written_cur_second;
36900         }
36901 -       
36902 +
36903         /* a sliding average */
36904         p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
36905         p->mod_5s_requests   [p->mod_5s_ndx] = p->requests;
36906 -       
36907 +
36908         p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
36909 -       
36910 +
36911         p->abs_traffic_out += p->bytes_written;
36912         p->rel_traffic_out += p->bytes_written;
36913 -       
36914 +
36915         p->bytes_written = 0;
36916 -       
36917 +
36918         /* reset storage - second */
36919         p->traffic_out = 0;
36920         p->requests    = 0;
36921 -       
36922 +
36923         return HANDLER_GO_ON;
36924  }
36925  
36926  REQUESTDONE_FUNC(mod_status_account) {
36927         plugin_data *p = p_d;
36928 -       
36929 +
36930         UNUSED(srv);
36931  
36932         p->requests++;
36933         p->rel_requests++;
36934         p->abs_requests++;
36935 -       
36936 +
36937         p->bytes_written += con->bytes_written_cur_second;
36938 -       
36939 +
36940         return HANDLER_GO_ON;
36941  }
36942  
36943  int mod_status_plugin_init(plugin *p) {
36944         p->version     = LIGHTTPD_VERSION_ID;
36945         p->name        = buffer_init_string("status");
36946 -       
36947 +
36948         p->init        = mod_status_init;
36949         p->cleanup     = mod_status_free;
36950         p->set_defaults= mod_status_set_defaults;
36951 -       
36952 +
36953         p->handle_uri_clean    = mod_status_handler;
36954         p->handle_trigger      = mod_status_trigger;
36955         p->handle_request_done = mod_status_account;
36956 -       
36957 +
36958         p->data        = NULL;
36959 -       
36960 +
36961         return 0;
36962  }
36963 --- ../lighttpd-1.4.11/src/mod_trigger_b4_dl.c  2005-09-23 22:53:55.000000000 +0300
36964 +++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c     2006-07-11 22:07:51.000000000 +0300
36965 @@ -24,18 +24,18 @@
36966  
36967  /**
36968   * this is a trigger_b4_dl for a lighttpd plugin
36969 - * 
36970 + *
36971   */
36972  
36973  /* plugin config for all request/connections */
36974  
36975  typedef struct {
36976         buffer *db_filename;
36977 -       
36978 +
36979         buffer *trigger_url;
36980         buffer *download_url;
36981         buffer *deny_url;
36982 -       
36983 +
36984         array  *mc_hosts;
36985         buffer *mc_namespace;
36986  #if defined(HAVE_PCRE_H)
36987 @@ -46,58 +46,58 @@
36988         GDBM_FILE db;
36989  #endif
36990  
36991 -#if defined(HAVE_MEMCACHE_H) 
36992 +#if defined(HAVE_MEMCACHE_H)
36993         struct memcache *mc;
36994  #endif
36995 -       
36996 +
36997         unsigned short trigger_timeout;
36998         unsigned short debug;
36999  } plugin_config;
37000  
37001  typedef struct {
37002         PLUGIN_DATA;
37003 -       
37004 +
37005         buffer *tmp_buf;
37006 -       
37007 +
37008         plugin_config **config_storage;
37009 -       
37010 -       plugin_config conf; 
37011 +
37012 +       plugin_config conf;
37013  } plugin_data;
37014  
37015  /* init the plugin data */
37016  INIT_FUNC(mod_trigger_b4_dl_init) {
37017         plugin_data *p;
37018 -       
37019 +
37020         p = calloc(1, sizeof(*p));
37021 -       
37022 +
37023         p->tmp_buf = buffer_init();
37024 -       
37025 +
37026         return p;
37027  }
37028  
37029  /* detroy the plugin data */
37030  FREE_FUNC(mod_trigger_b4_dl_free) {
37031         plugin_data *p = p_d;
37032 -       
37033 +
37034         UNUSED(srv);
37035  
37036         if (!p) return HANDLER_GO_ON;
37037 -       
37038 +
37039         if (p->config_storage) {
37040                 size_t i;
37041                 for (i = 0; i < srv->config_context->used; i++) {
37042                         plugin_config *s = p->config_storage[i];
37043  
37044                         if (!s) continue;
37045 -                       
37046 +
37047                         buffer_free(s->db_filename);
37048                         buffer_free(s->download_url);
37049                         buffer_free(s->trigger_url);
37050                         buffer_free(s->deny_url);
37051 -                       
37052 +
37053                         buffer_free(s->mc_namespace);
37054                         array_free(s->mc_hosts);
37055 -                       
37056 +
37057  #if defined(HAVE_PCRE_H)
37058                         if (s->trigger_regex) pcre_free(s->trigger_regex);
37059                         if (s->download_regex) pcre_free(s->download_regex);
37060 @@ -108,16 +108,16 @@
37061  #if defined(HAVE_MEMCACHE_H)
37062                         if (s->mc) mc_free(s->mc);
37063  #endif
37064 -                       
37065 +
37066                         free(s);
37067                 }
37068                 free(p->config_storage);
37069         }
37070 -       
37071 +
37072         buffer_free(p->tmp_buf);
37073 -       
37074 +
37075         free(p);
37076 -       
37077 +
37078         return HANDLER_GO_ON;
37079  }
37080  
37081 @@ -126,9 +126,9 @@
37082  SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
37083         plugin_data *p = p_d;
37084         size_t i = 0;
37085 -       
37086 -       
37087 -       config_values_t cv[] = { 
37088 +
37089 +
37090 +       config_values_t cv[] = {
37091                 { "trigger-before-download.gdbm-filename",   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
37092                 { "trigger-before-download.trigger-url",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
37093                 { "trigger-before-download.download-url",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
37094 @@ -139,18 +139,18 @@
37095                 { "trigger-before-download.debug",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 7 */
37096                 { NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37097         };
37098 -       
37099 +
37100         if (!p) return HANDLER_ERROR;
37101 -       
37102 +
37103         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37104 -       
37105 +
37106         for (i = 0; i < srv->config_context->used; i++) {
37107                 plugin_config *s;
37108  #if defined(HAVE_PCRE_H)
37109                 const char *errptr;
37110                 int erroff;
37111  #endif
37112 -               
37113 +
37114                 s = calloc(1, sizeof(plugin_config));
37115                 s->db_filename    = buffer_init();
37116                 s->download_url   = buffer_init();
37117 @@ -158,7 +158,7 @@
37118                 s->deny_url       = buffer_init();
37119                 s->mc_hosts       = array_init();
37120                 s->mc_namespace   = buffer_init();
37121 -               
37122 +
37123                 cv[0].destination = s->db_filename;
37124                 cv[1].destination = s->trigger_url;
37125                 cv[2].destination = s->download_url;
37126 @@ -167,41 +167,41 @@
37127                 cv[5].destination = s->mc_hosts;
37128                 cv[6].destination = s->mc_namespace;
37129                 cv[7].destination = &(s->debug);
37130 -               
37131 +
37132                 p->config_storage[i] = s;
37133 -       
37134 +
37135                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37136                         return HANDLER_ERROR;
37137                 }
37138  #if defined(HAVE_GDBM_H)
37139                 if (!buffer_is_empty(s->db_filename)) {
37140                         if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
37141 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
37142 +                               log_error_write(srv, __FILE__, __LINE__, "s",
37143                                                 "gdbm-open failed");
37144                                 return HANDLER_ERROR;
37145                         }
37146                 }
37147  #endif
37148 -#if defined(HAVE_PCRE_H)               
37149 +#if defined(HAVE_PCRE_H)
37150                 if (!buffer_is_empty(s->download_url)) {
37151                         if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
37152                                                                       0, &errptr, &erroff, NULL))) {
37153 -                               
37154 -                               log_error_write(srv, __FILE__, __LINE__, "sbss", 
37155 -                                               "compiling regex for download-url failed:", 
37156 +
37157 +                               log_error_write(srv, __FILE__, __LINE__, "sbss",
37158 +                                               "compiling regex for download-url failed:",
37159                                                 s->download_url, "pos:", erroff);
37160                                 return HANDLER_ERROR;
37161                         }
37162                 }
37163 -               
37164 +
37165                 if (!buffer_is_empty(s->trigger_url)) {
37166                         if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
37167                                                                      0, &errptr, &erroff, NULL))) {
37168 -                               
37169 -                               log_error_write(srv, __FILE__, __LINE__, "sbss", 
37170 -                                               "compiling regex for trigger-url failed:", 
37171 +
37172 +                               log_error_write(srv, __FILE__, __LINE__, "sbss",
37173 +                                               "compiling regex for trigger-url failed:",
37174                                                 s->trigger_url, "pos:", erroff);
37175 -                               
37176 +
37177                                 return HANDLER_ERROR;
37178                         }
37179                 }
37180 @@ -211,100 +211,97 @@
37181  #if defined(HAVE_MEMCACHE_H)
37182                         size_t k;
37183                         s->mc = mc_new();
37184 -               
37185 +
37186                         for (k = 0; k < s->mc_hosts->used; k++) {
37187                                 data_string *ds = (data_string *)s->mc_hosts->data[k];
37188 -                               
37189 +
37190                                 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
37191 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
37192 -                                                       "connection to host failed:", 
37193 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
37194 +                                                       "connection to host failed:",
37195                                                         ds->value);
37196 -                                       
37197 +
37198                                         return HANDLER_ERROR;
37199                                 }
37200                         }
37201  #else
37202 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
37203 +                       log_error_write(srv, __FILE__, __LINE__, "s",
37204                                         "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
37205                         return HANDLER_ERROR;
37206  #endif
37207                 }
37208 -               
37209 +
37210  
37211  #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
37212 -               log_error_write(srv, __FILE__, __LINE__, "s", 
37213 +               log_error_write(srv, __FILE__, __LINE__, "s",
37214                                 "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
37215                 return HANDLER_ERROR;
37216  #endif
37217         }
37218 -       
37219 +
37220         return HANDLER_GO_ON;
37221  }
37222  
37223 -#define PATCH(x) \
37224 -       p->conf.x = s->x;
37225  static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
37226         size_t i, j;
37227         plugin_config *s = p->config_storage[0];
37228 -       
37229 +
37230  #if defined(HAVE_GDBM)
37231 -       PATCH(db);
37232 -#endif 
37233 +       PATCH_OPTION(db);
37234 +#endif
37235  #if defined(HAVE_PCRE_H)
37236 -       PATCH(download_regex);
37237 -       PATCH(trigger_regex);
37238 -#endif 
37239 -       PATCH(trigger_timeout);
37240 -       PATCH(deny_url);
37241 -       PATCH(mc_namespace);
37242 -       PATCH(debug);
37243 +       PATCH_OPTION(download_regex);
37244 +       PATCH_OPTION(trigger_regex);
37245 +#endif
37246 +       PATCH_OPTION(trigger_timeout);
37247 +       PATCH_OPTION(deny_url);
37248 +       PATCH_OPTION(mc_namespace);
37249 +       PATCH_OPTION(debug);
37250  #if defined(HAVE_MEMCACHE_H)
37251 -       PATCH(mc);
37252 +       PATCH_OPTION(mc);
37253  #endif
37254 -       
37255 +
37256         /* skip the first, the global context */
37257         for (i = 1; i < srv->config_context->used; i++) {
37258                 data_config *dc = (data_config *)srv->config_context->data[i];
37259                 s = p->config_storage[i];
37260 -               
37261 +
37262                 /* condition didn't match */
37263                 if (!config_check_cond(srv, con, dc)) continue;
37264 -               
37265 +
37266                 /* merge config */
37267                 for (j = 0; j < dc->value->used; j++) {
37268                         data_unset *du = dc->value->data[j];
37269  
37270                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
37271  #if defined(HAVE_PCRE_H)
37272 -                               PATCH(download_regex);
37273 +                               PATCH_OPTION(download_regex);
37274  #endif
37275                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
37276  # if defined(HAVE_PCRE_H)
37277 -                               PATCH(trigger_regex);
37278 +                               PATCH_OPTION(trigger_regex);
37279  # endif
37280                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
37281  #if defined(HAVE_GDBM_H)
37282 -                               PATCH(db);
37283 +                               PATCH_OPTION(db);
37284  #endif
37285                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
37286 -                               PATCH(trigger_timeout);
37287 +                               PATCH_OPTION(trigger_timeout);
37288                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
37289 -                               PATCH(debug);
37290 +                               PATCH_OPTION(debug);
37291                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
37292 -                               PATCH(deny_url);
37293 +                               PATCH_OPTION(deny_url);
37294                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
37295 -                               PATCH(mc_namespace);
37296 +                               PATCH_OPTION(mc_namespace);
37297                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
37298  #if defined(HAVE_MEMCACHE_H)
37299 -                               PATCH(mc);
37300 +                               PATCH_OPTION(mc);
37301  #endif
37302                         }
37303                 }
37304         }
37305 -       
37306 +
37307         return 0;
37308  }
37309 -#undef PATCH
37310  
37311  URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
37312         plugin_data *p = p_d;
37313 @@ -315,20 +312,20 @@
37314         int n;
37315  # define N 10
37316         int ovec[N * 3];
37317 -       
37318 +
37319         if (con->uri.path->used == 0) return HANDLER_GO_ON;
37320 -       
37321 +
37322         mod_trigger_b4_dl_patch_connection(srv, con, p);
37323 -       
37324 +
37325         if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
37326 -       
37327 +
37328  # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
37329         return HANDLER_GO_ON;
37330  # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
37331         if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
37332         if (p->conf.db && p->conf.mc) {
37333                 /* can't decide which one */
37334 -               
37335 +
37336                 return HANDLER_GO_ON;
37337         }
37338  # elif defined(HAVE_GDBM_H)
37339 @@ -336,12 +333,12 @@
37340  # else
37341         if (!p->conf.mc) return HANDLER_GO_ON;
37342  # endif
37343 -       
37344 +
37345         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) {
37346                 /* X-Forwarded-For contains the ip behind the proxy */
37347 -               
37348 +
37349                 remote_ip = ds->value->ptr;
37350 -               
37351 +
37352                 /* memcache can't handle spaces */
37353         } else {
37354                 remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
37355 @@ -350,13 +347,13 @@
37356         if (p->conf.debug) {
37357                 log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
37358         }
37359 -               
37360 +
37361         /* check if URL is a trigger -> insert IP into DB */
37362         if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37363                 if (n != PCRE_ERROR_NOMATCH) {
37364                         log_error_write(srv, __FILE__, __LINE__, "sd",
37365                                         "execution error while matching:", n);
37366 -                       
37367 +
37368                         return HANDLER_ERROR;
37369                 }
37370         } else {
37371 @@ -364,34 +361,34 @@
37372                 if (p->conf.db) {
37373                         /* the trigger matched */
37374                         datum key, val;
37375 -                       
37376 +
37377                         key.dptr = (char *)remote_ip;
37378                         key.dsize = strlen(remote_ip);
37379 -                       
37380 +
37381                         val.dptr = (char *)&(srv->cur_ts);
37382                         val.dsize = sizeof(srv->cur_ts);
37383 -                       
37384 +
37385                         if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37386                                 log_error_write(srv, __FILE__, __LINE__, "s",
37387                                                 "insert failed");
37388                         }
37389                 }
37390  # endif
37391 -# if defined(HAVE_MEMCACHE_H)          
37392 +# if defined(HAVE_MEMCACHE_H)
37393                 if (p->conf.mc) {
37394                         size_t i;
37395                         buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37396                         buffer_append_string(p->tmp_buf, remote_ip);
37397 -                       
37398 +
37399                         for (i = 0; i < p->tmp_buf->used - 1; i++) {
37400                                 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37401                         }
37402 -                       
37403 +
37404                         if (p->conf.debug) {
37405                                 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
37406                         }
37407  
37408 -                       if (0 != mc_set(p->conf.mc, 
37409 +                       if (0 != mc_set(p->conf.mc,
37410                                         CONST_BUF_LEN(p->tmp_buf),
37411                                         (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37412                                         p->conf.trigger_timeout, 0)) {
37413 @@ -401,7 +398,7 @@
37414                 }
37415  # endif
37416         }
37417 -               
37418 +
37419         /* check if URL is a download -> check IP in DB, update timestamp */
37420         if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37421                 if (n != PCRE_ERROR_NOMATCH) {
37422 @@ -411,93 +408,93 @@
37423                 }
37424         } else {
37425                 /* the download uri matched */
37426 -# if defined(HAVE_GDBM_H)              
37427 +# if defined(HAVE_GDBM_H)
37428                 if (p->conf.db) {
37429                         datum key, val;
37430                         time_t last_hit;
37431 -               
37432 +
37433                         key.dptr = (char *)remote_ip;
37434                         key.dsize = strlen(remote_ip);
37435 -                       
37436 +
37437                         val = gdbm_fetch(p->conf.db, key);
37438 -               
37439 +
37440                         if (val.dptr == NULL) {
37441                                 /* not found, redirect */
37442 -                               
37443 +
37444                                 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37445 -                               
37446 +
37447                                 con->http_status = 307;
37448 -                               
37449 +
37450                                 return HANDLER_FINISHED;
37451                         }
37452 -                       
37453 +
37454                         last_hit = *(time_t *)(val.dptr);
37455 -                       
37456 +
37457                         free(val.dptr);
37458 -                       
37459 +
37460                         if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
37461                                 /* found, but timeout, redirect */
37462 -                               
37463 +
37464                                 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37465                                 con->http_status = 307;
37466 -                               
37467 +
37468                                 if (p->conf.db) {
37469                                         if (0 != gdbm_delete(p->conf.db, key)) {
37470                                                 log_error_write(srv, __FILE__, __LINE__, "s",
37471                                                                 "delete failed");
37472                                         }
37473                                 }
37474 -                               
37475 +
37476                                 return HANDLER_FINISHED;
37477                         }
37478 -                       
37479 +
37480                         val.dptr = (char *)&(srv->cur_ts);
37481                         val.dsize = sizeof(srv->cur_ts);
37482 -                       
37483 +
37484                         if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37485                                 log_error_write(srv, __FILE__, __LINE__, "s",
37486                                                 "insert failed");
37487                         }
37488                 }
37489  # endif
37490 -               
37491 -# if defined(HAVE_MEMCACHE_H)          
37492 +
37493 +# if defined(HAVE_MEMCACHE_H)
37494                 if (p->conf.mc) {
37495                         void *r;
37496                         size_t i;
37497 -                       
37498 +
37499                         buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37500                         buffer_append_string(p->tmp_buf, remote_ip);
37501 -                       
37502 +
37503                         for (i = 0; i < p->tmp_buf->used - 1; i++) {
37504                                 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37505                         }
37506 -                       
37507 +
37508                         if (p->conf.debug) {
37509                                 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
37510                         }
37511  
37512                         /**
37513 -                        * 
37514 +                        *
37515                          * memcached is do expiration for us, as long as we can fetch it every thing is ok
37516 -                        * and the timestamp is updated 
37517 -                        * 
37518 +                        * and the timestamp is updated
37519 +                        *
37520                          */
37521 -                       if (NULL == (r = mc_aget(p->conf.mc, 
37522 +                       if (NULL == (r = mc_aget(p->conf.mc,
37523                                                  CONST_BUF_LEN(p->tmp_buf)
37524                                                  ))) {
37525 -                               
37526 +
37527                                 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37528 -                               
37529 +
37530                                 con->http_status = 307;
37531 -                               
37532 +
37533                                 return HANDLER_FINISHED;
37534                         }
37535 -                       
37536 +
37537                         free(r);
37538 -                       
37539 +
37540                         /* set a new timeout */
37541 -                       if (0 != mc_set(p->conf.mc, 
37542 +                       if (0 != mc_set(p->conf.mc,
37543                                         CONST_BUF_LEN(p->tmp_buf),
37544                                         (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37545                                         p->conf.trigger_timeout, 0)) {
37546 @@ -507,13 +504,13 @@
37547                 }
37548  # endif
37549         }
37550 -       
37551 +
37552  #else
37553         UNUSED(srv);
37554         UNUSED(con);
37555         UNUSED(p_d);
37556  #endif
37557 -       
37558 +
37559         return HANDLER_GO_ON;
37560  }
37561  
37562 @@ -521,21 +518,21 @@
37563  TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
37564         plugin_data *p = p_d;
37565         size_t i;
37566 -       
37567 +
37568         /* check DB each minute */
37569         if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
37570 -       
37571 +
37572         /* cleanup */
37573         for (i = 0; i < srv->config_context->used; i++) {
37574                 plugin_config *s = p->config_storage[i];
37575                 datum key, val, okey;
37576 -               
37577 +
37578                 if (!s->db) continue;
37579 -               
37580 +
37581                 okey.dptr = NULL;
37582 -               
37583 -               /* according to the manual this loop + delete does delete all entries on its way 
37584 -                * 
37585 +
37586 +               /* according to the manual this loop + delete does delete all entries on its way
37587 +                *
37588                  * we don't care as the next round will remove them. We don't have to perfect here.
37589                  */
37590                 for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
37591 @@ -544,21 +541,21 @@
37592                                 free(okey.dptr);
37593                                 okey.dptr = NULL;
37594                         }
37595 -                       
37596 +
37597                         val = gdbm_fetch(s->db, key);
37598 -                       
37599 +
37600                         last_hit = *(time_t *)(val.dptr);
37601 -                       
37602 +
37603                         free(val.dptr);
37604 -                       
37605 +
37606                         if (srv->cur_ts - last_hit > s->trigger_timeout) {
37607                                 gdbm_delete(s->db, key);
37608                         }
37609 -                       
37610 +
37611                         okey = key;
37612                 }
37613                 if (okey.dptr) free(okey.dptr);
37614 -               
37615 +
37616                 /* reorg once a day */
37617                 if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
37618         }
37619 @@ -571,7 +568,7 @@
37620  int mod_trigger_b4_dl_plugin_init(plugin *p) {
37621         p->version     = LIGHTTPD_VERSION_ID;
37622         p->name        = buffer_init_string("trigger_b4_dl");
37623 -       
37624 +
37625         p->init        = mod_trigger_b4_dl_init;
37626         p->handle_uri_clean  = mod_trigger_b4_dl_uri_handler;
37627         p->set_defaults  = mod_trigger_b4_dl_set_defaults;
37628 @@ -579,8 +576,8 @@
37629         p->handle_trigger  = mod_trigger_b4_dl_handle_trigger;
37630  #endif
37631         p->cleanup     = mod_trigger_b4_dl_free;
37632 -       
37633 +
37634         p->data        = NULL;
37635 -       
37636 +
37637         return 0;
37638  }
37639 --- ../lighttpd-1.4.11/src/mod_userdir.c        2005-10-28 16:48:28.000000000 +0300
37640 +++ lighttpd-1.4.12/src/mod_userdir.c   2006-07-11 22:07:52.000000000 +0300
37641 @@ -10,6 +10,7 @@
37642  #include "response.h"
37643  
37644  #include "plugin.h"
37645 +#include "sys-files.h"
37646  
37647  #ifdef HAVE_PWD_H
37648  #include <pwd.h>
37649 @@ -25,54 +26,54 @@
37650  
37651  typedef struct {
37652         PLUGIN_DATA;
37653 -       
37654 +
37655         buffer *username;
37656         buffer *temp_path;
37657 -       
37658 +
37659         plugin_config **config_storage;
37660 -       
37661 -       plugin_config conf; 
37662 +
37663 +       plugin_config conf;
37664  } plugin_data;
37665  
37666  /* init the plugin data */
37667  INIT_FUNC(mod_userdir_init) {
37668         plugin_data *p;
37669 -       
37670 +
37671         p = calloc(1, sizeof(*p));
37672 -       
37673 +
37674         p->username = buffer_init();
37675         p->temp_path = buffer_init();
37676 -       
37677 +
37678         return p;
37679  }
37680  
37681  /* detroy the plugin data */
37682  FREE_FUNC(mod_userdir_free) {
37683         plugin_data *p = p_d;
37684 -       
37685 +
37686         if (!p) return HANDLER_GO_ON;
37687 -       
37688 +
37689         if (p->config_storage) {
37690                 size_t i;
37691 -               
37692 +
37693                 for (i = 0; i < srv->config_context->used; i++) {
37694                         plugin_config *s = p->config_storage[i];
37695 -                       
37696 +
37697                         array_free(s->include_user);
37698                         array_free(s->exclude_user);
37699                         buffer_free(s->path);
37700                         buffer_free(s->basepath);
37701 -                       
37702 +
37703                         free(s);
37704                 }
37705                 free(p->config_storage);
37706         }
37707 -       
37708 +
37709         buffer_free(p->username);
37710         buffer_free(p->temp_path);
37711 -       
37712 +
37713         free(p);
37714 -       
37715 +
37716         return HANDLER_GO_ON;
37717  }
37718  
37719 @@ -81,81 +82,78 @@
37720  SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
37721         plugin_data *p = p_d;
37722         size_t i;
37723 -       
37724 -       config_values_t cv[] = { 
37725 +
37726 +       config_values_t cv[] = {
37727                 { "userdir.path",               NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
37728                 { "userdir.exclude-user",       NULL, T_CONFIG_ARRAY,  T_CONFIG_SCOPE_CONNECTION },       /* 1 */
37729                 { "userdir.include-user",       NULL, T_CONFIG_ARRAY,  T_CONFIG_SCOPE_CONNECTION },       /* 2 */
37730                 { "userdir.basepath",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
37731                 { NULL,                         NULL, T_CONFIG_UNSET,  T_CONFIG_SCOPE_UNSET }
37732         };
37733 -       
37734 +
37735         if (!p) return HANDLER_ERROR;
37736 -       
37737 +
37738         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37739 -       
37740 +
37741         for (i = 0; i < srv->config_context->used; i++) {
37742                 plugin_config *s;
37743 -               
37744 +
37745                 s = calloc(1, sizeof(plugin_config));
37746                 s->exclude_user = array_init();
37747                 s->include_user = array_init();
37748                 s->path = buffer_init();
37749                 s->basepath = buffer_init();
37750 -       
37751 +
37752                 cv[0].destination = s->path;
37753                 cv[1].destination = s->exclude_user;
37754                 cv[2].destination = s->include_user;
37755                 cv[3].destination = s->basepath;
37756 -               
37757 +
37758                 p->config_storage[i] = s;
37759 -       
37760 +
37761                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37762                         return HANDLER_ERROR;
37763                 }
37764         }
37765 -       
37766 +
37767         return HANDLER_GO_ON;
37768  }
37769  
37770 -#define PATCH(x) \
37771 -       p->conf.x = s->x;
37772  static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
37773         size_t i, j;
37774         plugin_config *s = p->config_storage[0];
37775 -       
37776 -       PATCH(path);
37777 -       PATCH(exclude_user);
37778 -       PATCH(include_user);
37779 -       PATCH(basepath);
37780 -       
37781 +
37782 +       PATCH_OPTION(path);
37783 +       PATCH_OPTION(exclude_user);
37784 +       PATCH_OPTION(include_user);
37785 +       PATCH_OPTION(basepath);
37786 +
37787         /* skip the first, the global context */
37788         for (i = 1; i < srv->config_context->used; i++) {
37789                 data_config *dc = (data_config *)srv->config_context->data[i];
37790                 s = p->config_storage[i];
37791 -               
37792 +
37793                 /* condition didn't match */
37794                 if (!config_check_cond(srv, con, dc)) continue;
37795 -               
37796 +
37797                 /* merge config */
37798                 for (j = 0; j < dc->value->used; j++) {
37799                         data_unset *du = dc->value->data[j];
37800 -                       
37801 +
37802                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
37803 -                               PATCH(path);
37804 +                               PATCH_OPTION(path);
37805                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
37806 -                               PATCH(exclude_user);
37807 +                               PATCH_OPTION(exclude_user);
37808                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
37809 -                               PATCH(include_user);
37810 +                               PATCH_OPTION(include_user);
37811                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
37812 -                               PATCH(basepath);
37813 +                               PATCH_OPTION(basepath);
37814                         }
37815                 }
37816         }
37817 -       
37818 +
37819         return 0;
37820  }
37821 -#undef PATCH
37822  
37823  URIHANDLER_FUNC(mod_userdir_docroot_handler) {
37824         plugin_data *p = p_d;
37825 @@ -169,18 +167,18 @@
37826         if (con->uri.path->used == 0) return HANDLER_GO_ON;
37827  
37828         mod_userdir_patch_connection(srv, con, p);
37829 -       
37830 +
37831         uri_len = con->uri.path->used - 1;
37832 -       
37833 +
37834         /* /~user/foo.html -> /home/user/public_html/foo.html */
37835 -       
37836 +
37837         if (con->uri.path->ptr[0] != '/' ||
37838             con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
37839 -       
37840 +
37841         if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
37842                 /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
37843                 http_response_redirect_to_directory(srv, con);
37844 -               
37845 +
37846                 return HANDLER_FINISHED;
37847         }
37848  
37849 @@ -188,10 +186,10 @@
37850         if (0 == rel_url - (con->uri.path->ptr + 2)) {
37851                 return HANDLER_GO_ON;
37852         }
37853 -       
37854 +
37855         buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
37856 -       
37857 -       if (buffer_is_empty(p->conf.basepath) 
37858 +
37859 +       if (buffer_is_empty(p->conf.basepath)
37860  #ifdef HAVE_PWD_H
37861             && NULL == (pwd = getpwnam(p->username->ptr))
37862  #endif
37863 @@ -200,31 +198,31 @@
37864                 return HANDLER_GO_ON;
37865         }
37866  
37867 -       
37868 +
37869         for (k = 0; k < p->conf.exclude_user->used; k++) {
37870                 data_string *ds = (data_string *)p->conf.exclude_user->data[k];
37871 -               
37872 +
37873                 if (buffer_is_equal(ds->value, p->username)) {
37874                         /* user in exclude list */
37875                         return HANDLER_GO_ON;
37876                 }
37877         }
37878 -       
37879 +
37880         if (p->conf.include_user->used) {
37881                 int found_user = 0;
37882                 for (k = 0; k < p->conf.include_user->used; k++) {
37883                         data_string *ds = (data_string *)p->conf.include_user->data[k];
37884 -                       
37885 +
37886                         if (buffer_is_equal(ds->value, p->username)) {
37887                                 /* user in include list */
37888                                 found_user = 1;
37889                                 break;
37890                         }
37891                 }
37892 -               
37893 +
37894                 if (!found_user) return HANDLER_GO_ON;
37895         }
37896 -       
37897 +
37898         /* we build the physical path */
37899  
37900         if (buffer_is_empty(p->conf.basepath)) {
37901 @@ -252,23 +250,23 @@
37902                 }
37903  
37904                 buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
37905 -               BUFFER_APPEND_SLASH(p->temp_path);
37906 +               PATHNAME_APPEND_SLASH(p->temp_path);
37907                 buffer_append_string_buffer(p->temp_path, p->username);
37908         }
37909 -       BUFFER_APPEND_SLASH(p->temp_path);
37910 -       buffer_append_string_buffer(p->temp_path, p->conf.path); 
37911 +       PATHNAME_APPEND_SLASH(p->temp_path);
37912 +       buffer_append_string_buffer(p->temp_path, p->conf.path);
37913  
37914         if (buffer_is_empty(p->conf.basepath)) {
37915                 struct stat st;
37916                 int ret;
37917 -               
37918 +
37919                 ret = stat(p->temp_path->ptr, &st);
37920                 if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
37921                         return HANDLER_GO_ON;
37922 -               } 
37923 +               }
37924         }
37925  
37926 -       BUFFER_APPEND_SLASH(p->temp_path);
37927 +       PATHNAME_APPEND_SLASH(p->temp_path);
37928         buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
37929         buffer_copy_string_buffer(con->physical.path, p->temp_path);
37930  
37931 @@ -282,13 +280,13 @@
37932  int mod_userdir_plugin_init(plugin *p) {
37933         p->version     = LIGHTTPD_VERSION_ID;
37934         p->name        = buffer_init_string("userdir");
37935 -       
37936 +
37937         p->init           = mod_userdir_init;
37938         p->handle_physical = mod_userdir_docroot_handler;
37939         p->set_defaults   = mod_userdir_set_defaults;
37940         p->cleanup        = mod_userdir_free;
37941 -       
37942 +
37943         p->data        = NULL;
37944 -       
37945 +
37946         return 0;
37947  }
37948 --- ../lighttpd-1.4.11/src/mod_usertrack.c      2006-01-31 15:01:20.000000000 +0200
37949 +++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-11 22:07:53.000000000 +0300
37950 @@ -24,44 +24,44 @@
37951  
37952  typedef struct {
37953         PLUGIN_DATA;
37954 -       
37955 +
37956         plugin_config **config_storage;
37957 -       
37958 -       plugin_config conf; 
37959 +
37960 +       plugin_config conf;
37961  } plugin_data;
37962  
37963  /* init the plugin data */
37964  INIT_FUNC(mod_usertrack_init) {
37965         plugin_data *p;
37966 -       
37967 +
37968         p = calloc(1, sizeof(*p));
37969 -       
37970 +
37971         return p;
37972  }
37973  
37974  /* detroy the plugin data */
37975  FREE_FUNC(mod_usertrack_free) {
37976         plugin_data *p = p_d;
37977 -       
37978 +
37979         UNUSED(srv);
37980 -       
37981 +
37982         if (!p) return HANDLER_GO_ON;
37983 -       
37984 +
37985         if (p->config_storage) {
37986                 size_t i;
37987                 for (i = 0; i < srv->config_context->used; i++) {
37988                         plugin_config *s = p->config_storage[i];
37989 -                       
37990 +
37991                         buffer_free(s->cookie_name);
37992                         buffer_free(s->cookie_domain);
37993 -                       
37994 +
37995                         free(s);
37996                 }
37997                 free(p->config_storage);
37998         }
37999 -       
38000 +
38001         free(p);
38002 -       
38003 +
38004         return HANDLER_GO_ON;
38005  }
38006  
38007 @@ -70,38 +70,38 @@
38008  SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
38009         plugin_data *p = p_d;
38010         size_t i = 0;
38011 -       
38012 -       config_values_t cv[] = { 
38013 +
38014 +       config_values_t cv[] = {
38015                 { "usertrack.cookie-name",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
38016                 { "usertrack.cookie-max-age",    NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 1 */
38017                 { "usertrack.cookie-domain",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
38018 -               
38019 -               { "usertrack.cookiename",        NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },   
38020 +
38021 +               { "usertrack.cookiename",        NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38022                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38023         };
38024 -       
38025 +
38026         if (!p) return HANDLER_ERROR;
38027 -       
38028 +
38029         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38030 -       
38031 +
38032         for (i = 0; i < srv->config_context->used; i++) {
38033                 plugin_config *s;
38034 -               
38035 +
38036                 s = calloc(1, sizeof(plugin_config));
38037                 s->cookie_name    = buffer_init();
38038                 s->cookie_domain  = buffer_init();
38039                 s->cookie_max_age = 0;
38040 -               
38041 +
38042                 cv[0].destination = s->cookie_name;
38043                 cv[1].destination = &(s->cookie_max_age);
38044                 cv[2].destination = s->cookie_domain;
38045 -               
38046 +
38047                 p->config_storage[i] = s;
38048 -       
38049 +
38050                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38051                         return HANDLER_ERROR;
38052                 }
38053 -       
38054 +
38055                 if (buffer_is_empty(s->cookie_name)) {
38056                         buffer_copy_string(s->cookie_name, "TRACKID");
38057                 } else {
38058 @@ -109,68 +109,65 @@
38059                         for (j = 0; j < s->cookie_name->used - 1; j++) {
38060                                 char c = s->cookie_name->ptr[j] | 32;
38061                                 if (c < 'a' || c > 'z') {
38062 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
38063 -                                                       "invalid character in usertrack.cookie-name:", 
38064 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
38065 +                                                       "invalid character in usertrack.cookie-name:",
38066                                                         s->cookie_name);
38067 -                                       
38068 +
38069                                         return HANDLER_ERROR;
38070                                 }
38071                         }
38072                 }
38073 -               
38074 +
38075                 if (!buffer_is_empty(s->cookie_domain)) {
38076                         size_t j;
38077                         for (j = 0; j < s->cookie_domain->used - 1; j++) {
38078                                 char c = s->cookie_domain->ptr[j];
38079                                 if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
38080 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
38081 -                                                       "invalid character in usertrack.cookie-domain:", 
38082 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
38083 +                                                       "invalid character in usertrack.cookie-domain:",
38084                                                         s->cookie_domain);
38085 -                                       
38086 +
38087                                         return HANDLER_ERROR;
38088                                 }
38089                         }
38090                 }
38091         }
38092 -               
38093 +
38094         return HANDLER_GO_ON;
38095  }
38096  
38097 -#define PATCH(x) \
38098 -       p->conf.x = s->x;
38099  static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
38100         size_t i, j;
38101         plugin_config *s = p->config_storage[0];
38102 -       
38103 -       PATCH(cookie_name);
38104 -       PATCH(cookie_domain);
38105 -       PATCH(cookie_max_age);
38106 -       
38107 +
38108 +       PATCH_OPTION(cookie_name);
38109 +       PATCH_OPTION(cookie_domain);
38110 +       PATCH_OPTION(cookie_max_age);
38111 +
38112         /* skip the first, the global context */
38113         for (i = 1; i < srv->config_context->used; i++) {
38114                 data_config *dc = (data_config *)srv->config_context->data[i];
38115                 s = p->config_storage[i];
38116 -               
38117 +
38118                 /* condition didn't match */
38119                 if (!config_check_cond(srv, con, dc)) continue;
38120 -               
38121 +
38122                 /* merge config */
38123                 for (j = 0; j < dc->value->used; j++) {
38124                         data_unset *du = dc->value->data[j];
38125 -                       
38126 +
38127                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
38128 -                               PATCH(cookie_name);
38129 +                               PATCH_OPTION(cookie_name);
38130                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
38131 -                               PATCH(cookie_max_age);
38132 +                               PATCH_OPTION(cookie_max_age);
38133                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
38134 -                               PATCH(cookie_domain);
38135 +                               PATCH_OPTION(cookie_domain);
38136                         }
38137                 }
38138         }
38139 -       
38140 +
38141         return 0;
38142  }
38143 -#undef PATCH
38144  
38145  URIHANDLER_FUNC(mod_usertrack_uri_handler) {
38146         plugin_data *p = p_d;
38147 @@ -178,38 +175,38 @@
38148         unsigned char h[16];
38149         MD5_CTX Md5Ctx;
38150         char hh[32];
38151 -       
38152 +
38153         if (con->uri.path->used == 0) return HANDLER_GO_ON;
38154 -       
38155 +
38156         mod_usertrack_patch_connection(srv, con, p);
38157 -       
38158 +
38159         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
38160                 char *g;
38161                 /* we have a cookie, does it contain a valid name ? */
38162 -               
38163 -               /* parse the cookie 
38164 -                * 
38165 +
38166 +               /* parse the cookie
38167 +                *
38168                  * check for cookiename + (WS | '=')
38169 -                * 
38170 +                *
38171                  */
38172 -               
38173 +
38174                 if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
38175                         char *nc;
38176 -                       
38177 +
38178                         /* skip WS */
38179                         for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
38180 -                       
38181 +
38182                         if (*nc == '=') {
38183                                 /* ok, found the key of our own cookie */
38184 -                               
38185 +
38186                                 if (strlen(nc) > 32) {
38187                                         /* i'm lazy */
38188                                         return HANDLER_GO_ON;
38189                                 }
38190                         }
38191                 }
38192 -       } 
38193 -       
38194 +       }
38195 +
38196         /* set a cookie */
38197         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
38198                 ds = data_response_init();
38199 @@ -217,39 +214,39 @@
38200         buffer_copy_string(ds->key, "Set-Cookie");
38201         buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
38202         buffer_append_string(ds->value, "=");
38203 -       
38204 +
38205  
38206         /* taken from mod_auth.c */
38207 -       
38208 +
38209         /* generate shared-secret */
38210         MD5_Init(&Md5Ctx);
38211         MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
38212         MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
38213 -       
38214 +
38215         /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
38216         ltostr(hh, srv->cur_ts);
38217         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38218         ltostr(hh, rand());
38219         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38220 -       
38221 +
38222         MD5_Final(h, &Md5Ctx);
38223 -       
38224 +
38225         buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
38226         buffer_append_string(ds->value, "; Path=/");
38227         buffer_append_string(ds->value, "; Version=1");
38228 -       
38229 +
38230         if (!buffer_is_empty(p->conf.cookie_domain)) {
38231                 buffer_append_string(ds->value, "; Domain=");
38232                 buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
38233         }
38234 -       
38235 +
38236         if (p->conf.cookie_max_age) {
38237                 buffer_append_string(ds->value, "; max-age=");
38238                 buffer_append_long(ds->value, p->conf.cookie_max_age);
38239         }
38240 -       
38241 +
38242         array_insert_unique(con->response.headers, (data_unset *)ds);
38243 -       
38244 +
38245         return HANDLER_GO_ON;
38246  }
38247  
38248 @@ -258,13 +255,13 @@
38249  int mod_usertrack_plugin_init(plugin *p) {
38250         p->version     = LIGHTTPD_VERSION_ID;
38251         p->name        = buffer_init_string("usertrack");
38252 -       
38253 +
38254         p->init        = mod_usertrack_init;
38255         p->handle_uri_clean  = mod_usertrack_uri_handler;
38256         p->set_defaults  = mod_usertrack_set_defaults;
38257         p->cleanup     = mod_usertrack_free;
38258 -       
38259 +
38260         p->data        = NULL;
38261 -       
38262 +
38263         return 0;
38264  }
38265 --- ../lighttpd-1.4.11/src/mod_webdav.c 2006-03-03 01:28:58.000000000 +0200
38266 +++ lighttpd-1.4.12/src/mod_webdav.c    2006-07-11 22:07:53.000000000 +0300
38267 @@ -3,13 +3,10 @@
38268  #include <ctype.h>
38269  #include <stdlib.h>
38270  #include <string.h>
38271 -#include <dirent.h>
38272  #include <errno.h>
38273 -#include <unistd.h>
38274  #include <fcntl.h>
38275  #include <stdio.h>
38276  #include <assert.h>
38277 -#include <sys/mman.h>
38278  
38279  #ifdef HAVE_CONFIG_H
38280  #include "config.h"
38281 @@ -23,6 +20,11 @@
38282  #include <sqlite3.h>
38283  #endif
38284  
38285 +#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
38286 +#define USE_LOCKS
38287 +#include <uuid/uuid.h>
38288 +#endif
38289 +
38290  #include "base.h"
38291  #include "log.h"
38292  #include "buffer.h"
38293 @@ -33,13 +35,16 @@
38294  #include "stream.h"
38295  #include "stat_cache.h"
38296  
38297 +#include "sys-files.h"
38298 +#include "sys-mmap.h"
38299 +#include "sys-strings.h"
38300  
38301  /**
38302   * this is a webdav for a lighttpd plugin
38303   *
38304 - * at least a very basic one. 
38305 + * at least a very basic one.
38306   * - for now it is read-only and we only support PROPFIND
38307 - * 
38308 + *
38309   */
38310  
38311  
38312 @@ -58,64 +63,70 @@
38313         sqlite3_stmt *stmt_delete_prop;
38314         sqlite3_stmt *stmt_select_prop;
38315         sqlite3_stmt *stmt_select_propnames;
38316 -       
38317 +
38318         sqlite3_stmt *stmt_delete_uri;
38319         sqlite3_stmt *stmt_move_uri;
38320         sqlite3_stmt *stmt_copy_uri;
38321 +
38322 +       sqlite3_stmt *stmt_remove_lock;
38323 +       sqlite3_stmt *stmt_create_lock;
38324 +       sqlite3_stmt *stmt_read_lock;
38325 +       sqlite3_stmt *stmt_read_lock_by_uri;
38326 +       sqlite3_stmt *stmt_refresh_lock;
38327  #endif
38328  } plugin_config;
38329  
38330  typedef struct {
38331         PLUGIN_DATA;
38332 -       
38333 +
38334         buffer *tmp_buf;
38335         request_uri uri;
38336         physical physical;
38337  
38338         plugin_config **config_storage;
38339 -       
38340 -       plugin_config conf; 
38341 +
38342 +       plugin_config conf;
38343  } plugin_data;
38344  
38345  /* init the plugin data */
38346  INIT_FUNC(mod_webdav_init) {
38347         plugin_data *p;
38348 -       
38349 +
38350         p = calloc(1, sizeof(*p));
38351 -       
38352 +
38353         p->tmp_buf = buffer_init();
38354  
38355         p->uri.scheme = buffer_init();
38356         p->uri.path_raw = buffer_init();
38357         p->uri.path = buffer_init();
38358         p->uri.authority = buffer_init();
38359 -       
38360 +
38361         p->physical.path = buffer_init();
38362         p->physical.rel_path = buffer_init();
38363         p->physical.doc_root = buffer_init();
38364         p->physical.basedir = buffer_init();
38365 -       
38366 +
38367         return p;
38368  }
38369  
38370  /* detroy the plugin data */
38371  FREE_FUNC(mod_webdav_free) {
38372         plugin_data *p = p_d;
38373 -       
38374 +
38375         UNUSED(srv);
38376  
38377         if (!p) return HANDLER_GO_ON;
38378 -       
38379 +
38380         if (p->config_storage) {
38381                 size_t i;
38382                 for (i = 0; i < srv->config_context->used; i++) {
38383                         plugin_config *s = p->config_storage[i];
38384  
38385                         if (!s) continue;
38386 -       
38387 +
38388                         buffer_free(s->sqlite_db_name);
38389  #ifdef USE_PROPPATCH
38390 -                       if (s->sql) {   
38391 +                       if (s->sql) {
38392                                 sqlite3_finalize(s->stmt_delete_prop);
38393                                 sqlite3_finalize(s->stmt_delete_uri);
38394                                 sqlite3_finalize(s->stmt_copy_uri);
38395 @@ -123,9 +134,15 @@
38396                                 sqlite3_finalize(s->stmt_update_prop);
38397                                 sqlite3_finalize(s->stmt_select_prop);
38398                                 sqlite3_finalize(s->stmt_select_propnames);
38399 +
38400 +                               sqlite3_finalize(s->stmt_read_lock);
38401 +                               sqlite3_finalize(s->stmt_read_lock_by_uri);
38402 +                               sqlite3_finalize(s->stmt_create_lock);
38403 +                               sqlite3_finalize(s->stmt_remove_lock);
38404 +                               sqlite3_finalize(s->stmt_refresh_lock);
38405                                 sqlite3_close(s->sql);
38406                         }
38407 -#endif 
38408 +#endif
38409                         free(s);
38410                 }
38411                 free(p->config_storage);
38412 @@ -135,16 +152,16 @@
38413         buffer_free(p->uri.path_raw);
38414         buffer_free(p->uri.path);
38415         buffer_free(p->uri.authority);
38416 -       
38417 +
38418         buffer_free(p->physical.path);
38419         buffer_free(p->physical.rel_path);
38420         buffer_free(p->physical.doc_root);
38421         buffer_free(p->physical.basedir);
38422 -       
38423 +
38424         buffer_free(p->tmp_buf);
38425 -       
38426 +
38427         free(p);
38428 -       
38429 +
38430         return HANDLER_GO_ON;
38431  }
38432  
38433 @@ -153,32 +170,32 @@
38434  SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
38435         plugin_data *p = p_d;
38436         size_t i = 0;
38437 -       
38438 -       config_values_t cv[] = { 
38439 +
38440 +       config_values_t cv[] = {
38441                 { "webdav.activate",            NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
38442                 { "webdav.is-readonly",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
38443                 { "webdav.sqlite-db-name",      NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION },       /* 2 */
38444                 { "webdav.log-xml",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
38445                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38446         };
38447 -       
38448 +
38449         if (!p) return HANDLER_ERROR;
38450 -       
38451 +
38452         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38453 -       
38454 +
38455         for (i = 0; i < srv->config_context->used; i++) {
38456                 plugin_config *s;
38457 -               
38458 +
38459                 s = calloc(1, sizeof(plugin_config));
38460                 s->sqlite_db_name = buffer_init();
38461 -               
38462 +
38463                 cv[0].destination = &(s->enabled);
38464                 cv[1].destination = &(s->is_readonly);
38465                 cv[2].destination = s->sqlite_db_name;
38466                 cv[3].destination = &(s->log_xml);
38467 -               
38468 +
38469                 p->config_storage[i] = s;
38470 -       
38471 +
38472                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38473                         return HANDLER_ERROR;
38474                 }
38475 @@ -193,8 +210,26 @@
38476                                 return HANDLER_ERROR;
38477                         }
38478  
38479 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38480 -                               CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"), 
38481 +                       if (SQLITE_OK != sqlite3_exec(s->sql,
38482 +                                       "CREATE TABLE properties ("
38483 +                                       "  resource TEXT NOT NULL,"
38484 +                                       "  prop TEXT NOT NULL,"
38485 +                                       "  ns TEXT NOT NULL,"
38486 +                                       "  value TEXT NOT NULL,"
38487 +                                       "  PRIMARY KEY(resource, prop, ns))",
38488 +                                       NULL, NULL, &err)) {
38489 +
38490 +                               if (0 != strcmp(err, "table properties already exists")) {
38491 +                                       log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38492 +                                       sqlite3_free(err);
38493 +
38494 +                                       return HANDLER_ERROR;
38495 +                               }
38496 +                               sqlite3_free(err);
38497 +                       }
38498 +
38499 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38500 +                               CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38501                                 &(s->stmt_select_prop), &next_stmt)) {
38502                                 /* prepare failed */
38503  
38504 @@ -202,8 +237,8 @@
38505                                 return HANDLER_ERROR;
38506                         }
38507  
38508 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38509 -                               CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"), 
38510 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38511 +                               CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
38512                                 &(s->stmt_select_propnames), &next_stmt)) {
38513                                 /* prepare failed */
38514  
38515 @@ -211,16 +246,67 @@
38516                                 return HANDLER_ERROR;
38517                         }
38518  
38519 -                       if (SQLITE_OK != sqlite3_exec(s->sql, 
38520 -                                       "CREATE TABLE properties ("
38521 +
38522 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38523 +                               CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
38524 +                               &(s->stmt_update_prop), &next_stmt)) {
38525 +                               /* prepare failed */
38526 +
38527 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38528 +                               return HANDLER_ERROR;
38529 +                       }
38530 +
38531 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38532 +                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38533 +                               &(s->stmt_delete_prop), &next_stmt)) {
38534 +                               /* prepare failed */
38535 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38536 +
38537 +                               return HANDLER_ERROR;
38538 +                       }
38539 +
38540 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38541 +                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
38542 +                               &(s->stmt_delete_uri), &next_stmt)) {
38543 +                               /* prepare failed */
38544 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38545 +
38546 +                               return HANDLER_ERROR;
38547 +                       }
38548 +
38549 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38550 +                               CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
38551 +                               &(s->stmt_copy_uri), &next_stmt)) {
38552 +                               /* prepare failed */
38553 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38554 +
38555 +                               return HANDLER_ERROR;
38556 +                       }
38557 +
38558 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38559 +                               CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
38560 +                               &(s->stmt_move_uri), &next_stmt)) {
38561 +                               /* prepare failed */
38562 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38563 +
38564 +                               return HANDLER_ERROR;
38565 +                       }
38566 +
38567 +                       /* LOCKS */
38568 +
38569 +                       if (SQLITE_OK != sqlite3_exec(s->sql,
38570 +                                       "CREATE TABLE locks ("
38571 +                                       "  locktoken TEXT NOT NULL,"
38572                                         "  resource TEXT NOT NULL,"
38573 -                                       "  prop TEXT NOT NULL,"
38574 -                                       "  ns TEXT NOT NULL,"
38575 -                                       "  value TEXT NOT NULL,"
38576 -                                       "  PRIMARY KEY(resource, prop, ns))",
38577 +                                       "  lockscope TEXT NOT NULL,"
38578 +                                       "  locktype TEXT NOT NULL,"
38579 +                                       "  owner TEXT NOT NULL,"
38580 +                                       "  depth INT NOT NULL,"
38581 +                                       "  timeout TIMESTAMP NOT NULL,"
38582 +                                       "  PRIMARY KEY(locktoken))",
38583                                         NULL, NULL, &err)) {
38584  
38585 -                               if (0 != strcmp(err, "table properties already exists")) {
38586 +                               if (0 != strcmp(err, "table locks already exists")) {
38587                                         log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38588                                         sqlite3_free(err);
38589  
38590 @@ -228,127 +314,138 @@
38591                                 }
38592                                 sqlite3_free(err);
38593                         }
38594 -       
38595 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38596 -                               CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"), 
38597 -                               &(s->stmt_update_prop), &next_stmt)) {
38598 +
38599 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38600 +                               CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
38601 +                               &(s->stmt_create_lock), &next_stmt)) {
38602                                 /* prepare failed */
38603 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38604  
38605 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38606                                 return HANDLER_ERROR;
38607                         }
38608  
38609 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38610 -                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"), 
38611 -                               &(s->stmt_delete_prop), &next_stmt)) {
38612 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38613 +                               CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
38614 +                               &(s->stmt_remove_lock), &next_stmt)) {
38615                                 /* prepare failed */
38616                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38617  
38618                                 return HANDLER_ERROR;
38619                         }
38620  
38621 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38622 -                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"), 
38623 -                               &(s->stmt_delete_uri), &next_stmt)) {
38624 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38625 +                               CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
38626 +                               &(s->stmt_read_lock), &next_stmt)) {
38627                                 /* prepare failed */
38628                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38629  
38630                                 return HANDLER_ERROR;
38631                         }
38632  
38633 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38634 -                               CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"), 
38635 -                               &(s->stmt_copy_uri), &next_stmt)) {
38636 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38637 +                               CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
38638 +                               &(s->stmt_read_lock_by_uri), &next_stmt)) {
38639                                 /* prepare failed */
38640                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38641  
38642                                 return HANDLER_ERROR;
38643                         }
38644  
38645 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38646 -                               CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"), 
38647 -                               &(s->stmt_move_uri), &next_stmt)) {
38648 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38649 +                               CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
38650 +                               &(s->stmt_refresh_lock), &next_stmt)) {
38651                                 /* prepare failed */
38652                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38653  
38654                                 return HANDLER_ERROR;
38655                         }
38656 +
38657 +
38658  #else
38659                         log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
38660                         return HANDLER_ERROR;
38661  #endif
38662                 }
38663         }
38664 -       
38665 +
38666         return HANDLER_GO_ON;
38667  }
38668  
38669 -#define PATCH(x) \
38670 -       p->conf.x = s->x;
38671  static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
38672         size_t i, j;
38673         plugin_config *s = p->config_storage[0];
38674 -       
38675 -       PATCH(enabled);
38676 -       PATCH(is_readonly);
38677 -       PATCH(log_xml);
38678 -       
38679 +
38680 +       PATCH_OPTION(enabled);
38681 +       PATCH_OPTION(is_readonly);
38682 +       PATCH_OPTION(log_xml);
38683 +
38684  #ifdef USE_PROPPATCH
38685 -       PATCH(sql);
38686 -       PATCH(stmt_update_prop);
38687 -       PATCH(stmt_delete_prop);
38688 -       PATCH(stmt_select_prop);
38689 -       PATCH(stmt_select_propnames);
38690 -
38691 -       PATCH(stmt_delete_uri);
38692 -       PATCH(stmt_move_uri);
38693 -       PATCH(stmt_copy_uri);
38694 +       PATCH_OPTION(sql);
38695 +       PATCH_OPTION(stmt_update_prop);
38696 +       PATCH_OPTION(stmt_delete_prop);
38697 +       PATCH_OPTION(stmt_select_prop);
38698 +       PATCH_OPTION(stmt_select_propnames);
38699 +
38700 +       PATCH_OPTION(stmt_delete_uri);
38701 +       PATCH_OPTION(stmt_move_uri);
38702 +       PATCH_OPTION(stmt_copy_uri);
38703 +
38704 +       PATCH_OPTION(stmt_remove_lock);
38705 +       PATCH_OPTION(stmt_refresh_lock);
38706 +       PATCH_OPTION(stmt_create_lock);
38707 +       PATCH_OPTION(stmt_read_lock);
38708 +       PATCH_OPTION(stmt_read_lock_by_uri);
38709  #endif
38710         /* skip the first, the global context */
38711         for (i = 1; i < srv->config_context->used; i++) {
38712                 data_config *dc = (data_config *)srv->config_context->data[i];
38713                 s = p->config_storage[i];
38714 -               
38715 +
38716                 /* condition didn't match */
38717                 if (!config_check_cond(srv, con, dc)) continue;
38718 -               
38719 +
38720                 /* merge config */
38721                 for (j = 0; j < dc->value->used; j++) {
38722                         data_unset *du = dc->value->data[j];
38723 -                       
38724 +
38725                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
38726 -                               PATCH(enabled);
38727 +                               PATCH_OPTION(enabled);
38728                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
38729 -                               PATCH(is_readonly);
38730 +                               PATCH_OPTION(is_readonly);
38731                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
38732 -                               PATCH(log_xml);
38733 +                               PATCH_OPTION(log_xml);
38734                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
38735  #ifdef USE_PROPPATCH
38736 -                               PATCH(sql);
38737 -                               PATCH(stmt_update_prop);
38738 -                               PATCH(stmt_delete_prop);
38739 -                               PATCH(stmt_select_prop);
38740 -                               PATCH(stmt_select_propnames);
38741 -                               
38742 -                               PATCH(stmt_delete_uri);
38743 -                               PATCH(stmt_move_uri);
38744 -                               PATCH(stmt_copy_uri);
38745 +                               PATCH_OPTION(sql);
38746 +                               PATCH_OPTION(stmt_update_prop);
38747 +                               PATCH_OPTION(stmt_delete_prop);
38748 +                               PATCH_OPTION(stmt_select_prop);
38749 +                               PATCH_OPTION(stmt_select_propnames);
38750 +
38751 +                               PATCH_OPTION(stmt_delete_uri);
38752 +                               PATCH_OPTION(stmt_move_uri);
38753 +                               PATCH_OPTION(stmt_copy_uri);
38754 +
38755 +                               PATCH_OPTION(stmt_remove_lock);
38756 +                               PATCH_OPTION(stmt_refresh_lock);
38757 +                               PATCH_OPTION(stmt_create_lock);
38758 +                               PATCH_OPTION(stmt_read_lock);
38759 +                               PATCH_OPTION(stmt_read_lock_by_uri);
38760  #endif
38761                         }
38762                 }
38763         }
38764 -       
38765 +
38766         return 0;
38767  }
38768 -#undef PATCH
38769  
38770  URIHANDLER_FUNC(mod_webdav_uri_handler) {
38771         plugin_data *p = p_d;
38772 -       
38773 +
38774         UNUSED(srv);
38775  
38776         if (con->uri.path->used == 0) return HANDLER_GO_ON;
38777 -       
38778 +
38779         mod_webdav_patch_connection(srv, con, p);
38780  
38781         if (!p->conf.enabled) return HANDLER_GO_ON;
38782 @@ -362,20 +459,20 @@
38783                 if (p->conf.is_readonly) {
38784                         response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
38785                 } else {
38786 -                       response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
38787 +                       response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
38788                 }
38789                 break;
38790         default:
38791                 break;
38792         }
38793 -       
38794 +
38795         /* not found */
38796         return HANDLER_GO_ON;
38797  }
38798 -static int webdav_gen_prop_tag(server *srv, connection *con, 
38799 -               char *prop_name, 
38800 -               char *prop_ns, 
38801 -               char *value, 
38802 +static int webdav_gen_prop_tag(server *srv, connection *con,
38803 +               char *prop_name,
38804 +               char *prop_ns,
38805 +               char *value,
38806                 buffer *b) {
38807  
38808         UNUSED(srv);
38809 @@ -414,7 +511,7 @@
38810         buffer_append_string_buffer(b, dst->rel_path);
38811         buffer_append_string(b,"</D:href>\n");
38812         buffer_append_string(b,"<D:status>\n");
38813 -       
38814 +
38815         if (con->request.http_version == HTTP_VERSION_1_1) {
38816                 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
38817         } else {
38818 @@ -458,11 +555,11 @@
38819  
38820                         /* bind the values to the insert */
38821  
38822 -                       sqlite3_bind_text(stmt, 1, 
38823 -                                         dst->rel_path->ptr, 
38824 +                       sqlite3_bind_text(stmt, 1,
38825 +                                         dst->rel_path->ptr,
38826                                           dst->rel_path->used - 1,
38827                                           SQLITE_TRANSIENT);
38828 -                                                                       
38829 +
38830                         if (SQLITE_DONE != sqlite3_step(stmt)) {
38831                                 /* */
38832                                 WP();
38833 @@ -493,14 +590,14 @@
38834                             (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38835                                 continue;
38836                                 /* ignore the parent dir */
38837 -                       } 
38838 +                       }
38839  
38840                         buffer_copy_string_buffer(d.path, dst->path);
38841 -                       BUFFER_APPEND_SLASH(d.path);
38842 +                       PATHNAME_APPEND_SLASH(d.path);
38843                         buffer_append_string(d.path, de->d_name);
38844 -                       
38845 +
38846                         buffer_copy_string_buffer(d.rel_path, dst->rel_path);
38847 -                       BUFFER_APPEND_SLASH(d.rel_path);
38848 +                       PATHNAME_APPEND_SLASH(d.rel_path);
38849                         buffer_append_string(d.rel_path, de->d_name);
38850  
38851                         /* stat and unlink afterwards */
38852 @@ -508,7 +605,7 @@
38853                                 /* don't about it yet, rmdir will fail too */
38854                         } else if (S_ISDIR(st.st_mode)) {
38855                                 have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
38856 -                                       
38857 +
38858                                 /* try to unlink it */
38859                                 if (-1 == rmdir(d.path->ptr)) {
38860                                         switch(errno) {
38861 @@ -535,11 +632,11 @@
38862  
38863                                                 /* bind the values to the insert */
38864  
38865 -                                               sqlite3_bind_text(stmt, 1, 
38866 -                                                                 d.rel_path->ptr, 
38867 +                                               sqlite3_bind_text(stmt, 1,
38868 +                                                                 d.rel_path->ptr,
38869                                                                   d.rel_path->used - 1,
38870                                                                   SQLITE_TRANSIENT);
38871 -                                                                                                       
38872 +
38873                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
38874                                                         /* */
38875                                                         WP();
38876 @@ -569,7 +666,7 @@
38877         if (stream_open(&s, src->path)) {
38878                 return 403;
38879         }
38880 -                       
38881 +
38882         if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) {
38883                 /* opening the destination failed for some reason */
38884                 switch(errno) {
38885 @@ -601,7 +698,7 @@
38886                         break;
38887                 }
38888         }
38889 -       
38890 +
38891         stream_close(&s);
38892         close(ofd);
38893  
38894 @@ -614,16 +711,16 @@
38895                         sqlite3_reset(stmt);
38896  
38897                         /* bind the values to the insert */
38898 -                       sqlite3_bind_text(stmt, 1, 
38899 -                                         dst->rel_path->ptr, 
38900 +                       sqlite3_bind_text(stmt, 1,
38901 +                                         dst->rel_path->ptr,
38902                                           dst->rel_path->used - 1,
38903                                           SQLITE_TRANSIENT);
38904  
38905 -                       sqlite3_bind_text(stmt, 2, 
38906 -                                         src->rel_path->ptr, 
38907 +                       sqlite3_bind_text(stmt, 2,
38908 +                                         src->rel_path->ptr,
38909                                           src->rel_path->used - 1,
38910                                           SQLITE_TRANSIENT);
38911 -                                                                                                       
38912 +
38913                         if (SQLITE_DONE != sqlite3_step(stmt)) {
38914                                 /* */
38915                                 WP();
38916 @@ -655,21 +752,21 @@
38917                             (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38918                                 continue;
38919                         }
38920 -                       
38921 +
38922                         buffer_copy_string_buffer(s.path, src->path);
38923 -                       BUFFER_APPEND_SLASH(s.path);
38924 +                       PATHNAME_APPEND_SLASH(s.path);
38925                         buffer_append_string(s.path, de->d_name);
38926  
38927                         buffer_copy_string_buffer(d.path, dst->path);
38928 -                       BUFFER_APPEND_SLASH(d.path);
38929 +                       PATHNAME_APPEND_SLASH(d.path);
38930                         buffer_append_string(d.path, de->d_name);
38931  
38932                         buffer_copy_string_buffer(s.rel_path, src->rel_path);
38933 -                       BUFFER_APPEND_SLASH(s.rel_path);
38934 +                       PATHNAME_APPEND_SLASH(s.rel_path);
38935                         buffer_append_string(s.rel_path, de->d_name);
38936  
38937                         buffer_copy_string_buffer(d.rel_path, dst->rel_path);
38938 -                       BUFFER_APPEND_SLASH(d.rel_path);
38939 +                       PATHNAME_APPEND_SLASH(d.rel_path);
38940                         buffer_append_string(d.rel_path, de->d_name);
38941  
38942                         if (-1 == stat(s.path->ptr, &st)) {
38943 @@ -692,16 +789,16 @@
38944                                                 sqlite3_reset(stmt);
38945  
38946                                                 /* bind the values to the insert */
38947 -                                               sqlite3_bind_text(stmt, 1, 
38948 -                                                         dst->rel_path->ptr, 
38949 +                                               sqlite3_bind_text(stmt, 1,
38950 +                                                         dst->rel_path->ptr,
38951                                                           dst->rel_path->used - 1,
38952                                                           SQLITE_TRANSIENT);
38953  
38954 -                                               sqlite3_bind_text(stmt, 2, 
38955 -                                                         src->rel_path->ptr, 
38956 +                                               sqlite3_bind_text(stmt, 2,
38957 +                                                         src->rel_path->ptr,
38958                                                           src->rel_path->used - 1,
38959                                                           SQLITE_TRANSIENT);
38960 -                                                                                                       
38961 +
38962                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
38963                                                         /* */
38964                                                         WP();
38965 @@ -721,7 +818,7 @@
38966                 buffer_free(s.rel_path);
38967                 buffer_free(d.path);
38968                 buffer_free(d.rel_path);
38969 -               
38970 +
38971                 closedir(srcdir);
38972         }
38973  
38974 @@ -748,12 +845,12 @@
38975                         if (S_ISDIR(sce->st.st_mode)) {
38976                                 buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
38977                                 found = 1;
38978 -                       } else if(S_ISREG(sce->st.st_mode)) { 
38979 +                       } else if(S_ISREG(sce->st.st_mode)) {
38980                                 for (k = 0; k < con->conf.mimetypes->used; k++) {
38981                                         data_string *ds = (data_string *)con->conf.mimetypes->data[k];
38982 -               
38983 +
38984                                         if (ds->key->used == 0) continue;
38985 -                               
38986 +
38987                                         if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
38988                                                 buffer_append_string(b,"<D:getcontenttype>");
38989                                                 buffer_append_string_buffer(b, ds->value);
38990 @@ -807,23 +904,23 @@
38991  
38992                         /* bind the values to the insert */
38993  
38994 -                       sqlite3_bind_text(stmt, 1, 
38995 -                                         dst->rel_path->ptr, 
38996 +                       sqlite3_bind_text(stmt, 1,
38997 +                                         dst->rel_path->ptr,
38998                                           dst->rel_path->used - 1,
38999                                           SQLITE_TRANSIENT);
39000 -                       sqlite3_bind_text(stmt, 2, 
39001 +                       sqlite3_bind_text(stmt, 2,
39002                                           prop_name,
39003                                           strlen(prop_name),
39004                                           SQLITE_TRANSIENT);
39005 -                       sqlite3_bind_text(stmt, 3, 
39006 +                       sqlite3_bind_text(stmt, 3,
39007                                           prop_ns,
39008                                           strlen(prop_ns),
39009                                           SQLITE_TRANSIENT);
39010  
39011                         /* it is the PK */
39012 -                       while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
39013 +                       while (SQLITE_ROW == sqlite3_step(stmt)) {
39014                                 /* there is a row for us, we only expect a single col 'value' */
39015 -                               webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
39016 +                               webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
39017                                 found = 1;
39018                         }
39019                 }
39020 @@ -840,7 +937,7 @@
39021         char *prop;
39022  } webdav_property;
39023  
39024 -webdav_property live_properties[] = { 
39025 +webdav_property live_properties[] = {
39026         { "DAV:", "creationdate" },
39027         { "DAV:", "displayname" },
39028         { "DAV:", "getcontentlanguage" },
39029 @@ -871,8 +968,8 @@
39030                         webdav_property *prop;
39031  
39032                         prop = props->ptr[i];
39033 -                       
39034 -                       if (0 != webdav_get_property(srv, con, p, 
39035 +
39036 +                       if (0 != webdav_get_property(srv, con, p,
39037                                 dst, prop->prop, prop->ns, b_200)) {
39038                                 webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
39039                         }
39040 @@ -916,12 +1013,12 @@
39041                                 if (-1 == c->file.fd &&  /* open the file if not already open */
39042                                     -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39043                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39044 -               
39045 +
39046                                         return -1;
39047                                 }
39048 -       
39049 +
39050                                 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39051 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 
39052 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39053                                                         strerror(errno), c->file.name,  c->file.fd);
39054  
39055                                         return -1;
39056 @@ -938,7 +1035,7 @@
39057                         if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
39058                                 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39059                         }
39060 -                       
39061 +
39062                         c->offset += weHave;
39063                         cq->bytes_out += weHave;
39064  
39065 @@ -956,7 +1053,7 @@
39066                         if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
39067                                 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39068                         }
39069 -                       
39070 +
39071                         c->offset += weHave;
39072                         cq->bytes_out += weHave;
39073  
39074 @@ -991,6 +1088,113 @@
39075  }
39076  #endif
39077  
39078 +int webdav_lockdiscovery(server *srv, connection *con,
39079 +               buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
39080 +
39081 +       buffer *b;
39082 +
39083 +       response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
39084 +
39085 +       response_header_overwrite(srv, con,
39086 +               CONST_STR_LEN("Content-Type"),
39087 +               CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39088 +
39089 +       b = chunkqueue_get_append_buffer(con->write_queue);
39090 +
39091 +       buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39092 +
39093 +       buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39094 +       buffer_append_string(b,"<D:lockdiscovery>\n");
39095 +       buffer_append_string(b,"<D:activelock>\n");
39096 +
39097 +       buffer_append_string(b,"<D:lockscope>");
39098 +       buffer_append_string(b,"<D:");
39099 +       buffer_append_string(b, lockscope);
39100 +       buffer_append_string(b, "/>");
39101 +       buffer_append_string(b,"</D:lockscope>\n");
39102 +
39103 +       buffer_append_string(b,"<D:locktype>");
39104 +       buffer_append_string(b,"<D:");
39105 +       buffer_append_string(b, locktype);
39106 +       buffer_append_string(b, "/>");
39107 +       buffer_append_string(b,"</D:locktype>\n");
39108 +
39109 +       buffer_append_string(b,"<D:depth>");
39110 +       buffer_append_string(b, depth == 0 ? "0" : "infinity");
39111 +       buffer_append_string(b,"</D:depth>\n");
39112 +
39113 +       buffer_append_string(b,"<D:timeout>");
39114 +       buffer_append_string(b, "Second-600");
39115 +       buffer_append_string(b,"</D:timeout>\n");
39116 +
39117 +       buffer_append_string(b,"<D:owner>");
39118 +       buffer_append_string(b,"</D:owner>\n");
39119 +
39120 +       buffer_append_string(b,"<D:locktoken>");
39121 +       buffer_append_string(b, "<D:href>");
39122 +       buffer_append_string_buffer(b, locktoken);
39123 +       buffer_append_string(b, "</D:href>");
39124 +       buffer_append_string(b,"</D:locktoken>\n");
39125 +
39126 +       buffer_append_string(b,"</D:activelock>\n");
39127 +       buffer_append_string(b,"</D:lockdiscovery>\n");
39128 +       buffer_append_string(b,"</D:prop>\n");
39129 +
39130 +       return 0;
39131 +}
39132 +/**
39133 + * check if resource is having the right locks to access to resource
39134 + *
39135 + *
39136 + *
39137 + */
39138 +int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
39139 +       int has_lock = 1;
39140 +
39141 +#ifdef USE_LOCKS
39142 +       data_string *ds;
39143 +
39144 +       /**
39145 +        * If can have
39146 +        * - <lock-token>
39147 +        * - [etag]
39148 +        *
39149 +        * there is NOT, AND and OR
39150 +        * and a list can be tagged
39151 +        *
39152 +        * (<lock-token>) is untagged
39153 +        * <tag> (<lock-token>) is tagged
39154 +        *
39155 +        * as long as we don't handle collections it is simple. :)
39156 +        *
39157 +        * X-Litmus: locks: 11 (owner_modify)
39158 +        * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
39159 +        *
39160 +        * X-Litmus: locks: 16 (fail_cond_put)
39161 +        * If: (<DAV:no-lock> ["-1622396671"])
39162 +        */
39163 +       if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39164 +       } else {
39165 +               /* we didn't provided a lock-token -> */
39166 +               /* if the resource is locked -> 423 */
39167 +
39168 +               sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39169 +
39170 +               sqlite3_reset(stmt);
39171 +
39172 +               sqlite3_bind_text(stmt, 1,
39173 +                         CONST_BUF_LEN(uri),
39174 +                         SQLITE_TRANSIENT);
39175 +
39176 +               while (SQLITE_ROW == sqlite3_step(stmt)) {
39177 +                       has_lock = 0;
39178 +               }
39179 +       }
39180 +#endif
39181 +
39182 +       return has_lock;
39183 +}
39184 +
39185  URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
39186         plugin_data *p = p_d;
39187         buffer *b;
39188 @@ -1001,7 +1205,8 @@
39189         buffer *prop_200;
39190         buffer *prop_404;
39191         webdav_properties *req_props;
39192 -       
39193 +       stat_cache_entry *sce = NULL;
39194 +
39195         UNUSED(srv);
39196  
39197         if (!p->conf.enabled) return HANDLER_GO_ON;
39198 @@ -1019,7 +1224,19 @@
39199                 req_props = NULL;
39200  
39201                 /* is there a content-body ? */
39202 -       
39203 +
39204 +               switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
39205 +               case HANDLER_ERROR:
39206 +                       if (errno == ENOENT) {
39207 +                               con->http_status = 404;
39208 +                               return HANDLER_FINISHED;
39209 +                       }
39210 +                       break;
39211 +               default:
39212 +                       break;
39213 +               }
39214 +
39215 +
39216  #ifdef USE_PROPPATCH
39217                 /* any special requests or just allprop ? */
39218                 if (con->request.content_length) {
39219 @@ -1087,12 +1304,12 @@
39220                                                                 /* get all property names (EMPTY) */
39221                                                                 sqlite3_reset(stmt);
39222                                                                 /* bind the values to the insert */
39223 -       
39224 -                                                               sqlite3_bind_text(stmt, 1, 
39225 -                                                                                 con->uri.path->ptr, 
39226 +
39227 +                                                               sqlite3_bind_text(stmt, 1,
39228 +                                                                                 con->uri.path->ptr,
39229                                                                                   con->uri.path->used - 1,
39230                                                                                   SQLITE_TRANSIENT);
39231 -                                               
39232 +
39233                                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
39234                                                                         WP();
39235                                                                 }
39236 @@ -1115,13 +1332,13 @@
39237                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39238  
39239                 b = chunkqueue_get_append_buffer(con->write_queue);
39240 -                               
39241 +
39242                 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39243  
39244                 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39245  
39246                 /* allprop */
39247 -               
39248 +
39249                 prop_200 = buffer_init();
39250                 prop_404 = buffer_init();
39251  
39252 @@ -1129,7 +1346,7 @@
39253                 case 0:
39254                         /* Depth: 0 */
39255                         webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
39256 -       
39257 +
39258                         buffer_append_string(b,"<D:response>\n");
39259                         buffer_append_string(b,"<D:href>");
39260                         buffer_append_string_buffer(b, con->uri.scheme);
39261 @@ -1145,9 +1362,9 @@
39262                                 buffer_append_string_buffer(b, prop_200);
39263  
39264                                 buffer_append_string(b,"</D:prop>\n");
39265 -       
39266 +
39267                                 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39268 -       
39269 +
39270                                 buffer_append_string(b,"</D:propstat>\n");
39271                         }
39272                         if (!buffer_is_empty(prop_404)) {
39273 @@ -1157,16 +1374,16 @@
39274                                 buffer_append_string_buffer(b, prop_404);
39275  
39276                                 buffer_append_string(b,"</D:prop>\n");
39277 -       
39278 +
39279                                 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39280 -       
39281 +
39282                                 buffer_append_string(b,"</D:propstat>\n");
39283                         }
39284  
39285                         buffer_append_string(b,"</D:response>\n");
39286  
39287                         break;
39288 -               case 1: 
39289 +               case 1:
39290                         if (NULL != (dir = opendir(con->physical.path->ptr))) {
39291                                 struct dirent *de;
39292                                 physical d;
39293 @@ -1179,16 +1396,16 @@
39294                                         if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
39295                                                 continue;
39296                                                 /* ignore the parent dir */
39297 -                                       } 
39298 +                                       }
39299  
39300                                         buffer_copy_string_buffer(d.path, dst->path);
39301 -                                       BUFFER_APPEND_SLASH(d.path);
39302 +                                       PATHNAME_APPEND_SLASH(d.path);
39303  
39304                                         buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39305 -                                       BUFFER_APPEND_SLASH(d.rel_path);
39306 +                                       PATHNAME_APPEND_SLASH(d.rel_path);
39307  
39308                                         if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
39309 -                                               /* don't append the . */ 
39310 +                                               /* don't append the . */
39311                                         } else {
39312                                                 buffer_append_string(d.path, de->d_name);
39313                                                 buffer_append_string(d.rel_path, de->d_name);
39314 @@ -1198,7 +1415,7 @@
39315                                         buffer_reset(prop_404);
39316  
39317                                         webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
39318 -                                       
39319 +
39320                                         buffer_append_string(b,"<D:response>\n");
39321                                         buffer_append_string(b,"<D:href>");
39322                                         buffer_append_string_buffer(b, con->uri.scheme);
39323 @@ -1214,9 +1431,9 @@
39324                                                 buffer_append_string_buffer(b, prop_200);
39325  
39326                                                 buffer_append_string(b,"</D:prop>\n");
39327 -                       
39328 +
39329                                                 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39330 -                       
39331 +
39332                                                 buffer_append_string(b,"</D:propstat>\n");
39333                                         }
39334                                         if (!buffer_is_empty(prop_404)) {
39335 @@ -1226,9 +1443,9 @@
39336                                                 buffer_append_string_buffer(b, prop_404);
39337  
39338                                                 buffer_append_string(b,"</D:prop>\n");
39339 -       
39340 +
39341                                                 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39342 -       
39343 +
39344                                                 buffer_append_string(b,"</D:propstat>\n");
39345                                         }
39346  
39347 @@ -1275,7 +1492,7 @@
39348  
39349                         return HANDLER_FINISHED;
39350                 }
39351 -       
39352 +
39353                 /* let's create the directory */
39354  
39355                 if (-1 == mkdir(con->physical.path->ptr, 0700)) {
39356 @@ -1303,7 +1520,13 @@
39357                         con->http_status = 403;
39358                         return HANDLER_FINISHED;
39359                 }
39360 -               
39361 +
39362 +               /* does the client have a lock for this connection ? */
39363 +               if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39364 +                       con->http_status = 423;
39365 +                       return HANDLER_FINISHED;
39366 +               }
39367 +
39368                 /* stat and unlink afterwards */
39369                 if (-1 == stat(con->physical.path->ptr, &st)) {
39370                         /* don't about it yet, unlink will fail too */
39371 @@ -1323,7 +1546,7 @@
39372                                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39373  
39374                                 b = chunkqueue_get_append_buffer(con->write_queue);
39375 -                       
39376 +
39377                                 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39378  
39379                                 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
39380 @@ -1331,7 +1554,7 @@
39381                                 buffer_append_string_buffer(b, multi_status_resp);
39382  
39383                                 buffer_append_string(b,"</D:multistatus>\n");
39384 -                       
39385 +
39386                                 if (p->conf.log_xml) {
39387                                         log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
39388                                 }
39389 @@ -1340,7 +1563,7 @@
39390                                 con->file_finished = 1;
39391                         } else {
39392                                 /* everything went fine, remove the directory */
39393 -       
39394 +
39395                                 if (-1 == rmdir(con->physical.path->ptr)) {
39396                                         switch(errno) {
39397                                         case ENOENT:
39398 @@ -1375,97 +1598,174 @@
39399         case HTTP_METHOD_PUT: {
39400                 int fd;
39401                 chunkqueue *cq = con->request_content_queue;
39402 +               chunk *c;
39403 +               data_string *ds_range;
39404  
39405                 if (p->conf.is_readonly) {
39406                         con->http_status = 403;
39407                         return HANDLER_FINISHED;
39408                 }
39409  
39410 +               /* is a exclusive lock set on the source */
39411 +               if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39412 +                       con->http_status = 423;
39413 +                       return HANDLER_FINISHED;
39414 +               }
39415 +
39416 +
39417                 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
39418  
39419 -               /* taken what we have in the request-body and write it to a file */
39420 -               if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
39421 -                       /* we can't open the file */
39422 -                       con->http_status = 403;
39423 -               } else {
39424 -                       chunk *c;
39425 +               /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
39426 +                * - most important Content-Range
39427 +                *
39428 +                *
39429 +                * Example: Content-Range: bytes 100-1037/1038 */
39430  
39431 -                       con->http_status = 201; /* created */
39432 -                       con->file_finished = 1;
39433 +               if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
39434 +                       const char *num = ds_range->value->ptr;
39435 +                       off_t offset;
39436 +                       char *err = NULL;
39437  
39438 -                       for (c = cq->first; c; c = cq->first) {
39439 -                               int r = 0; 
39440 +                       if (0 != strncmp(num, "bytes ", 6)) {
39441 +                               con->http_status = 501; /* not implemented */
39442  
39443 -                               /* copy all chunks */
39444 -                               switch(c->type) {
39445 -                               case FILE_CHUNK:
39446 -
39447 -                                       if (c->file.mmap.start == MAP_FAILED) {
39448 -                                               if (-1 == c->file.fd &&  /* open the file if not already open */
39449 -                                                   -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39450 -                                                       log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39451 -                                       
39452 -                                                       return -1;
39453 -                                               }
39454 -                               
39455 -                                               if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39456 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 
39457 -                                                                       strerror(errno), c->file.name,  c->file.fd);
39458 +                               return HANDLER_FINISHED;
39459 +                       }
39460  
39461 -                                                       return -1;
39462 -                                               }
39463 +                       /* we only support <num>- ... */
39464  
39465 -                                               c->file.mmap.length = c->file.length;
39466 +                       num += 6;
39467  
39468 -                                               close(c->file.fd);
39469 -                                               c->file.fd = -1;
39470 -       
39471 -                                               /* chunk_reset() or chunk_free() will cleanup for us */
39472 -                                       }
39473 -
39474 -                                       if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39475 -                                               switch(errno) {
39476 -                                               case ENOSPC:
39477 -                                                       con->http_status = 507;
39478 -               
39479 -                                                       break;
39480 -                                               default:
39481 -                                                       con->http_status = 403;
39482 -                                                       break;
39483 -                                               }
39484 -                                       }
39485 -                                       break;
39486 -                               case MEM_CHUNK:
39487 -                                       if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39488 -                                               switch(errno) {
39489 -                                               case ENOSPC:
39490 -                                                       con->http_status = 507;
39491 -               
39492 -                                                       break;
39493 -                                               default:
39494 -                                                       con->http_status = 403;
39495 -                                                       break;
39496 -                                               }
39497 -                                       }
39498 +                       /* skip WS */
39499 +                       while (*num == ' ' || *num == '\t') num++;
39500 +
39501 +                       if (*num == '\0') {
39502 +                               con->http_status = 501; /* not implemented */
39503 +
39504 +                               return HANDLER_FINISHED;
39505 +                       }
39506 +
39507 +                       offset = strtoll(num, &err, 10);
39508 +
39509 +                       if (*err != '-' || offset < 0) {
39510 +                               con->http_status = 501; /* not implemented */
39511 +
39512 +                               return HANDLER_FINISHED;
39513 +                       }
39514 +
39515 +                       if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
39516 +                               switch (errno) {
39517 +                               case ENOENT:
39518 +                                       con->http_status = 404; /* not found */
39519                                         break;
39520 -                               case UNUSED_CHUNK:
39521 +                               default:
39522 +                                       con->http_status = 403; /* not found */
39523                                         break;
39524                                 }
39525 +                               return HANDLER_FINISHED;
39526 +                       }
39527 +
39528 +                       if (-1 == lseek(fd, offset, SEEK_SET)) {
39529 +                               con->http_status = 501; /* not implemented */
39530 +
39531 +                               close(fd);
39532 +
39533 +                               return HANDLER_FINISHED;
39534 +                       }
39535 +                       con->http_status = 200; /* modified */
39536 +               } else {
39537 +                       /* take what we have in the request-body and write it to a file */
39538 +
39539 +                       /* if the file doesn't exist, create it */
39540 +                       if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
39541 +                               if (errno == ENOENT &&
39542 +                                   -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
39543 +                                       /* we can't open the file */
39544 +                                       con->http_status = 403;
39545  
39546 -                               if (r > 0) {
39547 -                                       c->offset += r;
39548 -                                       cq->bytes_out += r;
39549 +                                       return HANDLER_FINISHED;
39550                                 } else {
39551 -                                       break;
39552 +                                       con->http_status = 201; /* created */
39553 +                               }
39554 +                       } else {
39555 +                               con->http_status = 200; /* modified */
39556 +                       }
39557 +               }
39558 +
39559 +               con->file_finished = 1;
39560 +
39561 +               for (c = cq->first; c; c = cq->first) {
39562 +                       int r = 0;
39563 +
39564 +                       /* copy all chunks */
39565 +                       switch(c->type) {
39566 +                       case FILE_CHUNK:
39567 +
39568 +                               if (c->file.mmap.start == MAP_FAILED) {
39569 +                                       if (-1 == c->file.fd &&  /* open the file if not already open */
39570 +                                           -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39571 +                                               log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39572 +
39573 +                                               return -1;
39574 +                                       }
39575 +
39576 +                                       if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39577 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39578 +                                                               strerror(errno), c->file.name,  c->file.fd);
39579 +
39580 +                                               return -1;
39581 +                                       }
39582 +
39583 +                                       c->file.mmap.length = c->file.length;
39584 +
39585 +                                       close(c->file.fd);
39586 +                                       c->file.fd = -1;
39587 +
39588 +                                       /* chunk_reset() or chunk_free() will cleanup for us */
39589 +                               }
39590 +
39591 +                               if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39592 +                                       switch(errno) {
39593 +                                       case ENOSPC:
39594 +                                               con->http_status = 507;
39595 +
39596 +                                               break;
39597 +                                       default:
39598 +                                               con->http_status = 403;
39599 +                                               break;
39600 +                                       }
39601                                 }
39602 -                               chunkqueue_remove_finished_chunks(cq);
39603 +                               break;
39604 +                       case MEM_CHUNK:
39605 +                               if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39606 +                                       switch(errno) {
39607 +                                       case ENOSPC:
39608 +                                               con->http_status = 507;
39609 +
39610 +                                               break;
39611 +                                       default:
39612 +                                               con->http_status = 403;
39613 +                                               break;
39614 +                                       }
39615 +                               }
39616 +                               break;
39617 +                       case UNUSED_CHUNK:
39618 +                               break;
39619                         }
39620 -                       close(fd);
39621  
39622 +                       if (r > 0) {
39623 +                               c->offset += r;
39624 +                               cq->bytes_out += r;
39625 +                       } else {
39626 +                               break;
39627 +                       }
39628 +                       chunkqueue_remove_finished_chunks(cq);
39629                 }
39630 +               close(fd);
39631 +
39632                 return HANDLER_FINISHED;
39633         }
39634 -       case HTTP_METHOD_MOVE: 
39635 +       case HTTP_METHOD_MOVE:
39636         case HTTP_METHOD_COPY: {
39637                 buffer *destination = NULL;
39638                 char *sep, *start;
39639 @@ -1475,7 +1775,15 @@
39640                         con->http_status = 403;
39641                         return HANDLER_FINISHED;
39642                 }
39643 -               
39644 +
39645 +               /* is a exclusive lock set on the source */
39646 +               if (con->request.http_method == HTTP_METHOD_MOVE) {
39647 +                       if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39648 +                               con->http_status = 423;
39649 +                               return HANDLER_FINISHED;
39650 +                       }
39651 +               }
39652 +
39653                 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
39654                         destination = ds->value;
39655                 } else {
39656 @@ -1549,10 +1857,10 @@
39657                 }
39658  
39659                 buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
39660 -               BUFFER_APPEND_SLASH(p->physical.path);
39661 +               PATHNAME_APPEND_SLASH(p->physical.path);
39662                 buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
39663  
39664 -               /* don't add a second / */ 
39665 +               /* don't add a second / */
39666                 if (p->physical.rel_path->ptr[0] == '/') {
39667                         buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
39668                 } else {
39669 @@ -1613,6 +1921,12 @@
39670                         /* it is just a file, good */
39671                         int r;
39672  
39673 +                       /* does the client have a lock for this connection ? */
39674 +                       if (!webdav_has_lock(srv, con, p, p->uri.path)) {
39675 +                               con->http_status = 423;
39676 +                               return HANDLER_FINISHED;
39677 +                       }
39678 +
39679                         /* destination exists */
39680                         if (0 == (r = stat(p->physical.path->ptr, &st))) {
39681                                 if (S_ISDIR(st.st_mode)) {
39682 @@ -1636,7 +1950,7 @@
39683                                         return HANDLER_FINISHED;
39684                                 }
39685                         } else if (overwrite == 0) {
39686 -                               /* destination exists, but overwrite is not set */ 
39687 +                               /* destination exists, but overwrite is not set */
39688                                 con->http_status = 412;
39689                                 return HANDLER_FINISHED;
39690                         } else {
39691 @@ -1655,16 +1969,16 @@
39692                                                 sqlite3_reset(stmt);
39693  
39694                                                 /* bind the values to the insert */
39695 -                                               sqlite3_bind_text(stmt, 1, 
39696 -                                                                 p->uri.path->ptr, 
39697 +                                               sqlite3_bind_text(stmt, 1,
39698 +                                                                 p->uri.path->ptr,
39699                                                                   p->uri.path->used - 1,
39700                                                                   SQLITE_TRANSIENT);
39701  
39702 -                                               sqlite3_bind_text(stmt, 2, 
39703 -                                                                 con->uri.path->ptr, 
39704 +                                               sqlite3_bind_text(stmt, 2,
39705 +                                                                 con->uri.path->ptr,
39706                                                                   con->uri.path->used - 1,
39707                                                                   SQLITE_TRANSIENT);
39708 -                                               
39709 +
39710                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
39711                                                         log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
39712                                                 }
39713 @@ -1691,12 +2005,17 @@
39714  
39715                 return HANDLER_FINISHED;
39716         }
39717 -       case HTTP_METHOD_PROPPATCH: {
39718 +       case HTTP_METHOD_PROPPATCH:
39719                 if (p->conf.is_readonly) {
39720                         con->http_status = 403;
39721                         return HANDLER_FINISHED;
39722                 }
39723  
39724 +               if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39725 +                       con->http_status = 423;
39726 +                       return HANDLER_FINISHED;
39727 +               }
39728 +
39729                 /* check if destination exists */
39730                 if (-1 == stat(con->physical.path->ptr, &st)) {
39731                         switch(errno) {
39732 @@ -1737,7 +2056,7 @@
39733  
39734                                                         sqlite3_stmt *stmt;
39735  
39736 -                                                       stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ? 
39737 +                                                       stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
39738                                                                 p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
39739  
39740                                                         for (props = cmd->children; props; props = props->next) {
39741 @@ -1762,34 +2081,35 @@
39742  
39743                                                                         /* bind the values to the insert */
39744  
39745 -                                                                       sqlite3_bind_text(stmt, 1, 
39746 -                                                                                         con->uri.path->ptr, 
39747 +                                                                       sqlite3_bind_text(stmt, 1,
39748 +                                                                                         con->uri.path->ptr,
39749                                                                                           con->uri.path->used - 1,
39750                                                                                           SQLITE_TRANSIENT);
39751 -                                                                       sqlite3_bind_text(stmt, 2, 
39752 +                                                                       sqlite3_bind_text(stmt, 2,
39753                                                                                           (char *)prop->name,
39754                                                                                           strlen((char *)prop->name),
39755                                                                                           SQLITE_TRANSIENT);
39756                                                                         if (prop->ns) {
39757 -                                                                               sqlite3_bind_text(stmt, 3, 
39758 +                                                                               sqlite3_bind_text(stmt, 3,
39759                                                                                                   (char *)prop->ns->href,
39760                                                                                                   strlen((char *)prop->ns->href),
39761                                                                                                   SQLITE_TRANSIENT);
39762                                                                         } else {
39763 -                                                                               sqlite3_bind_text(stmt, 3, 
39764 +                                                                               sqlite3_bind_text(stmt, 3,
39765                                                                                                   "",
39766                                                                                                   0,
39767                                                                                                   SQLITE_TRANSIENT);
39768                                                                         }
39769                                                                         if (stmt == p->conf.stmt_update_prop) {
39770 -                                                                               sqlite3_bind_text(stmt, 4, 
39771 +                                                                               sqlite3_bind_text(stmt, 4,
39772                                                                                           (char *)xmlNodeGetContent(prop),
39773                                                                                           strlen((char *)xmlNodeGetContent(prop)),
39774                                                                                           SQLITE_TRANSIENT);
39775                                                                         }
39776 -                                                               
39777 +
39778                                                                         if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
39779 -                                                                               log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39780 +                                                                               log_error_write(srv, __FILE__, __LINE__, "ss",
39781 +                                                                                               "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39782                                                                         }
39783                                                                 }
39784                                                         }
39785 @@ -1804,7 +2124,7 @@
39786  
39787                                                         goto propmatch_cleanup;
39788                                                 }
39789 -       
39790 +
39791                                                 con->http_status = 400;
39792                                         } else {
39793                                                 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
39794 @@ -1821,6 +2141,7 @@
39795                                 }
39796  
39797  propmatch_cleanup:
39798 +
39799                                 xmlFreeDoc(xml);
39800                         } else {
39801                                 con->http_status = 400;
39802 @@ -1830,11 +2151,307 @@
39803  #endif
39804                 con->http_status = 501;
39805                 return HANDLER_FINISHED;
39806 -       }
39807 +       case HTTP_METHOD_LOCK:
39808 +               /**
39809 +                * a mac wants to write
39810 +                *
39811 +                * LOCK /dav/expire.txt HTTP/1.1\r\n
39812 +                * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
39813 +                * Accept: * / *\r\n
39814 +                * Depth: 0\r\n
39815 +                * Timeout: Second-600\r\n
39816 +                * Content-Type: text/xml; charset=\"utf-8\"\r\n
39817 +                * Content-Length: 229\r\n
39818 +                * Connection: keep-alive\r\n
39819 +                * Host: 192.168.178.23:1025\r\n
39820 +                * \r\n
39821 +                * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
39822 +                * <D:lockinfo xmlns:D=\"DAV:\">\n
39823 +                *  <D:lockscope><D:exclusive/></D:lockscope>\n
39824 +                *  <D:locktype><D:write/></D:locktype>\n
39825 +                *  <D:owner>\n
39826 +                *   <D:href>http://www.apple.com/webdav_fs/</D:href>\n
39827 +                *  </D:owner>\n
39828 +                * </D:lockinfo>\n
39829 +                */
39830 +
39831 +               if (depth != 0 && depth != -1) {
39832 +                       con->http_status = 400;
39833 +
39834 +                       return HANDLER_FINISHED;
39835 +               }
39836 +
39837 +#ifdef USE_LOCKS
39838 +               if (con->request.content_length) {
39839 +                       xmlDocPtr xml;
39840 +                       buffer *hdr_if = NULL;
39841 +
39842 +                       if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39843 +                               hdr_if = ds->value;
39844 +                       }
39845 +
39846 +                       /* we don't support Depth: Infinity on locks */
39847 +                       if (hdr_if == NULL && depth == -1) {
39848 +                               con->http_status = 409; /* Conflict */
39849 +
39850 +                               return HANDLER_FINISHED;
39851 +                       }
39852 +
39853 +                       if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
39854 +                               xmlNode *rootnode = xmlDocGetRootElement(xml);
39855 +
39856 +                               assert(rootnode);
39857 +
39858 +                               if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
39859 +                                       xmlNode *lockinfo;
39860 +                                       const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
39861 +
39862 +                                       for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
39863 +                                               if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
39864 +                                                       xmlNode *value;
39865 +                                                       for (value = lockinfo->children; value; value = value->next) {
39866 +                                                               if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
39867 +                                                                   (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
39868 +                                                                       lockscope = value->name;
39869 +                                                               } else {
39870 +                                                                       con->http_status = 400;
39871 +
39872 +                                                                       xmlFreeDoc(xml);
39873 +                                                                       return HANDLER_FINISHED;
39874 +                                                               }
39875 +                                                       }
39876 +                                               } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
39877 +                                                       xmlNode *value;
39878 +                                                       for (value = lockinfo->children; value; value = value->next) {
39879 +                                                               if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
39880 +                                                                       locktype = value->name;
39881 +                                                               } else {
39882 +                                                                       con->http_status = 400;
39883 +
39884 +                                                                       xmlFreeDoc(xml);
39885 +                                                                       return HANDLER_FINISHED;
39886 +                                                               }
39887 +                                                       }
39888 +
39889 +                                               } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
39890 +                                               }
39891 +                                       }
39892 +
39893 +                                       if (lockscope && locktype) {
39894 +                                               sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39895 +
39896 +                                               /* is this resourse already locked ? */
39897 +
39898 +                                               /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
39899 +                                                *   FROM locks
39900 +                                                *  WHERE resource = ? */
39901 +
39902 +                                               if (stmt) {
39903 +
39904 +                                                       sqlite3_reset(stmt);
39905 +
39906 +                                                       sqlite3_bind_text(stmt, 1,
39907 +                                                                         p->uri.path->ptr,
39908 +                                                                         p->uri.path->used - 1,
39909 +                                                                         SQLITE_TRANSIENT);
39910 +
39911 +                                                       /* it is the PK */
39912 +                                                       while (SQLITE_ROW == sqlite3_step(stmt)) {
39913 +                                                               /* we found a lock
39914 +                                                                * 1. is it compatible ?
39915 +                                                                * 2. is it ours */
39916 +                                                               char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
39917 +
39918 +                                                               if (strcmp(sql_lockscope, "exclusive")) {
39919 +                                                                       con->http_status = 423;
39920 +                                                               } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
39921 +                                                                       /* resourse is locked with a shared lock
39922 +                                                                        * client wants exclusive */
39923 +                                                                       con->http_status = 423;
39924 +                                                               }
39925 +                                                       }
39926 +                                                       if (con->http_status == 423) {
39927 +                                                               xmlFreeDoc(xml);
39928 +                                                               return HANDLER_FINISHED;
39929 +                                                       }
39930 +                                               }
39931 +
39932 +                                               stmt = p->conf.stmt_create_lock;
39933 +                                               if (stmt) {
39934 +                                                       /* create a lock-token */
39935 +                                                       uuid_t id;
39936 +                                                       char uuid[37] /* 36 + \0 */;
39937 +
39938 +                                                       uuid_generate(id);
39939 +                                                       uuid_unparse(id, uuid);
39940 +
39941 +                                                       buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
39942 +                                                       buffer_append_string(p->tmp_buf, uuid);
39943 +
39944 +                                                       /* "CREATE TABLE locks ("
39945 +                                                        * "  locktoken TEXT NOT NULL,"
39946 +                                                        * "  resource TEXT NOT NULL,"
39947 +                                                        * "  lockscope TEXT NOT NULL,"
39948 +                                                        * "  locktype TEXT NOT NULL,"
39949 +                                                        * "  owner TEXT NOT NULL,"
39950 +                                                        * "  depth INT NOT NULL,"
39951 +                                                        */
39952 +
39953 +                                                       sqlite3_reset(stmt);
39954 +
39955 +                                                       sqlite3_bind_text(stmt, 1,
39956 +                                                                         CONST_BUF_LEN(p->tmp_buf),
39957 +                                                                         SQLITE_TRANSIENT);
39958 +
39959 +                                                       sqlite3_bind_text(stmt, 2,
39960 +                                                                         CONST_BUF_LEN(con->uri.path),
39961 +                                                                         SQLITE_TRANSIENT);
39962 +
39963 +                                                       sqlite3_bind_text(stmt, 3,
39964 +                                                                         lockscope,
39965 +                                                                         xmlStrlen(lockscope),
39966 +                                                                         SQLITE_TRANSIENT);
39967 +
39968 +                                                       sqlite3_bind_text(stmt, 4,
39969 +                                                                         locktype,
39970 +                                                                         xmlStrlen(locktype),
39971 +                                                                         SQLITE_TRANSIENT);
39972 +
39973 +                                                       /* owner */
39974 +                                                       sqlite3_bind_text(stmt, 5,
39975 +                                                                         "",
39976 +                                                                         0,
39977 +                                                                         SQLITE_TRANSIENT);
39978 +
39979 +                                                       /* depth */
39980 +                                                       sqlite3_bind_int(stmt, 6,
39981 +                                                                        depth);
39982 +
39983 +
39984 +                                                       if (SQLITE_DONE != sqlite3_step(stmt)) {
39985 +                                                               log_error_write(srv, __FILE__, __LINE__, "ss",
39986 +                                                                               "create lock:", sqlite3_errmsg(p->conf.sql));
39987 +                                                       }
39988 +
39989 +                                                       /* looks like we survived */
39990 +                                                       webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
39991 +
39992 +                                                       con->http_status = 201;
39993 +                                                       con->file_finished = 1;
39994 +                                               }
39995 +                                       }
39996 +                               }
39997 +
39998 +                               xmlFreeDoc(xml);
39999 +                               return HANDLER_FINISHED;
40000 +                       } else {
40001 +                               con->http_status = 400;
40002 +                               return HANDLER_FINISHED;
40003 +                       }
40004 +               } else {
40005 +
40006 +                       if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
40007 +                               buffer *locktoken = ds->value;
40008 +                               sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
40009 +
40010 +                               /* remove the < > around the token */
40011 +                               if (locktoken->used < 6) {
40012 +                                       con->http_status = 400;
40013 +
40014 +                                       return HANDLER_FINISHED;
40015 +                               }
40016 +
40017 +                               buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
40018 +
40019 +                               sqlite3_reset(stmt);
40020 +
40021 +                               sqlite3_bind_text(stmt, 1,
40022 +                                         CONST_BUF_LEN(p->tmp_buf),
40023 +                                         SQLITE_TRANSIENT);
40024 +
40025 +                               if (SQLITE_DONE != sqlite3_step(stmt)) {
40026 +                                       log_error_write(srv, __FILE__, __LINE__, "ss",
40027 +                                               "refresh lock:", sqlite3_errmsg(p->conf.sql));
40028 +                               }
40029 +
40030 +                               webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
40031 +
40032 +                               con->http_status = 200;
40033 +                               con->file_finished = 1;
40034 +                               return HANDLER_FINISHED;
40035 +                       } else {
40036 +                               /* we need a lock-token to refresh */
40037 +                               con->http_status = 400;
40038 +
40039 +                               return HANDLER_FINISHED;
40040 +                       }
40041 +               }
40042 +               break;
40043 +#else
40044 +               con->http_status = 501;
40045 +               return HANDLER_FINISHED;
40046 +#endif
40047 +       case HTTP_METHOD_UNLOCK:
40048 +#ifdef USE_LOCKS
40049 +               if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
40050 +                       buffer *locktoken = ds->value;
40051 +                       sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
40052 +
40053 +                       /* remove the < > around the token */
40054 +                       if (locktoken->used < 4) {
40055 +                               con->http_status = 400;
40056 +
40057 +                               return HANDLER_FINISHED;
40058 +                       }
40059 +
40060 +                       /**
40061 +                        * FIXME:
40062 +                        *
40063 +                        * if the resourse is locked:
40064 +                        * - by us: unlock
40065 +                        * - by someone else: 401
40066 +                        * if the resource is not locked:
40067 +                        * - 412
40068 +                        *  */
40069 +
40070 +                       buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
40071 +
40072 +                       sqlite3_reset(stmt);
40073 +
40074 +                       sqlite3_bind_text(stmt, 1,
40075 +                                 CONST_BUF_LEN(p->tmp_buf),
40076 +                                 SQLITE_TRANSIENT);
40077 +
40078 +                       sqlite3_bind_text(stmt, 2,
40079 +                                 CONST_BUF_LEN(con->uri.path),
40080 +                                 SQLITE_TRANSIENT);
40081 +
40082 +                       if (SQLITE_DONE != sqlite3_step(stmt)) {
40083 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
40084 +                                       "remove lock:", sqlite3_errmsg(p->conf.sql));
40085 +                       }
40086 +
40087 +                       if (0 == sqlite3_changes(p->conf.sql)) {
40088 +                               con->http_status = 401;
40089 +                       } else {
40090 +                               con->http_status = 204;
40091 +                       }
40092 +                       return HANDLER_FINISHED;
40093 +               } else {
40094 +                       /* we need a lock-token to unlock */
40095 +                       con->http_status = 400;
40096 +
40097 +                       return HANDLER_FINISHED;
40098 +               }
40099 +               break;
40100 +#else
40101 +               con->http_status = 501;
40102 +               return HANDLER_FINISHED;
40103 +#endif
40104         default:
40105                 break;
40106         }
40107 -       
40108 +
40109         /* not found */
40110         return HANDLER_GO_ON;
40111  }
40112 @@ -1845,14 +2462,14 @@
40113  int mod_webdav_plugin_init(plugin *p) {
40114         p->version     = LIGHTTPD_VERSION_ID;
40115         p->name        = buffer_init_string("webdav");
40116 -       
40117 +
40118         p->init        = mod_webdav_init;
40119         p->handle_uri_clean  = mod_webdav_uri_handler;
40120         p->handle_physical   = mod_webdav_subrequest_handler;
40121         p->set_defaults  = mod_webdav_set_defaults;
40122         p->cleanup     = mod_webdav_free;
40123 -       
40124 +
40125         p->data        = NULL;
40126 -       
40127 +
40128         return 0;
40129  }
40130 --- ../lighttpd-1.4.11/src/network.c    2006-03-04 16:45:46.000000000 +0200
40131 +++ lighttpd-1.4.12/src/network.c       2006-07-11 22:07:51.000000000 +0300
40132 @@ -1,14 +1,14 @@
40133  #include <sys/types.h>
40134  #include <sys/stat.h>
40135 -#include <sys/time.h>
40136  
40137  #include <errno.h>
40138  #include <fcntl.h>
40139 -#include <unistd.h>
40140  #include <string.h>
40141  #include <stdlib.h>
40142  #include <assert.h>
40143  
40144 +#include <stdio.h>
40145 +
40146  #include "network.h"
40147  #include "fdevent.h"
40148  #include "log.h"
40149 @@ -19,11 +19,12 @@
40150  #include "network_backends.h"
40151  #include "sys-mmap.h"
40152  #include "sys-socket.h"
40153 +#include "sys-files.h"
40154  
40155  #ifdef USE_OPENSSL
40156 -# include <openssl/ssl.h> 
40157 -# include <openssl/err.h> 
40158 -# include <openssl/rand.h> 
40159 +# include <openssl/ssl.h>
40160 +# include <openssl/err.h>
40161 +# include <openssl/rand.h>
40162  #endif
40163  
40164  handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
40165 @@ -31,11 +32,11 @@
40166         server_socket *srv_socket = (server_socket *)context;
40167         connection *con;
40168         int loops = 0;
40169 -       
40170 +
40171         UNUSED(context);
40172 -       
40173 +
40174         if (revents != FDEVENT_IN) {
40175 -               log_error_write(srv, __FILE__, __LINE__, "sdd", 
40176 +               log_error_write(srv, __FILE__, __LINE__, "sdd",
40177                                 "strange event for server socket",
40178                                 srv_socket->fd,
40179                                 revents);
40180 @@ -44,12 +45,12 @@
40181  
40182         /* accept()s at most 100 connections directly
40183          *
40184 -        * we jump out after 100 to give the waiting connections a chance */    
40185 +        * we jump out after 100 to give the waiting connections a chance */
40186         for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
40187                 handler_t r;
40188 -               
40189 +
40190                 connection_state_machine(srv, con);
40191 -               
40192 +
40193                 switch(r = plugins_call_handle_joblist(srv, con)) {
40194                 case HANDLER_FINISHED:
40195                 case HANDLER_GO_ON:
40196 @@ -72,18 +73,18 @@
40197         buffer *b;
40198         int is_unix_domain_socket = 0;
40199         int fd;
40200 -       
40201 +
40202  #ifdef SO_ACCEPTFILTER
40203         struct accept_filter_arg afa;
40204  #endif
40205  
40206 -#ifdef __WIN32
40207 +#ifdef _WIN32
40208         WORD wVersionRequested;
40209         WSADATA wsaData;
40210         int err;
40211 -        
40212 +
40213         wVersionRequested = MAKEWORD( 2, 2 );
40214 -        
40215 +
40216         err = WSAStartup( wVersionRequested, &wsaData );
40217         if ( err != 0 ) {
40218                     /* Tell the user that we could not find a usable */
40219 @@ -91,37 +92,37 @@
40220                     return -1;
40221         }
40222  #endif
40223 -       
40224 +
40225         srv_socket = calloc(1, sizeof(*srv_socket));
40226         srv_socket->fd = -1;
40227 -       
40228 +
40229         srv_socket->srv_token = buffer_init();
40230         buffer_copy_string_buffer(srv_socket->srv_token, host_token);
40231 -       
40232 +
40233         b = buffer_init();
40234         buffer_copy_string_buffer(b, host_token);
40235 -       
40236 -       /* ipv4:port 
40237 +
40238 +       /* ipv4:port
40239          * [ipv6]:port
40240          */
40241         if (NULL == (sp = strrchr(b->ptr, ':'))) {
40242                 log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
40243 -               
40244 +
40245                 return -1;
40246         }
40247 -       
40248 +
40249         host = b->ptr;
40250 -       
40251 +
40252         /* check for [ and ] */
40253         if (b->ptr[0] == '[' && *(sp-1) == ']') {
40254                 *(sp-1) = '\0';
40255                 host++;
40256 -               
40257 +
40258                 s->use_ipv6 = 1;
40259         }
40260 -       
40261 +
40262         *(sp++) = '\0';
40263 -       
40264 +
40265         port = strtol(sp, NULL, 10);
40266  
40267         if (host[0] == '/') {
40268 @@ -129,17 +130,17 @@
40269                 is_unix_domain_socket = 1;
40270         } else if (port == 0 || port > 65535) {
40271                 log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
40272 -       
40273 +
40274                 return -1;
40275         }
40276 -       
40277 +
40278         if (*host == '\0') host = NULL;
40279  
40280         if (is_unix_domain_socket) {
40281  #ifdef HAVE_SYS_UN_H
40282  
40283                 srv_socket->addr.plain.sa_family = AF_UNIX;
40284 -               
40285 +
40286                 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
40287                         log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40288                         return -1;
40289 @@ -154,7 +155,7 @@
40290  #ifdef HAVE_IPV6
40291         if (s->use_ipv6) {
40292                 srv_socket->addr.plain.sa_family = AF_INET6;
40293 -               
40294 +
40295                 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40296                         log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40297                         return -1;
40298 @@ -162,7 +163,7 @@
40299                 srv_socket->use_ipv6 = 1;
40300         }
40301  #endif
40302 -                               
40303 +
40304         if (srv_socket->fd == -1) {
40305                 srv_socket->addr.plain.sa_family = AF_INET;
40306                 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40307 @@ -170,16 +171,16 @@
40308                         return -1;
40309                 }
40310         }
40311 -       
40312 +
40313         /* */
40314         srv->cur_fds = srv_socket->fd;
40315 -       
40316 +
40317         val = 1;
40318         if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
40319                 log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
40320                 return -1;
40321         }
40322 -       
40323 +
40324         switch(srv_socket->addr.plain.sa_family) {
40325  #ifdef HAVE_IPV6
40326         case AF_INET6:
40327 @@ -190,23 +191,23 @@
40328                 } else {
40329                         struct addrinfo hints, *res;
40330                         int r;
40331 -                       
40332 +
40333                         memset(&hints, 0, sizeof(hints));
40334 -                       
40335 +
40336                         hints.ai_family   = AF_INET6;
40337                         hints.ai_socktype = SOCK_STREAM;
40338                         hints.ai_protocol = IPPROTO_TCP;
40339 -                       
40340 +
40341                         if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
40342 -                               log_error_write(srv, __FILE__, __LINE__, 
40343 -                                               "sssss", "getaddrinfo failed: ", 
40344 +                               log_error_write(srv, __FILE__, __LINE__,
40345 +                                               "sssss", "getaddrinfo failed: ",
40346                                                 gai_strerror(r), "'", host, "'");
40347 -                               
40348 +
40349                                 return -1;
40350                         }
40351 -                       
40352 +
40353                         memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
40354 -                       
40355 +
40356                         freeaddrinfo(res);
40357                 }
40358                 srv_socket->addr.ipv6.sin6_port = htons(port);
40359 @@ -221,33 +222,34 @@
40360                 } else {
40361                         struct hostent *he;
40362                         if (NULL == (he = gethostbyname(host))) {
40363 -                               log_error_write(srv, __FILE__, __LINE__, 
40364 -                                               "sds", "gethostbyname failed: ", 
40365 +                               log_error_write(srv, __FILE__, __LINE__,
40366 +                                               "sds", "gethostbyname failed: ",
40367                                                 h_errno, host);
40368                                 return -1;
40369                         }
40370 -                       
40371 +
40372                         if (he->h_addrtype != AF_INET) {
40373                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
40374                                 return -1;
40375                         }
40376 -                       
40377 +
40378                         if (he->h_length != sizeof(struct in_addr)) {
40379                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
40380                                 return -1;
40381                         }
40382 -                       
40383 +
40384                         memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
40385                 }
40386                 srv_socket->addr.ipv4.sin_port = htons(port);
40387 -               
40388 +
40389                 addr_len = sizeof(struct sockaddr_in);
40390 -               
40391 +
40392                 break;
40393 +#ifndef _WIN32
40394         case AF_UNIX:
40395                 srv_socket->addr.un.sun_family = AF_UNIX;
40396                 strcpy(srv_socket->addr.un.sun_path, host);
40397 -               
40398 +
40399  #ifdef SUN_LEN
40400                 addr_len = SUN_LEN(&srv_socket->addr.un);
40401  #else
40402 @@ -259,8 +261,8 @@
40403                 if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
40404                         close(fd);
40405  
40406 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
40407 -                               "server socket is still in use:", 
40408 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
40409 +                               "server socket is still in use:",
40410                                 host);
40411  
40412  
40413 @@ -275,88 +277,89 @@
40414                 case ENOENT:
40415                         break;
40416                 default:
40417 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
40418 -                               "testing socket failed:", 
40419 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
40420 +                               "testing socket failed:",
40421                                 host, strerror(errno));
40422  
40423                         return -1;
40424                 }
40425  
40426                 break;
40427 +#endif
40428         default:
40429                 addr_len = 0;
40430 -               
40431 +
40432                 return -1;
40433         }
40434 -       
40435 +
40436         if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
40437                 switch(srv_socket->addr.plain.sa_family) {
40438                 case AF_UNIX:
40439 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
40440 -                                       "can't bind to socket:", 
40441 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
40442 +                                       "can't bind to socket:",
40443                                         host, strerror(errno));
40444                         break;
40445                 default:
40446 -                       log_error_write(srv, __FILE__, __LINE__, "ssds", 
40447 -                                       "can't bind to port:", 
40448 +                       log_error_write(srv, __FILE__, __LINE__, "ssds",
40449 +                                       "can't bind to port:",
40450                                         host, port, strerror(errno));
40451                         break;
40452                 }
40453                 return -1;
40454         }
40455 -       
40456 +
40457         if (-1 == listen(srv_socket->fd, 128 * 8)) {
40458                 log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
40459                 return -1;
40460         }
40461 -       
40462 +
40463         if (s->is_ssl) {
40464  #ifdef USE_OPENSSL
40465                 if (srv->ssl_is_init == 0) {
40466                         SSL_load_error_strings();
40467                         SSL_library_init();
40468                         srv->ssl_is_init = 1;
40469 -                       
40470 +
40471                         if (0 == RAND_status()) {
40472 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
40473 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40474                                                 "not enough entropy in the pool");
40475                                 return -1;
40476                         }
40477                 }
40478 -               
40479 +
40480                 if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
40481 -                       log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
40482 +                       log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40483                                         ERR_error_string(ERR_get_error(), NULL));
40484                         return -1;
40485                 }
40486 -               
40487 +
40488                 if (buffer_is_empty(s->ssl_pemfile)) {
40489                         log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
40490                         return -1;
40491                 }
40492 -               
40493 +
40494                 if (!buffer_is_empty(s->ssl_ca_file)) {
40495                         if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
40496 -                               log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", 
40497 +                               log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40498                                                 ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
40499                                 return -1;
40500                         }
40501                 }
40502 -               
40503 +
40504                 if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40505 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", 
40506 +                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40507                                         ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40508                         return -1;
40509                 }
40510 -               
40511 +
40512                 if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40513 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", 
40514 +                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40515                                         ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40516                         return -1;
40517                 }
40518 -               
40519 +
40520                 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
40521 -                       log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", 
40522 +                       log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
40523                                         "Private key does not match the certificate public key, reason:",
40524                                         ERR_error_string(ERR_get_error(), NULL),
40525                                         s->ssl_pemfile);
40526 @@ -364,15 +367,15 @@
40527                 }
40528                 srv_socket->ssl_ctx = s->ssl_ctx;
40529  #else
40530 -               
40531 +
40532                 buffer_free(srv_socket->srv_token);
40533                 free(srv_socket);
40534 -               
40535 +
40536                 buffer_free(b);
40537 -               
40538 -               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
40539 +
40540 +               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40541                                 "ssl requested but openssl support is not compiled in");
40542 -               
40543 +
40544                 return -1;
40545  #endif
40546         } else {
40547 @@ -390,10 +393,10 @@
40548                 }
40549  #endif
40550         }
40551 -       
40552 +
40553         srv_socket->is_ssl = s->is_ssl;
40554         srv_socket->fde_ndx = -1;
40555 -       
40556 +
40557         if (srv->srv_sockets.size == 0) {
40558                 srv->srv_sockets.size = 4;
40559                 srv->srv_sockets.used = 0;
40560 @@ -402,11 +405,10 @@
40561                 srv->srv_sockets.size += 4;
40562                 srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
40563         }
40564 -       
40565 +
40566         srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
40567 -       
40568         buffer_free(b);
40569 -       
40570 +
40571         return 0;
40572  }
40573  
40574 @@ -414,45 +416,58 @@
40575         size_t i;
40576         for (i = 0; i < srv->srv_sockets.used; i++) {
40577                 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40578 -               
40579 +
40580                 if (srv_socket->fd != -1) {
40581                         /* check if server fd are already registered */
40582                         if (srv_socket->fde_ndx != -1) {
40583                                 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
40584                                 fdevent_unregister(srv->ev, srv_socket->fd);
40585                         }
40586 -               
40587 +
40588                         close(srv_socket->fd);
40589                 }
40590 -               
40591 +
40592 +               if (srv_socket->is_ssl) {
40593 +#ifdef USE_OPENSSL
40594 +                       SSL_CTX_free(srv_socket->ssl_ctx);
40595 +#endif
40596 +               }
40597 +
40598                 buffer_free(srv_socket->srv_token);
40599 -               
40600 +
40601                 free(srv_socket);
40602         }
40603 -       
40604 +
40605 +#ifdef USE_OPENSSL
40606 +       ERR_free_strings();
40607 +#endif
40608         free(srv->srv_sockets.ptr);
40609 -       
40610 +
40611         return 0;
40612  }
40613  
40614  typedef enum {
40615         NETWORK_BACKEND_UNSET,
40616 +
40617         NETWORK_BACKEND_WRITE,
40618         NETWORK_BACKEND_WRITEV,
40619         NETWORK_BACKEND_LINUX_SENDFILE,
40620         NETWORK_BACKEND_FREEBSD_SENDFILE,
40621 -       NETWORK_BACKEND_SOLARIS_SENDFILEV
40622 +       NETWORK_BACKEND_SOLARIS_SENDFILEV,
40623 +
40624 +    NETWORK_BACKEND_WIN32_SEND,
40625 +    NETWORK_BACKEND_WIN32_TRANSMITFILE,
40626  } network_backend_t;
40627  
40628  int network_init(server *srv) {
40629         buffer *b;
40630         size_t i;
40631         network_backend_t backend;
40632 -       
40633 -       struct nb_map { 
40634 -               network_backend_t nb; 
40635 -               const char *name; 
40636 -       } network_backends[] = { 
40637 +
40638 +       struct nb_map {
40639 +               network_backend_t nb;
40640 +               const char *name;
40641 +       } network_backends[] = {
40642                 /* lowest id wins */
40643  #if defined USE_LINUX_SENDFILE
40644                 { NETWORK_BACKEND_LINUX_SENDFILE,       "linux-sendfile" },
40645 @@ -466,21 +481,30 @@
40646  #if defined USE_WRITEV
40647                 { NETWORK_BACKEND_WRITEV,               "writev" },
40648  #endif
40649 +#if defined USE_WRITE
40650                 { NETWORK_BACKEND_WRITE,                "write" },
40651 +#endif
40652 +#if defined USE_WIN32_TRANSMITFILE
40653 +               { NETWORK_BACKEND_WIN32_TRANSMITFILE,   "win32-transmitfile" },
40654 +#endif
40655 +#if defined USE_WIN32_SEND
40656 +               { NETWORK_BACKEND_WIN32_SEND,           "win32-send" },
40657 +#endif
40658 +
40659                 { NETWORK_BACKEND_UNSET,                NULL }
40660         };
40661 -       
40662 +
40663         b = buffer_init();
40664 -               
40665 +
40666         buffer_copy_string_buffer(b, srv->srvconf.bindhost);
40667         buffer_append_string(b, ":");
40668         buffer_append_long(b, srv->srvconf.port);
40669 -       
40670 +
40671         if (0 != network_server_init(srv, b, srv->config_storage[0])) {
40672                 return -1;
40673         }
40674         buffer_free(b);
40675 -               
40676 +
40677  #ifdef USE_OPENSSL
40678         srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
40679  #endif
40680 @@ -500,54 +524,80 @@
40681                 if (NULL == network_backends[i].name) {
40682                         /* we don't know it */
40683  
40684 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
40685 -                                       "server.network-backend has a unknown value:", 
40686 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
40687 +                                       "server.network-backend has a unknown value:",
40688                                         srv->srvconf.network_backend);
40689  
40690                         return -1;
40691                 }
40692         }
40693  
40694 +#define SET_NETWORK_BACKEND(read, write) \
40695 +    srv->network_backend_write = network_write_chunkqueue_##write;\
40696 +    srv->network_backend_read = network_read_chunkqueue_##read
40697 +
40698 +#define SET_NETWORK_BACKEND_SSL(read, write) \
40699 +    srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
40700 +    srv->network_ssl_backend_read = network_read_chunkqueue_##read
40701 +
40702         switch(backend) {
40703 +
40704 +#ifdef USE_WIN32_SEND
40705 +       case NETWORK_BACKEND_WIN32_SEND:
40706 +        SET_NETWORK_BACKEND(win32recv, win32send);
40707 +               break;
40708 +#ifdef USE_WIN32_TRANSMITFILE
40709 +       case NETWORK_BACKEND_WIN32_TRANSMITFILE:
40710 +        SET_NETWORK_BACKEND(win32recv, win32transmitfile);
40711 +               break;
40712 +#endif
40713 +#endif
40714 +
40715 +#ifdef USE_WRITE
40716         case NETWORK_BACKEND_WRITE:
40717 -               srv->network_backend_write = network_write_chunkqueue_write;
40718 +        SET_NETWORK_BACKEND(read, write);
40719                 break;
40720 +
40721  #ifdef USE_WRITEV
40722         case NETWORK_BACKEND_WRITEV:
40723 -               srv->network_backend_write = network_write_chunkqueue_writev;
40724 +        SET_NETWORK_BACKEND(read, writev);
40725                 break;
40726  #endif
40727  #ifdef USE_LINUX_SENDFILE
40728         case NETWORK_BACKEND_LINUX_SENDFILE:
40729 -               srv->network_backend_write = network_write_chunkqueue_linuxsendfile; 
40730 +        SET_NETWORK_BACKEND(read, linuxsendfile);
40731                 break;
40732  #endif
40733  #ifdef USE_FREEBSD_SENDFILE
40734         case NETWORK_BACKEND_FREEBSD_SENDFILE:
40735 -               srv->network_backend_write = network_write_chunkqueue_freebsdsendfile; 
40736 +        SET_NETWORK_BACKEND(read, freebsdsendfile);
40737                 break;
40738  #endif
40739  #ifdef USE_SOLARIS_SENDFILEV
40740         case NETWORK_BACKEND_SOLARIS_SENDFILEV:
40741 -               srv->network_backend_write = network_write_chunkqueue_solarissendfilev; 
40742 +        SET_NETWORK_BACKEND(read, solarissendfilev);
40743                 break;
40744  #endif
40745 +#endif
40746         default:
40747                 return -1;
40748         }
40749 +#ifdef USE_OPENSSL
40750 +        SET_NETWORK_BACKEND_SSL(openssl, openssl);
40751 +#endif
40752  
40753         /* check for $SERVER["socket"] */
40754         for (i = 1; i < srv->config_context->used; i++) {
40755                 data_config *dc = (data_config *)srv->config_context->data[i];
40756                 specific_config *s = srv->config_storage[i];
40757                 size_t j;
40758 -               
40759 +
40760                 /* not our stage */
40761                 if (COMP_SERVER_SOCKET != dc->comp) continue;
40762 -               
40763 +
40764                 if (dc->cond != CONFIG_COND_EQ) {
40765                         log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
40766 -                       
40767 +
40768                         return -1;
40769                 }
40770  
40771 @@ -558,36 +608,47 @@
40772                                 break;
40773                         }
40774                 }
40775 -               
40776 +
40777                 if (j == srv->srv_sockets.used) {
40778                         if (0 != network_server_init(srv, dc->string, s)) return -1;
40779                 }
40780         }
40781 -       
40782 +
40783         return 0;
40784  }
40785  
40786  int network_register_fdevents(server *srv) {
40787         size_t i;
40788 -       
40789         if (-1 == fdevent_reset(srv->ev)) {
40790                 return -1;
40791         }
40792 -       
40793         /* register fdevents after reset */
40794         for (i = 0; i < srv->srv_sockets.used; i++) {
40795                 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40796 -               
40797                 fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
40798                 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
40799         }
40800         return 0;
40801  }
40802  
40803 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40804 -       int ret = -1;
40805 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40806 +    server_socket *srv_socket = con->srv_socket;
40807 +
40808 +       if (srv_socket->is_ssl) {
40809 +#ifdef USE_OPENSSL
40810 +               return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
40811 +#else
40812 +               return NETWORK_STATUS_FATAL_ERROR;
40813 +#endif
40814 +       } else {
40815 +               return srv->network_backend_read(srv, con, con->fd, cq);
40816 +       }
40817 +}
40818 +
40819 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40820 +       network_status_t ret = NETWORK_STATUS_UNSET;
40821         off_t written = 0;
40822 -#ifdef TCP_CORK        
40823 +#ifdef TCP_CORK
40824         int corked = 0;
40825  #endif
40826         server_socket *srv_socket = con->srv_socket;
40827 @@ -600,11 +661,11 @@
40828                 joblist_append(srv, con);
40829  
40830                 return 1;
40831 -       }  
40832 +       }
40833  
40834         written = cq->bytes_out;
40835  
40836 -#ifdef TCP_CORK        
40837 +#ifdef TCP_CORK
40838         /* Linux: put a cork into the socket as we want to combine the write() calls
40839          * but only if we really have multiple chunks
40840          */
40841 @@ -613,7 +674,7 @@
40842                 setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
40843         }
40844  #endif
40845 -       
40846 +
40847         if (srv_socket->is_ssl) {
40848  #ifdef USE_OPENSSL
40849                 ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
40850 @@ -621,12 +682,17 @@
40851         } else {
40852                 ret = srv->network_backend_write(srv, con, con->fd, cq);
40853         }
40854 -       
40855 -       if (ret >= 0) {
40856 +
40857 +    switch (ret) {
40858 +    case NETWORK_STATUS_WAIT_FOR_EVENT:
40859 +    case NETWORK_STATUS_SUCCESS:
40860                 chunkqueue_remove_finished_chunks(cq);
40861 -               ret = chunkqueue_is_empty(cq) ? 0 : 1;
40862 +
40863 +        break;
40864 +    default:
40865 +        break;
40866         }
40867 -       
40868 +
40869  #ifdef TCP_CORK
40870         if (corked) {
40871                 corked = 0;
40872 @@ -639,13 +705,13 @@
40873         con->bytes_written_cur_second += written;
40874  
40875         *(con->conf.global_bytes_per_second_cnt_ptr) += written;
40876 -       
40877 +
40878         if (con->conf.kbytes_per_second &&
40879             (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
40880                 /* we reached the traffic limit */
40881  
40882                 con->traffic_limit_reached = 1;
40883                 joblist_append(srv, con);
40884 -       }  
40885 +       }
40886         return ret;
40887  }
40888 --- ../lighttpd-1.4.11/src/network.h    2005-08-11 01:26:42.000000000 +0300
40889 +++ lighttpd-1.4.12/src/network.h       2006-07-11 22:07:51.000000000 +0300
40890 @@ -3,7 +3,8 @@
40891  
40892  #include "server.h"
40893  
40894 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
40895 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
40896 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
40897  
40898  int network_init(server *srv);
40899  int network_close(server *srv);
40900 --- ../lighttpd-1.4.11/src/network_backends.h   2005-10-24 15:13:51.000000000 +0300
40901 +++ lighttpd-1.4.12/src/network_backends.h      2006-07-11 22:07:52.000000000 +0300
40902 @@ -43,16 +43,52 @@
40903  # define USE_AIX_SENDFILE
40904  #endif
40905  
40906 +/**
40907 +* unix can use read/write or recv/send on sockets
40908 +* win32 only recv/send
40909 +*/
40910 +#ifdef _WIN32
40911 +# define USE_WIN32_SEND
40912 +/* wait for async-io support
40913 +# define USE_WIN32_TRANSMITFILE
40914 +*/
40915 +#else
40916 +# define USE_WRITE
40917 +#endif
40918 +
40919  #include "base.h"
40920 +#include "network.h"
40921 +
40922 +#define NETWORK_BACKEND_WRITE_CHUNK(x) \
40923 +    network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c)
40924 +
40925 +#define NETWORK_BACKEND_WRITE(x) \
40926 +    network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
40927 +#define NETWORK_BACKEND_READ(x) \
40928 +    network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
40929  
40930 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
40931 +
40932 +NETWORK_BACKEND_WRITE(write);
40933 +NETWORK_BACKEND_WRITE(writev);
40934 +NETWORK_BACKEND_WRITE(linuxsendfile);
40935 +NETWORK_BACKEND_WRITE(freebsdsendfile);
40936 +NETWORK_BACKEND_WRITE(solarissendfilev);
40937 +
40938 +NETWORK_BACKEND_WRITE(win32transmitfile);
40939 +NETWORK_BACKEND_WRITE(win32send);
40940 +
40941 +NETWORK_BACKEND_READ(read);
40942 +NETWORK_BACKEND_READ(win32recv);
40943  
40944 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
40945 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
40946 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
40947 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
40948 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
40949  #ifdef USE_OPENSSL
40950 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
40951 +#define NETWORK_BACKEND_WRITE_SSL(x) \
40952 +    network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
40953 +#define NETWORK_BACKEND_READ_SSL(x) \
40954 +    network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
40955 +
40956 +NETWORK_BACKEND_WRITE_SSL(openssl);
40957 +NETWORK_BACKEND_READ_SSL(openssl);
40958  #endif
40959  
40960  #endif
40961 --- ../lighttpd-1.4.11/src/network_freebsd_sendfile.c   2005-10-22 12:28:18.000000000 +0300
40962 +++ lighttpd-1.4.12/src/network_freebsd_sendfile.c      2006-07-11 22:07:52.000000000 +0300
40963 @@ -26,142 +26,61 @@
40964  
40965  #ifndef UIO_MAXIOV
40966  # ifdef __FreeBSD__
40967 -/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */ 
40968 +/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
40969  #  define UIO_MAXIOV 1024
40970  # endif
40971  #endif
40972  
40973 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
40974 +NETWORK_BACKEND_WRITE(freebsdsendfile) {
40975         chunk *c;
40976         size_t chunks_written = 0;
40977 -       
40978 +
40979         for(c = cq->first; c; c = c->next, chunks_written++) {
40980                 int chunk_finished = 0;
40981 -               
40982 +               network_status_t ret;
40983 +
40984                 switch(c->type) {
40985 -               case MEM_CHUNK: {
40986 -                       char * offset;
40987 -                       size_t toSend;
40988 -                       ssize_t r;
40989 -                       
40990 -                       size_t num_chunks, i;
40991 -                       struct iovec chunks[UIO_MAXIOV];
40992 -                       chunk *tc;
40993 -                       size_t num_bytes = 0;
40994 -                       
40995 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
40996 -                       
40997 -                       /* build writev list 
40998 -                        * 
40999 -                        * 1. limit: num_chunks < UIO_MAXIOV
41000 -                        * 2. limit: num_bytes < SSIZE_MAX
41001 -                        */
41002 -                       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41003 -                       
41004 -                       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41005 -                               if (tc->mem->used == 0) {
41006 -                                       chunks[i].iov_base = tc->mem->ptr;
41007 -                                       chunks[i].iov_len  = 0;
41008 -                               } else {
41009 -                                       offset = tc->mem->ptr + tc->offset;
41010 -                                       toSend = tc->mem->used - 1 - tc->offset;
41011 -                                       
41012 -                                       chunks[i].iov_base = offset;
41013 -                                       
41014 -                                       /* protect the return value of writev() */
41015 -                                       if (toSend > SSIZE_MAX ||
41016 -                                           num_bytes + toSend > SSIZE_MAX) {
41017 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
41018 -                                               
41019 -                                               num_chunks = i + 1;
41020 -                                               break;
41021 -                                       } else {
41022 -                                               chunks[i].iov_len = toSend;
41023 -                                       }
41024 -                                
41025 -                                       num_bytes += toSend;
41026 -                               }
41027 -                       }
41028 -                       
41029 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
41030 -                               switch (errno) {
41031 -                               case EAGAIN:
41032 -                               case EINTR:
41033 -                                       r = 0;
41034 -                                       break;
41035 -                               case EPIPE:
41036 -                               case ECONNRESET:
41037 -                                       return -2;
41038 -                               default:
41039 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41040 -                                                       "writev failed:", strerror(errno), fd);
41041 -                                       
41042 -                                       return -1;
41043 -                               }
41044 +               case MEM_CHUNK:
41045 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41046  
41047 -                               r = 0;
41048 -                       }
41049 -                       
41050 -                       /* check which chunks have been written */
41051 -                       cq->bytes_out += r;
41052 -                       
41053 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41054 -                               if (r >= (ssize_t)chunks[i].iov_len) {
41055 -                                       /* written */
41056 -                                       r -= chunks[i].iov_len;
41057 -                                       tc->offset += chunks[i].iov_len;
41058 -                                       
41059 -                                       if (chunk_finished) {
41060 -                                               /* skip the chunks from further touches */
41061 -                                               chunks_written++;
41062 -                                               c = c->next;
41063 -                                       } else {
41064 -                                               /* chunks_written + c = c->next is done in the for()*/
41065 -                                               chunk_finished++;
41066 -                                       }
41067 -                               } else {
41068 -                                       /* partially written */
41069 -                                       
41070 -                                       tc->offset += r;
41071 -                                       chunk_finished = 0;
41072 -                                       
41073 -                                       break;
41074 -                               }
41075 +                       if (ret != NETWORK_STATUS_SUCCESS) {
41076 +                               return ret;
41077                         }
41078 -                       
41079 +
41080 +                       chunk_finished = 1;
41081 +
41082                         break;
41083 -               }
41084                 case FILE_CHUNK: {
41085                         off_t offset, r;
41086                         size_t toSend;
41087                         stat_cache_entry *sce = NULL;
41088                         int ifd;
41089 -                       
41090 +
41091                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41092                                 log_error_write(srv, __FILE__, __LINE__, "sb",
41093                                                 strerror(errno), c->file.name);
41094 -                               return -1;
41095 +                               return NETWORK_STATUS_FATAL_ERROR;
41096                         }
41097 -                       
41098 +
41099                         offset = c->file.start + c->offset;
41100                         /* limit the toSend to 2^31-1 bytes in a chunk */
41101 -                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ? 
41102 +                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41103                                 ((1 << 30) - 1) : c->file.length - c->offset;
41104 -                               
41105 +
41106                         if (offset > sce->st.st_size) {
41107                                 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41108 -                               
41109 -                               return -1;
41110 +
41111 +                               return NETWORK_STATUS_FATAL_ERROR;
41112                         }
41113 -                       
41114 +
41115                         if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41116                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41117 -                               
41118 -                               return -1;
41119 +
41120 +                               return NETWORK_STATUS_FATAL_ERROR;
41121                         }
41122 -                       
41123 +
41124                         r = 0;
41125 -                       
41126 +
41127                         /* FreeBSD sendfile() */
41128                         if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
41129                                 switch(errno) {
41130 @@ -169,39 +88,39 @@
41131                                         break;
41132                                 case ENOTCONN:
41133                                         close(ifd);
41134 -                                       return -2;
41135 +                                       return NETWORK_STATUS_CONNECTION_CLOSE;
41136                                 default:
41137                                         log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41138                                         close(ifd);
41139 -                                       return -1;
41140 +                                       return NETWORK_STATUS_FATAL_ERROR;
41141                                 }
41142                         }
41143                         close(ifd);
41144 -                       
41145 +
41146                         c->offset += r;
41147                         cq->bytes_out += r;
41148 -                       
41149 +
41150                         if (c->offset == c->file.length) {
41151                                 chunk_finished = 1;
41152                         }
41153 -                       
41154 +
41155                         break;
41156                 }
41157                 default:
41158 -                       
41159 +
41160                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41161 -                       
41162 +
41163                         return -1;
41164                 }
41165 -               
41166 +
41167                 if (!chunk_finished) {
41168                         /* not finished yet */
41169 -                       
41170 +
41171                         break;
41172                 }
41173         }
41174  
41175 -       return chunks_written;
41176 +       return NETWORK_STATUS_SUCCESS;
41177  }
41178  
41179  #endif
41180 --- ../lighttpd-1.4.11/src/network_linux_sendfile.c     2006-02-15 20:02:36.000000000 +0200
41181 +++ lighttpd-1.4.12/src/network_linux_sendfile.c        2006-07-15 22:43:21.000000000 +0300
41182 @@ -26,122 +26,54 @@
41183  /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
41184  #undef HAVE_POSIX_FADVISE
41185  
41186 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41187 -       chunk *c;
41188 +NETWORK_BACKEND_WRITE(linuxsendfile) {
41189 +       chunk *c, *tc;
41190         size_t chunks_written = 0;
41191 -       
41192 +
41193         for(c = cq->first; c; c = c->next, chunks_written++) {
41194                 int chunk_finished = 0;
41195 -               
41196 +               network_status_t ret;
41197 +
41198                 switch(c->type) {
41199 -               case MEM_CHUNK: {
41200 -                       char * offset;
41201 -                       size_t toSend;
41202 -                       ssize_t r;
41203 -                       
41204 -                       size_t num_chunks, i;
41205 -                       struct iovec chunks[UIO_MAXIOV];
41206 -                       chunk *tc;
41207 -                       size_t num_bytes = 0;
41208 -                       
41209 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
41210 -                       
41211 -                       /* build writev list 
41212 -                        * 
41213 -                        * 1. limit: num_chunks < UIO_MAXIOV
41214 -                        * 2. limit: num_bytes < SSIZE_MAX
41215 -                        */
41216 -                       for (num_chunks = 0, tc = c; 
41217 -                            tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; 
41218 -                            tc = tc->next, num_chunks++);
41219 -                       
41220 -                       for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41221 -                               if (tc->mem->used == 0) {
41222 -                                       chunks[i].iov_base = tc->mem->ptr;
41223 -                                       chunks[i].iov_len  = 0;
41224 -                               } else {
41225 -                                       offset = tc->mem->ptr + tc->offset;
41226 -                                       toSend = tc->mem->used - 1 - tc->offset;
41227 -                               
41228 -                                       chunks[i].iov_base = offset;
41229 -                                       
41230 -                                       /* protect the return value of writev() */
41231 -                                       if (toSend > SSIZE_MAX ||
41232 -                                           num_bytes + toSend > SSIZE_MAX) {
41233 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
41234 -                                               
41235 -                                               num_chunks = i + 1;
41236 -                                               break;
41237 -                                       } else {
41238 -                                               chunks[i].iov_len = toSend;
41239 -                                       }
41240 -                                
41241 -                                       num_bytes += toSend;
41242 -                               }
41243 -                       }
41244 -                       
41245 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
41246 -                               switch (errno) {
41247 -                               case EAGAIN:
41248 -                               case EINTR:
41249 -                                       r = 0;
41250 -                                       break;
41251 -                               case EPIPE:
41252 -                               case ECONNRESET:
41253 -                                       return -2;
41254 -                               default:
41255 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41256 -                                                       "writev failed:", strerror(errno), fd);
41257 -                               
41258 -                                       return -1;
41259 -                               }
41260 -                       }
41261 -                       
41262 -                       /* check which chunks have been written */
41263 -                       cq->bytes_out += r;
41264 +               case MEM_CHUNK:
41265 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
41266  
41267 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41268 -                               if (r >= (ssize_t)chunks[i].iov_len) {
41269 -                                       /* written */
41270 -                                       r -= chunks[i].iov_len;
41271 -                                       tc->offset += chunks[i].iov_len;
41272 -                                       
41273 +                       /* check which chunks are finished now */
41274 +                       for (tc = c; tc; tc = tc->next) {
41275 +                               /* finished the chunk */
41276 +                               if (tc->offset == tc->mem->used - 1) {
41277 +                                       /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
41278                                         if (chunk_finished) {
41279 -                                               /* skip the chunks from further touches */
41280 -                                               chunks_written++;
41281                                                 c = c->next;
41282                                         } else {
41283 -                                               /* chunks_written + c = c->next is done in the for()*/
41284 -                                               chunk_finished++;
41285 +                                               chunk_finished = 1;
41286                                         }
41287                                 } else {
41288 -                                       /* partially written */
41289 -                                       
41290 -                                       tc->offset += r;
41291 -                                       chunk_finished = 0;
41292 -                                       
41293                                         break;
41294                                 }
41295                         }
41296 -                       
41297 +
41298 +                       if (ret != NETWORK_STATUS_SUCCESS) {
41299 +                               return ret;
41300 +                       }
41301 +
41302                         break;
41303 -               }
41304                 case FILE_CHUNK: {
41305                         ssize_t r;
41306                         off_t offset;
41307                         size_t toSend;
41308                         stat_cache_entry *sce = NULL;
41309 -                       
41310 +
41311                         offset = c->file.start + c->offset;
41312                         /* limit the toSend to 2^31-1 bytes in a chunk */
41313 -                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ? 
41314 +                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41315                                 ((1 << 30) - 1) : c->file.length - c->offset;
41316 -                               
41317 -                       /* open file if not already opened */   
41318 +
41319 +                       /* open file if not already opened */
41320                         if (-1 == c->file.fd) {
41321                                 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
41322                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41323 -                               
41324 +
41325                                         return -1;
41326                                 }
41327  #ifdef FD_CLOEXEC
41328 @@ -151,7 +83,7 @@
41329                                 /* tell the kernel that we want to stream the file */
41330                                 if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
41331                                         if (ENOSYS != errno) {
41332 -                                               log_error_write(srv, __FILE__, __LINE__, "ssd", 
41333 +                                               log_error_write(srv, __FILE__, __LINE__, "ssd",
41334                                                         "posix_fadvise failed:", strerror(errno), c->file.fd);
41335                                         }
41336                                 }
41337 @@ -168,7 +100,7 @@
41338                                 case ECONNRESET:
41339                                         return -2;
41340                                 default:
41341 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41342 +                                       log_error_write(srv, __FILE__, __LINE__, "ssd",
41343                                                         "sendfile failed:", strerror(errno), fd);
41344                                         return -1;
41345                                 }
41346 @@ -179,7 +111,7 @@
41347                                  *
41348                                  * - the file shrinked -> error
41349                                  * - the remote side closed inbetween -> remote-close */
41350 -       
41351 +
41352                                 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41353                                         /* file is gone ? */
41354                                         return -1;
41355 @@ -196,22 +128,22 @@
41356  #ifdef HAVE_POSIX_FADVISE
41357  #if 0
41358  #define K * 1024
41359 -#define M * 1024 K     
41360 +#define M * 1024 K
41361  #define READ_AHEAD 4 M
41362                         /* check if we need a new chunk */
41363                         if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
41364                                 /* tell the kernel that we want to stream the file */
41365                                 if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
41366 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41367 +                                       log_error_write(srv, __FILE__, __LINE__, "ssd",
41368                                                 "posix_fadvise failed:", strerror(errno), c->file.fd);
41369                                 }
41370                         }
41371  #endif
41372  #endif
41373 -                       
41374 +
41375                         c->offset += r;
41376                         cq->bytes_out += r;
41377 -                       
41378 +
41379                         if (c->offset == c->file.length) {
41380                                 chunk_finished = 1;
41381  
41382 @@ -222,24 +154,24 @@
41383                                         c->file.fd = -1;
41384                                 }
41385                         }
41386 -                       
41387 +
41388                         break;
41389                 }
41390                 default:
41391 -                       
41392 +
41393                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41394 -                       
41395 +
41396                         return -1;
41397                 }
41398 -               
41399 +
41400                 if (!chunk_finished) {
41401                         /* not finished yet */
41402 -                       
41403 +
41404                         break;
41405                 }
41406         }
41407  
41408 -       return chunks_written;
41409 +       return NETWORK_STATUS_SUCCESS;
41410  }
41411  
41412  #endif
41413 --- ../lighttpd-1.4.11/src/network_openssl.c    2005-11-17 14:53:29.000000000 +0200
41414 +++ lighttpd-1.4.12/src/network_openssl.c       2006-07-11 22:07:52.000000000 +0300
41415 @@ -23,17 +23,87 @@
41416  #include "log.h"
41417  #include "stat_cache.h"
41418  
41419 -# include <openssl/ssl.h> 
41420 -# include <openssl/err.h> 
41421 +# include <openssl/ssl.h>
41422 +# include <openssl/err.h>
41423  
41424 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
41425 +NETWORK_BACKEND_READ_SSL(openssl) {
41426 +       buffer *b;
41427 +       off_t len;
41428 +
41429 +       b = chunkqueue_get_append_buffer(cq);
41430 +       buffer_prepare_copy(b, 8192);
41431 +       len = SSL_read(ssl, b->ptr, b->size - 1);
41432 +
41433 +       log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
41434 +
41435 +       if (len < 0) {
41436 +               int r, ssl_err;
41437 +
41438 +               switch ((r = SSL_get_error(con->ssl, len))) {
41439 +               case SSL_ERROR_WANT_READ:
41440 +                       return NETWORK_STATUS_WAIT_FOR_EVENT;
41441 +               case SSL_ERROR_SYSCALL:
41442 +                       /**
41443 +                        * man SSL_get_error()
41444 +                        *
41445 +                        * SSL_ERROR_SYSCALL
41446 +                        *   Some I/O error occurred.  The OpenSSL error queue may contain more
41447 +                        *   information on the error.  If the error queue is empty (i.e.
41448 +                        *   ERR_get_error() returns 0), ret can be used to find out more about
41449 +                        *   the error: If ret == 0, an EOF was observed that violates the
41450 +                        *   protocol.  If ret == -1, the underlying BIO reported an I/O error
41451 +                        *   (for socket I/O on Unix systems, consult errno for details).
41452 +                        *
41453 +                        */
41454 +                       while((ssl_err = ERR_get_error())) {
41455 +                               /* get all errors from the error-queue */
41456 +                               log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41457 +                                               r, ERR_error_string(ssl_err, NULL));
41458 +                       }
41459 +
41460 +                       switch(errno) {
41461 +                       default:
41462 +                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41463 +                                               len, r, errno,
41464 +                                               strerror(errno));
41465 +                               break;
41466 +                       }
41467 +
41468 +                       break;
41469 +               case SSL_ERROR_ZERO_RETURN:
41470 +                       /* clean shutdown on the remote side */
41471 +
41472 +                       if (r == 0) {
41473 +                               /* FIXME: later */
41474 +                       }
41475 +
41476 +                       /* fall thourgh */
41477 +               default:
41478 +                       while((ssl_err = ERR_get_error())) {
41479 +                               /* get all errors from the error-queue */
41480 +                               log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41481 +                                               r, ERR_error_string(ssl_err, NULL));
41482 +                       }
41483 +                       break;
41484 +               }
41485 +       }
41486 +
41487 +       assert(len > 0);
41488 +       b->used += len;
41489 +       b->ptr[b->used - 1] = '\0';
41490 +
41491 +       return NETWORK_STATUS_SUCCESS;
41492 +}
41493 +
41494 +
41495 +NETWORK_BACKEND_WRITE_SSL(openssl) {
41496         int ssl_r;
41497         chunk *c;
41498         size_t chunks_written = 0;
41499  
41500         /* this is a 64k sendbuffer
41501          *
41502 -        * it has to stay at the same location all the time to satisfy the needs 
41503 +        * it has to stay at the same location all the time to satisfy the needs
41504          * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
41505          *
41506          * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
41507 @@ -43,14 +113,14 @@
41508          * In reality we would like to use mmap() but we don't have a guarantee that
41509          * we get the same mmap() address for each call. On openbsd the mmap() address
41510          * even randomized.
41511 -        *   That means either we keep the mmap() open or we do a read() into a 
41512 -        * constant buffer 
41513 +        *   That means either we keep the mmap() open or we do a read() into a
41514 +        * constant buffer
41515          * */
41516  #define LOCAL_SEND_BUFSIZE (64 * 1024)
41517         static char *local_send_buffer = NULL;
41518  
41519         /* the remote side closed the connection before without shutdown request
41520 -        * - IE 
41521 +        * - IE
41522          * - wget
41523          * if keep-alive is disabled */
41524  
41525 @@ -60,32 +130,34 @@
41526  
41527         for(c = cq->first; c; c = c->next) {
41528                 int chunk_finished = 0;
41529 -               
41530 +
41531                 switch(c->type) {
41532                 case MEM_CHUNK: {
41533                         char * offset;
41534                         size_t toSend;
41535 -                       ssize_t r;
41536 -                       
41537 +                       ssize_t r = 0;
41538 +
41539                         if (c->mem->used == 0) {
41540                                 chunk_finished = 1;
41541                                 break;
41542                         }
41543 -                       
41544 +
41545                         offset = c->mem->ptr + c->offset;
41546                         toSend = c->mem->used - 1 - c->offset;
41547 -                       
41548 +
41549                         /**
41550                          * SSL_write man-page
41551 -                        * 
41552 +                        *
41553                          * WARNING
41554                          *        When an SSL_write() operation has to be repeated because of
41555                          *        SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
41556                          *        repeated with the same arguments.
41557 -                        * 
41558 +                        *
41559 +                        * SSL_write(..., 0) return 0 which is handle as an error (Success)
41560 +                        * checking toSend and not calling SSL_write() is simpler
41561                          */
41562 -                       
41563 -                       if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
41564 +
41565 +                       if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
41566                                 unsigned long err;
41567  
41568                                 switch ((ssl_r = SSL_get_error(ssl, r))) {
41569 @@ -95,7 +167,7 @@
41570                                         /* perhaps we have error waiting in our error-queue */
41571                                         if (0 != (err = ERR_get_error())) {
41572                                                 do {
41573 -                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41574 +                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41575                                                                         ssl_r, r,
41576                                                                         ERR_error_string(err, NULL));
41577                                                 } while((err = ERR_get_error()));
41578 @@ -105,43 +177,43 @@
41579                                                 case EPIPE:
41580                                                         return -2;
41581                                                 default:
41582 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 
41583 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41584                                                                         ssl_r, r, errno,
41585                                                                         strerror(errno));
41586                                                         break;
41587                                                 }
41588                                         } else {
41589                                                 /* neither error-queue nor errno ? */
41590 -                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", 
41591 +                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41592                                                                 ssl_r, r, errno,
41593                                                                 strerror(errno));
41594                                         }
41595 -                                       
41596 +
41597                                         return  -1;
41598                                 case SSL_ERROR_ZERO_RETURN:
41599                                         /* clean shutdown on the remote side */
41600 -                                       
41601 +
41602                                         if (r == 0) return -2;
41603 -                                       
41604 +
41605                                         /* fall through */
41606                                 default:
41607                                         while((err = ERR_get_error())) {
41608 -                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41609 +                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41610                                                                 ssl_r, r,
41611                                                                 ERR_error_string(err, NULL));
41612                                         }
41613 -                                       
41614 +
41615                                         return  -1;
41616                                 }
41617                         } else {
41618                                 c->offset += r;
41619                                 cq->bytes_out += r;
41620                         }
41621 -                       
41622 +
41623                         if (c->offset == (off_t)c->mem->used - 1) {
41624                                 chunk_finished = 1;
41625                         }
41626 -                       
41627 +
41628                         break;
41629                 }
41630                 case FILE_CHUNK: {
41631 @@ -150,7 +222,7 @@
41632                         stat_cache_entry *sce = NULL;
41633                         int ifd;
41634                         int write_wait = 0;
41635 -                       
41636 +
41637                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41638                                 log_error_write(srv, __FILE__, __LINE__, "sb",
41639                                                 strerror(errno), c->file.name);
41640 @@ -164,13 +236,13 @@
41641  
41642                         do {
41643                                 off_t offset = c->file.start + c->offset;
41644 -                               off_t toSend = c->file.length - c->offset; 
41645 +                               off_t toSend = c->file.length - c->offset;
41646  
41647                                 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
41648 -                       
41649 +
41650                                 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41651                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
41652 -                               
41653 +
41654                                         return -1;
41655                                 }
41656  
41657 @@ -183,9 +255,9 @@
41658                                 }
41659  
41660                                 s = local_send_buffer;
41661 -                       
41662 +
41663                                 close(ifd);
41664 -                       
41665 +
41666                                 if ((r = SSL_write(ssl, s, toSend)) <= 0) {
41667                                         unsigned long err;
41668  
41669 @@ -197,7 +269,7 @@
41670                                                 /* perhaps we have error waiting in our error-queue */
41671                                                 if (0 != (err = ERR_get_error())) {
41672                                                         do {
41673 -                                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41674 +                                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41675                                                                                 ssl_r, r,
41676                                                                                 ERR_error_string(err, NULL));
41677                                                         } while((err = ERR_get_error()));
41678 @@ -207,58 +279,58 @@
41679                                                         case EPIPE:
41680                                                                 return -2;
41681                                                         default:
41682 -                                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 
41683 +                                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41684                                                                                 ssl_r, r, errno,
41685                                                                                 strerror(errno));
41686                                                                 break;
41687                                                         }
41688                                                 } else {
41689                                                         /* neither error-queue nor errno ? */
41690 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", 
41691 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41692                                                                         ssl_r, r, errno,
41693                                                                         strerror(errno));
41694                                                 }
41695 -                                       
41696 +
41697                                                 return  -1;
41698                                         case SSL_ERROR_ZERO_RETURN:
41699                                                 /* clean shutdown on the remote side */
41700 -                                       
41701 +
41702                                                 if (r == 0)  return -2;
41703 -                                       
41704 +
41705                                                 /* fall thourgh */
41706                                         default:
41707                                                 while((err = ERR_get_error())) {
41708 -                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41709 +                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41710                                                                         ssl_r, r,
41711                                                                         ERR_error_string(err, NULL));
41712                                                 }
41713 -                                       
41714 +
41715                                                 return -1;
41716                                         }
41717                                 } else {
41718                                         c->offset += r;
41719                                         cq->bytes_out += r;
41720                                 }
41721 -                       
41722 +
41723                                 if (c->offset == c->file.length) {
41724                                         chunk_finished = 1;
41725                                 }
41726                         } while(!chunk_finished && !write_wait);
41727 -                       
41728 +
41729                         break;
41730                 }
41731                 default:
41732                         log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
41733 -                       
41734 +
41735                         return -1;
41736                 }
41737 -                       
41738 +
41739                 if (!chunk_finished) {
41740                         /* not finished yet */
41741 -                       
41742 +
41743                         break;
41744                 }
41745 -                       
41746 +
41747                 chunks_written++;
41748         }
41749  
41750 --- ../lighttpd-1.4.11/src/network_solaris_sendfilev.c  2005-10-22 12:28:27.000000000 +0300
41751 +++ lighttpd-1.4.12/src/network_solaris_sendfilev.c     2006-07-11 22:07:53.000000000 +0300
41752 @@ -29,114 +29,34 @@
41753  #endif
41754  
41755  /**
41756 - * a very simple sendfilev() interface for solaris which can be optimised a lot more 
41757 + * a very simple sendfilev() interface for solaris which can be optimised a lot more
41758   * as solaris sendfilev() supports 'sending everythin in one syscall()'
41759 - * 
41760 - * If you want such an interface and need the performance, just give me an account on 
41761 - * a solaris box. 
41762 + *
41763 + * If you want such an interface and need the performance, just give me an account on
41764 + * a solaris box.
41765   *   - jan@kneschke.de
41766   */
41767  
41768  
41769 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
41770 +NETWORK_BACKEND_WRITE(solarissendfilev) {
41771         chunk *c;
41772         size_t chunks_written = 0;
41773 -       
41774 +
41775         for(c = cq->first; c; c = c->next, chunks_written++) {
41776                 int chunk_finished = 0;
41777 -               
41778 +               network_status_t ret;
41779 +
41780                 switch(c->type) {
41781 -               case MEM_CHUNK: {
41782 -                       char * offset;
41783 -                       size_t toSend;
41784 -                       ssize_t r;
41785 -                       
41786 -                       size_t num_chunks, i;
41787 -                       struct iovec chunks[UIO_MAXIOV];
41788 -                       chunk *tc;
41789 -                       
41790 -                       size_t num_bytes = 0;
41791 -                       
41792 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
41793 -                       
41794 -                       /* build writev list 
41795 -                        * 
41796 -                        * 1. limit: num_chunks < UIO_MAXIOV
41797 -                        * 2. limit: num_bytes < SSIZE_MAX
41798 -                        */
41799 -                       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41800 -                       
41801 -                       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41802 -                               if (tc->mem->used == 0) {
41803 -                                       chunks[i].iov_base = tc->mem->ptr;
41804 -                                       chunks[i].iov_len  = 0;
41805 -                               } else {
41806 -                                       offset = tc->mem->ptr + tc->offset;
41807 -                                       toSend = tc->mem->used - 1 - tc->offset;
41808 -                               
41809 -                                       chunks[i].iov_base = offset;
41810 -                                       
41811 -                                       /* protect the return value of writev() */
41812 -                                       if (toSend > SSIZE_MAX ||
41813 -                                           num_bytes + toSend > SSIZE_MAX) {
41814 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
41815 -                                               
41816 -                                               num_chunks = i + 1;
41817 -                                               break;
41818 -                                       } else {
41819 -                                               chunks[i].iov_len = toSend;
41820 -                                       }
41821 -                                       
41822 -                                       num_bytes += toSend;
41823 -                               }
41824 -                       }
41825 -                       
41826 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
41827 -                               switch (errno) {
41828 -                               case EAGAIN:
41829 -                               case EINTR:
41830 -                                       r = 0;
41831 -                                       break;
41832 -                               case EPIPE:
41833 -                               case ECONNRESET:
41834 -                                       return -2;
41835 -                               default:
41836 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41837 -                                                       "writev failed:", strerror(errno), fd);
41838 -                               
41839 -                                       return -1;
41840 -                               }
41841 -                       }
41842 -                       
41843 -                       /* check which chunks have been written */
41844 -                       cq->bytes_out += r;
41845 -                       
41846 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41847 -                               if (r >= (ssize_t)chunks[i].iov_len) {
41848 -                                       /* written */
41849 -                                       r -= chunks[i].iov_len;
41850 -                                       tc->offset += chunks[i].iov_len;
41851 -                                       
41852 -                                       if (chunk_finished) {
41853 -                                               /* skip the chunks from further touches */
41854 -                                               chunks_written++;
41855 -                                               c = c->next;
41856 -                                       } else {
41857 -                                               /* chunks_written + c = c->next is done in the for()*/
41858 -                                               chunk_finished++;
41859 -                                       }
41860 -                               } else {
41861 -                                       /* partially written */
41862 -                                       
41863 -                                       tc->offset += r;
41864 -                                       chunk_finished = 0;
41865 -                                       
41866 -                                       break;
41867 -                               }
41868 +               case MEM_CHUNK:
41869 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41870 +
41871 +                       if (ret != NETWORK_STATUS_SUCCESS) {
41872 +                               return ret;
41873                         }
41874 -                       
41875 +
41876 +                       chunk_finished = 1;
41877 +
41878                         break;
41879 -               }
41880                 case FILE_CHUNK: {
41881                         ssize_t r;
41882                         off_t offset;
41883 @@ -144,25 +64,25 @@
41884                         sendfilevec_t fvec;
41885                         stat_cache_entry *sce = NULL;
41886                         int ifd;
41887 -                       
41888 +
41889                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41890                                 log_error_write(srv, __FILE__, __LINE__, "sb",
41891                                                 strerror(errno), c->file.name);
41892                                 return -1;
41893                         }
41894 -                                       
41895 +
41896                         offset = c->file.start + c->offset;
41897                         toSend = c->file.length - c->offset;
41898 -                       
41899 +
41900                         if (offset > sce->st.st_size) {
41901                                 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41902 -                               
41903 +
41904                                 return -1;
41905                         }
41906  
41907                         if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41908                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41909 -                               
41910 +
41911                                 return -1;
41912                         }
41913  
41914 @@ -170,44 +90,43 @@
41915                         fvec.sfv_flag = 0;
41916                         fvec.sfv_off = offset;
41917                         fvec.sfv_len = toSend;
41918 -                       
41919 +
41920                         /* Solaris sendfilev() */
41921                         if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
41922                                 if (errno != EAGAIN) {
41923                                         log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41924 -                                       
41925 +
41926                                         close(ifd);
41927 -                                       return -1;
41928 +                                       return NETWORK_STATUS_FATAL_ERROR;
41929                                 }
41930 -                               
41931 +
41932                                 r = 0;
41933                         }
41934 -                       
41935 +
41936                         close(ifd);
41937                         c->offset += written;
41938                         cq->bytes_out += written;
41939 -                       
41940 +
41941                         if (c->offset == c->file.length) {
41942                                 chunk_finished = 1;
41943                         }
41944 -                       
41945 +
41946                         break;
41947                 }
41948                 default:
41949 -                       
41950                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41951 -                       
41952 -                       return -1;
41953 +
41954 +                       return NETWORK_STATUS_FATAL_ERROR;
41955                 }
41956 -               
41957 +
41958                 if (!chunk_finished) {
41959                         /* not finished yet */
41960 -                       
41961 +
41962                         break;
41963                 }
41964         }
41965  
41966 -       return chunks_written;
41967 +       return NETWORK_STATUS_SUCCESS;
41968  }
41969  
41970  #endif
41971 --- ../lighttpd-1.4.11/src/network_write.c      2005-10-22 12:27:56.000000000 +0300
41972 +++ lighttpd-1.4.12/src/network_write.c 2006-07-15 22:43:21.000000000 +0300
41973 @@ -1,11 +1,11 @@
41974  #include <sys/types.h>
41975  #include <sys/stat.h>
41976 -#include <sys/time.h>
41977 +
41978  #include <errno.h>
41979  #include <fcntl.h>
41980 -#include <unistd.h>
41981  #include <string.h>
41982  #include <stdlib.h>
41983 +#include <assert.h>
41984  
41985  #include "network.h"
41986  #include "fdevent.h"
41987 @@ -13,9 +13,12 @@
41988  #include "stat_cache.h"
41989  
41990  #include "sys-socket.h"
41991 +#include "sys-files.h"
41992  
41993  #include "network_backends.h"
41994  
41995 +#ifdef USE_WRITE
41996 +
41997  #ifdef HAVE_SYS_FILIO_H
41998  # include <sys/filio.h>
41999  #endif
42000 @@ -24,47 +27,84 @@
42001  #include <sys/resource.h>
42002  #endif
42003  
42004 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
42005 +/**
42006 +* fill the chunkqueue will all the data that we can get
42007 +*
42008 +* this might be optimized into a readv() which uses the chunks
42009 +* as vectors
42010 +*/
42011 +NETWORK_BACKEND_READ(read) {
42012 +       int toread;
42013 +       buffer *b;
42014 +       off_t r;
42015 +
42016 +       /* use a chunk-size of 8k */
42017 +       do {
42018 +               toread = 8192;
42019 +
42020 +               b = chunkqueue_get_append_buffer(cq);
42021 +
42022 +               buffer_prepare_copy(b, toread);
42023 +
42024 +               if (-1 == (r = read(fd, b->ptr, toread))) {
42025 +                       switch (errno) {
42026 +                       case EAGAIN:
42027 +                               return NETWORK_STATUS_WAIT_FOR_EVENT;
42028 +                       default:
42029 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
42030 +                                       "unexpected end-of-file (perhaps the proxy process died):",
42031 +                                       fd, strerror(errno));
42032 +                               return NETWORK_STATUS_FATAL_ERROR;
42033 +                       }
42034 +               }
42035 +
42036 +               if (r == 0) {
42037 +                       return NETWORK_STATUS_CONNECTION_CLOSE;
42038 +               }
42039 +
42040 +               /* this should be catched by the b > 0 above */
42041 +               assert(r);
42042 +               b->used += r + 1;
42043 +               b->ptr[b->used - 1] = '\0';
42044 +       } while (r == toread);
42045 +
42046 +       return NETWORK_STATUS_SUCCESS;
42047 +}
42048 +
42049 +NETWORK_BACKEND_WRITE(write) {
42050         chunk *c;
42051         size_t chunks_written = 0;
42052 -       
42053 +
42054         for(c = cq->first; c; c = c->next) {
42055                 int chunk_finished = 0;
42056 -               
42057 +
42058                 switch(c->type) {
42059                 case MEM_CHUNK: {
42060                         char * offset;
42061                         size_t toSend;
42062                         ssize_t r;
42063 -                       
42064 +
42065                         if (c->mem->used == 0) {
42066                                 chunk_finished = 1;
42067                                 break;
42068                         }
42069 -                       
42070 +
42071                         offset = c->mem->ptr + c->offset;
42072                         toSend = c->mem->used - 1 - c->offset;
42073 -#ifdef __WIN32 
42074 -                       if ((r = send(fd, offset, toSend, 0)) < 0) {
42075 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42076 -                               
42077 -                               return -1;
42078 -                       }
42079 -#else
42080 +
42081                         if ((r = write(fd, offset, toSend)) < 0) {
42082                                 log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42083 -                               
42084 -                               return -1;
42085 +
42086 +                               return NETWORK_STATUS_FATAL_ERROR;
42087                         }
42088 -#endif
42089 -                       
42090 +
42091                         c->offset += r;
42092                         cq->bytes_out += r;
42093 -                       
42094 +
42095                         if (c->offset == (off_t)c->mem->used - 1) {
42096                                 chunk_finished = 1;
42097                         }
42098 -                       
42099 +
42100                         break;
42101                 }
42102                 case FILE_CHUNK: {
42103 @@ -76,93 +116,89 @@
42104                         size_t toSend;
42105                         stat_cache_entry *sce = NULL;
42106                         int ifd;
42107 -                       
42108 +
42109                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42110                                 log_error_write(srv, __FILE__, __LINE__, "sb",
42111                                                 strerror(errno), c->file.name);
42112 -                               return -1;
42113 +                               return NETWORK_STATUS_FATAL_ERROR;
42114                         }
42115 -                       
42116 +
42117                         offset = c->file.start + c->offset;
42118                         toSend = c->file.length - c->offset;
42119 -                       
42120 +
42121                         if (offset > sce->st.st_size) {
42122                                 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42123 -                               
42124 -                               return -1;
42125 +
42126 +                               return NETWORK_STATUS_FATAL_ERROR;
42127                         }
42128  
42129                         if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42130                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42131 -                               
42132 -                               return -1;
42133 +
42134 +                               return NETWORK_STATUS_FATAL_ERROR;
42135                         }
42136 -                       
42137 +
42138  #if defined USE_MMAP
42139                         if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
42140                                 log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
42141  
42142                                 close(ifd);
42143 -                               
42144 -                               return -1;
42145 +
42146 +                               return NETWORK_STATUS_FATAL_ERROR;
42147                         }
42148                         close(ifd);
42149  
42150                         if ((r = write(fd, p + offset, toSend)) <= 0) {
42151                                 log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
42152                                 munmap(p, sce->st.st_size);
42153 -                               return -1;
42154 +                               return NETWORK_STATUS_FATAL_ERROR;
42155                         }
42156 -                       
42157 +
42158                         munmap(p, sce->st.st_size);
42159  #else
42160                         buffer_prepare_copy(srv->tmp_buf, toSend);
42161 -                       
42162 +
42163                         lseek(ifd, offset, SEEK_SET);
42164                         if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
42165                                 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
42166                                 close(ifd);
42167 -                               
42168 -                               return -1;
42169 +
42170 +                               return NETWORK_STATUS_FATAL_ERROR;
42171                         }
42172                         close(ifd);
42173  
42174                         if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
42175                                 log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
42176 -                               
42177 -                               return -1;
42178 +
42179 +                               return NETWORK_STATUS_FATAL_ERROR;
42180                         }
42181  #endif
42182                         c->offset += r;
42183                         cq->bytes_out += r;
42184 -                       
42185 +
42186                         if (c->offset == c->file.length) {
42187                                 chunk_finished = 1;
42188                         }
42189 -                       
42190 +
42191                         break;
42192                 }
42193                 default:
42194 -                       
42195 +
42196                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42197 -                       
42198 -                       return -1;
42199 +
42200 +                       return NETWORK_STATUS_FATAL_ERROR;
42201                 }
42202 -               
42203 +
42204                 if (!chunk_finished) {
42205                         /* not finished yet */
42206 -                       
42207 +
42208                         break;
42209                 }
42210 -               
42211 +
42212                 chunks_written++;
42213         }
42214  
42215 -       return chunks_written;
42216 +       return NETWORK_STATUS_SUCCESS;
42217  }
42218  
42219 -#if 0
42220 -network_write_init(void) {
42221 -       p->write = network_write_write_chunkset;
42222 -}
42223  #endif
42224 --- ../lighttpd-1.4.11/src/network_writev.c     2006-02-15 01:02:36.000000000 +0200
42225 +++ lighttpd-1.4.12/src/network_writev.c        2006-07-15 22:43:21.000000000 +0300
42226 @@ -28,10 +28,10 @@
42227  
42228  #ifndef UIO_MAXIOV
42229  # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
42230 -/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */ 
42231 +/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42232  #  define UIO_MAXIOV 1024
42233  # elif defined(__sgi)
42234 -/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */ 
42235 +/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42236  #  define UIO_MAXIOV 512
42237  # elif defined(__sun)
42238  /* Solaris (and SunOS?) defines IOV_MAX instead */
42239 @@ -51,105 +51,121 @@
42240  #define LOCAL_BUFFERING 1
42241  #endif
42242  
42243 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
42244 -       chunk *c;
42245 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
42246 +       char * offset;
42247 +       size_t toSend;
42248 +       ssize_t r;
42249 +
42250 +       size_t num_chunks, i;
42251 +       struct iovec chunks[UIO_MAXIOV];
42252 +       chunk *tc; /* transfer chunks */
42253 +       size_t num_bytes = 0;
42254 +
42255 +       /* we can't send more then SSIZE_MAX bytes in one chunk */
42256 +
42257 +       /* build writev list
42258 +        *
42259 +        * 1. limit: num_chunks < UIO_MAXIOV
42260 +        * 2. limit: num_bytes < SSIZE_MAX
42261 +        */
42262 +       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42263 +
42264 +       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42265 +               if (tc->mem->used == 0) {
42266 +                       chunks[i].iov_base = tc->mem->ptr;
42267 +                       chunks[i].iov_len  = 0;
42268 +               } else {
42269 +                       offset = tc->mem->ptr + tc->offset;
42270 +                       toSend = tc->mem->used - 1 - tc->offset;
42271 +
42272 +                       chunks[i].iov_base = offset;
42273 +
42274 +                       /* protect the return value of writev() */
42275 +                       if (toSend > SSIZE_MAX ||
42276 +                           num_bytes + toSend > SSIZE_MAX) {
42277 +                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
42278 +
42279 +                               num_chunks = i + 1;
42280 +                               break;
42281 +                       } else {
42282 +                               chunks[i].iov_len = toSend;
42283 +                       }
42284 +
42285 +                       num_bytes += toSend;
42286 +               }
42287 +       }
42288 +
42289 +       if ((r = writev(fd, chunks, num_chunks)) < 0) {
42290 +               switch (errno) {
42291 +               case EAGAIN:
42292 +                       return NETWORK_STATUS_WAIT_FOR_EVENT;
42293 +               case EINTR:
42294 +                       return NETWORK_STATUS_INTERRUPTED;
42295 +               case EPIPE:
42296 +               case ECONNRESET:
42297 +                       return NETWORK_STATUS_CONNECTION_CLOSE;
42298 +               default:
42299 +                       log_error_write(srv, __FILE__, __LINE__, "ssd",
42300 +                                       "writev failed:", strerror(errno), fd);
42301 +
42302 +                       return NETWORK_STATUS_FATAL_ERROR;
42303 +               }
42304 +       }
42305 +
42306 +       cq->bytes_out += r;
42307 +
42308 +       /* check which chunks have been written */
42309 +
42310 +       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42311 +               if (r >= (ssize_t)chunks[i].iov_len) {
42312 +                       /* written */
42313 +                       r -= chunks[i].iov_len;
42314 +                       tc->offset += chunks[i].iov_len;
42315 +               } else {
42316 +                       /* partially written */
42317 +
42318 +                       tc->offset += r;
42319 +
42320 +                       return NETWORK_STATUS_WAIT_FOR_EVENT;
42321 +               }
42322 +       }
42323 +
42324 +       /* all chunks have been pushed out */
42325 +       return NETWORK_STATUS_SUCCESS;
42326 +}
42327 +
42328 +NETWORK_BACKEND_WRITE(writev) {
42329 +       chunk *c, *tc;
42330         size_t chunks_written = 0;
42331 -       
42332 +
42333         for(c = cq->first; c; c = c->next) {
42334                 int chunk_finished = 0;
42335 -               
42336 +               network_status_t ret;
42337 +
42338                 switch(c->type) {
42339 -               case MEM_CHUNK: {
42340 -                       char * offset;
42341 -                       size_t toSend;
42342 -                       ssize_t r;
42343 -                       
42344 -                       size_t num_chunks, i;
42345 -                       struct iovec chunks[UIO_MAXIOV];
42346 -                       chunk *tc;
42347 -                       size_t num_bytes = 0;
42348 -                       
42349 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
42350 -                       
42351 -                       /* build writev list 
42352 -                        * 
42353 -                        * 1. limit: num_chunks < UIO_MAXIOV
42354 -                        * 2. limit: num_bytes < SSIZE_MAX
42355 -                        */
42356 -                       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42357 -                       
42358 -                       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42359 -                               if (tc->mem->used == 0) {
42360 -                                       chunks[i].iov_base = tc->mem->ptr;
42361 -                                       chunks[i].iov_len  = 0;
42362 -                               } else {
42363 -                                       offset = tc->mem->ptr + tc->offset;
42364 -                                       toSend = tc->mem->used - 1 - tc->offset;
42365 -                               
42366 -                                       chunks[i].iov_base = offset;
42367 -                                       
42368 -                                       /* protect the return value of writev() */
42369 -                                       if (toSend > SSIZE_MAX ||
42370 -                                           num_bytes + toSend > SSIZE_MAX) {
42371 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
42372 -                                               
42373 -                                               num_chunks = i + 1;
42374 -                                               break;
42375 -                                       } else {
42376 -                                               chunks[i].iov_len = toSend;
42377 -                                       }
42378 -                                       
42379 -                                       num_bytes += toSend;
42380 -                               }
42381 -                       }
42382 -                       
42383 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
42384 -                               switch (errno) {
42385 -                               case EAGAIN:
42386 -                               case EINTR:
42387 -                                       r = 0;
42388 -                                       break;
42389 -                               case EPIPE:
42390 -                               case ECONNRESET:
42391 -                                       return -2;
42392 -                               default:
42393 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
42394 -                                                       "writev failed:", strerror(errno), fd);
42395 -                               
42396 -                                       return -1;
42397 -                               }
42398 -                       }
42399 -                       
42400 -                       cq->bytes_out += r;
42401 +               case MEM_CHUNK:
42402 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
42403  
42404 -                       /* check which chunks have been written */
42405 -                       
42406 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42407 -                               if (r >= (ssize_t)chunks[i].iov_len) {
42408 -                                       /* written */
42409 -                                       r -= chunks[i].iov_len;
42410 -                                       tc->offset += chunks[i].iov_len;
42411 -                                       
42412 +                       /* check which chunks are finished now */
42413 +                       for (tc = c; tc; tc = tc->next) {
42414 +                               /* finished the chunk */
42415 +                               if (tc->offset == tc->mem->used - 1) {
42416 +                                       /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
42417                                         if (chunk_finished) {
42418 -                                               /* skip the chunks from further touches */
42419 -                                               chunks_written++;
42420                                                 c = c->next;
42421                                         } else {
42422 -                                               /* chunks_written + c = c->next is done in the for()*/
42423 -                                               chunk_finished++;
42424 +                                               chunk_finished = 1;
42425                                         }
42426                                 } else {
42427 -                                       /* partially written */
42428 -                                       
42429 -                                       tc->offset += r;
42430 -                                       chunk_finished = 0;
42431 -
42432                                         break;
42433                                 }
42434                         }
42435 -                       
42436 +
42437 +                       if (ret != NETWORK_STATUS_SUCCESS) {
42438 +                               return ret;
42439 +                       }
42440 +
42441                         break;
42442 -               }
42443                 case FILE_CHUNK: {
42444                         ssize_t r;
42445                         off_t abs_offset;
42446 @@ -159,26 +175,26 @@
42447  #define KByte * 1024
42448  #define MByte * 1024 KByte
42449  #define GByte * 1024 MByte
42450 -                       const off_t we_want_to_mmap = 512 KByte; 
42451 +                       const off_t we_want_to_mmap = 512 KByte;
42452                         char *start = NULL;
42453  
42454                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42455                                 log_error_write(srv, __FILE__, __LINE__, "sb",
42456                                                 strerror(errno), c->file.name);
42457 -                               return -1;
42458 +                               return NETWORK_STATUS_FATAL_ERROR;
42459                         }
42460  
42461                         abs_offset = c->file.start + c->offset;
42462 -                       
42463 +
42464                         if (abs_offset > sce->st.st_size) {
42465 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
42466 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
42467                                                 "file was shrinked:", c->file.name);
42468 -                               
42469 -                               return -1;
42470 +
42471 +                               return NETWORK_STATUS_FATAL_ERROR;
42472                         }
42473  
42474 -                       /* mmap the buffer 
42475 -                        * - first mmap 
42476 +                       /* mmap the buffer
42477 +                        * - first mmap
42478                          * - new mmap as the we are at the end of the last one */
42479                         if (c->file.mmap.start == MAP_FAILED ||
42480                             abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
42481 @@ -188,7 +204,7 @@
42482                                  * adaptive mem-mapping
42483                                  *   the problem:
42484                                  *     we mmap() the whole file. If someone has alot large files and 32bit
42485 -                                *     machine the virtual address area will be unrun and we will have a failing 
42486 +                                *     machine the virtual address area will be unrun and we will have a failing
42487                                  *     mmap() call.
42488                                  *   solution:
42489                                  *     only mmap 16M in one chunk and move the window as soon as we have finished
42490 @@ -234,8 +250,8 @@
42491                                 if (-1 == c->file.fd) {  /* open the file if not already open */
42492                                         if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
42493                                                 log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
42494 -                               
42495 -                                               return -1;
42496 +
42497 +                                               return NETWORK_STATUS_FATAL_ERROR;
42498                                         }
42499  #ifdef FD_CLOEXEC
42500                                         fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
42501 @@ -245,10 +261,10 @@
42502                                 if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
42503                                         /* close it here, otherwise we'd have to set FD_CLOEXEC */
42504  
42505 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:", 
42506 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
42507                                                         strerror(errno), c->file.name, c->file.fd);
42508  
42509 -                                       return -1;
42510 +                                       return NETWORK_STATUS_FATAL_ERROR;
42511                                 }
42512  
42513                                 c->file.mmap.length = to_mmap;
42514 @@ -258,7 +274,7 @@
42515  #ifdef HAVE_MADVISE
42516                                 /* don't advise files < 64Kb */
42517                                 if (c->file.mmap.length > (64 KByte)) {
42518 -                                       /* darwin 7 is returning EINVAL all the time and I don't know how to 
42519 +                                       /* darwin 7 is returning EINVAL all the time and I don't know how to
42520                                          * detect this at runtime.i
42521                                          *
42522                                          * ignore the return value for now */
42523 @@ -274,12 +290,12 @@
42524                         toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
42525  
42526                         if (toSend < 0) {
42527 -                               log_error_write(srv, __FILE__, __LINE__, "soooo", 
42528 +                               log_error_write(srv, __FILE__, __LINE__, "soooo",
42529                                                 "toSend is negative:",
42530                                                 toSend,
42531                                                 c->file.mmap.length,
42532                                                 abs_offset,
42533 -                                               c->file.mmap.offset); 
42534 +                                               c->file.mmap.offset);
42535                                 assert(toSend < 0);
42536                         }
42537  
42538 @@ -297,18 +313,18 @@
42539                                         break;
42540                                 case EPIPE:
42541                                 case ECONNRESET:
42542 -                                       return -2;
42543 +                                       return NETWORK_STATUS_CONNECTION_CLOSE;
42544                                 default:
42545 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
42546 +                                       log_error_write(srv, __FILE__, __LINE__, "ssd",
42547                                                         "write failed:", strerror(errno), fd);
42548 -                                       
42549 -                                       return -1;
42550 +
42551 +                                       return NETWORK_STATUS_FATAL_ERROR;
42552                                 }
42553                         }
42554 -                       
42555 +
42556                         c->offset += r;
42557                         cq->bytes_out += r;
42558 -                       
42559 +
42560                         if (c->offset == c->file.length) {
42561                                 chunk_finished = 1;
42562  
42563 @@ -318,26 +334,26 @@
42564                                         c->file.mmap.start = MAP_FAILED;
42565                                 }
42566                         }
42567 -                       
42568 +
42569                         break;
42570                 }
42571                 default:
42572 -                       
42573 +
42574                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42575 -                       
42576 -                       return -1;
42577 +
42578 +                       return NETWORK_STATUS_FATAL_ERROR;
42579                 }
42580 -               
42581 +
42582                 if (!chunk_finished) {
42583                         /* not finished yet */
42584 -                       
42585 +
42586                         break;
42587                 }
42588 -               
42589 +
42590                 chunks_written++;
42591         }
42592  
42593 -       return chunks_written;
42594 +       return NETWORK_STATUS_SUCCESS;
42595  }
42596  
42597  #endif
42598 --- ../lighttpd-1.4.11/src/plugin.c     2006-02-08 14:00:54.000000000 +0200
42599 +++ lighttpd-1.4.12/src/plugin.c        2006-07-11 22:07:52.000000000 +0300
42600 @@ -13,27 +13,27 @@
42601  #include <valgrind/valgrind.h>
42602  #endif
42603  
42604 -#ifndef __WIN32
42605 +#ifndef _WIN32
42606  #include <dlfcn.h>
42607  #endif
42608  /*
42609 - * 
42610 + *
42611   * if you change this enum to add a new callback, be sure
42612   * - that PLUGIN_FUNC_SIZEOF is the last entry
42613   * - that you add PLUGIN_TO_SLOT twice:
42614 - *   1. as callback-dispatcher 
42615 + *   1. as callback-dispatcher
42616   *   2. in plugins_call_init()
42617 - * 
42618 + *
42619   */
42620  
42621  typedef struct {
42622         PLUGIN_DATA;
42623  } plugin_data;
42624  
42625 -typedef enum { 
42626 +typedef enum {
42627         PLUGIN_FUNC_UNSET,
42628 -               PLUGIN_FUNC_HANDLE_URI_CLEAN, 
42629 -               PLUGIN_FUNC_HANDLE_URI_RAW, 
42630 +               PLUGIN_FUNC_HANDLE_URI_CLEAN,
42631 +               PLUGIN_FUNC_HANDLE_URI_RAW,
42632                 PLUGIN_FUNC_HANDLE_REQUEST_DONE,
42633                 PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
42634                 PLUGIN_FUNC_HANDLE_TRIGGER,
42635 @@ -44,38 +44,42 @@
42636                 PLUGIN_FUNC_HANDLE_DOCROOT,
42637                 PLUGIN_FUNC_HANDLE_PHYSICAL,
42638                 PLUGIN_FUNC_CONNECTION_RESET,
42639 -               PLUGIN_FUNC_INIT, 
42640 +               PLUGIN_FUNC_INIT,
42641                 PLUGIN_FUNC_CLEANUP,
42642                 PLUGIN_FUNC_SET_DEFAULTS,
42643 -               
42644 +
42645                 PLUGIN_FUNC_SIZEOF
42646  } plugin_t;
42647  
42648  static plugin *plugin_init(void) {
42649         plugin *p;
42650 -       
42651 +
42652         p = calloc(1, sizeof(*p));
42653 -       
42654 +
42655 +       p->required_plugins = array_init();
42656 +
42657         return p;
42658  }
42659  
42660  static void plugin_free(plugin *p) {
42661         int use_dlclose = 1;
42662         if (p->name) buffer_free(p->name);
42663 +
42664 +       array_free(p->required_plugins);
42665  #ifdef HAVE_VALGRIND_VALGRIND_H
42666         /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
42667  #endif
42668  
42669  #ifndef LIGHTTPD_STATIC
42670 -       if (use_dlclose && p->lib) {    
42671 -#ifdef __WIN32
42672 +       if (use_dlclose && p->lib) {
42673 +#ifdef _WIN32
42674                 FreeLibrary(p->lib);
42675  #else
42676                 dlclose(p->lib);
42677  #endif
42678         }
42679  #endif
42680 -               
42681 +
42682         free(p);
42683  }
42684  
42685 @@ -89,17 +93,17 @@
42686                 srv->plugins.size += 4;
42687                 srv->plugins.ptr   = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
42688         }
42689 -       
42690 +
42691         ps = srv->plugins.ptr;
42692         ps[srv->plugins.used++] = p;
42693 -       
42694 +
42695         return 0;
42696  }
42697  
42698  /**
42699 - * 
42700 - * 
42701 - * 
42702 + *
42703 + *
42704 + *
42705   */
42706  
42707  #ifdef LIGHTTPD_STATIC
42708 @@ -121,30 +125,35 @@
42709  #else
42710  int plugins_load(server *srv) {
42711         plugin *p;
42712 +#ifdef _WIN32
42713 +    FARPROC init;
42714 +#else
42715         int (*init)(plugin *pl);
42716 +#endif
42717 +
42718         const char *error;
42719 -       size_t i;
42720 -       
42721 +       size_t i, j, k;
42722 +
42723         for (i = 0; i < srv->srvconf.modules->used; i++) {
42724                 data_string *d = (data_string *)srv->srvconf.modules->data[i];
42725                 char *modules = d->value->ptr;
42726 -       
42727 +
42728                 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
42729  
42730                 buffer_append_string(srv->tmp_buf, "/");
42731                 buffer_append_string(srv->tmp_buf, modules);
42732 -#if defined(__WIN32) || defined(__CYGWIN__)
42733 +#if defined(_WIN32) || defined(__CYGWIN__)
42734                 buffer_append_string(srv->tmp_buf, ".dll");
42735  #else
42736                 buffer_append_string(srv->tmp_buf, ".so");
42737  #endif
42738 -       
42739 +
42740                 p = plugin_init();
42741 -#ifdef __WIN32
42742 +#ifdef _WIN32
42743                 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
42744                         LPVOID lpMsgBuf;
42745                         FormatMessage(
42746 -                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
42747 +                               FORMAT_MESSAGE_ALLOCATE_BUFFER |
42748                                 FORMAT_MESSAGE_FROM_SYSTEM,
42749                                 NULL,
42750                                 GetLastError(),
42751 @@ -152,36 +161,36 @@
42752                                 (LPTSTR) &lpMsgBuf,
42753                                 0, NULL );
42754  
42755 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed", 
42756 +                       log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
42757                                         lpMsgBuf, srv->tmp_buf);
42758 -                       
42759 +
42760                         plugin_free(p);
42761 -                       
42762 +
42763                         return -1;
42764  
42765                 }
42766 -#else  
42767 +#else
42768                 if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
42769 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:", 
42770 +                       log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
42771                                         srv->tmp_buf, dlerror());
42772 -                       
42773 +
42774                         plugin_free(p);
42775 -                       
42776 +
42777                         return -1;
42778                 }
42779 -               
42780 +
42781  #endif
42782                 buffer_reset(srv->tmp_buf);
42783                 buffer_copy_string(srv->tmp_buf, modules);
42784                 buffer_append_string(srv->tmp_buf, "_plugin_init");
42785  
42786 -#ifdef __WIN32
42787 +#ifdef _WIN32
42788                 init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
42789  
42790                 if (init == NULL)  {
42791                         LPVOID lpMsgBuf;
42792                         FormatMessage(
42793 -                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
42794 +                               FORMAT_MESSAGE_ALLOCATE_BUFFER |
42795                                 FORMAT_MESSAGE_FROM_SYSTEM,
42796                                 NULL,
42797                                 GetLastError(),
42798 @@ -190,7 +199,7 @@
42799                                 0, NULL );
42800  
42801                         log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
42802 -                       
42803 +
42804                         plugin_free(p);
42805                         return -1;
42806                 }
42807 @@ -203,24 +212,43 @@
42808  #endif
42809                 if ((error = dlerror()) != NULL)  {
42810                         log_error_write(srv, __FILE__, __LINE__, "s", error);
42811 -                       
42812 +
42813                         plugin_free(p);
42814                         return -1;
42815                 }
42816 -       
42817 +
42818  #endif
42819                 if ((*init)(p)) {
42820                         log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
42821 -                       
42822 +
42823                         plugin_free(p);
42824                         return -1;
42825                 }
42826  #if 0
42827                 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
42828  #endif
42829 +               /* check if the required plugin is loaded */
42830 +               for (k = 0; k < p->required_plugins->used; k++) {
42831 +                       data_string *req = (data_string *)p->required_plugins->data[k];
42832 +
42833 +                       for (j = 0; j < i; j++) {
42834 +                               data_string *mod = (data_string *)srv->srvconf.modules->data[j];
42835 +
42836 +                               if (buffer_is_equal(req->value, mod->value)) break;
42837 +                       }
42838 +
42839 +                       if (j == i) {
42840 +                               /* not found */
42841 +                               log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
42842 +
42843 +                               plugin_free(p);
42844 +                       
42845 +                               return -1;
42846 +                       }
42847 +               }
42848                 plugins_register(srv, p);
42849         }
42850 -       
42851 +
42852         return 0;
42853  }
42854  #endif
42855 @@ -253,8 +281,8 @@
42856         }
42857  
42858  /**
42859 - * plugins that use 
42860 - * 
42861 + * plugins that use
42862 + *
42863   * - server *srv
42864   * - connection *con
42865   * - void *p_d (plugin_data *)
42866 @@ -301,12 +329,12 @@
42867         }
42868  
42869  /**
42870 - * plugins that use 
42871 - * 
42872 + * plugins that use
42873 + *
42874   * - server *srv
42875   * - void *p_d (plugin_data *)
42876   */
42877 -                                                                       
42878 +
42879  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
42880  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
42881  PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
42882 @@ -314,18 +342,18 @@
42883  
42884  #undef PLUGIN_TO_SLOT
42885  
42886 -#if 0                                                                  
42887 +#if 0
42888  /**
42889 - * 
42890 + *
42891   * special handler
42892 - * 
42893 + *
42894   */
42895  handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
42896         size_t i;
42897         plugin **ps;
42898 -       
42899 +
42900         ps = srv->plugins.ptr;
42901 -       
42902 +
42903         for (i = 0; i < srv->plugins.used; i++) {
42904                 plugin *p = ps[i];
42905                 if (p->handle_fdevent) {
42906 @@ -344,34 +372,34 @@
42907                         }
42908                 }
42909         }
42910 -       
42911 +
42912         return HANDLER_GO_ON;
42913  }
42914  #endif
42915  /**
42916 - * 
42917 + *
42918   * - call init function of all plugins to init the plugin-internals
42919   * - added each plugin that supports has callback to the corresponding slot
42920 - * 
42921 + *
42922   * - is only called once.
42923   */
42924  
42925  handler_t plugins_call_init(server *srv) {
42926         size_t i;
42927         plugin **ps;
42928 -       
42929 +
42930         ps = srv->plugins.ptr;
42931 -       
42932 +
42933         /* fill slots */
42934 -       
42935 +
42936         srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
42937 -       
42938 +
42939         for (i = 0; i < srv->plugins.used; i++) {
42940                 size_t j;
42941                 /* check which calls are supported */
42942 -               
42943 +
42944                 plugin *p = ps[i];
42945 -               
42946 +
42947  #define PLUGIN_TO_SLOT(x, y) \
42948         if (p->y) { \
42949                 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
42950 @@ -384,11 +412,11 @@
42951                         slot[j] = p;\
42952                         break;\
42953                 }\
42954 -       } 
42955 -               
42956 -               
42957 -               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean); 
42958 -               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw); 
42959 +       }
42960 +
42961 +
42962 +               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
42963 +               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
42964                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
42965                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
42966                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
42967 @@ -402,19 +430,19 @@
42968                 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
42969                 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
42970  #undef PLUGIN_TO_SLOT
42971 -               
42972 +
42973                 if (p->init) {
42974                         if (NULL == (p->data = p->init())) {
42975 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
42976 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
42977                                                 "plugin-init failed for module", p->name);
42978                                 return HANDLER_ERROR;
42979                         }
42980 -                       
42981 +
42982                         /* used for con->mode, DIRECT == 0, plugins above that */
42983                         ((plugin_data *)(p->data))->id = i + 1;
42984 -                       
42985 +
42986                         if (p->version != LIGHTTPD_VERSION_ID) {
42987 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
42988 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
42989                                                 "plugin-version doesn't match lighttpd-version for", p->name);
42990                                 return HANDLER_ERROR;
42991                         }
42992 @@ -422,29 +450,46 @@
42993                         p->data = NULL;
42994                 }
42995         }
42996 -       
42997 +
42998         return HANDLER_GO_ON;
42999  }
43000  
43001 +/**
43002 + * get the config-storage of the named plugin 
43003 + */
43004 +void *plugin_get_config(server *srv, const char *name) {
43005 +       size_t i;
43006 +
43007 +       for (i = 0; i < srv->plugins.used; i++) {
43008 +               plugin *p = ((plugin **)srv->plugins.ptr)[i];
43009 +
43010 +               if (buffer_is_equal_string(p->name, name, strlen(name))) {
43011 +                       return p->data;
43012 +               }
43013 +       }
43014 +
43015 +       return NULL;
43016 +}
43017 +
43018  void plugins_free(server *srv) {
43019         size_t i;
43020         plugins_call_cleanup(srv);
43021 -       
43022 +
43023         for (i = 0; i < srv->plugins.used; i++) {
43024                 plugin *p = ((plugin **)srv->plugins.ptr)[i];
43025 -               
43026 +
43027                 plugin_free(p);
43028         }
43029 -       
43030 +
43031         for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
43032                 plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
43033 -               
43034 +
43035                 if (slot) free(slot);
43036         }
43037 -       
43038 +
43039         free(srv->plugin_slots);
43040         srv->plugin_slots = NULL;
43041 -       
43042 +
43043         free(srv->plugins.ptr);
43044         srv->plugins.ptr = NULL;
43045         srv->plugins.used = 0;
43046 --- ../lighttpd-1.4.11/src/plugin.h     2005-08-15 12:28:56.000000000 +0300
43047 +++ lighttpd-1.4.12/src/plugin.h        2006-07-11 22:07:52.000000000 +0300
43048 @@ -12,6 +12,12 @@
43049  
43050  #define INIT_FUNC(x) \
43051                 static void *x()
43052 +/*
43053 + * The PATCH_OPTION() macro is used in the patch_connection() functions
43054 + * of the modules to update the config object for the current request.
43055 + */
43056 +#define PATCH_OPTION(x) \
43057 +               p->conf.x = s->x
43058  
43059  #define FREE_FUNC          SERVER_FUNC
43060  #define TRIGGER_FUNC       SERVER_FUNC
43061 @@ -25,19 +31,19 @@
43062  #define URIHANDLER_FUNC    CONNECTION_FUNC
43063  
43064  #define PLUGIN_DATA        size_t id
43065 -                                                                                                                                               
43066 +
43067  typedef struct {
43068         size_t version;
43069 -       
43070 +
43071         buffer *name; /* name of the plugin */
43072 -       
43073 +
43074         void *(* init)                       ();
43075         handler_t (* set_defaults)           (server *srv, void *p_d);
43076         handler_t (* cleanup)                (server *srv, void *p_d);
43077                                                                                            /* is called ... */
43078         handler_t (* handle_trigger)         (server *srv, void *p_d);                     /* once a second */
43079         handler_t (* handle_sighup)          (server *srv, void *p_d);                     /* at a signup */
43080 -       
43081 +
43082         handler_t (* handle_uri_raw)         (server *srv, connection *con, void *p_d);    /* after uri_raw is set */
43083         handler_t (* handle_uri_clean)       (server *srv, connection *con, void *p_d);    /* after uri is set */
43084         handler_t (* handle_docroot)         (server *srv, connection *con, void *p_d);    /* getting the document-root */
43085 @@ -45,20 +51,22 @@
43086         handler_t (* handle_request_done)    (server *srv, connection *con, void *p_d);    /* at the end of a request */
43087         handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d);    /* at the end of a connection */
43088         handler_t (* handle_joblist)         (server *srv, connection *con, void *p_d);    /* after all events are handled */
43089 -       
43090 -       
43091 -       
43092 -       handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);   
43093 -       
43094 -                                                                                          /* when a handler for the request 
43095 +
43096 +
43097 +
43098 +       handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43099 +
43100 +                                                                                          /* when a handler for the request
43101                                                                                             * has to be found
43102                                                                                             */
43103         handler_t (* handle_subrequest)      (server *srv, connection *con, void *p_d);    /* */
43104         handler_t (* connection_reset)       (server *srv, connection *con, void *p_d);    /* */
43105         void *data;
43106 -       
43107 +
43108         /* dlopen handle */
43109         void *lib;
43110 +
43111 +       array *required_plugins;
43112  } plugin;
43113  
43114  int plugins_load(server *srv);
43115 @@ -88,5 +96,8 @@
43116  int config_patch_connection(server *srv, connection *con, comp_key_t comp);
43117  int config_check_cond(server *srv, connection *con, data_config *dc);
43118  int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
43119 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
43120 +
43121 +void *plugin_get_config(server *srv, const char *name);
43122  
43123  #endif
43124 --- ../lighttpd-1.4.11/src/proc_open.c  2005-08-11 01:26:39.000000000 +0300
43125 +++ lighttpd-1.4.12/src/proc_open.c     2006-07-11 22:07:53.000000000 +0300
43126 @@ -13,13 +13,13 @@
43127  #endif
43128  
43129  
43130 -#ifdef WIN32
43131 +#ifdef _WIN32
43132  /* {{{ win32 stuff */
43133  # define SHELLENV "ComSpec"
43134  # define SECURITY_DC , SECURITY_ATTRIBUTES *security
43135  # define SECURITY_CC , security
43136  # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
43137 -static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43138 +static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43139  {
43140         HANDLE copy, self = GetCurrentProcess();
43141  
43142 @@ -148,11 +148,14 @@
43143         STARTUPINFO si;
43144         BOOL procok;
43145         SECURITY_ATTRIBUTES security;
43146 -       const char *shell;
43147 +       const char *shell = NULL;
43148 +       const char *windir = NULL;
43149         buffer *cmdline;
43150  
43151 -       if (NULL == (shell = getenv(SHELLENV))) {
43152 -               fprintf(stderr, "env %s is required", SHELLENV);
43153 +       if (NULL == (shell = getenv(SHELLENV)) &&
43154 +                       NULL == (windir = getenv("SystemRoot")) &&
43155 +                       NULL == (windir = getenv("windir"))) {
43156 +               fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
43157                 return -1;
43158         }
43159  
43160 @@ -177,17 +180,23 @@
43161         memset(&pi, 0, sizeof(pi));
43162  
43163         cmdline = buffer_init();
43164 -       buffer_append_string(cmdline, shell);
43165 +       if (shell) {
43166 +               buffer_append_string(cmdline, shell);
43167 +       } else {
43168 +               buffer_append_string(cmdline, windir);
43169 +               buffer_append_string(cmdline, "\\system32\\cmd.exe");
43170 +       }
43171         buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
43172         buffer_append_string(cmdline, command);
43173         procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
43174                         NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
43175 -       buffer_free(cmdline);
43176  
43177         if (FALSE == procok) {
43178 -               fprintf(stderr, "failed to CreateProcess");
43179 +               fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
43180 +               buffer_free(cmdline);
43181                 return -1;
43182         }
43183 +       buffer_free(cmdline);
43184  
43185         proc->child = pi.hProcess;
43186         CloseHandle(pi.hThread);
43187 @@ -226,8 +235,7 @@
43188         const char *shell;
43189  
43190         if (NULL == (shell = getenv(SHELLENV))) {
43191 -               fprintf(stderr, "env %s is required", SHELLENV);
43192 -               return -1;
43193 +               shell = "/bin/sh";
43194         }
43195  
43196         if (proc_open_pipes(proc) != 0) {
43197 @@ -262,11 +270,11 @@
43198         }
43199  }
43200  /* }}} */
43201 -#endif /* WIN32 */
43202 +#endif /* _WIN32 */
43203  
43204  /* {{{ proc_read_fd_to_buffer */
43205  static void proc_read_fd_to_buffer(int fd, buffer *b) {
43206 -       ssize_t s;
43207 +       int s; /* win32 has not ssize_t */
43208  
43209         for (;;) {
43210                 buffer_prepare_append(b, 512);
43211 --- ../lighttpd-1.4.11/src/proc_open.h  2005-08-11 01:26:39.000000000 +0300
43212 +++ lighttpd-1.4.12/src/proc_open.h     2006-07-11 22:07:53.000000000 +0300
43213 @@ -1,7 +1,7 @@
43214  
43215  #include "buffer.h"
43216  
43217 -#ifdef WIN32
43218 +#ifdef _WIN32
43219  #include <windows.h>
43220  typedef HANDLE descriptor_t;
43221  typedef HANDLE proc_pid_t;
43222 --- ../lighttpd-1.4.11/src/request.c    2006-03-05 11:58:09.000000000 +0200
43223 +++ lighttpd-1.4.12/src/request.c       2006-07-11 22:07:52.000000000 +0300
43224 @@ -10,15 +10,17 @@
43225  #include "keyvalue.h"
43226  #include "log.h"
43227  
43228 +#include "sys-strings.h"
43229 +
43230  static int request_check_hostname(server *srv, connection *con, buffer *host) {
43231         enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
43232         size_t i;
43233         int label_len = 0;
43234         size_t host_len;
43235         char *colon;
43236 -       int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */ 
43237 +       int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
43238         int level = 0;
43239 -       
43240 +
43241         UNUSED(srv);
43242         UNUSED(con);
43243  
43244 @@ -32,17 +34,17 @@
43245          *       IPv6address   = "[" ... "]"
43246          *       port          = *digit
43247          */
43248 -       
43249 +
43250         /* no Host: */
43251         if (!host || host->used == 0) return 0;
43252 -       
43253 +
43254         host_len = host->used - 1;
43255 -       
43256 +
43257         /* IPv6 adress */
43258         if (host->ptr[0] == '[') {
43259                 char *c = host->ptr + 1;
43260                 int colon_cnt = 0;
43261 -               
43262 +
43263                 /* check portnumber */
43264                 for (; *c && *c != ']'; c++) {
43265                         if (*c == ':') {
43266 @@ -53,12 +55,12 @@
43267                                 return -1;
43268                         }
43269                 }
43270 -               
43271 +
43272                 /* missing ] */
43273                 if (!*c) {
43274                         return -1;
43275                 }
43276 -               
43277 +
43278                 /* check port */
43279                 if (*(c+1) == ':') {
43280                         for (c += 2; *c; c++) {
43281 @@ -69,39 +71,39 @@
43282                 }
43283                 return 0;
43284         }
43285 -       
43286 +
43287         if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
43288                 char *c = colon + 1;
43289 -               
43290 +
43291                 /* check portnumber */
43292                 for (; *c; c++) {
43293                         if (!light_isdigit(*c)) return -1;
43294                 }
43295 -               
43296 +
43297                 /* remove the port from the host-len */
43298                 host_len = colon - host->ptr;
43299         }
43300 -       
43301 +
43302         /* Host is empty */
43303         if (host_len == 0) return -1;
43304 -       
43305 +
43306         /* scan from the right and skip the \0 */
43307         for (i = host_len - 1; i + 1 > 0; i--) {
43308                 const char c = host->ptr[i];
43309  
43310                 switch (stage) {
43311 -               case TOPLABEL: 
43312 +               case TOPLABEL:
43313                         if (c == '.') {
43314                                 /* only switch stage, if this is not the last character */
43315                                 if (i != host_len - 1) {
43316                                         if (label_len == 0) {
43317                                                 return -1;
43318                                         }
43319 -                                       
43320 +
43321                                         /* check the first character at right of the dot */
43322                                         if (is_ip == 0) {
43323                                                 if (!light_isalpha(host->ptr[i+1])) {
43324 -                                                       return -1; 
43325 +                                                       return -1;
43326                                                 }
43327                                         } else if (!light_isdigit(host->ptr[i+1])) {
43328                                                 is_ip = 0;
43329 @@ -111,9 +113,9 @@
43330                                                 /* just digits */
43331                                                 is_ip = 1;
43332                                         }
43333 -                                               
43334 +
43335                                         stage = DOMAINLABEL;
43336 -                                       
43337 +
43338                                         label_len = 0;
43339                                         level++;
43340                                 } else if (i == 0) {
43341 @@ -135,7 +137,7 @@
43342                                 }
43343                                 label_len++;
43344                         }
43345 -                       
43346 +
43347                         break;
43348                 case DOMAINLABEL:
43349                         if (is_ip == 1) {
43350 @@ -143,7 +145,7 @@
43351                                         if (label_len == 0) {
43352                                                 return -1;
43353                                         }
43354 -                                       
43355 +
43356                                         label_len = 0;
43357                                         level++;
43358                                 } else if (!light_isdigit(c)) {
43359 @@ -156,12 +158,12 @@
43360                                         if (label_len == 0) {
43361                                                 return -1;
43362                                         }
43363 -                                       
43364 +
43365                                         /* c is either - or alphanum here */
43366                                         if ('-' == host->ptr[i+1]) {
43367                                                 return -1;
43368                                         }
43369 -                                       
43370 +
43371                                         label_len = 0;
43372                                         level++;
43373                                 } else if (i == 0) {
43374 @@ -176,20 +178,20 @@
43375                                         label_len++;
43376                                 }
43377                         }
43378 -                       
43379 +
43380                         break;
43381                 }
43382         }
43383 -       
43384 +
43385         /* a IP has to consist of 4 parts */
43386         if (is_ip == 1 && level != 3) {
43387                 return -1;
43388         }
43389 -       
43390 +
43391         if (label_len == 0) {
43392                 return -1;
43393         }
43394 -       
43395 +
43396         return 0;
43397  }
43398  
43399 @@ -201,53 +203,53 @@
43400         char *s;
43401         size_t i;
43402         int state = 0;
43403 -       /*  
43404 -        * parse 
43405 -        * 
43406 +       /*
43407 +        * parse
43408 +        *
43409          * val1, val2, val3, val4
43410 -        * 
43411 +        *
43412          * into a array (more or less a explode() incl. striping of whitespaces
43413          */
43414 -       
43415 +
43416         if (b->used == 0) return 0;
43417 -       
43418 +
43419         s = b->ptr;
43420 -       
43421 +
43422         for (i =0; i < b->used - 1; ) {
43423                 char *start = NULL, *end = NULL;
43424                 data_string *ds;
43425 -               
43426 +
43427                 switch (state) {
43428                 case 0: /* ws */
43429 -                       
43430 +
43431                         /* skip ws */
43432                         for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
43433 -                       
43434 -                       
43435 +
43436 +
43437                         state = 1;
43438                         break;
43439                 case 1: /* value */
43440                         start = s;
43441 -                       
43442 +
43443                         for (; *s != ',' && i < b->used - 1; i++, s++);
43444                         end = s - 1;
43445 -                       
43446 +
43447                         for (; (*end == ' ' || *end == '\t') && end > start; end--);
43448 -                       
43449 +
43450                         if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
43451                                 ds = data_string_init();
43452                         }
43453  
43454                         buffer_copy_string_len(ds->value, start, end-start+1);
43455                         array_insert_unique(vals, (data_unset *)ds);
43456 -                       
43457 +
43458                         if (*s == ',') {
43459                                 state = 0;
43460                                 i++;
43461                                 s++;
43462                         } else {
43463                                 /* end of string */
43464 -                               
43465 +
43466                                 state = 2;
43467                         }
43468                         break;
43469 @@ -263,7 +265,7 @@
43470         if (c <= 32) return 0;
43471         if (c == 127) return 0;
43472         if (c == 255) return 0;
43473 -       
43474 +
43475         return 1;
43476  }
43477  
43478 @@ -271,28 +273,28 @@
43479         char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
43480         int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
43481         char *value = NULL, *key = NULL;
43482 -       
43483 +
43484         enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
43485 -       
43486 +
43487         int line = 0;
43488 -       
43489 +
43490         int request_line_stage = 0;
43491         size_t i, first;
43492 -       
43493 +
43494         int done = 0;
43495 -       
43496 +
43497         data_string *ds = NULL;
43498 -       
43499 -       /* 
43500 -        * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$" 
43501 -        * Option : "^([-a-zA-Z]+): (.+)$"                    
43502 +
43503 +       /*
43504 +        * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43505 +        * Option : "^([-a-zA-Z]+): (.+)$"
43506          * End    : "^$"
43507          */
43508  
43509         if (con->conf.log_request_header) {
43510 -               log_error_write(srv, __FILE__, __LINE__, "sdsdSb", 
43511 -                               "fd:", con->fd, 
43512 -                               "request-len:", con->request.request->used, 
43513 +               log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43514 +                               "fd:", con->fd,
43515 +                               "request-len:", con->request.request->used,
43516                                 "\n", con->request.request);
43517         }
43518  
43519 @@ -300,13 +302,13 @@
43520             con->request.request->ptr[0] == '\r' &&
43521             con->request.request->ptr[1] == '\n') {
43522                 /* we are in keep-alive and might get \r\n after a previous POST request.*/
43523 -               
43524 +
43525                 buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
43526         } else {
43527                 /* fill the local request buffer */
43528                 buffer_copy_string_buffer(con->parse_request, con->request.request);
43529         }
43530 -       
43531 +
43532         keep_alive_set = 0;
43533         con_length_set = 0;
43534  
43535 @@ -318,25 +320,25 @@
43536          * */
43537         for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
43538                 char *cur = con->parse_request->ptr + i;
43539 -               
43540 +
43541                 switch(*cur) {
43542 -               case '\r': 
43543 +               case '\r':
43544                         if (con->parse_request->ptr[i+1] == '\n') {
43545                                 http_method_t r;
43546                                 char *nuri = NULL;
43547                                 size_t j;
43548 -                               
43549 +
43550                                 /* \r\n -> \0\0 */
43551                                 con->parse_request->ptr[i] = '\0';
43552                                 con->parse_request->ptr[i+1] = '\0';
43553 -                               
43554 +
43555                                 buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
43556 -                               
43557 +
43558                                 if (request_line_stage != 2) {
43559                                         con->http_status = 400;
43560                                         con->response.keep_alive = 0;
43561                                         con->keep_alive = 0;
43562 -                                       
43563 +
43564                                         if (srv->srvconf.log_request_header_on_error) {
43565                                                 log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
43566                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
43567 @@ -345,36 +347,36 @@
43568                                         }
43569                                         return 0;
43570                                 }
43571 -                               
43572 +
43573                                 proto = con->parse_request->ptr + first;
43574 -                               
43575 +
43576                                 *(uri - 1) = '\0';
43577                                 *(proto - 1) = '\0';
43578 -                               
43579 +
43580                                 /* we got the first one :) */
43581                                 if (-1 == (r = get_http_method_key(method))) {
43582                                         con->http_status = 501;
43583                                         con->response.keep_alive = 0;
43584                                         con->keep_alive = 0;
43585 -                                       
43586 +
43587                                         if (srv->srvconf.log_request_header_on_error) {
43588                                                 log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
43589                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
43590                                                                 "request-header:\n",
43591                                                                 con->request.request);
43592                                         }
43593 -                               
43594 +
43595                                         return 0;
43596                                 }
43597 -                               
43598 +
43599                                 con->request.http_method = r;
43600 -                       
43601 -                               /* 
43602 +
43603 +                               /*
43604                                  * RFC2616 says:
43605                                  *
43606                                  * HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
43607                                  *
43608 -                                * */   
43609 +                                * */
43610                                 if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
43611                                         char * major = proto + sizeof("HTTP/") - 1;
43612                                         char * minor = strchr(major, '.');
43613 @@ -413,10 +415,10 @@
43614                                         }
43615  
43616                                         if (major_num == 1 && minor_num == 1) {
43617 -                                               con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
43618 +                                               con->request.http_version = HTTP_VERSION_1_1;
43619                                         } else if (major_num == 1 && minor_num == 0) {
43620                                                 con->request.http_version = HTTP_VERSION_1_0;
43621 -                                       } else { 
43622 +                                       } else {
43623                                                 con->http_status = 505;
43624  
43625                                                 if (srv->srvconf.log_request_header_on_error) {
43626 @@ -439,30 +441,30 @@
43627                                         }
43628                                         return 0;
43629                                 }
43630 -                               
43631 +
43632                                 if (0 == strncmp(uri, "http://", 7) &&
43633                                     NULL != (nuri = strchr(uri + 7, '/'))) {
43634                                         /* ignore the host-part */
43635 -                                       
43636 +
43637                                         buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
43638                                 } else {
43639                                         /* everything looks good so far */
43640                                         buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
43641                                 }
43642 -                               
43643 +
43644                                 /* check uri for invalid characters */
43645                                 for (j = 0; j < con->request.uri->used - 1; j++) {
43646                                         if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
43647                                                 unsigned char buf[2];
43648                                                 con->http_status = 400;
43649                                                 con->keep_alive = 0;
43650 -                                               
43651 +
43652                                                 if (srv->srvconf.log_request_header_on_error) {
43653                                                         buf[0] = con->request.uri->ptr[j];
43654                                                         buf[1] = '\0';
43655 -                                       
43656 +
43657                                                         if (con->request.uri->ptr[j] > 32 &&
43658 -                                                           con->request.uri->ptr[j] != 127) {  
43659 +                                                           con->request.uri->ptr[j] != 127) {
43660                                                                 /* the character is printable -> print it */
43661                                                                 log_error_write(srv, __FILE__, __LINE__, "ss",
43662                                                                                 "invalid character in URI -> 400",
43663 @@ -473,20 +475,20 @@
43664                                                                                 "invalid character in URI -> 400",
43665                                                                                 con->request.uri->ptr[j]);
43666                                                         }
43667 -                                               
43668 +
43669                                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43670                                                                         "request-header:\n",
43671                                                                         con->request.request);
43672                                                 }
43673 -                                               
43674 +
43675                                                 return 0;
43676                                         }
43677                                 }
43678 -                               
43679 +
43680                                 buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
43681 -                               
43682 +
43683                                 con->http_status = 0;
43684 -                               
43685 +
43686                                 i++;
43687                                 line++;
43688                                 first = i+1;
43689 @@ -494,14 +496,14 @@
43690                         break;
43691                 case ' ':
43692                         switch(request_line_stage) {
43693 -                       case 0: 
43694 +                       case 0:
43695                                 /* GET|POST|... */
43696 -                               method = con->parse_request->ptr + first; 
43697 +                               method = con->parse_request->ptr + first;
43698                                 first = i + 1;
43699                                 break;
43700                         case 1:
43701                                 /* /foobar/... */
43702 -                               uri = con->parse_request->ptr + first; 
43703 +                               uri = con->parse_request->ptr + first;
43704                                 first = i + 1;
43705                                 break;
43706                         default:
43707 @@ -509,7 +511,7 @@
43708                                 con->http_status = 400;
43709                                 con->response.keep_alive = 0;
43710                                 con->keep_alive = 0;
43711 -                               
43712 +
43713                                 if (srv->srvconf.log_request_header_on_error) {
43714                                         log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
43715                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43716 @@ -518,12 +520,12 @@
43717                                 }
43718                                 return 0;
43719                         }
43720 -                       
43721 +
43722                         request_line_stage++;
43723                         break;
43724                 }
43725         }
43726 -       
43727 +
43728         in_folding = 0;
43729  
43730         if (con->request.uri->used == 1) {
43731 @@ -540,30 +542,30 @@
43732                 return 0;
43733         }
43734  
43735 -       
43736 +
43737         for (; i < con->parse_request->used && !done; i++) {
43738                 char *cur = con->parse_request->ptr + i;
43739 -               
43740 +
43741                 if (is_key) {
43742                         size_t j;
43743                         int got_colon = 0;
43744 -                       
43745 +
43746                         /**
43747                          * 1*<any CHAR except CTLs or separators>
43748                          * CTLs == 0-31 + 127
43749 -                        * 
43750 +                        *
43751                          */
43752                         switch(*cur) {
43753                         case ':':
43754                                 is_key = 0;
43755 -                               
43756 +
43757                                 value = cur + 1;
43758 -                               
43759 +
43760                                 if (is_ws_after_key == 0) {
43761                                         key_len = i - first;
43762                                 }
43763                                 is_ws_after_key = 0;
43764 -                                       
43765 +
43766                                 break;
43767                         case '(':
43768                         case ')':
43769 @@ -584,8 +586,8 @@
43770                                 con->http_status = 400;
43771                                 con->keep_alive = 0;
43772                                 con->response.keep_alive = 0;
43773 -                               
43774 -                               log_error_write(srv, __FILE__, __LINE__, "sbsds", 
43775 +
43776 +                               log_error_write(srv, __FILE__, __LINE__, "sbsds",
43777                                                 "invalid character in key", con->request.request, cur, *cur, "-> 400");
43778                                 return 0;
43779                         case ' ':
43780 @@ -594,13 +596,13 @@
43781                                         is_key = 0;
43782                                         in_folding = 1;
43783                                         value = cur;
43784 -                                       
43785 +
43786                                         break;
43787                                 }
43788 -                               
43789 -                               
43790 +
43791 +
43792                                 key_len = i - first;
43793 -                               
43794 +
43795                                 /* skip every thing up to the : */
43796                                 for (j = 1; !got_colon; j++) {
43797                                         switch(con->parse_request->ptr[j + i]) {
43798 @@ -610,40 +612,40 @@
43799                                                 continue;
43800                                         case ':':
43801                                                 /* ok, done */
43802 -                                               
43803 +
43804                                                 i += j - 1;
43805                                                 got_colon = 1;
43806 -                                               
43807 +
43808                                                 break;
43809                                         default:
43810                                                 /* error */
43811 -                                               
43812 +
43813                                                 if (srv->srvconf.log_request_header_on_error) {
43814                                                         log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
43815                                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43816                                                                 "request-header:\n",
43817                                                                 con->request.request);
43818                                                 }
43819 -                                       
43820 +
43821                                                 con->http_status = 400;
43822                                                 con->response.keep_alive = 0;
43823                                                 con->keep_alive = 0;
43824 -                                               
43825 +
43826                                                 return 0;
43827                                         }
43828                                 }
43829 -                               
43830 +
43831                                 break;
43832                         case '\r':
43833                                 if (con->parse_request->ptr[i+1] == '\n' && i == first) {
43834                                         /* End of Header */
43835                                         con->parse_request->ptr[i] = '\0';
43836                                         con->parse_request->ptr[i+1] = '\0';
43837 -                                       
43838 +
43839                                         i++;
43840 -                                       
43841 +
43842                                         done = 1;
43843 -                                       
43844 +
43845                                         break;
43846                                 } else {
43847                                         if (srv->srvconf.log_request_header_on_error) {
43848 @@ -652,7 +654,7 @@
43849                                                         "request-header:\n",
43850                                                         con->request.request);
43851                                         }
43852 -                                       
43853 +
43854                                         con->http_status = 400;
43855                                         con->keep_alive = 0;
43856                                         con->response.keep_alive = 0;
43857 @@ -693,16 +695,16 @@
43858                                 con->http_status = 400;
43859                                 con->keep_alive = 0;
43860                                 con->response.keep_alive = 0;
43861 -                               
43862 +
43863                                 if (srv->srvconf.log_request_header_on_error) {
43864 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsds", 
43865 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsds",
43866                                                 "CTL character in key", con->request.request, cur, *cur, "-> 400");
43867  
43868                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43869                                                 "request-header:\n",
43870                                                 con->request.request);
43871                                 }
43872 -                               
43873 +
43874                                 return 0;
43875                         default:
43876                                 /* ok */
43877 @@ -710,25 +712,25 @@
43878                         }
43879                 } else {
43880                         switch(*cur) {
43881 -                       case '\r': 
43882 +                       case '\r':
43883                                 if (con->parse_request->ptr[i+1] == '\n') {
43884                                         /* End of Headerline */
43885                                         con->parse_request->ptr[i] = '\0';
43886                                         con->parse_request->ptr[i+1] = '\0';
43887 -                                       
43888 +
43889                                         if (in_folding) {
43890                                                 if (!ds) {
43891                                                         /* 400 */
43892 -                                       
43893 +
43894                                                         if (srv->srvconf.log_request_header_on_error) {
43895                                                                 log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
43896 -                                                       
43897 +
43898                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
43899                                                                         "request-header:\n",
43900                                                                         con->request.request);
43901                                                         }
43902  
43903 -                                       
43904 +
43905                                                         con->http_status = 400;
43906                                                         con->keep_alive = 0;
43907                                                         con->response.keep_alive = 0;
43908 @@ -738,9 +740,9 @@
43909                                         } else {
43910                                                 int s_len;
43911                                                 key = con->parse_request->ptr + first;
43912 -                                       
43913 +
43914                                                 s_len = cur - value;
43915 -                                               
43916 +
43917                                                 if (s_len > 0) {
43918                                                         int cmp = 0;
43919                                                         if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
43920 @@ -748,86 +750,87 @@
43921                                                         }
43922                                                         buffer_copy_string_len(ds->key, key, key_len);
43923                                                         buffer_copy_string_len(ds->value, value, s_len);
43924 -                                                       
43925 -                                                       /* retreive values 
43926 -                                                        * 
43927 -                                                        * 
43928 +
43929 +                                                       /* retreive values
43930 +                                                        *
43931 +                                                        *
43932                                                          * the list of options is sorted to simplify the search
43933                                                          */
43934 -                                                       
43935 +
43936                                                         if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
43937                                                                 array *vals;
43938                                                                 size_t vi;
43939 -                                                               
43940 +
43941                                                                 /* split on , */
43942 -                                                               
43943 +
43944                                                                 vals = srv->split_vals;
43945  
43946                                                                 array_reset(vals);
43947 -                                                               
43948 +
43949                                                                 http_request_split_value(vals, ds->value);
43950 -                                                               
43951 +
43952                                                                 for (vi = 0; vi < vals->used; vi++) {
43953                                                                         data_string *dsv = (data_string *)vals->data[vi];
43954 -                                                                       
43955 +
43956                                                                         if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
43957                                                                                 keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
43958 -                                                                               
43959 +
43960                                                                                 break;
43961                                                                         } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
43962                                                                                 keep_alive_set = HTTP_CONNECTION_CLOSE;
43963 -                                                                               
43964 +
43965                                                                                 break;
43966                                                                         }
43967                                                                 }
43968 -                                                               
43969 +
43970                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
43971                                                                 char *err;
43972                                                                 unsigned long int r;
43973                                                                 size_t j;
43974 -                                                               
43975 +
43976                                                                 if (con_length_set) {
43977                                                                         con->http_status = 400;
43978                                                                         con->keep_alive = 0;
43979 -                                                                       
43980 +
43981                                                                         if (srv->srvconf.log_request_header_on_error) {
43982 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
43983 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
43984                                                                                                 "duplicate Content-Length-header -> 400");
43985                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
43986                                                                                                 "request-header:\n",
43987                                                                                                 con->request.request);
43988                                                                         }
43989 +                                                                       ds->free((data_unset *) ds);
43990                                                                         return 0;
43991                                                                 }
43992 -                                                               
43993 +
43994                                                                 if (ds->value->used == 0) SEGFAULT();
43995 -                                                               
43996 +
43997                                                                 for (j = 0; j < ds->value->used - 1; j++) {
43998                                                                         char c = ds->value->ptr[j];
43999                                                                         if (!isdigit((unsigned char)c)) {
44000 -                                                                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
44001 +                                                                               log_error_write(srv, __FILE__, __LINE__, "sbs",
44002                                                                                                 "content-length broken:", ds->value, "-> 400");
44003 -                                                                               
44004 +
44005                                                                                 con->http_status = 400;
44006                                                                                 con->keep_alive = 0;
44007 -                                                                               
44008 +
44009                                                                                 array_insert_unique(con->request.headers, (data_unset *)ds);
44010                                                                                 return 0;
44011                                                                         }
44012                                                                 }
44013 -                                                               
44014 +
44015                                                                 r = strtoul(ds->value->ptr, &err, 10);
44016 -                                                               
44017 +
44018                                                                 if (*err == '\0') {
44019                                                                         con_length_set = 1;
44020                                                                         con->request.content_length = r;
44021                                                                 } else {
44022 -                                                                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
44023 +                                                                       log_error_write(srv, __FILE__, __LINE__, "sbs",
44024                                                                                         "content-length broken:", ds->value, "-> 400");
44025 -                                                                       
44026 +
44027                                                                         con->http_status = 400;
44028                                                                         con->keep_alive = 0;
44029 -                                                                       
44030 +
44031                                                                         array_insert_unique(con->request.headers, (data_unset *)ds);
44032                                                                         return 0;
44033                                                                 }
44034 @@ -838,23 +841,24 @@
44035                                                                 } else {
44036                                                                         con->http_status = 400;
44037                                                                         con->keep_alive = 0;
44038 -                                                                       
44039 +
44040                                                                         if (srv->srvconf.log_request_header_on_error) {
44041 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44042 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44043                                                                                                 "duplicate Content-Type-header -> 400");
44044                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44045                                                                                                 "request-header:\n",
44046                                                                                                 con->request.request);
44047                                                                         }
44048 +                                                                       ds->free((data_unset *) ds);
44049                                                                         return 0;
44050                                                                 }
44051                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
44052 -                                                               /* HTTP 2616 8.2.3 
44053 +                                                               /* HTTP 2616 8.2.3
44054                                                                  * Expect: 100-continue
44055 -                                                                * 
44056 +                                                                *
44057                                                                  *   -> (10.1.1)  100 (read content, process request, send final status-code)
44058                                                                  *   -> (10.4.18) 417 (close)
44059 -                                                                * 
44060 +                                                                *
44061                                                                  * (not handled at all yet, we always send 417 here)
44062                                                                  *
44063                                                                  * What has to be added ?
44064 @@ -863,10 +867,10 @@
44065                                                                  *    header
44066                                                                  *
44067                                                                  */
44068 -                                                               
44069 +
44070                                                                 con->http_status = 417;
44071                                                                 con->keep_alive = 0;
44072 -                                                               
44073 +
44074                                                                 array_insert_unique(con->request.headers, (data_unset *)ds);
44075                                                                 return 0;
44076                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
44077 @@ -875,14 +879,15 @@
44078                                                                 } else {
44079                                                                         con->http_status = 400;
44080                                                                         con->keep_alive = 0;
44081 -                                                                       
44082 +
44083                                                                         if (srv->srvconf.log_request_header_on_error) {
44084 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44085 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44086                                                                                                 "duplicate Host-header -> 400");
44087                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44088                                                                                                 "request-header:\n",
44089                                                                                                 con->request.request);
44090                                                                         }
44091 +                                                                       ds->free((data_unset *) ds);
44092                                                                         return 0;
44093                                                                 }
44094                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
44095 @@ -897,14 +902,15 @@
44096                                                                 } else {
44097                                                                         con->http_status = 400;
44098                                                                         con->keep_alive = 0;
44099 -                                                                       
44100 +
44101                                                                         if (srv->srvconf.log_request_header_on_error) {
44102 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44103 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44104                                                                                                 "duplicate If-Modified-Since header -> 400");
44105                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44106                                                                                                 "request-header:\n",
44107                                                                                                 con->request.request);
44108                                                                         }
44109 +                                                                       ds->free((data_unset *) ds);
44110                                                                         return 0;
44111                                                                 }
44112                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
44113 @@ -914,47 +920,49 @@
44114                                                                 } else {
44115                                                                         con->http_status = 400;
44116                                                                         con->keep_alive = 0;
44117 -                                                                       
44118 +
44119                                                                         if (srv->srvconf.log_request_header_on_error) {
44120 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44121 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44122                                                                                                 "duplicate If-None-Match-header -> 400");
44123                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44124                                                                                                 "request-header:\n",
44125                                                                                                 con->request.request);
44126                                                                         }
44127 +                                                                       ds->free((data_unset *) ds);
44128                                                                         return 0;
44129                                                                 }
44130                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
44131                                                                 if (!con->request.http_range) {
44132                                                                         /* bytes=.*-.* */
44133 -                                                               
44134 +
44135                                                                         if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
44136                                                                             NULL != strchr(ds->value->ptr+6, '-')) {
44137 -                                                                               
44138 +
44139                                                                                 /* if dup, only the first one will survive */
44140                                                                                 con->request.http_range = ds->value->ptr + 6;
44141                                                                         }
44142                                                                 } else {
44143                                                                         con->http_status = 400;
44144                                                                         con->keep_alive = 0;
44145 -                                                                       
44146 +
44147                                                                         if (srv->srvconf.log_request_header_on_error) {
44148 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44149 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44150                                                                                                 "duplicate Range-header -> 400");
44151                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44152                                                                                                 "request-header:\n",
44153                                                                                                 con->request.request);
44154                                                                         }
44155 +                                                                       ds->free((data_unset *) ds);
44156                                                                         return 0;
44157                                                                 }
44158                                                         }
44159 -                                                       
44160 +
44161                                                         array_insert_unique(con->request.headers, (data_unset *)ds);
44162                                                 } else {
44163                                                         /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
44164                                                 }
44165                                         }
44166 -                                       
44167 +
44168                                         i++;
44169                                         first = i+1;
44170                                         is_key = 1;
44171 @@ -963,10 +971,10 @@
44172                                         in_folding = 0;
44173                                 } else {
44174                                         if (srv->srvconf.log_request_header_on_error) {
44175 -                                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
44176 +                                               log_error_write(srv, __FILE__, __LINE__, "sbs",
44177                                                                 "CR without LF", con->request.request, "-> 400");
44178                                         }
44179 -                                       
44180 +
44181                                         con->http_status = 400;
44182                                         con->keep_alive = 0;
44183                                         con->response.keep_alive = 0;
44184 @@ -982,28 +990,28 @@
44185                         }
44186                 }
44187         }
44188 -       
44189 +
44190         con->header_len = i;
44191 -       
44192 +
44193         /* do some post-processing */
44194  
44195         if (con->request.http_version == HTTP_VERSION_1_1) {
44196                 if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
44197                         /* no Connection-Header sent */
44198 -                       
44199 +
44200                         /* HTTP/1.1 -> keep-alive default TRUE */
44201                         con->keep_alive = 1;
44202                 } else {
44203                         con->keep_alive = 0;
44204                 }
44205 -               
44206 +
44207                 /* RFC 2616, 14.23 */
44208                 if (con->request.http_host == NULL ||
44209                     buffer_is_empty(con->request.http_host)) {
44210                         con->http_status = 400;
44211                         con->response.keep_alive = 0;
44212                         con->keep_alive = 0;
44213 -                       
44214 +
44215                         if (srv->srvconf.log_request_header_on_error) {
44216                                 log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
44217                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44218 @@ -1015,18 +1023,18 @@
44219         } else {
44220                 if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
44221                         /* no Connection-Header sent */
44222 -                       
44223 +
44224                         /* HTTP/1.0 -> keep-alive default FALSE  */
44225                         con->keep_alive = 1;
44226                 } else {
44227                         con->keep_alive = 0;
44228                 }
44229         }
44230 -       
44231 +
44232         /* check hostname field if it is set */
44233         if (NULL != con->request.http_host &&
44234             0 != request_check_hostname(srv, con, con->request.http_host)) {
44235 -               
44236 +
44237                 if (srv->srvconf.log_request_header_on_error) {
44238                         log_error_write(srv, __FILE__, __LINE__, "s",
44239                                         "Invalid Hostname -> 400");
44240 @@ -1038,7 +1046,7 @@
44241                 con->http_status = 400;
44242                 con->response.keep_alive = 0;
44243                 con->keep_alive = 0;
44244 -               
44245 +
44246                 return 0;
44247         }
44248  
44249 @@ -1048,7 +1056,7 @@
44250                 /* content-length is forbidden for those */
44251                 if (con_length_set && con->request.content_length != 0) {
44252                         /* content-length is missing */
44253 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
44254 +                       log_error_write(srv, __FILE__, __LINE__, "s",
44255                                         "GET/HEAD with content-length -> 400");
44256  
44257                         con->keep_alive = 0;
44258 @@ -1060,7 +1068,7 @@
44259                 /* content-length is required for them */
44260                 if (!con_length_set) {
44261                         /* content-length is missing */
44262 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
44263 +                       log_error_write(srv, __FILE__, __LINE__, "s",
44264                                         "POST-request, but content-length missing -> 411");
44265  
44266                         con->keep_alive = 0;
44267 @@ -1073,16 +1081,16 @@
44268                 /* the may have a content-length */
44269                 break;
44270         }
44271 -                       
44272 -       
44273 +
44274 +
44275         /* check if we have read post data */
44276         if (con_length_set) {
44277                 /* don't handle more the SSIZE_MAX bytes in content-length */
44278                 if (con->request.content_length > SSIZE_MAX) {
44279 -                       con->http_status = 413; 
44280 +                       con->http_status = 413;
44281                         con->keep_alive = 0;
44282  
44283 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
44284 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
44285                                         "request-size too long:", con->request.content_length, "-> 413");
44286                         return 0;
44287                 }
44288 @@ -1090,25 +1098,25 @@
44289                 /* divide by 1024 as srvconf.max_request_size is in kBytes */
44290                 if (srv->srvconf.max_request_size != 0 &&
44291                     (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
44292 -                       /* the request body itself is larger then 
44293 +                       /* the request body itself is larger then
44294                          * our our max_request_size
44295                          */
44296 -               
44297 +
44298                         con->http_status = 413;
44299                         con->keep_alive = 0;
44300 -               
44301 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
44302 +
44303 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
44304                                         "request-size too long:", con->request.content_length, "-> 413");
44305                         return 0;
44306                 }
44307 -               
44308 -               
44309 +
44310 +
44311                 /* we have content */
44312                 if (con->request.content_length != 0) {
44313                         return 1;
44314                 }
44315         }
44316 -       
44317 +
44318         return 0;
44319  }
44320  
44321 @@ -1116,9 +1124,9 @@
44322         UNUSED(srv);
44323  
44324         if (con->request.request->used < 5) return 0;
44325 -       
44326 +
44327         if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
44328         if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
44329 -       
44330 +
44331         return 0;
44332  }
44333 --- ../lighttpd-1.4.11/src/response.c   2006-03-04 16:41:39.000000000 +0200
44334 +++ lighttpd-1.4.12/src/response.c      2006-07-11 22:07:52.000000000 +0300
44335 @@ -7,7 +7,6 @@
44336  #include <stdlib.h>
44337  #include <string.h>
44338  #include <time.h>
44339 -#include <unistd.h>
44340  #include <ctype.h>
44341  #include <assert.h>
44342  
44343 @@ -24,15 +23,17 @@
44344  #include "plugin.h"
44345  
44346  #include "sys-socket.h"
44347 +#include "sys-files.h"
44348 +#include "sys-strings.h"
44349  
44350  int http_response_write_header(server *srv, connection *con) {
44351         buffer *b;
44352         size_t i;
44353         int have_date = 0;
44354         int have_server = 0;
44355 -       
44356 +
44357         b = chunkqueue_get_prepend_buffer(con->write_queue);
44358 -       
44359 +
44360         if (con->request.http_version == HTTP_VERSION_1_1) {
44361                 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
44362         } else {
44363 @@ -41,25 +42,26 @@
44364         buffer_append_long(b, con->http_status);
44365         BUFFER_APPEND_STRING_CONST(b, " ");
44366         buffer_append_string(b, get_http_status_name(con->http_status));
44367 -       
44368 +
44369         if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
44370                 BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
44371                 buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
44372         }
44373 -       
44374 +
44375         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
44376                 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
44377         }
44378 -       
44379 -       
44380 +
44381 +
44382         /* add all headers */
44383         for (i = 0; i < con->response.headers->used; i++) {
44384                 data_string *ds;
44385 -               
44386 +
44387                 ds = (data_string *)con->response.headers->data[i];
44388 -               
44389 +
44390                 if (ds->value->used && ds->key->used &&
44391 -                   0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
44392 +                   0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
44393 +                   0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
44394                         if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
44395                         if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
44396  
44397 @@ -68,28 +70,28 @@
44398                         BUFFER_APPEND_STRING_CONST(b, ": ");
44399                         buffer_append_string_buffer(b, ds->value);
44400  #if 0
44401 -                       log_error_write(srv, __FILE__, __LINE__, "bb", 
44402 +                       log_error_write(srv, __FILE__, __LINE__, "bb",
44403                                         ds->key, ds->value);
44404  #endif
44405                 }
44406         }
44407 -       
44408 +
44409         if (!have_date) {
44410                 /* HTTP/1.1 requires a Date: header */
44411                 BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
44412 -       
44413 +
44414                 /* cache the generated timestamp */
44415                 if (srv->cur_ts != srv->last_generated_date_ts) {
44416                         buffer_prepare_copy(srv->ts_date_str, 255);
44417 -               
44418 -                       strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1, 
44419 +
44420 +                       strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
44421                                  "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
44422 -                        
44423 +
44424                         srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
44425 -               
44426 +
44427                         srv->last_generated_date_ts = srv->cur_ts;
44428                 }
44429 -       
44430 +
44431                 buffer_append_string_buffer(b, srv->ts_date_str);
44432         }
44433  
44434 @@ -101,16 +103,16 @@
44435                         buffer_append_string_buffer(b, con->conf.server_tag);
44436                 }
44437         }
44438 -       
44439 +
44440         BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
44441 -       
44442 -       
44443 +
44444 +
44445         con->bytes_header = b->used - 1;
44446 -       
44447 +
44448         if (con->conf.log_response_header) {
44449                 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
44450         }
44451 -       
44452 +
44453         return 0;
44454  }
44455  
44456 @@ -118,71 +120,71 @@
44457  
44458  handler_t http_response_prepare(server *srv, connection *con) {
44459         handler_t r;
44460 -       
44461 -       /* looks like someone has already done a decision */
44462 -       if (con->mode == DIRECT && 
44463 +
44464 +       /* looks like someone has already made a decision */
44465 +       if (con->mode == DIRECT &&
44466             (con->http_status != 0 && con->http_status != 200)) {
44467                 /* remove a packets in the queue */
44468                 if (con->file_finished == 0) {
44469                         chunkqueue_reset(con->write_queue);
44470                 }
44471 -               
44472 +
44473                 return HANDLER_FINISHED;
44474         }
44475 -       
44476 +
44477         /* no decision yet, build conf->filename */
44478         if (con->mode == DIRECT && con->physical.path->used == 0) {
44479                 char *qstr;
44480  
44481 -               /* we only come here when we have the parse the full request again
44482 -                * 
44483 -                * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a 
44484 +               /* we only come here when we have to parse the full request again
44485 +                *
44486 +                * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44487                  * problem here as mod_setenv might get called multiple times
44488                  *
44489                  * fastcgi-auth might lead to a COMEBACK too
44490                  * fastcgi again dead server too
44491                  *
44492                  * mod_compress might add headers twice too
44493 -                * 
44494 +                *
44495                  *  */
44496 -               
44497 +
44498                 if (con->conf.log_condition_handling) {
44499                         log_error_write(srv, __FILE__, __LINE__,  "s",  "run condition");
44500                 }
44501                 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
44502 -               
44503 +
44504                 /**
44505                  * prepare strings
44506 -                * 
44507 -                * - uri.path_raw 
44508 +                *
44509 +                * - uri.path_raw
44510                  * - uri.path (secure)
44511                  * - uri.query
44512 -                * 
44513 +                *
44514                  */
44515 -               
44516 -               /** 
44517 +
44518 +               /**
44519                  * Name according to RFC 2396
44520 -                * 
44521 +                *
44522                  * - scheme
44523                  * - authority
44524                  * - path
44525                  * - query
44526 -                * 
44527 +                *
44528                  * (scheme)://(authority)(path)?(query)
44529 -                * 
44530 -                * 
44531 +                *
44532 +                *
44533                  */
44534 -       
44535 +
44536                 buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
44537                 buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
44538                 buffer_to_lower(con->uri.authority);
44539 -               
44540 +
44541                 config_patch_connection(srv, con, COMP_HTTP_HOST);      /* Host:        */
44542                 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP);  /* Client-IP */
44543                 config_patch_connection(srv, con, COMP_HTTP_REFERER);   /* Referer:     */
44544                 config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent:  */
44545                 config_patch_connection(srv, con, COMP_HTTP_COOKIE);    /* Cookie:  */
44546 -               
44547 +
44548                 /** extract query string from request.uri */
44549                 if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
44550                         buffer_copy_string    (con->uri.query, qstr + 1);
44551 @@ -200,22 +202,22 @@
44552                         log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-path     : ", con->uri.path_raw);
44553                         log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-query    : ", con->uri.query);
44554                 }
44555 -               
44556 +
44557                 /* disable keep-alive if requested */
44558 -               
44559 +
44560                 if (con->request_count > con->conf.max_keep_alive_requests) {
44561                         con->keep_alive = 0;
44562                 }
44563 -               
44564 -               
44565 +
44566 +
44567                 /**
44568 -                *  
44569 -                * call plugins 
44570 -                * 
44571 +                *
44572 +                * call plugins
44573 +                *
44574                  * - based on the raw URL
44575 -                * 
44576 +                *
44577                  */
44578 -               
44579 +
44580                 switch(r = plugins_call_handle_uri_raw(srv, con)) {
44581                 case HANDLER_GO_ON:
44582                         break;
44583 @@ -229,14 +231,14 @@
44584                         break;
44585                 }
44586  
44587 -               /* build filename 
44588 +               /* build filename
44589                  *
44590                  * - decode url-encodings  (e.g. %20 -> ' ')
44591                  * - remove path-modifiers (e.g. /../)
44592                  */
44593 -               
44594 -               
44595 -               
44596 +
44597 +
44598 +
44599                 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44600                     con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44601                         /* OPTIONS * ... */
44602 @@ -253,15 +255,20 @@
44603                 }
44604  
44605                 /**
44606 -                *  
44607 -                * call plugins 
44608 -                * 
44609 +                *
44610 +                * call plugins
44611 +                *
44612                  * - based on the clean URL
44613 -                * 
44614 +                *
44615                  */
44616 -               
44617 +
44618                 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
44619 -               
44620 +
44621 +               /* do we have to downgrade to 1.0 ? */
44622 +               if (!con->conf.allow_http11) {
44623 +                       con->request.http_version = HTTP_VERSION_1_0;
44624 +               }
44625 +
44626                 switch(r = plugins_call_handle_uri_clean(srv, con)) {
44627                 case HANDLER_GO_ON:
44628                         break;
44629 @@ -274,11 +281,11 @@
44630                         log_error_write(srv, __FILE__, __LINE__, "");
44631                         break;
44632                 }
44633 -               
44634 +
44635                 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44636                     con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44637 -                       /* option requests are handled directly without checking of the path */
44638 -               
44639 +                       /* option requests are handled directly without checking the path */
44640 +
44641                         response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
44642  
44643                         con->http_status = 200;
44644 @@ -288,46 +295,47 @@
44645                 }
44646  
44647                 /***
44648 -                * 
44649 -                * border 
44650 -                * 
44651 +                *
44652 +                * border
44653 +                *
44654                  * logical filename (URI) becomes a physical filename here
44655 -                * 
44656 -                * 
44657 -                * 
44658 +                *
44659 +                *
44660 +                *
44661                  */
44662 -               
44663 -               
44664 -               
44665 -               
44666 +
44667 +
44668 +
44669 +
44670                 /* 1. stat()
44671                  * ... ISREG() -> ok, go on
44672                  * ... ISDIR() -> index-file -> redirect
44673 -                * 
44674 -                * 2. pathinfo() 
44675 +                *
44676 +                * 2. pathinfo()
44677                  * ... ISREG()
44678 -                * 
44679 +                *
44680                  * 3. -> 404
44681 -                * 
44682 +                *
44683                  */
44684 -               
44685 +
44686                 /*
44687                  * SEARCH DOCUMENT ROOT
44688                  */
44689 -               
44690 +
44691                 /* set a default */
44692 -               
44693 +
44694                 buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
44695                 buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
44696 -               
44697 -#if defined(__WIN32) || defined(__CYGWIN__)
44698 -               /* strip dots from the end and spaces
44699 +
44700 +               filename_unix2local(con->physical.rel_path);
44701 +#if defined(_WIN32) || defined(__CYGWIN__)
44702 +               /* strip dots and spaces from the end
44703                  *
44704                  * windows/dos handle those filenames as the same file
44705                  *
44706                  * foo == foo. == foo..... == "foo...   " == "foo..  ./"
44707                  *
44708 -                * This will affect in some cases PATHINFO
44709 +                * This will affect PATHINFO in some cases
44710                  *
44711                  * on native windows we could prepend the filename with \\?\ to circumvent
44712                  * this behaviour. I have no idea how to push this through cygwin
44713 @@ -377,36 +385,41 @@
44714                         log_error_write(srv, __FILE__, __LINE__, "");
44715                         break;
44716                 }
44717 -               
44718 -               /* MacOS X and Windows can't distiguish between upper and lower-case 
44719 -                * 
44720 -                * convert to lower-case
44721 +
44722 +               /* The default Mac OS X and Windows filesystems can't distiguish between
44723 +                * upper- and lowercase, so convert to lowercase
44724                  */
44725                 if (con->conf.force_lowercase_filenames) {
44726                         buffer_to_lower(con->physical.rel_path);
44727                 }
44728  
44729 -               /* the docroot plugins might set the servername, if they don't we take http-host */
44730 +               /* the docroot plugins might set the servername; if they don't we take http-host */
44731                 if (buffer_is_empty(con->server_name)) {
44732                         buffer_copy_string_buffer(con->server_name, con->uri.authority);
44733                 }
44734 -               
44735 -               /** 
44736 -                * create physical filename 
44737 +
44738 +               /**
44739 +                * create physical filename
44740                  * -> physical.path = docroot + rel_path
44741 -                * 
44742 +                *
44743                  */
44744 -               
44745 +
44746                 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
44747 -               BUFFER_APPEND_SLASH(con->physical.path);
44748 +               PATHNAME_APPEND_SLASH(con->physical.path);
44749                 buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
44750                 if (con->physical.rel_path->used &&
44751 -                   con->physical.rel_path->ptr[0] == '/') {
44752 +                   con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
44753                         buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
44754                 } else {
44755                         buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
44756                 }
44757  
44758 +        /* win32: directories can't have a trailing slash */
44759 +        if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
44760 +            con->physical.path->ptr[con->physical.path->used - 2] = '\0';
44761 +            con->physical.path->used--;
44762 +        }
44763 +
44764                 if (con->conf.log_request_handling) {
44765                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- after doc_root");
44766                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Doc-Root     :", con->physical.doc_root);
44767 @@ -426,7 +439,7 @@
44768                         log_error_write(srv, __FILE__, __LINE__, "");
44769                         break;
44770                 }
44771 -               
44772 +
44773                 if (con->conf.log_request_handling) {
44774                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- logical -> physical");
44775                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Doc-Root     :", con->physical.doc_root);
44776 @@ -434,38 +447,38 @@
44777                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44778                 }
44779         }
44780 -       
44781 -       /* 
44782 -        * Noone catched away the file from normal path of execution yet (like mod_access)
44783 -        * 
44784 +
44785 +       /*
44786 +        * No one took the file away from the normal path of execution yet (like mod_access)
44787 +        *
44788          * Go on and check of the file exists at all
44789          */
44790 -       
44791 +
44792         if (con->mode == DIRECT) {
44793                 char *slash = NULL;
44794                 char *pathinfo = NULL;
44795                 int found = 0;
44796                 stat_cache_entry *sce = NULL;
44797 -               
44798 +
44799                 if (con->conf.log_request_handling) {
44800                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling physical path");
44801                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44802                 }
44803 -               
44804 +
44805                 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
44806                         /* file exists */
44807 -                       
44808 +
44809                         if (con->conf.log_request_handling) {
44810                                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- file found");
44811                                 log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44812                         }
44813 -                       
44814 +
44815                         if (S_ISDIR(sce->st.st_mode)) {
44816 -                               if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
44817 +                               if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
44818                                         /* redirect to .../ */
44819 -                                       
44820 +
44821                                         http_response_redirect_to_directory(srv, con);
44822 -                                       
44823 +
44824                                         return HANDLER_FINISHED;
44825                                 }
44826                         } else if (!S_ISREG(sce->st.st_mode)) {
44827 @@ -477,12 +490,12 @@
44828                         switch (errno) {
44829                         case EACCES:
44830                                 con->http_status = 403;
44831 -       
44832 +
44833                                 if (con->conf.log_request_handling) {
44834                                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- access denied");
44835                                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44836                                 }
44837 -                       
44838 +
44839                                 buffer_reset(con->physical.path);
44840                                 return HANDLER_FINISHED;
44841                         case ENOENT:
44842 @@ -499,77 +512,77 @@
44843                                 /* PATH_INFO ! :) */
44844                                 break;
44845                         default:
44846 -                               /* we have no idea what happend. let's tell the user so. */
44847 +                               /* we have no idea what happened, so tell the user. */
44848                                 con->http_status = 500;
44849                                 buffer_reset(con->physical.path);
44850 -                               
44851 +
44852                                 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
44853                                                 "file not found ... or so: ", strerror(errno),
44854                                                 con->uri.path,
44855                                                 "->", con->physical.path);
44856 -                               
44857 +
44858                                 return HANDLER_FINISHED;
44859                         }
44860 -                       
44861 +
44862                         /* not found, perhaps PATHINFO */
44863 -                       
44864 +
44865                         buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
44866 -                       
44867 +
44868                         do {
44869                                 struct stat st;
44870 -                               
44871 +
44872                                 if (slash) {
44873                                         buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
44874                                 } else {
44875                                         buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
44876                                 }
44877 -                               
44878 +
44879                                 if (0 == stat(con->physical.path->ptr, &(st)) &&
44880                                     S_ISREG(st.st_mode)) {
44881                                         found = 1;
44882                                         break;
44883                                 }
44884 -                               
44885 +
44886                                 if (pathinfo != NULL) {
44887                                         *pathinfo = '\0';
44888                                 }
44889                                 slash = strrchr(srv->tmp_buf->ptr, '/');
44890 -                               
44891 +
44892                                 if (pathinfo != NULL) {
44893                                         /* restore '/' */
44894                                         *pathinfo = '/';
44895                                 }
44896 -                               
44897 +
44898                                 if (slash) pathinfo = slash;
44899                         } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
44900 -                       
44901 +
44902                         if (found == 0) {
44903 -                               /* no it really doesn't exists */
44904 +                               /* no, it really doesn't exists */
44905                                 con->http_status = 404;
44906 -                               
44907 +
44908                                 if (con->conf.log_file_not_found) {
44909                                         log_error_write(srv, __FILE__, __LINE__, "sbsb",
44910                                                         "file not found:", con->uri.path,
44911                                                         "->", con->physical.path);
44912                                 }
44913 -                               
44914 +
44915                                 buffer_reset(con->physical.path);
44916 -                               
44917 +
44918                                 return HANDLER_FINISHED;
44919                         }
44920 -                       
44921 +
44922                         /* we have a PATHINFO */
44923                         if (pathinfo) {
44924                                 buffer_copy_string(con->request.pathinfo, pathinfo);
44925 -                               
44926 +
44927                                 /*
44928                                  * shorten uri.path
44929                                  */
44930 -                               
44931 +
44932                                 con->uri.path->used -= strlen(pathinfo);
44933                                 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
44934                         }
44935 -                       
44936 +
44937                         if (con->conf.log_request_handling) {
44938                                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- after pathinfo check");
44939                                 log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44940 @@ -577,12 +590,12 @@
44941                                 log_error_write(srv, __FILE__, __LINE__,  "sb", "Pathinfo     :", con->request.pathinfo);
44942                         }
44943                 }
44944 -               
44945 +
44946                 if (con->conf.log_request_handling) {
44947                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling subrequest");
44948                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44949                 }
44950 -               
44951 +
44952                 /* call the handlers */
44953                 switch(r = plugins_call_handle_subrequest_start(srv, con)) {
44954                 case HANDLER_GO_ON:
44955 @@ -593,32 +606,32 @@
44956                         if (con->conf.log_request_handling) {
44957                                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- subrequest finished");
44958                         }
44959 -                       
44960 -                       /* something strange happend */
44961 +
44962 +                       /* something strange happened */
44963                         return r;
44964                 }
44965 -               
44966 -               /* if we are still here, no one wanted the file, status 403 is ok I think */
44967 -               
44968 +
44969 +               /* if we are still here, no one wanted the file; status 403 is ok I think */
44970 +
44971                 if (con->mode == DIRECT) {
44972                         con->http_status = 403;
44973 -                       
44974 +
44975                         return HANDLER_FINISHED;
44976                 }
44977 -               
44978 +
44979         }
44980 -       
44981 +
44982         switch(r = plugins_call_handle_subrequest(srv, con)) {
44983         case HANDLER_GO_ON:
44984 -               /* request was not handled, looks like we are done */
44985 +               /* request was not handled; looks like we are done */
44986                 return HANDLER_FINISHED;
44987         case HANDLER_FINISHED:
44988                 /* request is finished */
44989         default:
44990 -               /* something strange happend */
44991 +               /* something strange happened */
44992                 return r;
44993         }
44994 -       
44995 +
44996         /* can't happen */
44997         return HANDLER_COMEBACK;
44998  }
44999 --- ../lighttpd-1.4.11/src/server.c     2006-03-04 19:12:17.000000000 +0200
45000 +++ lighttpd-1.4.12/src/server.c        2006-07-11 22:07:53.000000000 +0300
45001 @@ -1,11 +1,9 @@
45002  #include <sys/types.h>
45003 -#include <sys/time.h>
45004  #include <sys/stat.h>
45005  
45006  #include <string.h>
45007  #include <errno.h>
45008  #include <fcntl.h>
45009 -#include <unistd.h>
45010  #include <stdlib.h>
45011  #include <time.h>
45012  #include <signal.h>
45013 @@ -29,9 +27,14 @@
45014  #include "plugin.h"
45015  #include "joblist.h"
45016  #include "network_backends.h"
45017 -
45018 +#ifdef _WIN32
45019 +/* use local getopt implementation */
45020 +# undef HAVE_GETOPT_H
45021 +#endif
45022  #ifdef HAVE_GETOPT_H
45023  #include <getopt.h>
45024 +#else
45025 +#include "getopt.h"
45026  #endif
45027  
45028  #ifdef HAVE_VALGRIND_VALGRIND_H
45029 @@ -60,8 +63,16 @@
45030  /* #define USE_ALARM */
45031  #endif
45032  
45033 +#ifdef _WIN32
45034 +#undef HAVE_SIGNAL
45035 +#endif
45036 +
45037 +#include "sys-files.h"
45038 +#include "sys-process.h"
45039 +
45040  static volatile sig_atomic_t srv_shutdown = 0;
45041  static volatile sig_atomic_t graceful_shutdown = 0;
45042 +static volatile sig_atomic_t graceful_restart = 0;
45043  static volatile sig_atomic_t handle_sig_alarm = 1;
45044  static volatile sig_atomic_t handle_sig_hup = 0;
45045  
45046 @@ -72,9 +83,9 @@
45047  
45048         switch (sig) {
45049         case SIGTERM: srv_shutdown = 1; break;
45050 -       case SIGINT: 
45051 +       case SIGINT:
45052              if (graceful_shutdown) srv_shutdown = 1;
45053 -            else graceful_shutdown = 1; 
45054 +            else graceful_shutdown = 1;
45055  
45056              break;
45057         case SIGALRM: handle_sig_alarm = 1; break;
45058 @@ -86,9 +97,9 @@
45059  static void signal_handler(int sig) {
45060         switch (sig) {
45061         case SIGTERM: srv_shutdown = 1; break;
45062 -       case SIGINT: 
45063 +       case SIGINT:
45064              if (graceful_shutdown) srv_shutdown = 1;
45065 -            else graceful_shutdown = 1; 
45066 +            else graceful_shutdown = 1;
45067  
45068              break;
45069         case SIGALRM: handle_sig_alarm = 1; break;
45070 @@ -110,25 +121,26 @@
45071         signal(SIGTSTP, SIG_IGN);
45072  #endif
45073         if (0 != fork()) exit(0);
45074 -       
45075 +
45076         if (-1 == setsid()) exit(0);
45077  
45078         signal(SIGHUP, SIG_IGN);
45079  
45080         if (0 != fork()) exit(0);
45081 -       
45082 +
45083         if (0 != chdir("/")) exit(0);
45084  }
45085  #endif
45086  
45087  static server *server_init(void) {
45088         int i;
45089 -       
45090 +
45091         server *srv = calloc(1, sizeof(*srv));
45092         assert(srv);
45093 +    srv->max_fds = 1024;
45094  #define CLEAN(x) \
45095         srv->x = buffer_init();
45096 -       
45097 +
45098         CLEAN(response_header);
45099         CLEAN(parse_full_path);
45100         CLEAN(ts_debug_str);
45101 @@ -138,7 +150,7 @@
45102         CLEAN(tmp_buf);
45103         srv->empty_string = buffer_init_string("");
45104         CLEAN(cond_check_buf);
45105 -       
45106 +
45107         CLEAN(srvconf.errorlog_file);
45108         CLEAN(srvconf.groupname);
45109         CLEAN(srvconf.username);
45110 @@ -146,58 +158,58 @@
45111         CLEAN(srvconf.bindhost);
45112         CLEAN(srvconf.event_handler);
45113         CLEAN(srvconf.pid_file);
45114 -       
45115 +
45116         CLEAN(tmp_chunk_len);
45117  #undef CLEAN
45118 -       
45119 +
45120  #define CLEAN(x) \
45121         srv->x = array_init();
45122 -       
45123 +
45124         CLEAN(config_context);
45125         CLEAN(config_touched);
45126         CLEAN(status);
45127  #undef CLEAN
45128 -       
45129 +
45130         for (i = 0; i < FILE_CACHE_MAX; i++) {
45131                 srv->mtime_cache[i].str = buffer_init();
45132         }
45133 -       
45134 +
45135         srv->cur_ts = time(NULL);
45136         srv->startup_ts = srv->cur_ts;
45137 -       
45138 +
45139         srv->conns = calloc(1, sizeof(*srv->conns));
45140         assert(srv->conns);
45141 -       
45142 +
45143         srv->joblist = calloc(1, sizeof(*srv->joblist));
45144         assert(srv->joblist);
45145 -       
45146 +
45147         srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
45148         assert(srv->fdwaitqueue);
45149 -       
45150 +
45151         srv->srvconf.modules = array_init();
45152         srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
45153         srv->srvconf.network_backend = buffer_init();
45154         srv->srvconf.upload_tempdirs = array_init();
45155 -       
45156 +
45157         /* use syslog */
45158         srv->errorlog_fd = -1;
45159         srv->errorlog_mode = ERRORLOG_STDERR;
45160  
45161         srv->split_vals = array_init();
45162 -       
45163 +
45164         return srv;
45165  }
45166  
45167  static void server_free(server *srv) {
45168         size_t i;
45169 -       
45170 +
45171         for (i = 0; i < FILE_CACHE_MAX; i++) {
45172                 buffer_free(srv->mtime_cache[i].str);
45173         }
45174 -       
45175 +
45176  #define CLEAN(x) \
45177         buffer_free(srv->x);
45178 -       
45179 +
45180         CLEAN(response_header);
45181         CLEAN(parse_full_path);
45182         CLEAN(ts_debug_str);
45183 @@ -207,7 +219,7 @@
45184         CLEAN(tmp_buf);
45185         CLEAN(empty_string);
45186         CLEAN(cond_check_buf);
45187 -       
45188 +
45189         CLEAN(srvconf.errorlog_file);
45190         CLEAN(srvconf.groupname);
45191         CLEAN(srvconf.username);
45192 @@ -217,7 +229,7 @@
45193         CLEAN(srvconf.pid_file);
45194         CLEAN(srvconf.modules_dir);
45195         CLEAN(srvconf.network_backend);
45196 -       
45197 +
45198         CLEAN(tmp_chunk_len);
45199  #undef CLEAN
45200  
45201 @@ -225,15 +237,15 @@
45202         fdevent_unregister(srv->ev, srv->fd);
45203  #endif
45204         fdevent_free(srv->ev);
45205 -       
45206 +
45207         free(srv->conns);
45208 -       
45209 +
45210         if (srv->config_storage) {
45211                 for (i = 0; i < srv->config_context->used; i++) {
45212                         specific_config *s = srv->config_storage[i];
45213  
45214                         if (!s) continue;
45215 -                       
45216 +
45217                         buffer_free(s->document_root);
45218                         buffer_free(s->server_name);
45219                         buffer_free(s->server_tag);
45220 @@ -242,32 +254,32 @@
45221                         buffer_free(s->error_handler);
45222                         buffer_free(s->errorfile_prefix);
45223                         array_free(s->mimetypes);
45224 -                       
45225 +
45226                         free(s);
45227                 }
45228                 free(srv->config_storage);
45229                 srv->config_storage = NULL;
45230         }
45231 -       
45232 +
45233  #define CLEAN(x) \
45234         array_free(srv->x);
45235 -       
45236 +
45237         CLEAN(config_context);
45238         CLEAN(config_touched);
45239         CLEAN(status);
45240         CLEAN(srvconf.upload_tempdirs);
45241  #undef CLEAN
45242 -       
45243 +
45244         joblist_free(srv, srv->joblist);
45245         fdwaitqueue_free(srv, srv->fdwaitqueue);
45246 -       
45247 +
45248         if (srv->stat_cache) {
45249                 stat_cache_free(srv->stat_cache);
45250         }
45251  
45252         array_free(srv->srvconf.modules);
45253         array_free(srv->split_vals);
45254 -       
45255 +
45256         free(srv);
45257  }
45258  
45259 @@ -281,14 +293,12 @@
45260  " - a light and fast webserver\n" \
45261  "Build-Date: " __DATE__ " " __TIME__ "\n";
45262  ;
45263 -#undef TEXT_SSL        
45264 +#undef TEXT_SSL
45265         write(STDOUT_FILENO, b, strlen(b));
45266  }
45267  
45268  static void show_features (void) {
45269 -  show_version();
45270 -  printf("\nEvent Handlers:\n\n%s",
45271 -
45272 +  const char *s = ""
45273  #ifdef USE_SELECT
45274        "\t+ select (generic)\n"
45275  #else
45276 @@ -355,11 +365,6 @@
45277  #else
45278        "\t- crypt support\n"
45279  #endif
45280 -#ifdef USE_PAM
45281 -      "\t+ PAM support\n"
45282 -#else
45283 -      "\t- PAM support\n"
45284 -#endif
45285  #ifdef USE_OPENSSL
45286        "\t+ SSL Support\n"
45287  #else
45288 @@ -371,9 +376,9 @@
45289        "\t- PCRE support\n"
45290  #endif
45291  #ifdef HAVE_MYSQL
45292 -      "\t+ mySQL support\n"
45293 +      "\t+ MySQL support\n"
45294  #else
45295 -      "\t- mySQL support\n"
45296 +      "\t- MySQL support\n"
45297  #endif
45298  #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
45299        "\t+ LDAP support\n"
45300 @@ -410,8 +415,11 @@
45301  #else
45302        "\t- GDBM support\n"
45303  #endif
45304 -      "\n"
45305 -      );
45306 +      "\n";
45307 +
45308 +  show_version();
45309 +
45310 +  printf("\nEvent Handlers:\n\n%s", s);
45311  }
45312  
45313  static void show_help (void) {
45314 @@ -433,12 +441,12 @@
45315  " -h         show this help\n" \
45316  "\n"
45317  ;
45318 -#undef TEXT_SSL        
45319 +#undef TEXT_SSL
45320  #undef TEXT_IPV6
45321         write(STDOUT_FILENO, b, strlen(b));
45322  }
45323  
45324 -int main (int argc, char **argv) {
45325 +int main (int argc, char **argv, char **envp) {
45326         server *srv = NULL;
45327         int print_config = 0;
45328         int test_config = 0;
45329 @@ -447,33 +455,37 @@
45330         int num_childs = 0;
45331         int pid_fd = -1, fd;
45332         size_t i;
45333 +#ifdef _WIN32
45334 +       char *optarg = NULL;
45335 +#endif
45336 +
45337  #ifdef HAVE_SIGACTION
45338         struct sigaction act;
45339  #endif
45340  #ifdef HAVE_GETRLIMIT
45341         struct rlimit rlim;
45342  #endif
45343 -       
45344 +
45345  #ifdef USE_ALARM
45346         struct itimerval interval;
45347 -       
45348 +
45349         interval.it_interval.tv_sec = 1;
45350         interval.it_interval.tv_usec = 0;
45351         interval.it_value.tv_sec = 1;
45352         interval.it_value.tv_usec = 0;
45353  #endif
45354 -       
45355 -       
45356 +
45357 +
45358         /* for nice %b handling in strfime() */
45359         setlocale(LC_TIME, "C");
45360 -       
45361 +
45362         if (NULL == (srv = server_init())) {
45363                 fprintf(stderr, "did this really happen?\n");
45364                 return -1;
45365         }
45366 -       
45367 +
45368         /* init structs done */
45369 -       
45370 +
45371         srv->srvconf.port = 0;
45372  #ifdef HAVE_GETUID
45373         i_am_root = (getuid() == 0);
45374 @@ -481,14 +493,19 @@
45375         i_am_root = 0;
45376  #endif
45377         srv->srvconf.dont_daemonize = 0;
45378 -       
45379 +
45380         while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
45381                 switch(o) {
45382 -               case 'f': 
45383 -                       if (config_read(srv, optarg)) { 
45384 +               case 'f':
45385 +#ifdef _WIN32
45386 +                       /* evil HACK for windows, optarg is not set */
45387 +                       optarg = argv[optind-1];
45388 +#endif
45389 +                       if (config_read(srv, optarg)) {
45390                                 server_free(srv);
45391                                 return -1;
45392                         }
45393 +
45394                         break;
45395                 case 'm':
45396                         buffer_copy_string(srv->srvconf.modules_dir, optarg);
45397 @@ -497,23 +514,23 @@
45398                 case 't': test_config = 1; break;
45399                 case 'D': srv->srvconf.dont_daemonize = 1; break;
45400                 case 'v': show_version(); return 0;
45401 -               case 'V': show_features(); return 0;          
45402 +               case 'V': show_features(); return 0;
45403                 case 'h': show_help(); return 0;
45404 -               default: 
45405 +               default:
45406                         show_help();
45407                         server_free(srv);
45408                         return -1;
45409                 }
45410         }
45411 -       
45412 +
45413         if (!srv->config_storage) {
45414                 log_error_write(srv, __FILE__, __LINE__, "s",
45415                                 "No configuration available. Try using -f option.");
45416 -               
45417 +
45418                 server_free(srv);
45419                 return -1;
45420         }
45421 -       
45422 +
45423         if (print_config) {
45424                 data_unset *dc = srv->config_context->data[0];
45425                 if (dc) {
45426 @@ -533,7 +550,7 @@
45427                 server_free(srv);
45428                 return 0;
45429         }
45430 -       
45431 +
45432         /* close stdin and stdout, as they are not needed */
45433         /* move stdin to /dev/null */
45434         if (-1 != (fd = open("/dev/null", O_RDONLY))) {
45435 @@ -541,54 +558,55 @@
45436                 dup2(fd, STDIN_FILENO);
45437                 close(fd);
45438         }
45439 -       
45440 +
45441         /* move stdout to /dev/null */
45442         if (-1 != (fd = open("/dev/null", O_WRONLY))) {
45443                 close(STDOUT_FILENO);
45444                 dup2(fd, STDOUT_FILENO);
45445                 close(fd);
45446         }
45447 -       
45448 +
45449         if (0 != config_set_defaults(srv)) {
45450 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45451 +               log_error_write(srv, __FILE__, __LINE__, "s",
45452                                 "setting default values failed");
45453                 server_free(srv);
45454                 return -1;
45455         }
45456 -       
45457 +
45458         /* UID handling */
45459  #ifdef HAVE_GETUID
45460         if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
45461                 /* we are setuid-root */
45462 -               
45463 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45464 +
45465 +               log_error_write(srv, __FILE__, __LINE__, "s",
45466                                 "Are you nuts ? Don't apply a SUID bit to this binary");
45467 -               
45468 +
45469                 server_free(srv);
45470                 return -1;
45471         }
45472  #endif
45473 -       
45474 +
45475         /* check document-root */
45476         if (srv->config_storage[0]->document_root->used <= 1) {
45477 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45478 +               log_error_write(srv, __FILE__, __LINE__, "s",
45479                                 "document-root is not set\n");
45480 -               
45481 +
45482                 server_free(srv);
45483 -               
45484 +
45485                 return -1;
45486         }
45487 -       
45488 +
45489         if (plugins_load(srv)) {
45490                 log_error_write(srv, __FILE__, __LINE__, "s",
45491                                 "loading plugins finally failed");
45492 -               
45493 +
45494                 plugins_free(srv);
45495                 server_free(srv);
45496 -               
45497 +
45498                 return -1;
45499         }
45500 -       
45501 +
45502 +#ifndef _WIN32
45503         /* open pid file BEFORE chroot */
45504         if (srv->srvconf.pid_file->used) {
45505                 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))) {
45506 @@ -598,18 +616,18 @@
45507                                         "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45508                                 return -1;
45509                         }
45510 -                       
45511 +
45512                         if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
45513                                 log_error_write(srv, __FILE__, __LINE__, "sbs",
45514                                                 "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45515                         }
45516 -                       
45517 +
45518                         if (!S_ISREG(st.st_mode)) {
45519                                 log_error_write(srv, __FILE__, __LINE__, "sb",
45520                                                 "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
45521                                 return -1;
45522                         }
45523 -                       
45524 +
45525                         if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
45526                                 log_error_write(srv, __FILE__, __LINE__, "sbs",
45527                                                 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45528 @@ -617,13 +635,14 @@
45529                         }
45530                 }
45531         }
45532 -
45533 +#endif
45534         if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45535                 /* select limits itself
45536                  *
45537                  * as it is a hard limit and will lead to a segfault we add some safety
45538                  * */
45539 -               srv->max_fds = FD_SETSIZE - 200;
45540 +        fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
45541 +               srv->max_fds = FD_SETSIZE - 4;
45542         } else {
45543                 srv->max_fds = 4096;
45544         }
45545 @@ -636,7 +655,7 @@
45546  #ifdef HAVE_VALGRIND_VALGRIND_H
45547                 if (RUNNING_ON_VALGRIND) use_rlimit = 0;
45548  #endif
45549 -               
45550 +
45551  #ifdef HAVE_GETRLIMIT
45552                 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
45553                         log_error_write(srv, __FILE__, __LINE__,
45554 @@ -644,13 +663,13 @@
45555                                         strerror(errno));
45556                         return -1;
45557                 }
45558 -               
45559 +
45560                 if (use_rlimit && srv->srvconf.max_fds) {
45561                         /* set rlimits */
45562 -                       
45563 +
45564                         rlim.rlim_cur = srv->srvconf.max_fds;
45565                         rlim.rlim_max = srv->srvconf.max_fds;
45566 -                       
45567 +
45568                         if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
45569                                 log_error_write(srv, __FILE__, __LINE__,
45570                                                 "ss", "couldn't set 'max filedescriptors'",
45571 @@ -659,7 +678,7 @@
45572                         }
45573                 }
45574  
45575 -               /* #372: solaris need some fds extra for devpoll */     
45576 +               /* #372: solaris need some fds extra for devpoll */
45577                 if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
45578  
45579                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45580 @@ -677,33 +696,33 @@
45581                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45582                         /* don't raise the limit above FD_SET_SIZE */
45583                         if (srv->max_fds > FD_SETSIZE - 200) {
45584 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
45585 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
45586                                                 "can't raise max filedescriptors above",  FD_SETSIZE - 200,
45587                                                 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45588                                 return -1;
45589                         }
45590                 }
45591  
45592 -               
45593 +
45594  #ifdef HAVE_PWD_H
45595                 /* set user and group */
45596                 if (srv->srvconf.username->used) {
45597                         if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
45598 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
45599 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
45600                                                 "can't find username", srv->srvconf.username);
45601                                 return -1;
45602                         }
45603 -                       
45604 +
45605                         if (pwd->pw_uid == 0) {
45606                                 log_error_write(srv, __FILE__, __LINE__, "s",
45607                                                 "I will not set uid to 0\n");
45608                                 return -1;
45609                         }
45610                 }
45611 -               
45612 +
45613                 if (srv->srvconf.groupname->used) {
45614                         if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
45615 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
45616 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
45617                                         "can't find groupname", srv->srvconf.groupname);
45618                                 return -1;
45619                         }
45620 @@ -713,15 +732,15 @@
45621                                 return -1;
45622                         }
45623                 }
45624 -#endif         
45625 +#endif
45626                 /* we need root-perms for port < 1024 */
45627                 if (0 != network_init(srv)) {
45628                         plugins_free(srv);
45629                         server_free(srv);
45630 -                       
45631 +
45632                         return -1;
45633                 }
45634 -#ifdef HAVE_CHROOT     
45635 +#ifdef HAVE_CHROOT
45636                 if (srv->srvconf.changeroot->used) {
45637                         tzset();
45638  
45639 @@ -761,7 +780,7 @@
45640                 }
45641  
45642                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45643 -                       srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
45644 +                       srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
45645                 } else {
45646                         srv->max_fds = rlim.rlim_cur;
45647                 }
45648 @@ -775,18 +794,18 @@
45649  #endif
45650                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45651                         /* don't raise the limit above FD_SET_SIZE */
45652 -                       if (srv->max_fds > FD_SETSIZE - 200) {
45653 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
45654 -                                               "can't raise max filedescriptors above",  FD_SETSIZE - 200,
45655 +                       if (srv->max_fds > FD_SETSIZE - 4) {
45656 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
45657 +                                               "can't raise max filedescriptors above",  FD_SETSIZE - 4,
45658                                                 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45659                                 return -1;
45660                         }
45661                 }
45662 -               
45663 +
45664                 if (0 != network_init(srv)) {
45665                         plugins_free(srv);
45666                         server_free(srv);
45667 -                       
45668 +
45669                         return -1;
45670                 }
45671         }
45672 @@ -802,25 +821,27 @@
45673                 /* or use the default */
45674                 srv->max_conns = srv->max_fds;
45675         }
45676 -       
45677 +
45678         if (HANDLER_GO_ON != plugins_call_init(srv)) {
45679                 log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
45680 -               
45681 +
45682                 plugins_free(srv);
45683                 network_close(srv);
45684                 server_free(srv);
45685 -               
45686 +
45687                 return -1;
45688         }
45689  
45690 -#ifdef HAVE_FORK       
45691 +#ifdef HAVE_FORK
45692         /* network is up, let's deamonize ourself */
45693         if (srv->srvconf.dont_daemonize == 0) daemonize();
45694  #endif
45695  
45696 +#ifdef HAVE_PWD_H
45697         srv->gid = getgid();
45698         srv->uid = getuid();
45699 -       
45700 +#endif
45701 +
45702         /* write pid file */
45703         if (pid_fd != -1) {
45704                 buffer_copy_long(srv->tmp_buf, getpid());
45705 @@ -829,17 +850,17 @@
45706                 close(pid_fd);
45707                 pid_fd = -1;
45708         }
45709 -       
45710 +
45711         if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
45712                 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
45713 -               
45714 +
45715                 plugins_free(srv);
45716                 network_close(srv);
45717                 server_free(srv);
45718 -               
45719 +
45720                 return -1;
45721         }
45722 -       
45723 +
45724         /* dump unused config-keys */
45725         for (i = 0; i < srv->config_context->used; i++) {
45726                 array *config = ((data_config *)srv->config_context->data[i])->value;
45727 @@ -847,43 +868,42 @@
45728  
45729                 for (j = 0; config && j < config->used; j++) {
45730                         data_unset *du = config->data[j];
45731 -                       
45732 +
45733                         /* all var.* is known as user defined variable */
45734                         if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
45735                                 continue;
45736                         }
45737  
45738                         if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
45739 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
45740 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
45741                                                 "WARNING: unknown config-key:",
45742                                                 du->key,
45743                                                 "(ignored)");
45744                         }
45745                 }
45746         }
45747 -       
45748 +
45749         if (srv->config_deprecated) {
45750 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45751 +               log_error_write(srv, __FILE__, __LINE__, "s",
45752                                 "Configuration contains deprecated keys. Going down.");
45753 -               
45754 +
45755                 plugins_free(srv);
45756                 network_close(srv);
45757                 server_free(srv);
45758 -               
45759 +
45760                 return -1;
45761         }
45762 -       
45763 +
45764         if (-1 == log_error_open(srv)) {
45765 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45766 +               log_error_write(srv, __FILE__, __LINE__, "s",
45767                                 "opening errorlog failed, dying");
45768 -               
45769 +
45770                 plugins_free(srv);
45771                 network_close(srv);
45772                 server_free(srv);
45773                 return -1;
45774         }
45775 -       
45776 -       
45777 +
45778  #ifdef HAVE_SIGACTION
45779         memset(&act, 0, sizeof(act));
45780         act.sa_handler = SIG_IGN;
45781 @@ -903,7 +923,7 @@
45782         sigaction(SIGHUP,  &act, NULL);
45783         sigaction(SIGALRM, &act, NULL);
45784         sigaction(SIGCHLD, &act, NULL);
45785 -       
45786 +
45787  #elif defined(HAVE_SIGNAL)
45788         /* ignore the SIGPIPE from sendfile() */
45789         signal(SIGPIPE, SIG_IGN);
45790 @@ -914,20 +934,20 @@
45791         signal(SIGCHLD,  signal_handler);
45792         signal(SIGINT,  signal_handler);
45793  #endif
45794 -       
45795 +
45796  #ifdef USE_ALARM
45797         signal(SIGALRM, signal_handler);
45798 -       
45799 +
45800         /* setup periodic timer (1 second) */
45801         if (setitimer(ITIMER_REAL, &interval, NULL)) {
45802                 log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
45803                 return -1;
45804         }
45805 -       
45806 +
45807         getitimer(ITIMER_REAL, &interval);
45808  #endif
45809  
45810 -#ifdef HAVE_FORK       
45811 +#ifdef HAVE_FORK
45812         /* start watcher and workers */
45813         num_childs = srv->srvconf.max_worker;
45814         if (num_childs > 0) {
45815 @@ -957,13 +977,13 @@
45816         }
45817  #endif
45818  
45819 -       if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
45820 +       if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
45821                 log_error_write(srv, __FILE__, __LINE__,
45822                                 "s", "fdevent_init failed");
45823                 return -1;
45824         }
45825 -       /* 
45826 -        * kqueue() is called here, select resets its internals, 
45827 +       /*
45828 +        * kqueue() is called here, select resets its internals,
45829          * all server sockets get their handlers
45830          *
45831          * */
45832 @@ -971,7 +991,7 @@
45833                 plugins_free(srv);
45834                 network_close(srv);
45835                 server_free(srv);
45836 -               
45837 +
45838                 return -1;
45839         }
45840  
45841 @@ -986,7 +1006,7 @@
45842         /* setup FAM */
45843         if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
45844                 if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
45845 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
45846 +                       log_error_write(srv, __FILE__, __LINE__, "s",
45847                                          "could not open a fam connection, dieing.");
45848                         return -1;
45849                 }
45850 @@ -1018,16 +1038,40 @@
45851                 int n;
45852                 size_t ndx;
45853                 time_t min_ts;
45854 -               
45855 +
45856                 if (handle_sig_hup) {
45857                         handler_t r;
45858 -                       
45859 +
45860                         /* reset notification */
45861                         handle_sig_hup = 0;
45862 -                       
45863 -                       
45864 +
45865 +#if 0
45866 +                               pid_t pid;
45867 +
45868 +                       /* send the old process into a graceful-shutdown and start a
45869 +                        * new process right away
45870 +                        *
45871 +                        * BUGS:
45872 +                        * - if webserver is running on port < 1024 (e.g. 80, 433)
45873 +                        *   we don't have the permissions to bind to that port anymore
45874 +                        *
45875 +                        *
45876 +                        *  */
45877 +                       if (0 == (pid = fork())) {
45878 +                               execve(argv[0], argv, envp);
45879 +
45880 +                               exit(-1);
45881 +                       } else if (pid == -1) {
45882 +
45883 +                       } else {
45884 +                               /* parent */
45885 +
45886 +                               graceful_shutdown = 1; /* shutdown without killing running connections */
45887 +                               graceful_restart = 1;  /* don't delete pid file */
45888 +                       }
45889 +#else
45890                         /* cycle logfiles */
45891 -                       
45892 +
45893                         switch(r = plugins_call_handle_sighup(srv)) {
45894                         case HANDLER_GO_ON:
45895                                 break;
45896 @@ -1035,30 +1079,31 @@
45897                                 log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
45898                                 break;
45899                         }
45900 -                       
45901 +
45902                         if (-1 == log_error_cycle(srv)) {
45903                                 log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
45904 -                               
45905 +
45906                                 return -1;
45907                         }
45908 +#endif
45909                 }
45910 -               
45911 +
45912                 if (handle_sig_alarm) {
45913                         /* a new second */
45914 -                       
45915 +
45916  #ifdef USE_ALARM
45917                         /* reset notification */
45918                         handle_sig_alarm = 0;
45919  #endif
45920 -                       
45921 +
45922                         /* get current time */
45923                         min_ts = time(NULL);
45924 -                       
45925 +
45926                         if (min_ts != srv->cur_ts) {
45927                                 int cs = 0;
45928                                 connections *conns = srv->conns;
45929                                 handler_t r;
45930 -                               
45931 +
45932                                 switch(r = plugins_call_handle_trigger(srv)) {
45933                                 case HANDLER_GO_ON:
45934                                         break;
45935 @@ -1069,21 +1114,21 @@
45936                                         log_error_write(srv, __FILE__, __LINE__, "d", r);
45937                                         break;
45938                                 }
45939 -                               
45940 +
45941                                 /* trigger waitpid */
45942                                 srv->cur_ts = min_ts;
45943 -                       
45944 -                               /* cleanup stat-cache */        
45945 +
45946 +                               /* cleanup stat-cache */
45947                                 stat_cache_trigger_cleanup(srv);
45948                                 /**
45949 -                                * check all connections for timeouts 
45950 -                                * 
45951 +                                * check all connections for timeouts
45952 +                                *
45953                                  */
45954                                 for (ndx = 0; ndx < conns->used; ndx++) {
45955                                         int changed = 0;
45956                                         connection *con;
45957                                         int t_diff;
45958 -                                       
45959 +
45960                                         con = conns->ptr[ndx];
45961  
45962                                         if (con->state == CON_STATE_READ ||
45963 @@ -1092,7 +1137,7 @@
45964                                                         if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
45965                                                                 /* time - out */
45966  #if 0
45967 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
45968 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
45969                                                                                 "connection closed - read-timeout:", con->fd);
45970  #endif
45971                                                                 connection_set_state(srv, con, CON_STATE_ERROR);
45972 @@ -1102,7 +1147,7 @@
45973                                                         if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
45974                                                                 /* time - out */
45975  #if 0
45976 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
45977 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
45978                                                                                 "connection closed - read-timeout:", con->fd);
45979  #endif
45980                                                                 connection_set_state(srv, con, CON_STATE_ERROR);
45981 @@ -1110,20 +1155,20 @@
45982                                                         }
45983                                                 }
45984                                         }
45985 -                                       
45986 +
45987                                         if ((con->state == CON_STATE_WRITE) &&
45988 -                                           (con->write_request_ts != 0)) { 
45989 +                                           (con->write_request_ts != 0)) {
45990  #if 0
45991                                                 if (srv->cur_ts - con->write_request_ts > 60) {
45992 -                                                       log_error_write(srv, __FILE__, __LINE__, "sdd", 
45993 +                                                       log_error_write(srv, __FILE__, __LINE__, "sdd",
45994                                                                         "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
45995                                                 }
45996  #endif
45997 -                                               
45998 +
45999                                                 if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
46000                                                         /* time - out */
46001  #if 1
46002 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsosds", 
46003 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46004                                                                         "NOTE: a request for",
46005                                                                         con->request.uri,
46006                                                                         "timed out after writing",
46007 @@ -1138,35 +1183,35 @@
46008                                         }
46009                                         /* we don't like div by zero */
46010                                         if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
46011 -       
46012 -                                       if (con->traffic_limit_reached && 
46013 -                                           (con->conf.kbytes_per_second == 0 || 
46014 +
46015 +                                       if (con->traffic_limit_reached &&
46016 +                                           (con->conf.kbytes_per_second == 0 ||
46017                                              ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
46018                                                 /* enable connection again */
46019                                                 con->traffic_limit_reached = 0;
46020 -                                               
46021 +
46022                                                 changed = 1;
46023                                         }
46024 -                                       
46025 +
46026                                         if (changed) {
46027                                                 connection_state_machine(srv, con);
46028                                         }
46029                                         con->bytes_written_cur_second = 0;
46030                                         *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
46031 -                                       
46032 +
46033  #if 0
46034                                         if (cs == 0) {
46035                                                 fprintf(stderr, "connection-state: ");
46036                                                 cs = 1;
46037                                         }
46038 -                                       
46039 +
46040                                         fprintf(stderr, "c[%d,%d]: %s ",
46041                                                 con->fd,
46042                                                 con->fcgi.fd,
46043                                                 connection_get_state(con->state));
46044  #endif
46045                                 }
46046 -                               
46047 +
46048                                 if (cs == 1) fprintf(stderr, "\n");
46049                         }
46050                 }
46051 @@ -1181,18 +1226,18 @@
46052                                         server_socket *srv_socket = srv->srv_sockets.ptr[i];
46053                                         fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
46054                                 }
46055 -                       
46056 +
46057                                 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
46058 -                       
46059 +
46060                                 srv->sockets_disabled = 0;
46061                         }
46062                 } else {
46063                         if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
46064                             (srv->conns->used > srv->max_conns) || /* out of connections */
46065 -                           (graceful_shutdown)) { /* graceful_shutdown */ 
46066 +                           (graceful_shutdown)) { /* graceful_shutdown */
46067  
46068                                 /* disable server-fds */
46069 -                       
46070 +
46071                                 for (i = 0; i < srv->srv_sockets.used; i++) {
46072                                         server_socket *srv_socket = srv->srv_sockets.ptr[i];
46073                                         fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
46074 @@ -1211,7 +1256,7 @@
46075                                                 /* network_close() will cleanup after us */
46076                                         }
46077                                 }
46078 -               
46079 +
46080                                 if (graceful_shutdown) {
46081                                         log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
46082                                 } else if (srv->conns->used > srv->max_conns) {
46083 @@ -1219,7 +1264,7 @@
46084                                 } else {
46085                                         log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
46086                                 }
46087 -                       
46088 +
46089                                 srv->sockets_disabled = 1;
46090                         }
46091                 }
46092 @@ -1229,16 +1274,16 @@
46093                          * we are ready to terminate without harming anyone */
46094                         srv_shutdown = 1;
46095                 }
46096 -               
46097 +
46098                 /* we still have some fds to share */
46099 -               if (srv->want_fds) { 
46100 +               if (srv->want_fds) {
46101                         /* check the fdwaitqueue for waiting fds */
46102                         int free_fds = srv->max_fds - srv->cur_fds - 16;
46103                         connection *con;
46104 -                       
46105 +
46106                         for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
46107                                 connection_state_machine(srv, con);
46108 -                               
46109 +
46110                                 srv->want_fds--;
46111                         }
46112                 }
46113 @@ -1249,27 +1294,27 @@
46114                         int fd_ndx;
46115  #if 0
46116                         if (n > 0) {
46117 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
46118 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
46119                                                 "polls:", n);
46120                         }
46121 -#endif                 
46122 +#endif
46123                         fd_ndx = -1;
46124                         do {
46125                                 fdevent_handler handler;
46126                                 void *context;
46127                                 handler_t r;
46128 -                               
46129 +
46130                                 fd_ndx  = fdevent_event_next_fdndx (srv->ev, fd_ndx);
46131                                 revents = fdevent_event_get_revent (srv->ev, fd_ndx);
46132                                 fd      = fdevent_event_get_fd     (srv->ev, fd_ndx);
46133                                 handler = fdevent_get_handler(srv->ev, fd);
46134                                 context = fdevent_get_context(srv->ev, fd);
46135 -                               
46136 +
46137                                 /* connection_handle_fdevent needs a joblist_append */
46138  #if 0
46139 -                               log_error_write(srv, __FILE__, __LINE__, "sdd", 
46140 +                               log_error_write(srv, __FILE__, __LINE__, "sdd",
46141                                                 "event for", fd, revents);
46142 -#endif                         
46143 +#endif
46144                                 switch (r = (*handler)(srv, context, revents)) {
46145                                 case HANDLER_FINISHED:
46146                                 case HANDLER_GO_ON:
46147 @@ -1286,17 +1331,17 @@
46148                                 }
46149                         } while (--n > 0);
46150                 } else if (n < 0 && errno != EINTR) {
46151 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
46152 -                                       "fdevent_poll failed:", 
46153 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
46154 +                                       "fdevent_poll failed:",
46155                                         strerror(errno));
46156                 }
46157 -               
46158 +
46159                 for (ndx = 0; ndx < srv->joblist->used; ndx++) {
46160                         connection *con = srv->joblist->ptr[ndx];
46161                         handler_t r;
46162 -                       
46163 +
46164                         connection_state_machine(srv, con);
46165 -                       
46166 +
46167                         switch(r = plugins_call_handle_joblist(srv, con)) {
46168                         case HANDLER_FINISHED:
46169                         case HANDLER_GO_ON:
46170 @@ -1305,32 +1350,33 @@
46171                                 log_error_write(srv, __FILE__, __LINE__, "d", r);
46172                                 break;
46173                         }
46174 -                       
46175 +
46176                         con->in_joblist = 0;
46177                 }
46178 -               
46179 +
46180                 srv->joblist->used = 0;
46181         }
46182 -       
46183 -       if (srv->srvconf.pid_file->used &&
46184 +
46185 +       if (0 == graceful_restart &&
46186 +           srv->srvconf.pid_file->used &&
46187             srv->srvconf.changeroot->used == 0) {
46188                 if (0 != unlink(srv->srvconf.pid_file->ptr)) {
46189                         if (errno != EACCES && errno != EPERM) {
46190 -                               log_error_write(srv, __FILE__, __LINE__, "sbds", 
46191 -                                               "unlink failed for:", 
46192 +                               log_error_write(srv, __FILE__, __LINE__, "sbds",
46193 +                                               "unlink failed for:",
46194                                                 srv->srvconf.pid_file,
46195                                                 errno,
46196                                                 strerror(errno));
46197                         }
46198                 }
46199         }
46200 -       
46201 +
46202         /* clean-up */
46203         log_error_close(srv);
46204         network_close(srv);
46205         connections_free(srv);
46206         plugins_free(srv);
46207         server_free(srv);
46208 -       
46209 +
46210         return 0;
46211  }
46212 --- ../lighttpd-1.4.11/src/settings.h   2005-08-11 01:26:41.000000000 +0300
46213 +++ lighttpd-1.4.12/src/settings.h      2006-07-11 22:07:53.000000000 +0300
46214 @@ -9,24 +9,24 @@
46215  /**
46216   * max size of a buffer which will just be reset
46217   * to ->used = 0 instead of really freeing the buffer
46218 - * 
46219 + *
46220   * 64kB (no real reason, just a guess)
46221   */
46222  #define BUFFER_MAX_REUSE_SIZE  (4 * 1024)
46223  
46224  /**
46225   * max size of the HTTP request header
46226 - * 
46227 + *
46228   * 32k should be enough for everything (just a guess)
46229 - * 
46230 + *
46231   */
46232  #define MAX_HTTP_REQUEST_HEADER  (32 * 1024)
46233  
46234 -typedef enum { HANDLER_UNSET, 
46235 -               HANDLER_GO_ON, 
46236 +typedef enum { HANDLER_UNSET,
46237 +               HANDLER_GO_ON,
46238                 HANDLER_FINISHED,
46239 -               HANDLER_COMEBACK, 
46240 -               HANDLER_WAIT_FOR_EVENT, 
46241 +               HANDLER_COMEBACK,
46242 +               HANDLER_WAIT_FOR_EVENT,
46243                 HANDLER_ERROR,
46244                 HANDLER_WAIT_FOR_FD
46245  } handler_t;
46246 --- ../lighttpd-1.4.11/src/spawn-fcgi.c 2006-03-07 14:18:10.000000000 +0200
46247 +++ lighttpd-1.4.12/src/spawn-fcgi.c    2006-07-11 22:07:53.000000000 +0300
46248 @@ -1,19 +1,16 @@
46249  #include <sys/types.h>
46250 -#include <sys/time.h>
46251  #include <sys/stat.h>
46252  
46253  #include <stdlib.h>
46254  #include <string.h>
46255  #include <errno.h>
46256  #include <stdio.h>
46257 -#include <unistd.h>
46258  #include <fcntl.h>
46259 -
46260 +#include <time.h>
46261  #ifdef HAVE_CONFIG_H
46262  #include "config.h"
46263  #endif
46264  
46265 -
46266  #ifdef HAVE_PWD_H
46267  #include <grp.h>
46268  #include <pwd.h>
46269 @@ -30,6 +27,7 @@
46270  #endif
46271  
46272  #include "sys-socket.h"
46273 +#include "sys-files.h"
46274  
46275  #ifdef HAVE_SYS_WAIT_H
46276  #include <sys/wait.h>
46277 @@ -45,28 +43,28 @@
46278         int fcgi_fd;
46279         int socket_type, status;
46280         struct timeval tv = { 0, 100 * 1000 };
46281 -       
46282 +
46283         struct sockaddr_un fcgi_addr_un;
46284         struct sockaddr_in fcgi_addr_in;
46285         struct sockaddr *fcgi_addr;
46286 -       
46287 +
46288         socklen_t servlen;
46289 -       
46290 +
46291         if (child_count < 2) {
46292                 child_count = 5;
46293         }
46294 -       
46295 +
46296         if (child_count > 256) {
46297                 child_count = 256;
46298         }
46299 -       
46300 -       
46301 +
46302 +
46303         if (unixsocket) {
46304                 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
46305 -               
46306 +
46307                 fcgi_addr_un.sun_family = AF_UNIX;
46308                 strcpy(fcgi_addr_un.sun_path, unixsocket);
46309 -               
46310 +
46311  #ifdef SUN_LEN
46312                 servlen = SUN_LEN(&fcgi_addr_un);
46313  #else
46314 @@ -84,50 +82,50 @@
46315                  }
46316                 fcgi_addr_in.sin_port = htons(port);
46317                 servlen = sizeof(fcgi_addr_in);
46318 -               
46319 +
46320                 socket_type = AF_INET;
46321                 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
46322         }
46323 -       
46324 +
46325         if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46326 -               fprintf(stderr, "%s.%d\n", 
46327 +               fprintf(stderr, "%s.%d\n",
46328                         __FILE__, __LINE__);
46329                 return -1;
46330         }
46331 -       
46332 +
46333         if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
46334                 /* server is not up, spawn in  */
46335                 pid_t child;
46336                 int val;
46337 -               
46338 +
46339                 if (unixsocket) unlink(unixsocket);
46340 -               
46341 +
46342                 close(fcgi_fd);
46343 -               
46344 +
46345                 /* reopen socket */
46346                 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46347 -                       fprintf(stderr, "%s.%d\n", 
46348 +                       fprintf(stderr, "%s.%d\n",
46349                                 __FILE__, __LINE__);
46350                         return -1;
46351                 }
46352  
46353                 val = 1;
46354                 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
46355 -                       fprintf(stderr, "%s.%d\n", 
46356 +                       fprintf(stderr, "%s.%d\n",
46357                                 __FILE__, __LINE__);
46358                         return -1;
46359                 }
46360  
46361                 /* create socket */
46362                 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
46363 -                       fprintf(stderr, "%s.%d: bind failed: %s\n", 
46364 +                       fprintf(stderr, "%s.%d: bind failed: %s\n",
46365                                 __FILE__, __LINE__,
46366                                 strerror(errno));
46367                         return -1;
46368                 }
46369 -               
46370 +
46371                 if (-1 == listen(fcgi_fd, 1024)) {
46372 -                       fprintf(stderr, "%s.%d: fd = -1\n", 
46373 +                       fprintf(stderr, "%s.%d: fd = -1\n",
46374                                 __FILE__, __LINE__);
46375                         return -1;
46376                 }
46377 @@ -137,42 +135,45 @@
46378                 } else {
46379                         child = 0;
46380                 }
46381 -               
46382 +
46383                 switch (child) {
46384                 case 0: {
46385                         char cgi_childs[64];
46386                         char *b;
46387 -                       
46388 +
46389                         int i = 0;
46390 -                       
46391 +
46392 +                       /* loose control terminal */
46393 +                       setsid();
46394 +
46395                         /* is save as we limit to 256 childs */
46396                         sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
46397 -                       
46398 +
46399                         if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
46400                                 close(FCGI_LISTENSOCK_FILENO);
46401                                 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
46402                                 close(fcgi_fd);
46403                         }
46404 -                       
46405 +
46406                         /* we don't need the client socket */
46407                         for (i = 3; i < 256; i++) {
46408                                 close(i);
46409                         }
46410 -                       
46411 +
46412                         /* create environment */
46413 -                       
46414 +
46415                         putenv(cgi_childs);
46416 -                       
46417 +
46418                         /* fork and replace shell */
46419                         b = malloc(strlen("exec ") + strlen(appPath) + 1);
46420                         strcpy(b, "exec ");
46421                         strcat(b, appPath);
46422 -                       
46423 +
46424                         /* exec the cgi */
46425                         execl("/bin/sh", "sh", "-c", b, NULL);
46426 -                       
46427 +
46428                         exit(errno);
46429 -                       
46430 +
46431                         break;
46432                 }
46433                 case -1:
46434 @@ -180,47 +181,47 @@
46435                         break;
46436                 default:
46437                         /* father */
46438 -                       
46439 +
46440                         /* wait */
46441                         select(0, NULL, NULL, NULL, &tv);
46442 -                       
46443 +
46444                         switch (waitpid(child, &status, WNOHANG)) {
46445                         case 0:
46446 -                               fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n", 
46447 +                               fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
46448                                         __FILE__, __LINE__,
46449                                         child);
46450 -                               
46451 +
46452                                 /* write pid file */
46453                                 if (pid_fd != -1) {
46454                                         /* assume a 32bit pid_t */
46455                                         char pidbuf[12];
46456 -                                       
46457 +
46458                                         snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
46459 -                                       
46460 +
46461                                         write(pid_fd, pidbuf, strlen(pidbuf));
46462                                         close(pid_fd);
46463                                         pid_fd = -1;
46464                                 }
46465 -                               
46466 +
46467                                 break;
46468                         case -1:
46469                                 break;
46470                         default:
46471                                 if (WIFEXITED(status)) {
46472 -                                       fprintf(stderr, "%s.%d: child exited with: %d, %s\n", 
46473 +                                       fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
46474                                                 __FILE__, __LINE__,
46475                                                 WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
46476                                 } else if (WIFSIGNALED(status)) {
46477 -                                       fprintf(stderr, "%s.%d: child signaled: %d\n", 
46478 +                                       fprintf(stderr, "%s.%d: child signaled: %d\n",
46479                                                 __FILE__, __LINE__,
46480                                                 WTERMSIG(status));
46481                                 } else {
46482 -                                       fprintf(stderr, "%s.%d: child died somehow: %d\n", 
46483 +                                       fprintf(stderr, "%s.%d: child died somehow: %d\n",
46484                                                 __FILE__, __LINE__,
46485                                                 status);
46486                                 }
46487                         }
46488 -                               
46489 +
46490                         break;
46491                 }
46492         } else {
46493 @@ -228,16 +229,16 @@
46494                         __FILE__, __LINE__);
46495                 return -1;
46496         }
46497 -       
46498 +
46499         close(fcgi_fd);
46500 -       
46501 +
46502         return 0;
46503  }
46504  
46505  
46506  void show_version () {
46507         char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
46508 -" - spawns fastcgi processes\n" 
46509 +" - spawns fastcgi processes\n"
46510  ;
46511         write(1, b, strlen(b));
46512  }
46513 @@ -265,7 +266,7 @@
46514  
46515  
46516  int main(int argc, char **argv) {
46517 -       char *fcgi_app = NULL, *changeroot = NULL, *username = NULL, 
46518 +       char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
46519                 *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
46520                  *addr = NULL;
46521         unsigned short port = 0;
46522 @@ -273,9 +274,9 @@
46523         int i_am_root, o;
46524         int pid_fd = -1;
46525         int nofork = 0;
46526 -       
46527 +
46528         i_am_root = (getuid() == 0);
46529 -       
46530 +
46531         while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
46532                 switch(o) {
46533                 case 'f': fcgi_app = optarg; break;
46534 @@ -290,137 +291,137 @@
46535                 case 'P': pid_file = optarg; /* PID file */ break;
46536                 case 'v': show_version(); return 0;
46537                 case 'h': show_help(); return 0;
46538 -               default: 
46539 +               default:
46540                         show_help();
46541                         return -1;
46542                 }
46543         }
46544 -       
46545 +
46546         if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
46547                 show_help();
46548                 return -1;
46549         }
46550 -           
46551 +
46552         if (unixsocket && port) {
46553 -               fprintf(stderr, "%s.%d: %s\n", 
46554 +               fprintf(stderr, "%s.%d: %s\n",
46555                         __FILE__, __LINE__,
46556                         "either a unix domain socket or a tcp-port, but not both\n");
46557 -               
46558 +
46559                 return -1;
46560         }
46561 -       
46562 +
46563         if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) {
46564 -               fprintf(stderr, "%s.%d: %s\n", 
46565 +               fprintf(stderr, "%s.%d: %s\n",
46566                         __FILE__, __LINE__,
46567                         "path of the unix socket is too long\n");
46568 -               
46569 +
46570                 return -1;
46571         }
46572  
46573         /* UID handling */
46574         if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
46575                 /* we are setuid-root */
46576 -               
46577 -               fprintf(stderr, "%s.%d: %s\n", 
46578 +
46579 +               fprintf(stderr, "%s.%d: %s\n",
46580                         __FILE__, __LINE__,
46581                         "Are you nuts ? Don't apply a SUID bit to this binary\n");
46582 -               
46583 +
46584                 return -1;
46585         }
46586 -       
46587 -       if (pid_file && 
46588 +
46589 +       if (pid_file &&
46590             (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
46591                 struct stat st;
46592                 if (errno != EEXIST) {
46593 -                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", 
46594 +                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46595                                 __FILE__, __LINE__,
46596                                 pid_file, strerror(errno));
46597 -                       
46598 +
46599                         return -1;
46600                 }
46601 -               
46602 +
46603                 /* ok, file exists */
46604 -               
46605 +
46606                 if (0 != stat(pid_file, &st)) {
46607 -                       fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n", 
46608 +                       fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
46609                                 __FILE__, __LINE__,
46610                                 pid_file, strerror(errno));
46611 -                       
46612 +
46613                         return -1;
46614                 }
46615 -               
46616 +
46617                 /* is it a regular file ? */
46618 -               
46619 +
46620                 if (!S_ISREG(st.st_mode)) {
46621 -                       fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n", 
46622 +                       fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
46623                                 __FILE__, __LINE__,
46624                                 pid_file);
46625 -                       
46626 +
46627                         return -1;
46628                 }
46629 -               
46630 +
46631                 if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
46632 -                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", 
46633 +                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46634                                 __FILE__, __LINE__,
46635                                 pid_file, strerror(errno));
46636 -                       
46637 +
46638                         return -1;
46639                 }
46640         }
46641 -       
46642 +
46643         if (i_am_root) {
46644                 struct group *grp = NULL;
46645                 struct passwd *pwd = NULL;
46646 -               
46647 +
46648                 /* set user and group */
46649 -               
46650 +
46651                 if (username) {
46652                         if (NULL == (pwd = getpwnam(username))) {
46653 -                               fprintf(stderr, "%s.%d: %s, %s\n", 
46654 +                               fprintf(stderr, "%s.%d: %s, %s\n",
46655                                         __FILE__, __LINE__,
46656                                         "can't find username", username);
46657                                 return -1;
46658                         }
46659 -                       
46660 +
46661                         if (pwd->pw_uid == 0) {
46662 -                               fprintf(stderr, "%s.%d: %s\n", 
46663 +                               fprintf(stderr, "%s.%d: %s\n",
46664                                         __FILE__, __LINE__,
46665                                         "I will not set uid to 0\n");
46666                                 return -1;
46667                         }
46668                 }
46669 -               
46670 +
46671                 if (groupname) {
46672                         if (NULL == (grp = getgrnam(groupname))) {
46673 -                               fprintf(stderr, "%s.%d: %s %s\n", 
46674 +                               fprintf(stderr, "%s.%d: %s %s\n",
46675                                         __FILE__, __LINE__,
46676 -                                       "can't find groupname", 
46677 +                                       "can't find groupname",
46678                                         groupname);
46679                                 return -1;
46680                         }
46681                         if (grp->gr_gid == 0) {
46682 -                               fprintf(stderr, "%s.%d: %s\n", 
46683 +                               fprintf(stderr, "%s.%d: %s\n",
46684                                         __FILE__, __LINE__,
46685                                         "I will not set gid to 0\n");
46686                                 return -1;
46687                         }
46688                 }
46689 -               
46690 +
46691                 if (changeroot) {
46692                         if (-1 == chroot(changeroot)) {
46693 -                               fprintf(stderr, "%s.%d: %s %s\n", 
46694 +                               fprintf(stderr, "%s.%d: %s %s\n",
46695                                         __FILE__, __LINE__,
46696                                         "chroot failed: ", strerror(errno));
46697                                 return -1;
46698                         }
46699                         if (-1 == chdir("/")) {
46700 -                               fprintf(stderr, "%s.%d: %s %s\n", 
46701 +                               fprintf(stderr, "%s.%d: %s %s\n",
46702                                         __FILE__, __LINE__,
46703                                         "chdir failed: ", strerror(errno));
46704                                 return -1;
46705                         }
46706                 }
46707 -               
46708 +
46709                 /* drop root privs */
46710                 if (groupname) {
46711                         setgid(grp->gr_gid);
46712 @@ -428,7 +429,7 @@
46713                 }
46714                 if (username) setuid(pwd->pw_uid);
46715         }
46716 -       
46717 +
46718         return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
46719  }
46720  #else
46721 --- ../lighttpd-1.4.11/src/splaytree.c  2005-09-12 21:51:28.000000000 +0300
46722 +++ lighttpd-1.4.12/src/splaytree.c     2006-07-11 22:07:51.000000000 +0300
46723 @@ -56,19 +56,19 @@
46724  
46725  #define node_size splaytree_size
46726  
46727 -/* Splay using the key i (which may or may not be in the tree.) 
46728 - * The starting root is t, and the tree used is defined by rat 
46729 +/* Splay using the key i (which may or may not be in the tree.)
46730 + * The starting root is t, and the tree used is defined by rat
46731   * size fields are maintained */
46732  splay_tree * splaytree_splay (splay_tree *t, int i) {
46733      splay_tree N, *l, *r, *y;
46734      int comp, root_size, l_size, r_size;
46735 -    
46736 +
46737      if (t == NULL) return t;
46738      N.left = N.right = NULL;
46739      l = r = &N;
46740      root_size = node_size(t);
46741      l_size = r_size = 0;
46742
46743 +
46744      for (;;) {
46745          comp = compare(i, t->key);
46746          if (comp < 0) {
46747 @@ -120,7 +120,7 @@
46748          y->size = r_size;
46749          r_size -= 1+node_size(y->right);
46750      }
46751
46752 +
46753      l->right = t->left;                                /* assemble */
46754      r->left = t->right;
46755      t->left = N.right;
46756 --- ../lighttpd-1.4.11/src/splaytree.h  2005-09-12 21:51:13.000000000 +0300
46757 +++ lighttpd-1.4.12/src/splaytree.h     2006-07-11 22:07:51.000000000 +0300
46758 @@ -19,6 +19,6 @@
46759  /* This macro returns the size of a node.  Unlike "x->size",     */
46760  /* it works even if x=NULL.  The test could be avoided by using  */
46761  /* a special version of NULL which was a real node with size 0.  */
46762
46763 +
46764  
46765  #endif
46766 --- ../lighttpd-1.4.11/src/stat_cache.c 2005-11-22 15:23:51.000000000 +0200
46767 +++ lighttpd-1.4.12/src/stat_cache.c    2006-07-15 22:43:21.000000000 +0300
46768 @@ -6,7 +6,6 @@
46769  #include <stdlib.h>
46770  #include <string.h>
46771  #include <errno.h>
46772 -#include <unistd.h>
46773  #include <stdio.h>
46774  #include <fcntl.h>
46775  #include <assert.h>
46776 @@ -25,19 +24,8 @@
46777  #endif
46778  
46779  #include "sys-mmap.h"
46780 -
46781 -/* NetBSD 1.3.x needs it */
46782 -#ifndef MAP_FAILED
46783 -# define MAP_FAILED -1
46784 -#endif
46785 -
46786 -#ifndef O_LARGEFILE
46787 -# define O_LARGEFILE 0
46788 -#endif
46789 -
46790 -#ifndef HAVE_LSTAT
46791 -#define lstat stat
46792 -#endif
46793 +#include "sys-files.h"
46794 +#include "sys-strings.h"
46795  
46796  #if 0
46797  /* enables debug code for testing if all nodes in the stat-cache as accessable */
46798 @@ -52,8 +40,8 @@
46799   *
46800   * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
46801   *
46802 - * if the stat()-cache is queried we check if the version id for the directory is the 
46803 - * same and return immediatly. 
46804 + * if the stat()-cache is queried we check if the version id for the directory is the
46805 + * same and return immediatly.
46806   *
46807   *
46808   * What we need:
46809 @@ -62,17 +50,17 @@
46810   * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
46811   *
46812   * stat <<-> directory <-> FAMRequest
46813 - * 
46814 - * if file is deleted, directory is dirty, file is rechecked ... 
46815 + *
46816 + * if file is deleted, directory is dirty, file is rechecked ...
46817   * if directory is deleted, directory mapping is removed
46818 - *  
46819 + *
46820   * */
46821  
46822  #ifdef HAVE_FAM_H
46823  typedef struct {
46824         FAMRequest *req;
46825         FAMConnection *fc;
46826 -       
46827 +
46828         buffer *name;
46829  
46830         int version;
46831 @@ -83,16 +71,16 @@
46832   * - we need a hash
46833   * - the hash-key is used as sorting criteria for a tree
46834   * - a splay-tree is used as we can use the caching effect of it
46835 - */ 
46836 + */
46837  
46838  /* we want to cleanup the stat-cache every few seconds, let's say 10
46839   *
46840   * - remove entries which are outdated since 30s
46841   * - remove entries which are fresh but havn't been used since 60s
46842   * - if we don't have a stat-cache entry for a directory, release it from the monitor
46843 - */ 
46844 + */
46845  
46846 -#ifdef DEBUG_STAT_CACHE        
46847 +#ifdef DEBUG_STAT_CACHE
46848  typedef struct {
46849         int *ptr;
46850  
46851 @@ -105,15 +93,15 @@
46852  
46853  stat_cache *stat_cache_init(void) {
46854         stat_cache *fc = NULL;
46855 -       
46856 +
46857         fc = calloc(1, sizeof(*fc));
46858 -       
46859 +
46860         fc->dir_name = buffer_init();
46861  #ifdef HAVE_FAM_H
46862         fc->fam = calloc(1, sizeof(*fc->fam));
46863  #endif
46864  
46865 -#ifdef DEBUG_STAT_CACHE        
46866 +#ifdef DEBUG_STAT_CACHE
46867         ctrl.size = 0;
46868  #endif
46869  
46870 @@ -122,24 +110,24 @@
46871  
46872  static stat_cache_entry * stat_cache_entry_init(void) {
46873         stat_cache_entry *sce = NULL;
46874 -       
46875 +
46876         sce = calloc(1, sizeof(*sce));
46877 -       
46878 +
46879         sce->name = buffer_init();
46880         sce->etag = buffer_init();
46881         sce->content_type = buffer_init();
46882 -       
46883 +
46884         return sce;
46885  }
46886  
46887  static void stat_cache_entry_free(void *data) {
46888         stat_cache_entry *sce = data;
46889         if (!sce) return;
46890 -       
46891 +
46892         buffer_free(sce->etag);
46893         buffer_free(sce->name);
46894         buffer_free(sce->content_type);
46895 -       
46896 +
46897         free(sce);
46898  }
46899  
46900 @@ -148,22 +136,22 @@
46901         fam_dir_entry *fam_dir = NULL;
46902  
46903         fam_dir = calloc(1, sizeof(*fam_dir));
46904 -       
46905 +
46906         fam_dir->name = buffer_init();
46907 -       
46908 +
46909         return fam_dir;
46910  }
46911  
46912  static void fam_dir_entry_free(void *data) {
46913         fam_dir_entry *fam_dir = data;
46914 -       
46915 +
46916         if (!fam_dir) return;
46917 -       
46918 +
46919         FAMCancelMonitor(fam_dir->fc, fam_dir->req);
46920 -       
46921 +
46922         buffer_free(fam_dir->name);
46923         free(fam_dir->req);
46924 -       
46925 +
46926         free(fam_dir);
46927  }
46928  #endif
46929 @@ -174,7 +162,7 @@
46930                 splay_tree *node = sc->files;
46931  
46932                 osize = sc->files->size;
46933 -                       
46934 +
46935                 stat_cache_entry_free(node->data);
46936                 sc->files = splaytree_delete(sc->files, node->key);
46937  
46938 @@ -187,12 +175,12 @@
46939         while (sc->dirs) {
46940                 int osize;
46941                 splay_tree *node = sc->dirs;
46942 -               
46943 +
46944                 osize = sc->dirs->size;
46945  
46946                 fam_dir_entry_free(node->data);
46947                 sc->dirs = splaytree_delete(sc->dirs, node->key);
46948 -               
46949 +
46950                 if (osize == 1) {
46951                         assert(NULL == sc->dirs);
46952                 } else {
46953 @@ -212,7 +200,7 @@
46954  static int stat_cache_attr_get(buffer *buf, char *name) {
46955         int attrlen;
46956         int ret;
46957 -       
46958 +
46959         attrlen = 1024;
46960         buffer_prepare_copy(buf, attrlen);
46961         attrlen--;
46962 @@ -251,15 +239,15 @@
46963             sc->fam) {
46964  
46965                 events = FAMPending(sc->fam);
46966 -       
46967 +
46968                 for (i = 0; i < events; i++) {
46969                         FAMEvent fe;
46970                         fam_dir_entry *fam_dir;
46971                         splay_tree *node;
46972                         int ndx;
46973 -               
46974 +
46975                         FAMNextEvent(sc->fam, &fe);
46976 -       
46977 +
46978                         /* handle event */
46979  
46980                         switch(fe.code) {
46981 @@ -280,7 +268,7 @@
46982  
46983                                 sc->dirs = splaytree_splay(sc->dirs, ndx);
46984                                 node = sc->dirs;
46985 -                       
46986 +
46987                                 if (node && (node->key == ndx)) {
46988                                         int osize = splaytree_size(sc->dirs);
46989  
46990 @@ -308,7 +296,7 @@
46991  
46992                 sc->fam = NULL;
46993         }
46994 -       
46995 +
46996         return HANDLER_GO_ON;
46997  }
46998  
46999 @@ -332,7 +320,7 @@
47000   *
47001   *
47002   *
47003 - * returns: 
47004 + * returns:
47005   *  - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
47006   *  - HANDLER_ERROR on stat() failed -> see errno for problem
47007   */
47008 @@ -348,16 +336,16 @@
47009         struct stat st;
47010         size_t k;
47011         int fd;
47012 -#ifdef DEBUG_STAT_CACHE        
47013 +#ifdef DEBUG_STAT_CACHE
47014         size_t i;
47015  #endif
47016  
47017         int file_ndx;
47018         splay_tree *file_node = NULL;
47019  
47020 -       *ret_sce = NULL; 
47021 +       *ret_sce = NULL;
47022  
47023 -       /* 
47024 +       /*
47025          * check if the directory for this file has changed
47026          */
47027  
47028 @@ -366,23 +354,23 @@
47029         file_ndx = hashme(name);
47030         sc->files = splaytree_splay(sc->files, file_ndx);
47031  
47032 -#ifdef DEBUG_STAT_CACHE        
47033 +#ifdef DEBUG_STAT_CACHE
47034         for (i = 0; i < ctrl.used; i++) {
47035                 if (ctrl.ptr[i] == file_ndx) break;
47036         }
47037  #endif
47038  
47039         if (sc->files && (sc->files->key == file_ndx)) {
47040 -#ifdef DEBUG_STAT_CACHE        
47041 +#ifdef DEBUG_STAT_CACHE
47042                 /* it was in the cache */
47043                 assert(i < ctrl.used);
47044  #endif
47045 -               
47046 -               /* we have seen this file already and 
47047 +
47048 +               /* we have seen this file already and
47049                  * don't stat() it again in the same second */
47050  
47051                 file_node = sc->files;
47052 -               
47053 +
47054                 sce = file_node->data;
47055  
47056                 /* check if the name is the same, we might have a collision */
47057 @@ -390,7 +378,7 @@
47058                 if (buffer_is_equal(name, sce->name)) {
47059                         if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
47060                                 if (sce->stat_ts == srv->cur_ts) {
47061 -                                       *ret_sce = sce; 
47062 +                                       *ret_sce = sce;
47063                                         return HANDLER_GO_ON;
47064                                 }
47065                         }
47066 @@ -400,15 +388,15 @@
47067                          * file_node is used by the FAM check below to see if we know this file
47068                          * and if we can save a stat().
47069                          *
47070 -                        * BUT, the sce is not reset here as the entry into the cache is ok, we 
47071 +                        * BUT, the sce is not reset here as the entry into the cache is ok, we
47072                          * it is just not pointing to our requested file.
47073 -                        * 
47074 +                        *
47075                          *  */
47076  
47077                         file_node = NULL;
47078                 }
47079         } else {
47080 -#ifdef DEBUG_STAT_CACHE        
47081 +#ifdef DEBUG_STAT_CACHE
47082                 if (i != ctrl.used) {
47083                         fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr);
47084                 }
47085 @@ -424,23 +412,23 @@
47086                 }
47087  
47088                 dir_ndx = hashme(sc->dir_name);
47089 -               
47090 +
47091                 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
47092 -               
47093 +
47094                 if (sc->dirs && (sc->dirs->key == dir_ndx)) {
47095                         dir_node = sc->dirs;
47096                 }
47097 -               
47098 +
47099                 if (dir_node && file_node) {
47100                         /* we found a file */
47101 -                       
47102 +
47103                         sce = file_node->data;
47104                         fam_dir = dir_node->data;
47105 -                       
47106 +
47107                         if (fam_dir->version == sce->dir_version) {
47108                                 /* the stat()-cache entry is still ok */
47109 -                               
47110 -                               *ret_sce = sce; 
47111 +
47112 +                               *ret_sce = sce;
47113                                 return HANDLER_GO_ON;
47114                         }
47115                 }
47116 @@ -448,7 +436,7 @@
47117  #endif
47118  
47119         /*
47120 -        * *lol* 
47121 +        * *lol*
47122          * - open() + fstat() on a named-pipe results in a (intended) hang.
47123          * - stat() if regualar file + open() to see if we can read from it is better
47124          *
47125 @@ -469,16 +457,16 @@
47126  
47127         if (NULL == sce) {
47128                 int osize = 0;
47129 -                      
47130 +
47131                 if (sc->files) {
47132                         osize = sc->files->size;
47133                 }
47134  
47135                 sce = stat_cache_entry_init();
47136                 buffer_copy_string_buffer(sce->name, name);
47137 -               
47138 -               sc->files = splaytree_insert(sc->files, file_ndx, sce); 
47139 -#ifdef DEBUG_STAT_CACHE        
47140 +
47141 +               sc->files = splaytree_insert(sc->files, file_ndx, sce);
47142 +#ifdef DEBUG_STAT_CACHE
47143                 if (ctrl.size == 0) {
47144                         ctrl.size = 16;
47145                         ctrl.used = 0;
47146 @@ -499,29 +487,29 @@
47147         sce->st = st;
47148         sce->stat_ts = srv->cur_ts;
47149  
47150 -       /* catch the obvious symlinks 
47151 +       /* catch the obvious symlinks
47152          *
47153          * this is not a secure check as we still have a race-condition between
47154 -        * the stat() and the open. We can only solve this by 
47155 +        * the stat() and the open. We can only solve this by
47156          * 1. open() the file
47157          * 2. fstat() the fd
47158          *
47159          * and keeping the file open for the rest of the time. But this can
47160          * only be done at network level.
47161 -        * 
47162 +        *
47163          * */
47164         if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
47165                 return HANDLER_ERROR;
47166         }
47167  
47168 -       if (S_ISREG(st.st_mode)) {      
47169 +       if (S_ISREG(st.st_mode)) {
47170                 /* determine mimetype */
47171                 buffer_reset(sce->content_type);
47172 -               
47173 +
47174                 for (k = 0; k < con->conf.mimetypes->used; k++) {
47175                         data_string *ds = (data_string *)con->conf.mimetypes->data[k];
47176                         buffer *type = ds->key;
47177 -               
47178 +
47179                         if (type->used == 0) continue;
47180  
47181                         /* check if the right side is the same */
47182 @@ -538,8 +526,10 @@
47183                         stat_cache_attr_get(sce->content_type, name->ptr);
47184                 }
47185  #endif
47186 +       } else if (S_ISDIR(st.st_mode)) {
47187 +               etag_create(sce->etag, &(sce->st));
47188         }
47189 -               
47190 +
47191  #ifdef HAVE_FAM_H
47192         if (sc->fam &&
47193             (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
47194 @@ -549,19 +539,19 @@
47195                         fam_dir->fc = sc->fam;
47196  
47197                         buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
47198 -                       
47199 +
47200                         fam_dir->version = 1;
47201 -                       
47202 +
47203                         fam_dir->req = calloc(1, sizeof(FAMRequest));
47204 -                       
47205 -                       if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr, 
47206 +
47207 +                       if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47208                                                      fam_dir->req, fam_dir)) {
47209 -                               
47210 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
47211 -                                               "monitoring dir failed:", 
47212 -                                               fam_dir->name, 
47213 +
47214 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
47215 +                                               "monitoring dir failed:",
47216 +                                               fam_dir->name,
47217                                                 FamErrlist[FAMErrno]);
47218 -                               
47219 +
47220                                 fam_dir_entry_free(fam_dir);
47221                         } else {
47222                                 int osize = 0;
47223 @@ -570,7 +560,7 @@
47224                                         osize = sc->dirs->size;
47225                                 }
47226  
47227 -                               sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir); 
47228 +                               sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47229                                 assert(sc->dirs);
47230                                 assert(sc->dirs->data == fam_dir);
47231                                 assert(osize == (sc->dirs->size - 1));
47232 @@ -578,9 +568,9 @@
47233                 } else {
47234                         fam_dir = dir_node->data;
47235                 }
47236 -               
47237 +
47238                 /* bind the fam_fc to the stat() cache entry */
47239 -                       
47240 +
47241                 if (fam_dir) {
47242                         sce->dir_version = fam_dir->version;
47243                         sce->dir_ndx     = dir_ndx;
47244 @@ -594,11 +584,11 @@
47245  }
47246  
47247  /**
47248 - * remove stat() from cache which havn't been stat()ed for 
47249 + * remove stat() from cache which havn't been stat()ed for
47250   * more than 10 seconds
47251 - * 
47252   *
47253 - * walk though the stat-cache, collect the ids which are too old 
47254 + *
47255 + * walk though the stat-cache, collect the ids which are too old
47256   * and remove them in a second loop
47257   */
47258  
47259 @@ -639,9 +629,9 @@
47260                 sc->files = splaytree_splay(sc->files, ndx);
47261  
47262                 node = sc->files;
47263 -               
47264 +
47265                 if (node && (node->key == ndx)) {
47266 -#ifdef DEBUG_STAT_CACHE        
47267 +#ifdef DEBUG_STAT_CACHE
47268                         size_t j;
47269                         int osize = splaytree_size(sc->files);
47270                         stat_cache_entry *sce = node->data;
47271 @@ -649,7 +639,7 @@
47272                         stat_cache_entry_free(node->data);
47273                         sc->files = splaytree_delete(sc->files, ndx);
47274  
47275 -#ifdef DEBUG_STAT_CACHE        
47276 +#ifdef DEBUG_STAT_CACHE
47277                         for (j = 0; j < ctrl.used; j++) {
47278                                 if (ctrl.ptr[j] == ndx) {
47279                                         ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
47280 --- ../lighttpd-1.4.11/src/stream.c     2005-09-23 21:50:15.000000000 +0300
47281 +++ lighttpd-1.4.12/src/stream.c        2006-07-11 22:07:53.000000000 +0300
47282 @@ -1,7 +1,6 @@
47283  #include <sys/types.h>
47284  #include <sys/stat.h>
47285  
47286 -#include <unistd.h> 
47287  #include <fcntl.h>
47288  
47289  #include "stream.h"
47290 @@ -10,6 +9,7 @@
47291  #endif
47292  
47293  #include "sys-mmap.h"
47294 +#include "sys-files.h"
47295  
47296  #ifndef O_BINARY
47297  # define O_BINARY 0
47298 @@ -19,39 +19,39 @@
47299         struct stat st;
47300  #ifdef HAVE_MMAP
47301         int fd;
47302 -#elif defined __WIN32
47303 +#elif defined _WIN32
47304         HANDLE *fh, *mh;
47305         void *p;
47306  #endif
47307  
47308         f->start = NULL;
47309 -       
47310 +
47311         if (-1 == stat(fn->ptr, &st)) {
47312                 return -1;
47313         }
47314 -       
47315 +
47316         f->size = st.st_size;
47317  
47318  #ifdef HAVE_MMAP
47319         if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
47320                 return -1;
47321         }
47322 -       
47323 +
47324         f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
47325 -       
47326 +
47327         close(fd);
47328 -       
47329 +
47330         if (MAP_FAILED == f->start) {
47331                 return -1;
47332         }
47333  
47334 -#elif defined __WIN32
47335 -       fh = CreateFile(fn->ptr, 
47336 -                       GENERIC_READ, 
47337 -                       FILE_SHARE_READ, 
47338 -                       NULL, 
47339 -                       OPEN_EXISTING, 
47340 -                       FILE_ATTRIBUTE_READONLY, 
47341 +#elif defined _WIN32
47342 +       fh = CreateFile(fn->ptr,
47343 +                       GENERIC_READ,
47344 +                       FILE_SHARE_READ,
47345 +                       NULL,
47346 +                       OPEN_EXISTING,
47347 +                       FILE_ATTRIBUTE_READONLY,
47348                         NULL);
47349  
47350         if (!fh) return -1;
47351 @@ -66,7 +66,7 @@
47352         if (!mh) {
47353                 LPVOID lpMsgBuf;
47354                 FormatMessage(
47355 -                       FORMAT_MESSAGE_ALLOCATE_BUFFER | 
47356 +                       FORMAT_MESSAGE_ALLOCATE_BUFFER |
47357                         FORMAT_MESSAGE_FROM_SYSTEM,
47358                         NULL,
47359                         GetLastError(),
47360 @@ -76,7 +76,7 @@
47361  
47362                 return -1;
47363         }
47364 -       
47365 +
47366         p = MapViewOfFile(mh,
47367                         FILE_MAP_READ,
47368                         0,
47369 @@ -87,9 +87,9 @@
47370  
47371         f->start = p;
47372  #else
47373 -# error no mmap found  
47374 +# error no mmap found
47375  #endif
47376 -       
47377 +
47378         return 0;
47379  }
47380  
47381 --- ../lighttpd-1.4.11/src/sys-files.h  1970-01-01 03:00:00.000000000 +0300
47382 +++ lighttpd-1.4.12/src/sys-files.h     2006-07-11 22:07:53.000000000 +0300
47383 @@ -0,0 +1,67 @@
47384 +#ifndef _SYS_FILES_H_
47385 +#define _SYS_FILES_H_
47386 +
47387 +#define DIR_SEPERATOR_UNIX '/'
47388 +#define DIR_SEPERATOR_WIN '\\'
47389 +
47390 +#ifdef _WIN32
47391 +#include <windows.h>
47392 +#include <io.h>     /* open */
47393 +#include <direct.h> /* chdir */
47394 +
47395 +#include "buffer.h"
47396 +
47397 +#define DIR_SEPERATOR DIR_SEPERATOR_WIN
47398 +
47399 +#define __S_ISTYPE(mode, mask)  (((mode) & _S_IFMT) == (mask))
47400 +
47401 +#define S_ISDIR(mode)    __S_ISTYPE((mode), _S_IFDIR)
47402 +#define S_ISCHR(mode)    __S_ISTYPE((mode), _S_IFCHR)
47403 +#define S_ISBLK(mode)    __S_ISTYPE((mode), _S_IFBLK)
47404 +#define S_ISREG(mode)    __S_ISTYPE((mode), _S_IFREG)
47405 +/* we don't support symlinks */
47406 +#define S_ISLNK(mode)    0
47407 +
47408 +#define lstat stat
47409 +#define mkstemp mktemp
47410 +#define mkdir(x, y) mkdir(x)
47411 +
47412 +struct dirent {
47413 +    const char *d_name;
47414 +};
47415 +
47416 +typedef struct {
47417 +    HANDLE h;
47418 +    WIN32_FIND_DATA finddata;
47419 +    struct dirent dent;
47420 +} DIR;
47421 +
47422 +DIR *opendir(const char *dn);
47423 +struct dirent *readdir(DIR *d);
47424 +void closedir(DIR *d);
47425 +
47426 +buffer *filename_unix2local(buffer *b);
47427 +buffer *pathname_unix2local(buffer *b);
47428 +
47429 +#else
47430 +#include <unistd.h>
47431 +#include <dirent.h>
47432 +
47433 +#define DIR_SEPERATOR DIR_SEPERATOR_UNIX
47434 +
47435 +#define filename_unix2local(x) (x)
47436 +#define pathname_unix2local(x) (x)
47437 +#endif
47438 +
47439 +#define PATHNAME_APPEND_SLASH(x) \
47440 +       if (x->used > 1 && x->ptr[x->used - 2] != DIR_SEPERATOR) { \
47441 +        char sl[2] = { DIR_SEPERATOR, 0 }; \
47442 +        BUFFER_APPEND_STRING_CONST(x, sl); \
47443 +    }
47444 +
47445 +#ifndef O_LARGEFILE
47446 +# define O_LARGEFILE 0
47447 +#endif
47448 +
47449 +#endif
47450 +
47451 --- ../lighttpd-1.4.11/src/sys-mmap.h   2005-08-11 01:26:34.000000000 +0300
47452 +++ lighttpd-1.4.12/src/sys-mmap.h      2006-07-11 22:07:52.000000000 +0300
47453 @@ -1,7 +1,7 @@
47454  #ifndef WIN32_MMAP_H
47455  #define WIN32_MMAP_H
47456  
47457 -#ifdef __WIN32
47458 +#ifdef _WIN32
47459  
47460  #define MAP_FAILED -1
47461  #define PROT_SHARED 0
47462 --- ../lighttpd-1.4.11/src/sys-process.h        1970-01-01 03:00:00.000000000 +0300
47463 +++ lighttpd-1.4.12/src/sys-process.h   2006-07-15 22:43:21.000000000 +0300
47464 @@ -0,0 +1,17 @@
47465 +#ifndef _SYS_PROCESS_H_
47466 +#define _SYS_PROCESS_H_
47467 +
47468 +#ifdef _WIN32
47469 +#include <process.h>
47470 +#define pid_t int
47471 +/* win32 has no fork() */
47472 +#define kill(x, y)
47473 +#define getpid() 0
47474 +
47475 +#else
47476 +#include <sys/wait.h>
47477 +#include <unistd.h>
47478 +#endif
47479 +
47480 +#endif
47481 +
47482 --- ../lighttpd-1.4.11/src/sys-socket.h 2005-08-11 01:26:39.000000000 +0300
47483 +++ lighttpd-1.4.12/src/sys-socket.h    2006-07-15 22:43:21.000000000 +0300
47484 @@ -1,15 +1,26 @@
47485  #ifndef WIN32_SOCKET_H
47486  #define WIN32_SOCKET_H
47487  
47488 -#ifdef __WIN32
47489 +#ifdef _WIN32
47490  
47491  #include <winsock2.h>
47492  
47493  #define ECONNRESET WSAECONNRESET
47494  #define EINPROGRESS WSAEINPROGRESS
47495  #define EALREADY WSAEALREADY
47496 +#define ENOTCONN WSAENOTCONN
47497 +#define EWOULDBLOCK WSAEWOULDBLOCK
47498  #define ioctl ioctlsocket
47499  #define hstrerror(x) ""
47500 +#define STDIN_FILENO 0
47501 +#define STDOUT_FILENO 1
47502 +#define STDERR_FILENO 2
47503 +#define ssize_t int
47504 +
47505 +int inet_aton(const char *cp, struct in_addr *inp);
47506 +#define HAVE_INET_ADDR
47507 +#undef HAVE_INET_ATON
47508 +
47509  #else
47510  #include <sys/socket.h>
47511  #include <sys/ioctl.h>
47512 @@ -18,7 +29,23 @@
47513  #include <sys/un.h>
47514  #include <arpa/inet.h>
47515  
47516 +#ifndef SUN_LEN
47517 +#define SUN_LEN(su) \
47518 +        (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
47519 +#endif
47520 +
47521  #include <netdb.h>
47522  #endif
47523  
47524 +typedef union {
47525 +#ifdef HAVE_IPV6
47526 +       struct sockaddr_in6 ipv6;
47527 +#endif
47528 +       struct sockaddr_in ipv4;
47529 +#ifdef HAVE_SYS_UN_H
47530 +       struct sockaddr_un un;
47531 +#endif
47532 +       struct sockaddr plain;
47533 +} sock_addr;
47534 +
47535  #endif
47536 --- ../lighttpd-1.4.11/src/sys-strings.h        1970-01-01 03:00:00.000000000 +0300
47537 +++ lighttpd-1.4.12/src/sys-strings.h   2006-07-11 22:07:51.000000000 +0300
47538 @@ -0,0 +1,11 @@
47539 +#ifndef _SYS_STRINGS_H_
47540 +#define _SYS_STRINGS_H_
47541 +
47542 +#ifdef _WIN32
47543 +#define strcasecmp stricmp
47544 +#define strncasecmp strnicmp
47545 +#define strtoll(p, e, b) _strtoi64(p, e, b)
47546 +#endif
47547 +
47548 +#endif
47549 +
47550 --- ../lighttpd-1.4.11/tests/LightyTest.pm      2006-01-14 20:32:31.000000000 +0200
47551 +++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-11 22:07:53.000000000 +0300
47552 @@ -87,14 +87,14 @@
47553         # pre-process configfile if necessary
47554         #
47555  
47556 -       unlink($self->{TESTDIR}."/tmp/cfg.file");
47557 -       system("cat ".$self->{SRCDIR}."/".$self->{CONFIGFILE}.' | perl -pe "s#\@SRCDIR\@#'.$self->{BASEDIR}.'/tests/#" > '.$self->{TESTDIR}.'/tmp/cfg.file');
47558 +       $ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
47559 +       $ENV{'PORT'} = $self->{PORT};
47560  
47561         unlink($self->{LIGHTTPD_PIDFILE});
47562         if (1) {
47563 -               system($self->{LIGHTTPD_PATH}." -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH});
47564 +               system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH});
47565         } else {
47566 -               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}." &");
47567 +               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}." &");
47568         }
47569  
47570         select(undef, undef, undef, 0.1);
47571 @@ -184,7 +184,7 @@
47572                                         (my $h = $1) =~ tr/[A-Z]/[a-z]/;
47573  
47574                                         if (defined $resp_hdr{$h}) {
47575 -                                               diag(sprintf("header %s is duplicated: %s and %s\n",
47576 +                                               diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
47577                                                              $h, $resp_hdr{$h}, $2));
47578                                         } else {
47579                                                 $resp_hdr{$h} = $2;
47580 @@ -196,6 +196,9 @@
47581                         }
47582                 }
47583  
47584 +               $t->{etag} = $resp_hdr{'etag'};
47585 +               $t->{date} = $resp_hdr{'date'};
47586 +
47587                 # check length
47588                 if (defined $resp_hdr{"content-length"}) {
47589                         $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
47590 --- ../lighttpd-1.4.11/tests/Makefile.am        2005-09-16 15:48:40.000000000 +0300
47591 +++ lighttpd-1.4.12/tests/Makefile.am   2006-07-15 22:43:22.000000000 +0300
47592 @@ -39,10 +39,18 @@
47593        mod-redirect.t \
47594        mod-userdir.t \
47595        mod-rewrite.t \
47596 +      mod-proxy.t \
47597        request.t \
47598        mod-ssi.t \
47599        LightyTest.pm \
47600 -      mod-setenv.t 
47601 +      mod-setenv.t \
47602 +      lowercase.t \
47603 +      lowercase.conf \
47604 +      proxy.conf \
47605 +      cachable.t \
47606 +      default.conf \
47607 +      proxy-backend-1.conf \
47608 +      proxy-backend-2.conf 
47609  
47610  
47611  TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir) 
47612 --- ../lighttpd-1.4.11/tests/bug-06.conf        2005-08-27 17:44:19.000000000 +0300
47613 +++ lighttpd-1.4.12/tests/bug-06.conf   2006-07-11 22:07:53.000000000 +0300
47614 @@ -1,5 +1,5 @@
47615 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47616 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47617 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47618 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47619  
47620  ## bind to port (default: 80)
47621  server.port                 = 2048
47622 @@ -8,7 +8,7 @@
47623  
47624  ## bind to localhost (default: all interfaces)
47625  server.bind                = "localhost"
47626 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47627 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47628  server.name                = "www.example.org"
47629  server.tag                 = "Apache 1.3.29"
47630  
47631 @@ -59,7 +59,7 @@
47632  ######################## MODULE CONFIG ############################
47633  
47634  
47635 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47636 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47637  
47638  mimetype.assign             = ( ".png"  => "image/png", 
47639                                  ".jpg"  => "image/jpeg",
47640 @@ -77,7 +77,7 @@
47641                                 ".c"    => "text/plain",
47642                                 ".conf" => "text/plain" )
47643  
47644 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47645 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47646  compress.filetype           = ("text/plain", "text/html")
47647  
47648  setenv.add-environment      = ( "TRAC_ENV" => "foo")
47649 @@ -90,7 +90,7 @@
47650                                     "host" => "127.0.0.1",
47651                                     "port" => 1026,
47652  #                                  "mode" => "authorizer",
47653 -#                                  "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47654 +#                                  "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47655                                   )
47656                                 )
47657                               )
47658 @@ -106,7 +106,7 @@
47659  ssl.pemfile                 = "server.pem"
47660  
47661  auth.backend                = "plain"
47662 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47663 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47664  auth.backend.plain.groupfile = "lighttpd.group"
47665  
47666  auth.backend.ldap.hostname  = "localhost"
47667 @@ -149,15 +149,15 @@
47668  status.config-url           = "/server-config"
47669  
47670  simple-vhost.document-root  = "pages"
47671 -simple-vhost.server-root    = "@SRCDIR@/tmp/lighttpd/servers/"
47672 +simple-vhost.server-root    = env.SRCDIR + "/tmp/lighttpd/servers/"
47673  simple-vhost.default-host   = "www.example.org"
47674  
47675  $HTTP["host"] == "vvv.example.org" {
47676 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47677 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47678  }
47679  
47680  $HTTP["host"] == "zzz.example.org" {
47681 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47682 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47683    server.name = "zzz.example.org"
47684  }
47685  
47686 --- ../lighttpd-1.4.11/tests/bug-12.conf        2005-08-27 17:44:19.000000000 +0300
47687 +++ lighttpd-1.4.12/tests/bug-12.conf   2006-07-11 22:07:53.000000000 +0300
47688 @@ -1,5 +1,5 @@
47689 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47690 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47691 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47692 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47693  
47694  ## bind to port (default: 80)
47695  server.port                 = 2048
47696 @@ -8,7 +8,7 @@
47697  
47698  ## bind to localhost (default: all interfaces)
47699  server.bind                = "localhost"
47700 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47701 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47702  server.name                = "www.example.org"
47703  server.tag                 = "Apache 1.3.29"
47704  
47705 @@ -61,7 +61,7 @@
47706  ######################## MODULE CONFIG ############################
47707  
47708  
47709 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47710 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47711  
47712  mimetype.assign             = ( ".png"  => "image/png", 
47713                                  ".jpg"  => "image/jpeg",
47714 @@ -79,7 +79,7 @@
47715                                 ".c"    => "text/plain",
47716                                 ".conf" => "text/plain" )
47717  
47718 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47719 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47720  compress.filetype           = ("text/plain", "text/html")
47721  
47722  setenv.add-environment      = ( "TRAC_ENV" => "foo")
47723 @@ -92,7 +92,7 @@
47724                                     "host" => "127.0.0.1",
47725                                     "port" => 1026,
47726  #                                  "mode" => "authorizer",
47727 -#                                  "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47728 +#                                  "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47729                                   )
47730                                 )
47731                               )
47732 @@ -108,7 +108,7 @@
47733  ssl.pemfile                 = "server.pem"
47734  
47735  auth.backend                = "plain"
47736 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47737 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47738  auth.backend.plain.groupfile = "lighttpd.group"
47739  
47740  auth.backend.ldap.hostname  = "localhost"
47741 @@ -151,15 +151,15 @@
47742  status.config-url           = "/server-config"
47743  
47744  simple-vhost.document-root  = "pages"
47745 -simple-vhost.server-root    = "@SRCDIR@/tmp/lighttpd/servers/"
47746 +simple-vhost.server-root    = env.SRCDIR + "/tmp/lighttpd/servers/"
47747  simple-vhost.default-host   = "www.example.org"
47748  
47749  $HTTP["host"] == "vvv.example.org" {
47750 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47751 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47752  }
47753  
47754  $HTTP["host"] == "zzz.example.org" {
47755 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47756 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47757    server.name = "zzz.example.org"
47758  }
47759  
47760 --- ../lighttpd-1.4.11/tests/cachable.t 1970-01-01 03:00:00.000000000 +0300
47761 +++ lighttpd-1.4.12/tests/cachable.t    2006-07-11 22:07:53.000000000 +0300
47762 @@ -0,0 +1,112 @@
47763 +#!/usr/bin/env perl
47764 +BEGIN {
47765 +    # add current source dir to the include-path
47766 +    # we need this for make distcheck
47767 +   (my $srcdir = $0) =~ s#/[^/]+$#/#;
47768 +   unshift @INC, $srcdir;
47769 +}
47770 +
47771 +use strict;
47772 +use IO::Socket;
47773 +use Test::More tests => 12;
47774 +use LightyTest;
47775 +
47776 +my $tf = LightyTest->new();
47777 +my $t;
47778 +
47779 +$tf->{CONFIGFILE} = 'lighttpd.conf';
47780 +    
47781 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
47782 +
47783 +## check if If-Modified-Since, If-None-Match works
47784 +
47785 +$t->{REQUEST}  = ( <<EOF
47786 +GET / HTTP/1.0
47787 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
47788 +EOF
47789 + );
47790 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47791 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
47792 +
47793 +$t->{REQUEST}  = ( <<EOF
47794 +GET / HTTP/1.0
47795 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47796 +EOF
47797 + );
47798 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47799 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
47800 +
47801 +my $now = $t->{date};
47802 +
47803 +$t->{REQUEST}  = ( <<EOF
47804 +GET / HTTP/1.0
47805 +If-Modified-Since: $now
47806 +EOF
47807 + );
47808 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47809 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
47810 +
47811 +$t->{REQUEST}  = ( <<EOF
47812 +GET / HTTP/1.0
47813 +If-Modified-Since: $now; foo
47814 +EOF
47815 + );
47816 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47817 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
47818 +
47819 +$t->{REQUEST}  = ( <<EOF
47820 +GET / HTTP/1.0
47821 +If-None-Match: foo
47822 +EOF
47823 + );
47824 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47825 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47826 +
47827 +my $etag = $t->{etag};
47828 +
47829 +$t->{REQUEST}  = ( <<EOF
47830 +GET / HTTP/1.0
47831 +If-None-Match: $etag
47832 +EOF
47833 + );
47834 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47835 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47836 +
47837 +$t->{REQUEST}  = ( <<EOF
47838 +GET / HTTP/1.0
47839 +If-None-Match: $etag
47840 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47841 +EOF
47842 + );
47843 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47844 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
47845 +
47846 +$t->{REQUEST}  = ( <<EOF
47847 +GET / HTTP/1.0
47848 +If-None-Match: $etag
47849 +If-Modified-Since: $now; foo
47850 +EOF
47851 + );
47852 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47853 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
47854 +
47855 +$t->{REQUEST}  = ( <<EOF
47856 +GET / HTTP/1.0
47857 +If-None-Match: Foo
47858 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47859 +EOF
47860 + );
47861 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47862 +ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
47863 +
47864 +$t->{REQUEST}  = ( <<EOF
47865 +GET / HTTP/1.0
47866 +If-None-Match: $etag
47867 +If-Modified-Since: $now foo
47868 +EOF
47869 + );
47870 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
47871 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
47872 +
47873 +ok($tf->stop_proc == 0, "Stopping lighttpd");
47874 +
47875 --- ../lighttpd-1.4.11/tests/condition.conf     2005-08-27 17:44:19.000000000 +0300
47876 +++ lighttpd-1.4.12/tests/condition.conf        2006-07-11 22:07:53.000000000 +0300
47877 @@ -2,15 +2,15 @@
47878  debug.log-request-handling = "enable"
47879  debug.log-condition-handling = "enable"
47880  
47881 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47882 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47883 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47884 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47885  
47886  ## bind to port (default: 80)
47887  server.port                 = 2048
47888  
47889  ## bind to localhost (default: all interfaces)
47890  server.bind                = "localhost"
47891 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47892 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47893  server.name                = "www.example.org"
47894  server.tag                 = "Apache 1.3.29"
47895  
47896 @@ -22,25 +22,25 @@
47897  ######################## MODULE CONFIG ############################
47898  
47899  
47900 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47901 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47902  
47903  mimetype.assign             = ( ".html" => "text/html" )
47904  
47905  url.redirect = ("^" => "/default")
47906  
47907  $HTTP["host"] == "www.example.org" {
47908 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47909 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47910    server.name = "www.example.org"
47911    url.redirect = ("^" => "/match_1")
47912  }
47913  else $HTTP["host"] == "test1.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    server.name = "test1.example.org"
47917    url.redirect = ("^" => "/match_2")
47918  }
47919  # comments
47920  else $HTTP["host"] == "test2.example.org" {
47921 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47922 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47923    server.name = "test2.example.org"
47924    url.redirect = ("^" => "/match_3")
47925  }
47926 @@ -48,7 +48,7 @@
47927          # comments
47928  
47929  else $HTTP["host"] == "test3.example.org" {
47930 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47931 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47932    server.name = "test3.example.org"
47933    url.redirect = ("^" => "/match_4")
47934  
47935 --- ../lighttpd-1.4.11/tests/core-keepalive.t   2005-11-17 15:54:19.000000000 +0200
47936 +++ lighttpd-1.4.12/tests/core-keepalive.t      2006-07-11 22:07:53.000000000 +0300
47937 @@ -40,7 +40,7 @@
47938  
47939  GET /12345.txt HTTP/1.0
47940  Host: 123.example.org
47941 -Connection: keep-alive
47942 +Connection: close
47943  EOF
47944   );
47945  $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47946 --- ../lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries  2006-03-09 19:21:49.000000000 +0200
47947 +++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries     2006-07-15 22:43:22.000000000 +0300
47948 @@ -9,5 +9,6 @@
47949     last-author="jan"
47950     kind="dir"
47951     uuid="152afb58-edef-0310-8abb-c4023f1b3aa9"
47952 -   revision="1040"/>
47953 +   repos="svn://svn.lighttpd.net/lighttpd"
47954 +   revision="1173"/>
47955  </wc-entries>
47956 --- ../lighttpd-1.4.11/tests/fastcgi-10.conf    2005-08-31 23:36:34.000000000 +0300
47957 +++ lighttpd-1.4.12/tests/fastcgi-10.conf       2006-07-11 22:07:53.000000000 +0300
47958 @@ -1,12 +1,12 @@
47959 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47960 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47961 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47962 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47963  
47964  ## bind to port (default: 80)
47965  server.port                 = 2048
47966  
47967  ## bind to localhost (default: all interfaces)
47968  server.bind                = "localhost"
47969 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47970 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47971  server.name                = "www.example.org"
47972  server.tag                 = "Apache 1.3.29"
47973  
47974 @@ -44,7 +44,7 @@
47975  ######################## MODULE CONFIG ############################
47976  
47977  
47978 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47979 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47980  
47981  mimetype.assign             = ( ".png"  => "image/png", 
47982                                  ".jpg"  => "image/jpeg",
47983 @@ -62,7 +62,7 @@
47984                                 ".c"    => "text/plain",
47985                                 ".conf" => "text/plain" )
47986  
47987 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47988 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47989  compress.filetype           = ("text/plain", "text/html")
47990  
47991  fastcgi.debug               = 0
47992 @@ -85,7 +85,7 @@
47993  ssl.pemfile                 = "server.pem"
47994  
47995  auth.backend                = "plain"
47996 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47997 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47998  auth.backend.plain.groupfile = "lighttpd.group"
47999  
48000  auth.backend.ldap.hostname  = "localhost"
48001 @@ -128,11 +128,11 @@
48002  status.config-url           = "/server-config"
48003  
48004  $HTTP["host"] == "vvv.example.org" {
48005 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48006 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48007  }
48008  
48009  $HTTP["host"] == "zzz.example.org" {
48010 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48011 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48012    server.name = "zzz.example.org"
48013  }
48014  
48015 --- ../lighttpd-1.4.11/tests/fastcgi-13.conf    2006-01-03 12:38:17.000000000 +0200
48016 +++ lighttpd-1.4.12/tests/fastcgi-13.conf       2006-07-11 22:07:53.000000000 +0300
48017 @@ -1,5 +1,5 @@
48018 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48019 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48020 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48021 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48022  
48023  debug.log-request-header   = "enable"
48024  debug.log-response-header  = "enable"
48025 @@ -10,7 +10,7 @@
48026  
48027  ## bind to localhost (default: all interfaces)
48028  server.bind                = "localhost"
48029 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48030 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48031  server.name                = "www.example.org"
48032  server.tag                 = "Apache 1.3.29"
48033  
48034 @@ -59,7 +59,7 @@
48035  ######################## MODULE CONFIG ############################
48036  
48037  
48038 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48039 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48040  
48041  mimetype.assign             = ( ".png"  => "image/png", 
48042                                  ".jpg"  => "image/jpeg",
48043 @@ -77,7 +77,7 @@
48044                                 ".c"    => "text/plain",
48045                                 ".conf" => "text/plain" )
48046  
48047 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48048 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48049  compress.filetype           = ("text/plain", "text/html")
48050  
48051  fastcgi.debug               = 0
48052 @@ -102,7 +102,7 @@
48053  ssl.pemfile                 = "server.pem"
48054  
48055  auth.backend                = "plain"
48056 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48057 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48058  auth.backend.plain.groupfile = "lighttpd.group"
48059  
48060  auth.backend.ldap.hostname  = "localhost"
48061 @@ -145,11 +145,11 @@
48062  status.config-url           = "/server-config"
48063  
48064  $HTTP["host"] == "vvv.example.org" {
48065 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48066 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48067  }
48068  
48069  $HTTP["host"] == "zzz.example.org" {
48070 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48071 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48072    server.name = "zzz.example.org"
48073  }
48074  
48075 --- ../lighttpd-1.4.11/tests/fastcgi-auth.conf  2005-08-27 17:44:19.000000000 +0300
48076 +++ lighttpd-1.4.12/tests/fastcgi-auth.conf     2006-07-11 22:07:53.000000000 +0300
48077 @@ -1,5 +1,5 @@
48078 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48079 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48080 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48081 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48082  
48083  debug.log-request-header   = "enable"
48084  debug.log-response-header  = "enable"
48085 @@ -12,7 +12,7 @@
48086  
48087  ## bind to localhost (default: all interfaces)
48088  server.bind                = "localhost"
48089 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48090 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48091  server.name                = "www.example.org"
48092  server.tag                 = "Apache 1.3.29"
48093  
48094 @@ -61,7 +61,7 @@
48095  ######################## MODULE CONFIG ############################
48096  
48097  
48098 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48099 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48100  
48101  mimetype.assign             = ( ".png"  => "image/png", 
48102                                  ".jpg"  => "image/jpeg",
48103 @@ -79,7 +79,7 @@
48104                                 ".c"    => "text/plain",
48105                                 ".conf" => "text/plain" )
48106  
48107 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48108 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48109  compress.filetype           = ("text/plain", "text/html")
48110  
48111  fastcgi.debug               = 0
48112 @@ -87,9 +87,9 @@
48113                                    "grisu" => ( 
48114                                     "host" => "127.0.0.1",
48115                                     "port" => 20000,
48116 -                                   "bin-path" => "@SRCDIR@/fcgi-auth",
48117 +                                   "bin-path" => env.SRCDIR + "/fcgi-auth",
48118                                      "mode" => "authorizer",
48119 -                                    "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
48120 +                                    "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
48121                                     
48122                                   )
48123                                 )
48124 @@ -106,7 +106,7 @@
48125  ssl.pemfile                 = "server.pem"
48126  
48127  auth.backend                = "plain"
48128 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48129 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48130  auth.backend.plain.groupfile = "lighttpd.group"
48131  
48132  auth.backend.ldap.hostname  = "localhost"
48133 @@ -149,11 +149,11 @@
48134  status.config-url           = "/server-config"
48135  
48136  $HTTP["host"] == "vvv.example.org" {
48137 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48138 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48139  }
48140  
48141  $HTTP["host"] == "zzz.example.org" {
48142 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48143 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48144    server.name = "zzz.example.org"
48145  }
48146  
48147 --- ../lighttpd-1.4.11/tests/fastcgi-responder.conf     2005-08-27 17:44:19.000000000 +0300
48148 +++ lighttpd-1.4.12/tests/fastcgi-responder.conf        2006-07-11 22:07:53.000000000 +0300
48149 @@ -1,5 +1,5 @@
48150 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48151 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48152 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48153 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48154  
48155  #debug.log-request-header   = "enable"
48156  #debug.log-response-header  = "enable"
48157 @@ -15,7 +15,7 @@
48158  
48159  ## bind to localhost (default: all interfaces)
48160  server.bind                = "localhost"
48161 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48162 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48163  server.name                = "www.example.org"
48164  server.tag                 = "Apache 1.3.29"
48165  
48166 @@ -64,7 +64,7 @@
48167  ######################## MODULE CONFIG ############################
48168  
48169  
48170 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48171 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48172  
48173  mimetype.assign             = ( ".png"  => "image/png", 
48174                                  ".jpg"  => "image/jpeg",
48175 @@ -82,7 +82,7 @@
48176                                 ".c"    => "text/plain",
48177                                 ".conf" => "text/plain" )
48178  
48179 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48180 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48181  compress.filetype           = ("text/plain", "text/html")
48182  
48183  fastcgi.debug               = 0
48184 @@ -90,10 +90,11 @@
48185                                    "grisu" => ( 
48186                                     "host" => "127.0.0.1",
48187                                     "port" => 10000,
48188 -                                   "bin-path" => "@SRCDIR@/fcgi-responder",
48189 +                                   "bin-path" => env.SRCDIR + "/fcgi-responder",
48190                                     "check-local" => "disable",
48191                                     "max-procs" => 1,
48192 -                                   "min-procs" => 1
48193 +                                   "min-procs" => 1,
48194 +                                   "allow-x-send-file" => "enable",
48195                                   )
48196                                 )
48197                               )
48198 @@ -109,7 +110,7 @@
48199  ssl.pemfile                 = "server.pem"
48200  
48201  auth.backend                = "plain"
48202 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48203 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48204  auth.backend.plain.groupfile = "lighttpd.group"
48205  
48206  auth.backend.ldap.hostname  = "localhost"
48207 @@ -152,11 +153,11 @@
48208  status.config-url           = "/server-config"
48209  
48210  $HTTP["host"] == "vvv.example.org" {
48211 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48212 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48213  }
48214  
48215  $HTTP["host"] == "zzz.example.org" {
48216 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48217 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48218    server.name = "zzz.example.org"
48219  }
48220  
48221 --- ../lighttpd-1.4.11/tests/fcgi-responder.c   2005-08-11 01:26:55.000000000 +0300
48222 +++ lighttpd-1.4.12/tests/fcgi-responder.c      2006-07-11 22:07:53.000000000 +0300
48223 @@ -6,11 +6,17 @@
48224  int main () {
48225         int num_requests = 2;
48226         
48227 -       while (num_requests > 0 &&
48228 -              FCGI_Accept() >= 0) {
48229 -               char* p;
48230 -               
48231 -               if (NULL != (p = getenv("QUERY_STRING"))) {
48232 +       while (num_requests > 0 && FCGI_Accept() >= 0) {
48233 +               char* p = NULL;
48234 +               char* doc_root = NULL;
48235 +               char fname[4096];
48236 +               char* pfname = (char *)fname;
48237 +
48238 +               doc_root = getenv("DOCUMENT_ROOT");
48239 +               p = getenv("QUERY_STRING");
48240 +
48241 +               if (NULL != p && NULL != doc_root) {
48242 +                       snprintf(pfname, sizeof(fname), "%s/phpinfo.php", doc_root);
48243                         if (0 == strcmp(p, "lf")) {
48244                                 printf("Status: 200 OK\n\n");
48245                         } else if (0 == strcmp(p, "crlf")) {
48246 @@ -23,6 +29,18 @@
48247                                 printf("Status: 200 OK\r\n");
48248                                 fflush(stdout);
48249                                 printf("\r\n");
48250 +                       } else if (0 == strcmp(p,"x-lighttpd-send-file")) {
48251 +                               printf("Status: 200 OK\r\n");
48252 +                               printf("X-LIGHTTPD-send-file: %s\r\n", pfname);
48253 +                               printf("\r\n");
48254 +                       } else if (0 == strcmp(p,"xsendfile")) {
48255 +                               printf("Status: 200 OK\r\n");
48256 +                               printf("X-Sendfile: %s\r\n", pfname);
48257 +                               printf("\r\n");
48258 +                       } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
48259 +                               printf("Status: 200 OK\r\n");
48260 +                               printf("X-SeNdFiLe: %s\r\n", pfname);
48261 +                               printf("\r\n");
48262                         } else if (0 == strcmp(p, "die-at-end")) {
48263                                 printf("Status: 200 OK\r\n\r\n");
48264                                 num_requests--;
48265 --- ../lighttpd-1.4.11/tests/lighttpd.conf      2006-03-09 15:26:58.000000000 +0200
48266 +++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-11 22:07:53.000000000 +0300
48267 @@ -1,80 +1,18 @@
48268 -debug.log-request-handling = "enable"
48269 -debug.log-condition-handling = "enable"
48270 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48271 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48272 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48273 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48274 +server.tag = "Apache 1.3.29"
48275  
48276  ## 64 Mbyte ... nice limit
48277  server.max-request-size = 65000
48278  
48279 -## bind to port (default: 80)
48280 -server.port                 = 2048
48281 +include "default.conf"
48282  
48283 -## bind to localhost (default: all interfaces)
48284 -server.bind                = "localhost"
48285 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48286 -server.name                = "www.example.org"
48287 -server.tag                 = "Apache 1.3.29"
48288 -
48289 -server.dir-listing          = "enable"
48290 -
48291 -#server.event-handler        = "linux-sysepoll"
48292 -#server.event-handler        = "linux-rtsig"
48293 -
48294 -#server.modules.path         = ""
48295 -server.modules              = ( 
48296 -                               "mod_rewrite",
48297 -                               "mod_setenv",
48298 -                               "mod_secdownload",
48299 -                               "mod_access", 
48300 -                               "mod_auth",
48301 -#                              "mod_httptls",
48302 -                               "mod_status", 
48303 -                               "mod_expire",
48304 -                               "mod_simple_vhost",
48305 -                               "mod_redirect", 
48306 -#                              "mod_evhost",
48307 -#                              "mod_localizer",
48308 -                               "mod_fastcgi",
48309 -                               "mod_cgi",
48310 -                               "mod_compress",
48311 -                               "mod_userdir",
48312 -                               "mod_ssi",
48313 -                               "mod_accesslog" ) 
48314 -
48315 -server.indexfiles           = ( "index.php", "index.html", 
48316 -                                "index.htm", "default.htm" )
48317 -
48318 -
48319 -######################## MODULE CONFIG ############################
48320 -
48321 -ssi.extension = ( ".shtml" )
48322 -
48323 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48324 -
48325 -mimetype.assign             = ( ".png"  => "image/png", 
48326 -                                ".jpg"  => "image/jpeg",
48327 -                                ".jpeg" => "image/jpeg",
48328 -                                ".gif"  => "image/gif",
48329 -                                ".html" => "text/html",
48330 -                                ".htm"  => "text/html",
48331 -                                ".pdf"  => "application/pdf",
48332 -                                ".swf"  => "application/x-shockwave-flash",
48333 -                                ".spl"  => "application/futuresplash",
48334 -                                ".txt"  => "text/plain",
48335 -                                ".tar.gz" =>   "application/x-tgz",
48336 -                                ".tgz"  => "application/x-tgz",
48337 -                                ".gz"   => "application/x-gzip",
48338 -                               ".c"    => "text/plain",
48339 -                               ".conf" => "text/plain" )
48340 +setenv.add-request-header   = ( "FOO" => "foo")
48341 +setenv.add-response-header  = ( "BAR" => "foo")
48342  
48343  $HTTP["host"] == "cache.example.org" {
48344 -  compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48345 +  compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48346  }
48347 -compress.filetype           = ("text/plain", "text/html")
48348 -
48349 -setenv.add-environment      = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
48350 -setenv.add-request-header   = ( "FOO" => "foo")
48351 -setenv.add-response-header  = ( "BAR" => "foo")
48352  
48353  $HTTP["url"] =~ "\.pdf$" {
48354    server.range-requests = "disable"
48355 @@ -85,76 +23,31 @@
48356                                 "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48357                               )
48358                 
48359 -
48360 -cgi.assign                  = ( ".pl"  => "/usr/bin/perl",
48361 -                                ".cgi" => "/usr/bin/perl",
48362 -                               ".py"  => "/usr/bin/python" )
48363 -                       
48364 -userdir.include-user = ( "jan" )
48365 -userdir.path = "/"
48366 -
48367 -ssl.engine                  = "disable"
48368 -ssl.pemfile                 = "server.pem"
48369 -
48370  $HTTP["host"] == "auth-htpasswd.example.org" {
48371         auth.backend                = "htpasswd"
48372  }
48373  
48374 -auth.backend                = "plain"
48375 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48376 -
48377 -auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
48378 -
48379 -
48380 -auth.require                = ( "/server-status" => 
48381 -                                ( 
48382 -                                 "method"  => "digest",
48383 -                                 "realm"   => "download archiv",
48384 -                                 "require" => "group=www|user=jan|host=192.168.2.10"
48385 -                               ),
48386 -                               "/server-config" => 
48387 -                                ( 
48388 -                                 "method"  => "basic",
48389 -                                 "realm"   => "download archiv",
48390 -                                 "require" => "valid-user"
48391 -                               )
48392 -                              )
48393 -
48394 -url.access-deny             = ( "~", ".inc")
48395 -
48396 -url.rewrite                = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
48397 -                               "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48398 -
48399 -expire.url                  = ( "/expire/access" => "access 2 hours", 
48400 -                               "/expire/modification" => "access plus 1 seconds 2 minutes")
48401 -
48402 -#cache.cache-dir             = "/home/weigon/wwwroot/cache/"
48403 -
48404 -#### status module
48405 -status.status-url           = "/server-status"
48406 -status.config-url           = "/server-config"
48407 -
48408  $HTTP["host"] == "vvv.example.org" {
48409 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48410 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48411    secdownload.secret          = "verysecret"
48412 -  secdownload.document-root   = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48413 +  secdownload.document-root   = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48414    secdownload.uri-prefix      = "/sec/"
48415    secdownload.timeout         = 120
48416  }
48417  
48418  $HTTP["host"] == "zzz.example.org" {
48419 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48420 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48421    server.name = "zzz.example.org"
48422  }
48423  
48424  $HTTP["host"] == "no-simple.example.org" {
48425 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
48426 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/123.example.org/pages/"
48427    server.name = "zzz.example.org"
48428  }
48429  
48430  $HTTP["host"] !~ "(no-simple\.example\.org)" {
48431    simple-vhost.document-root  = "pages"
48432 -  simple-vhost.server-root    = "@SRCDIR@/tmp/lighttpd/servers/"
48433 +  simple-vhost.server-root    = env.SRCDIR + "/tmp/lighttpd/servers/"
48434    simple-vhost.default-host   = "www.example.org"
48435  }
48436  
48437 --- ../lighttpd-1.4.11/tests/lowercase.conf     1970-01-01 03:00:00.000000000 +0300
48438 +++ lighttpd-1.4.12/tests/lowercase.conf        2006-07-11 22:07:53.000000000 +0300
48439 @@ -0,0 +1,80 @@
48440 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48441 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48442 +
48443 +## bind to port (default: 80)
48444 +server.port                 = 2048
48445 +
48446 +## bind to localhost (default: all interfaces)
48447 +server.bind                = "localhost"
48448 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48449 +
48450 +server.force-lowercase-filenames = "enable"
48451 +
48452 +server.dir-listing          = "enable"
48453 +
48454 +server.modules              = ( 
48455 +                               "mod_rewrite",
48456 +                               "mod_setenv",
48457 +                               "mod_secdownload",
48458 +                               "mod_access", 
48459 +                               "mod_auth",
48460 +                               "mod_status", 
48461 +                               "mod_expire",
48462 +                               "mod_redirect", 
48463 +                               "mod_fastcgi",
48464 +                               "mod_cgi" ) 
48465 +
48466 +server.indexfiles           = ( "index.php", "index.html", 
48467 +                                "index.htm", "default.htm" )
48468 +
48469 +
48470 +######################## MODULE CONFIG ############################
48471 +
48472 +mimetype.assign             = ( ".png"  => "image/png", 
48473 +                                ".jpg"  => "image/jpeg",
48474 +                                ".jpeg" => "image/jpeg",
48475 +                                ".gif"  => "image/gif",
48476 +                                ".html" => "text/html",
48477 +                                ".htm"  => "text/html",
48478 +                                ".pdf"  => "application/pdf",
48479 +                                ".swf"  => "application/x-shockwave-flash",
48480 +                                ".spl"  => "application/futuresplash",
48481 +                                ".txt"  => "text/plain",
48482 +                                ".tar.gz" =>   "application/x-tgz",
48483 +                                ".tgz"  => "application/x-tgz",
48484 +                                ".gz"   => "application/x-gzip",
48485 +                               ".c"    => "text/plain",
48486 +                               ".conf" => "text/plain" )
48487 +
48488 +fastcgi.debug               = 0
48489 +fastcgi.server              = ( ".php" =>        ( ( "host" => "127.0.0.1", "port" => 1026, "broken-scriptfilename" => "enable" ) ),
48490 +                               "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48491 +                             )
48492 +               
48493 +
48494 +cgi.assign                  = ( ".pl"  => "/usr/bin/perl",
48495 +                                ".cgi" => "/usr/bin/perl",
48496 +                               ".py"  => "/usr/bin/python" )
48497 +                       
48498 +auth.backend                = "plain"
48499 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48500 +
48501 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
48502 +
48503 +$HTTP["host"] == "lowercase-auth" {
48504 +  auth.require             = ( "/image.jpg" => 
48505 +                                ( 
48506 +                                 "method"  => "digest",
48507 +                                 "realm"   => "download archiv",
48508 +                                 "require" => "valid-user"
48509 +                               )
48510 +                              )
48511 +}
48512 +
48513 +$HTTP["host"] == "lowercase-deny" {
48514 +  url.access-deny             = ( ".jpg")
48515 +}
48516 +
48517 +$HTTP["host"] == "lowercase-exclude" {
48518 +  static-file.exclude-extensions = ( ".jpg" )
48519 +}
48520 --- ../lighttpd-1.4.11/tests/lowercase.t        1970-01-01 03:00:00.000000000 +0300
48521 +++ lighttpd-1.4.12/tests/lowercase.t   2006-07-11 22:07:53.000000000 +0300
48522 @@ -0,0 +1,94 @@
48523 +#!/usr/bin/env perl
48524 +BEGIN {
48525 +    # add current source dir to the include-path
48526 +    # we need this for make distcheck
48527 +   (my $srcdir = $0) =~ s#/[^/]+$#/#;
48528 +   unshift @INC, $srcdir;
48529 +}
48530 +
48531 +use strict;
48532 +use IO::Socket;
48533 +use Test::More tests => 10;
48534 +use LightyTest;
48535 +
48536 +my $tf = LightyTest->new();
48537 +my $t;
48538 +
48539 +$tf->{CONFIGFILE} = 'lowercase.conf';
48540 +    
48541 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
48542 +
48543 +## check if lower-casing works
48544 +
48545 +$t->{REQUEST}  = ( <<EOF
48546 +GET /image.JPG HTTP/1.0
48547 +EOF
48548 + );
48549 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48550 +ok($tf->handle_http($t) == 0, 'uppercase access');
48551 +
48552 +$t->{REQUEST}  = ( <<EOF
48553 +GET /image.jpg HTTP/1.0
48554 +EOF
48555 + );
48556 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48557 +ok($tf->handle_http($t) == 0, 'lowercase access');
48558 +
48559 +## check that mod-auth works
48560 +
48561 +$t->{REQUEST}  = ( <<EOF
48562 +GET /image.JPG HTTP/1.0
48563 +Host: lowercase-auth
48564 +EOF
48565 + );
48566 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48567 +ok($tf->handle_http($t) == 0, 'uppercase access');
48568 +
48569 +$t->{REQUEST}  = ( <<EOF
48570 +GET /image.jpg HTTP/1.0
48571 +Host: lowercase-auth
48572 +EOF
48573 + );
48574 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48575 +ok($tf->handle_http($t) == 0, 'lowercase access');
48576 +
48577 +
48578 +## check that mod-staticfile exclude works
48579 +$t->{REQUEST}  = ( <<EOF
48580 +GET /image.JPG HTTP/1.0
48581 +Host: lowercase-exclude
48582 +EOF
48583 + );
48584 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48585 +ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
48586 +
48587 +$t->{REQUEST}  = ( <<EOF
48588 +GET /image.jpg HTTP/1.0
48589 +Host: lowercase-exclude
48590 +EOF
48591 + );
48592 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48593 +ok($tf->handle_http($t) == 0, 'lowercase access');
48594 +
48595 +
48596 +## check that mod-access exclude works
48597 +$t->{REQUEST}  = ( <<EOF
48598 +GET /image.JPG HTTP/1.0
48599 +Host: lowercase-deny
48600 +EOF
48601 + );
48602 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48603 +ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
48604 +
48605 +$t->{REQUEST}  = ( <<EOF
48606 +GET /image.jpg HTTP/1.0
48607 +Host: lowercase-deny
48608 +EOF
48609 + );
48610 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48611 +ok($tf->handle_http($t) == 0, 'lowercase access');
48612 +
48613 +
48614 +
48615 +ok($tf->stop_proc == 0, "Stopping lighttpd");
48616 +
48617 --- ../lighttpd-1.4.11/tests/mod-fastcgi.t      2006-03-09 15:30:45.000000000 +0200
48618 +++ lighttpd-1.4.12/tests/mod-fastcgi.t 2006-07-11 22:07:53.000000000 +0300
48619 @@ -7,7 +7,7 @@
48620  }
48621  
48622  use strict;
48623 -use Test::More tests => 47;
48624 +use Test::More tests => 49;
48625  use LightyTest;
48626  
48627  my $tf = LightyTest->new();
48628 @@ -15,7 +15,7 @@
48629  my $t;
48630  
48631  SKIP: {
48632 -       skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
48633 +       skip "no PHP running on port 1026", 29 unless $tf->listening_on(1026);
48634  
48635         ok($tf->start_proc == 0, "Starting lighttpd") or die();
48636  
48637 @@ -223,7 +223,7 @@
48638  }
48639  
48640  SKIP: {
48641 -       skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php"; 
48642 +       skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48643         $tf->{CONFIGFILE} = 'fastcgi-13.conf';
48644         ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
48645         $t->{REQUEST}  = ( <<EOF
48646 @@ -285,6 +285,34 @@
48647         $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
48648         ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
48649  
48650 +    # X-LIGHTTPD-send-file
48651 +       $t->{REQUEST}  = ( <<EOF
48652 +GET /index.fcgi?x-lighttpd-send-file HTTP/1.0
48653 +Host: www.example.org
48654 +EOF
48655 + );
48656 +       $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48657 +' } ];
48658 +       ok($tf->handle_http($t) == 0, 'X-LIGHTTPD-send-file');
48659 +    # X-Sendfile
48660 +       $t->{REQUEST}  = ( <<EOF
48661 +GET /index.fcgi?xsendfile HTTP/1.0
48662 +Host: www.example.org
48663 +EOF
48664 + );
48665 +       $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48666 +' } ];
48667 +       ok($tf->handle_http($t) == 0, 'X-Sendfile');
48668 +
48669 +       $t->{REQUEST}  = ( <<EOF
48670 +GET /index.fcgi?xsendfile-mixed-case HTTP/1.0
48671 +Host: www.example.org
48672 +EOF
48673 + );
48674 +       $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48675 +' } ];
48676 +       ok($tf->handle_http($t) == 0, 'X-SeNdFiLe in mixed case');
48677 +
48678         $t->{REQUEST}  = ( <<EOF
48679  GET /index.fcgi?die-at-end HTTP/1.0
48680  Host: www.example.org
48681 --- ../lighttpd-1.4.11/tests/mod-proxy.t        1970-01-01 03:00:00.000000000 +0300
48682 +++ lighttpd-1.4.12/tests/mod-proxy.t   2006-07-11 22:07:53.000000000 +0300
48683 @@ -0,0 +1,173 @@
48684 +#!/usr/bin/env perl
48685 +BEGIN {
48686 +    # add current source dir to the include-path
48687 +    # we need this for make distcheck
48688 +   (my $srcdir = $0) =~ s#/[^/]+$#/#;
48689 +   unshift @INC, $srcdir;
48690 +}
48691 +
48692 +use strict;
48693 +use IO::Socket;
48694 +use Test::More tests => 21;
48695 +use LightyTest;
48696 +
48697 +my $tf_proxy = LightyTest->new();
48698 +my $tf_backend1 = LightyTest->new();
48699 +my $tf_backend2 = LightyTest->new();
48700 +
48701 +my $t;
48702 +
48703 +## we need two procs
48704 +## 1. the real webserver
48705 +## 2. the proxy server
48706 +
48707 +$tf_proxy->{PORT} = 2048;
48708 +$tf_proxy->{CONFIGFILE} = 'proxy.conf';
48709 +$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
48710 +
48711 +$tf_backend1->{PORT} = 2050;
48712 +$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
48713 +$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
48714 +
48715 +$tf_backend2->{PORT} = 2051;
48716 +$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
48717 +$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
48718 +
48719 +
48720 +ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
48721 +
48722 +ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
48723 +
48724 +sleep(1);
48725 +
48726 +$t->{REQUEST}  = ( <<EOF
48727 +GET /index.html HTTP/1.0
48728 +Host: www.example.org
48729 +EOF
48730 + );
48731 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48732 +ok($tf_proxy->handle_http($t) == 0, 'valid request');
48733 +
48734 +$t->{REQUEST}  = ( <<EOF
48735 +GET /index.html HTTP/1.0
48736 +Host: www.example.org
48737 +EOF
48738 + );
48739 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'proxy-backend-1' } ];
48740 +ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
48741 +
48742 +$t->{REQUEST}  = ( <<EOF
48743 +GET /balance-rr/foo HTTP/1.0
48744 +Host: www.example.org
48745 +EOF
48746 + );
48747 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48748 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
48749 +
48750 +$t->{REQUEST}  = ( <<EOF
48751 +GET /balance-rr/foo HTTP/1.0
48752 +Host: www.example.org
48753 +EOF
48754 + );
48755 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48756 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
48757 +
48758 +$t->{REQUEST}  = ( <<EOF
48759 +GET /balance-fair/foo HTTP/1.0
48760 +Host: www.example.org
48761 +EOF
48762 + );
48763 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48764 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
48765 +
48766 +## backend 2 starting 
48767 +ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
48768 +
48769 +$t->{REQUEST}  = ( <<EOF
48770 +GET /balance-rr/foo HTTP/1.0
48771 +Host: www.example.org
48772 +EOF
48773 + );
48774 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48775 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
48776 +
48777 +$t->{REQUEST}  = ( <<EOF
48778 +GET /balance-rr/foo HTTP/1.0
48779 +Host: www.example.org
48780 +EOF
48781 + );
48782 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48783 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
48784 +
48785 +$t->{REQUEST}  = ( <<EOF
48786 +GET /balance-hash/foo HTTP/1.0
48787 +Host: www.example.org
48788 +EOF
48789 + );
48790 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48791 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
48792 +
48793 +$t->{REQUEST}  = ( <<EOF
48794 +GET /balance-hash/foo HTTP/1.0
48795 +Host: www.example.org
48796 +EOF
48797 + );
48798 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48799 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
48800 +
48801 +$t->{REQUEST}  = ( <<EOF
48802 +GET /balance-hash/bar HTTP/1.0
48803 +Host: www.example.org
48804 +EOF
48805 + );
48806 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48807 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
48808 +
48809 +$t->{REQUEST}  = ( <<EOF
48810 +GET /balance-hash/bar HTTP/1.0
48811 +Host: www.example.org
48812 +EOF
48813 + );
48814 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48815 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
48816 +
48817 +## backend 1 stopping, failover 
48818 +ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
48819 +
48820 +$t->{REQUEST}  = ( <<EOF
48821 +GET /balance-hash/foo HTTP/1.0
48822 +Host: www.example.org
48823 +EOF
48824 + );
48825 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48826 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
48827 +
48828 +$t->{REQUEST}  = ( <<EOF
48829 +GET /balance-hash/bar HTTP/1.0
48830 +Host: www.example.org
48831 +EOF
48832 + );
48833 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48834 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
48835 +
48836 +$t->{REQUEST}  = ( <<EOF
48837 +GET /balance-rr/foo HTTP/1.0
48838 +Host: www.example.org
48839 +EOF
48840 + );
48841 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48842 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
48843 +
48844 +$t->{REQUEST}  = ( <<EOF
48845 +GET /balance-fair/foo HTTP/1.0
48846 +Host: www.example.org
48847 +EOF
48848 + );
48849 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48850 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
48851 +
48852 +
48853 +ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
48854 +
48855 +ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
48856 +
48857 --- ../lighttpd-1.4.11/tests/proxy.conf 1970-01-01 03:00:00.000000000 +0300
48858 +++ lighttpd-1.4.12/tests/proxy.conf    2006-07-11 22:07:53.000000000 +0300
48859 @@ -0,0 +1,26 @@
48860 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48861 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
48862 +server.tag = "proxy"
48863 +
48864 +include "default.conf"
48865 +
48866 +## 127.0.0.1 and 127.0.0.2 are the same host
48867 +proxy.server              = ( 
48868 +  "" => (( "host" => "127.0.0.1",
48869 +          "port" => 2050 ),
48870 +         ( "host" => "127.0.0.2",
48871 +           "port" => 2051 )
48872 +  ))
48873 +               
48874 +$HTTP["url"] =~ "^/balance-rr/" {
48875 +  proxy.balance = "round-robin"
48876 +}
48877 +
48878 +$HTTP["url"] =~ "^/balance-hash/" {
48879 +  proxy.balance = "hash"
48880 +}
48881 +
48882 +$HTTP["url"] =~ "^/balance-fair/" {
48883 +  proxy.balance = "fair"
48884 +}
48885 +
48886 --- ../lighttpd-1.4.11/tests/var-include.conf   2005-08-27 17:44:19.000000000 +0300
48887 +++ lighttpd-1.4.12/tests/var-include.conf      2006-07-11 22:07:53.000000000 +0300
48888 @@ -2,15 +2,15 @@
48889  debug.log-request-handling = "enable"
48890  debug.log-condition-handling = "enable"
48891  
48892 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48893 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
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            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48903 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48904  server.name                = "www.example.org"
48905  server.tag                 = "Apache 1.3.29"
48906  
48907 @@ -21,19 +21,19 @@
48908  ######################## MODULE CONFIG ############################
48909  
48910  
48911 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48912 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48913  
48914  mimetype.assign             = ( ".html" => "text/html" )
48915  
48916  url.redirect = ("^" => "/default")
48917  
48918  $HTTP["host"] == "www.example.org" {
48919 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48920 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48921    server.name = "www.example.org"
48922    url.redirect = ("^" => "/redirect")
48923  }
48924  $HTTP["host"] == "test.example.org" {
48925 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48926 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48927    server.name = "test.example.org"
48928    var.myvar = "good"
48929    var.one = 1
This page took 4.480126 seconds and 4 git commands to generate.