1 --- lighttpd-1.4.11/Makefile.in 2006-03-07 14:21:08.000000000 +0200
2 +++ lighttpd-1.4.12/Makefile.in 2006-07-11 21:48:16.000000000 +0300
4 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
5 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
8 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
10 $(srcdir)/distribute.sh.in $(srcdir)/lighttpd.spec.in \
11 $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
12 compile config.guess config.sub depcomp install-sh ltmain.sh \
13 - missing mkinstalldirs
16 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
17 am__aclocal_m4_deps = $(top_srcdir)/configure.in
20 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
21 configure.lineno configure.status.lineno
22 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
23 +mkinstalldirs = $(install_sh) -d
24 CONFIG_HEADER = config.h
25 CONFIG_CLEAN_FILES = lighttpd.spec distribute.sh
30 LTLIBOBJS = @LTLIBOBJS@
31 -LUACONFIG = @LUACONFIG@
32 LUA_CFLAGS = @LUA_CFLAGS@
36 ac_ct_F77 = @ac_ct_F77@
37 ac_ct_RANLIB = @ac_ct_RANLIB@
38 ac_ct_STRIP = @ac_ct_STRIP@
39 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
40 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
41 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
42 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
43 --- lighttpd-1.4.11/NEWS 2006-03-09 19:34:33.000000000 +0200
44 +++ lighttpd-1.4.12/NEWS 2006-07-11 22:07:54.000000000 +0300
49 +- 1.4.12 - 2006-..-..
51 + * added handling of Content-Range to PUT requests in mod_webdav
52 + * added handling of ETag and If-Modified-Since to mod_compress if
53 + cache-dir is not set
54 + * added experimental LOCK support for mod_webdav
55 + * added support for X-Sendfile as addition to X-LIGHTTPD-send-file.
56 + This allows compatibility with mod_xsendfile for apache
57 + (http://celebnamer.celebworld.ws/stuff/mod_xsendfile/)
58 + * fixed handling of If-Modified-Since if Etag is not set
59 + * fixed hanging fastcgi connections
60 + * fixed stalling SSL POST requests
61 + * fixed round-robin load-balancing in mod_proxy
62 + * TODO: add fail-over to mod-proxy
63 + * TODO: fix CACHE_HIT/MISS in mod_cml
64 + * TODO: finish LOCK/UNLOCK in mod_webdav
68 * added ability to specify which ip address spawn-fci listens on
69 --- lighttpd-1.4.11/configure.in 2006-03-04 16:32:38.000000000 +0200
70 +++ lighttpd-1.4.12/configure.in 2006-07-11 22:07:54.000000000 +0300
73 # Process this file with autoconf to produce a configure script.
75 -AC_INIT(lighttpd, 1.4.11, jan@kneschke.de)
76 +AC_INIT(lighttpd, 1.4.12, jan@kneschke.de)
77 AC_CONFIG_SRCDIR([src/server.c])
84 -AC_CHECK_MEMBER(struct tm.tm_gmtoff,AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm]),,[#include <time.h>])
85 +AC_CHECK_MEMBER(struct tm.tm_gmtoff,[AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm])],,[#include <time.h>])
86 AC_CHECK_TYPES(struct sockaddr_storage,,,[#include <sys/socket.h>])
87 AC_CHECK_TYPES(socklen_t,,,[#include <sys/types.h>
88 #include <sys/socket.h>])
90 AC_DEFINE([HAVE_SQLITE3], [1], [libsqlite3])
91 AC_DEFINE([HAVE_SQLITE3_H], [1], [sqlite3.h])
94 + AC_MSG_CHECKING(for locks in mod_webdav)
95 + AC_ARG_WITH(webdav-locks, AC_HELP_STRING([--with-webdav-locks],[locks in mod_webdav]),
96 + [WITH_WEBDAV_LOCKS=$withval],[WITH_WEBDAV_LOCKS=no])
97 + AC_MSG_RESULT([$WITH_WEBDAV_LOCKS])
99 + if test "$WITH_WEBDAV_LOCKS" != "no"; then
100 + AC_CHECK_LIB(uuid, uuid_unparse, [
101 + AC_CHECK_HEADERS([uuid/uuid.h],[
103 + AC_DEFINE([HAVE_UUID], [1], [libuuid])
104 + AC_DEFINE([HAVE_UUID_H], [1], [uuid/uuid.h is available])
115 AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
116 - strdup strerror strstr strtol sendfile getopt socket \
117 + strdup strerror strstr strtol sendfile getopt socket lstat \
118 gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
119 getuid select signal pathconf madvise posix_fadvise posix_madvise \
120 writev sigaction sendfile64 send_file kqueue port_create localtime_r])
125 -do_build="mod_cgi mod_fastcgi mod_proxy mod_evhost mod_simple_vhost mod_access mod_alias mod_setenv mod_usertrack mod_auth mod_status mod_accesslog mod_rrdtool mod_secdownload mod_expire mod_compress mod_dirlisting mod_indexfiles mod_userdir mod_webdav mod_staticfile mod_scgi"
126 +do_build="mod_cgi mod_fastcgi mod_proxy mod_evhost mod_simple_vhost mod_access mod_alias mod_setenv mod_usertrack mod_auth mod_status mod_accesslog mod_rrdtool mod_secdownload mod_expire mod_compress mod_dirlisting mod_indexfiles mod_userdir mod_webdav mod_staticfile mod_scgi mod_flv_streaming"
128 plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
129 features="regex-conditionals"
131 disable_feature="$disable_feature $features"
134 +features="webdav-locks"
135 +if test "x$UUID_LIB" \!= x; then
136 + enable_feature="$enable_feature $features"
138 + disable_feature="$disable_feature $features"
145 --- lighttpd-1.4.11/cygwin/Makefile.in 2006-03-07 14:20:57.000000000 +0200
146 +++ lighttpd-1.4.12/cygwin/Makefile.in 2006-07-11 21:48:12.000000000 +0300
148 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
149 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
152 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
154 am__aclocal_m4_deps = $(top_srcdir)/configure.in
155 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
157 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
158 +mkinstalldirs = $(install_sh) -d
159 CONFIG_HEADER = $(top_builddir)/config.h
160 CONFIG_CLEAN_FILES = lighttpd.README
165 LTLIBOBJS = @LTLIBOBJS@
166 -LUACONFIG = @LUACONFIG@
167 LUA_CFLAGS = @LUA_CFLAGS@
168 LUA_LIBS = @LUA_LIBS@
171 ac_ct_F77 = @ac_ct_F77@
172 ac_ct_RANLIB = @ac_ct_RANLIB@
173 ac_ct_STRIP = @ac_ct_STRIP@
174 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
175 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
176 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
177 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
178 --- lighttpd-1.4.11/cygwin/lighttpd.README 2006-03-07 14:22:19.000000000 +0200
179 +++ lighttpd-1.4.12/cygwin/lighttpd.README 2006-07-11 22:08:04.000000000 +0300
182 -------------------------------------------
\r
183 -A fast, secure and flexible webserver
\r
185 -Runtime requirements:
\r
186 - cygwin-1.5.10 or newer
\r
187 - crypt-1.1 or newer
\r
188 - libbz2_1-1.0.2 or newer
\r
189 - libpcre0-4.5 or newer
\r
190 - openssl-0.9.7d or newer
\r
191 - zlib-1.2.1 or newer
\r
193 -Build requirements:
\r
194 - cygwin-1.5.10 or newer
\r
195 - gcc-3.3.1-3 or newer
\r
196 - binutils-20030901-1 or newer
\r
205 -Canonical homepage:
\r
206 - http://jan.kneschke.de/projects/lighttpd/
\r
208 -Canonical download:
\r
209 - http://jan.kneschke.de/projects/lighttpd/download
\r
211 -------------------------------------
\r
213 -Build instructions:
\r
214 - unpack lighttpd-1.4.11-<REL>-src.tar.bz2
\r
215 - if you use setup to install this src package, it will be
\r
216 - unpacked under /usr/src automatically
\r
218 - ./lighttpd-1.4.11-<REL>.sh all
\r
221 - /usr/src/lighttpd-1.4.11-<REL>.tar.bz2
\r
222 - /usr/src/lighttpd-1.4.11-<REL>-src.tar.bz2
\r
224 -Or use './lighttpd-1.4.11-<REL>.sh prep' to get a patched source directory
\r
226 --------------------------------------------
\r
228 -Files included in the binary distribution:
\r
230 - /etc/lighttpd/lighttpd.conf.default
\r
231 - /usr/lib/cyglightcomp.dll
\r
232 - /usr/lib/lighttpd/mod_access.dll
\r
233 - /usr/lib/lighttpd/mod_accesslog.dll
\r
234 - /usr/lib/lighttpd/mod_auth.dll
\r
235 - /usr/lib/lighttpd/mod_cgi.dll
\r
236 - /usr/lib/lighttpd/mod_compress.dll
\r
237 - /usr/lib/lighttpd/mod_evhost.dll
\r
238 - /usr/lib/lighttpd/mod_expire.dll
\r
239 - /usr/lib/lighttpd/mod_fastcgi.dll
\r
240 - /usr/lib/lighttpd/mod_httptls.dll
\r
241 - /usr/lib/lighttpd/mod_maps.dll
\r
242 - /usr/lib/lighttpd/mod_proxy.dll
\r
243 - /usr/lib/lighttpd/mod_redirect.dll
\r
244 - /usr/lib/lighttpd/mod_rewrite.dll
\r
245 - /usr/lib/lighttpd/mod_rrdtool.dll
\r
246 - /usr/lib/lighttpd/mod_secdownload.dll
\r
247 - /usr/lib/lighttpd/mod_simple_vhost.dll
\r
248 - /usr/lib/lighttpd/mod_ssi.dll
\r
249 - /usr/lib/lighttpd/mod_status.dll
\r
250 - /usr/lib/lighttpd/mod_usertrack.dll
\r
251 - /usr/sbin/lighttpd.exe
\r
252 - /usr/share/doc/Cygwin/lighttpd-1.3.0.README
\r
253 - /usr/share/doc/lighttpd-1.3.0/accesslog.txt
\r
254 - /usr/share/doc/lighttpd-1.3.0/authentification.txt
\r
255 - /usr/share/doc/lighttpd-1.3.0/AUTHORS
\r
256 - /usr/share/doc/lighttpd-1.3.0/cgi.txt
\r
257 - /usr/share/doc/lighttpd-1.3.0/ChangeLog
\r
258 - /usr/share/doc/lighttpd-1.3.0/compress.txt
\r
259 - /usr/share/doc/lighttpd-1.3.0/configuration.txt
\r
260 - /usr/share/doc/lighttpd-1.3.0/COPYING
\r
261 - /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
\r
262 - /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
\r
263 - /usr/share/doc/lighttpd-1.3.0/features.txt
\r
264 - /usr/share/doc/lighttpd-1.3.0/INSTALL
\r
265 - /usr/share/doc/lighttpd-1.3.0/NEWS
\r
266 - /usr/share/doc/lighttpd-1.3.0/performance.txt
\r
267 - /usr/share/doc/lighttpd-1.3.0/plugins.txt
\r
268 - /usr/share/doc/lighttpd-1.3.0/proxy.txt
\r
269 - /usr/share/doc/lighttpd-1.3.0/README
\r
270 - /usr/share/doc/lighttpd-1.3.0/redirect.txt
\r
271 - /usr/share/doc/lighttpd-1.3.0/rewrite.txt
\r
272 - /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
\r
273 - /usr/share/doc/lighttpd-1.3.0/secdownload.txt
\r
274 - /usr/share/doc/lighttpd-1.3.0/security.txt
\r
275 - /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
\r
276 - /usr/share/doc/lighttpd-1.3.0/skeleton.txt
\r
277 - /usr/share/doc/lighttpd-1.3.0/ssi.txt
\r
278 - /usr/share/doc/lighttpd-1.3.0/state.txt
\r
279 - /usr/share/man/man1/lighttpd.1.gz
\r
281 -------------------
\r
285 ----------- lighttpd-1.3.1-1 -----------
\r
289 ----------- lighttpd-1.3.0-1 -----------
\r
292 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
\r
293 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
\r
296 +------------------------------------------
297 +A fast, secure and flexible webserver
299 +Runtime requirements:
300 + cygwin-1.5.10 or newer
302 + libbz2_1-1.0.2 or newer
303 + libpcre0-4.5 or newer
304 + openssl-0.9.7d or newer
305 + zlib-1.2.1 or newer
308 + cygwin-1.5.10 or newer
309 + gcc-3.3.1-3 or newer
310 + binutils-20030901-1 or newer
320 + http://jan.kneschke.de/projects/lighttpd/
323 + http://jan.kneschke.de/projects/lighttpd/download
325 +------------------------------------
328 + unpack lighttpd-1.4.12-<REL>-src.tar.bz2
329 + if you use setup to install this src package, it will be
330 + unpacked under /usr/src automatically
332 + ./lighttpd-1.4.12-<REL>.sh all
335 + /usr/src/lighttpd-1.4.12-<REL>.tar.bz2
336 + /usr/src/lighttpd-1.4.12-<REL>-src.tar.bz2
338 +Or use './lighttpd-1.4.12-<REL>.sh prep' to get a patched source directory
340 +-------------------------------------------
342 +Files included in the binary distribution:
344 + /etc/lighttpd/lighttpd.conf.default
345 + /usr/lib/cyglightcomp.dll
346 + /usr/lib/lighttpd/mod_access.dll
347 + /usr/lib/lighttpd/mod_accesslog.dll
348 + /usr/lib/lighttpd/mod_auth.dll
349 + /usr/lib/lighttpd/mod_cgi.dll
350 + /usr/lib/lighttpd/mod_compress.dll
351 + /usr/lib/lighttpd/mod_evhost.dll
352 + /usr/lib/lighttpd/mod_expire.dll
353 + /usr/lib/lighttpd/mod_fastcgi.dll
354 + /usr/lib/lighttpd/mod_httptls.dll
355 + /usr/lib/lighttpd/mod_maps.dll
356 + /usr/lib/lighttpd/mod_proxy.dll
357 + /usr/lib/lighttpd/mod_redirect.dll
358 + /usr/lib/lighttpd/mod_rewrite.dll
359 + /usr/lib/lighttpd/mod_rrdtool.dll
360 + /usr/lib/lighttpd/mod_secdownload.dll
361 + /usr/lib/lighttpd/mod_simple_vhost.dll
362 + /usr/lib/lighttpd/mod_ssi.dll
363 + /usr/lib/lighttpd/mod_status.dll
364 + /usr/lib/lighttpd/mod_usertrack.dll
365 + /usr/sbin/lighttpd.exe
366 + /usr/share/doc/Cygwin/lighttpd-1.3.0.README
367 + /usr/share/doc/lighttpd-1.3.0/accesslog.txt
368 + /usr/share/doc/lighttpd-1.3.0/authentification.txt
369 + /usr/share/doc/lighttpd-1.3.0/AUTHORS
370 + /usr/share/doc/lighttpd-1.3.0/cgi.txt
371 + /usr/share/doc/lighttpd-1.3.0/ChangeLog
372 + /usr/share/doc/lighttpd-1.3.0/compress.txt
373 + /usr/share/doc/lighttpd-1.3.0/configuration.txt
374 + /usr/share/doc/lighttpd-1.3.0/COPYING
375 + /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
376 + /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
377 + /usr/share/doc/lighttpd-1.3.0/features.txt
378 + /usr/share/doc/lighttpd-1.3.0/INSTALL
379 + /usr/share/doc/lighttpd-1.3.0/NEWS
380 + /usr/share/doc/lighttpd-1.3.0/performance.txt
381 + /usr/share/doc/lighttpd-1.3.0/plugins.txt
382 + /usr/share/doc/lighttpd-1.3.0/proxy.txt
383 + /usr/share/doc/lighttpd-1.3.0/README
384 + /usr/share/doc/lighttpd-1.3.0/redirect.txt
385 + /usr/share/doc/lighttpd-1.3.0/rewrite.txt
386 + /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
387 + /usr/share/doc/lighttpd-1.3.0/secdownload.txt
388 + /usr/share/doc/lighttpd-1.3.0/security.txt
389 + /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
390 + /usr/share/doc/lighttpd-1.3.0/skeleton.txt
391 + /usr/share/doc/lighttpd-1.3.0/ssi.txt
392 + /usr/share/doc/lighttpd-1.3.0/state.txt
393 + /usr/share/man/man1/lighttpd.1.gz
399 +---------- lighttpd-1.3.1-1 -----------
403 +---------- lighttpd-1.3.0-1 -----------
406 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
407 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
409 --- lighttpd-1.4.11/cygwin/lighttpd.README.in 2005-08-11 01:26:59.000000000 +0300
410 +++ lighttpd-1.4.12/cygwin/lighttpd.README.in 2006-07-11 22:07:53.000000000 +0300
413 -------------------------------------------
\r
414 -A fast, secure and flexible webserver
\r
416 -Runtime requirements:
\r
417 - cygwin-1.5.10 or newer
\r
418 - crypt-1.1 or newer
\r
419 - libbz2_1-1.0.2 or newer
\r
420 - libpcre0-4.5 or newer
\r
421 - openssl-0.9.7d or newer
\r
422 - zlib-1.2.1 or newer
\r
424 -Build requirements:
\r
425 - cygwin-1.5.10 or newer
\r
426 - gcc-3.3.1-3 or newer
\r
427 - binutils-20030901-1 or newer
\r
436 -Canonical homepage:
\r
437 - http://jan.kneschke.de/projects/lighttpd/
\r
439 -Canonical download:
\r
440 - http://jan.kneschke.de/projects/lighttpd/download
\r
442 -------------------------------------
\r
444 -Build instructions:
\r
445 - unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
\r
446 - if you use setup to install this src package, it will be
\r
447 - unpacked under /usr/src automatically
\r
449 - ./lighttpd-@VERSION@-<REL>.sh all
\r
452 - /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
\r
453 - /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
\r
455 -Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
\r
457 --------------------------------------------
\r
459 -Files included in the binary distribution:
\r
461 - /etc/lighttpd/lighttpd.conf.default
\r
462 - /usr/lib/cyglightcomp.dll
\r
463 - /usr/lib/lighttpd/mod_access.dll
\r
464 - /usr/lib/lighttpd/mod_accesslog.dll
\r
465 - /usr/lib/lighttpd/mod_auth.dll
\r
466 - /usr/lib/lighttpd/mod_cgi.dll
\r
467 - /usr/lib/lighttpd/mod_compress.dll
\r
468 - /usr/lib/lighttpd/mod_evhost.dll
\r
469 - /usr/lib/lighttpd/mod_expire.dll
\r
470 - /usr/lib/lighttpd/mod_fastcgi.dll
\r
471 - /usr/lib/lighttpd/mod_httptls.dll
\r
472 - /usr/lib/lighttpd/mod_maps.dll
\r
473 - /usr/lib/lighttpd/mod_proxy.dll
\r
474 - /usr/lib/lighttpd/mod_redirect.dll
\r
475 - /usr/lib/lighttpd/mod_rewrite.dll
\r
476 - /usr/lib/lighttpd/mod_rrdtool.dll
\r
477 - /usr/lib/lighttpd/mod_secdownload.dll
\r
478 - /usr/lib/lighttpd/mod_simple_vhost.dll
\r
479 - /usr/lib/lighttpd/mod_ssi.dll
\r
480 - /usr/lib/lighttpd/mod_status.dll
\r
481 - /usr/lib/lighttpd/mod_usertrack.dll
\r
482 - /usr/sbin/lighttpd.exe
\r
483 - /usr/share/doc/Cygwin/lighttpd-1.3.0.README
\r
484 - /usr/share/doc/lighttpd-1.3.0/accesslog.txt
\r
485 - /usr/share/doc/lighttpd-1.3.0/authentification.txt
\r
486 - /usr/share/doc/lighttpd-1.3.0/AUTHORS
\r
487 - /usr/share/doc/lighttpd-1.3.0/cgi.txt
\r
488 - /usr/share/doc/lighttpd-1.3.0/ChangeLog
\r
489 - /usr/share/doc/lighttpd-1.3.0/compress.txt
\r
490 - /usr/share/doc/lighttpd-1.3.0/configuration.txt
\r
491 - /usr/share/doc/lighttpd-1.3.0/COPYING
\r
492 - /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
\r
493 - /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
\r
494 - /usr/share/doc/lighttpd-1.3.0/features.txt
\r
495 - /usr/share/doc/lighttpd-1.3.0/INSTALL
\r
496 - /usr/share/doc/lighttpd-1.3.0/NEWS
\r
497 - /usr/share/doc/lighttpd-1.3.0/performance.txt
\r
498 - /usr/share/doc/lighttpd-1.3.0/plugins.txt
\r
499 - /usr/share/doc/lighttpd-1.3.0/proxy.txt
\r
500 - /usr/share/doc/lighttpd-1.3.0/README
\r
501 - /usr/share/doc/lighttpd-1.3.0/redirect.txt
\r
502 - /usr/share/doc/lighttpd-1.3.0/rewrite.txt
\r
503 - /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
\r
504 - /usr/share/doc/lighttpd-1.3.0/secdownload.txt
\r
505 - /usr/share/doc/lighttpd-1.3.0/security.txt
\r
506 - /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
\r
507 - /usr/share/doc/lighttpd-1.3.0/skeleton.txt
\r
508 - /usr/share/doc/lighttpd-1.3.0/ssi.txt
\r
509 - /usr/share/doc/lighttpd-1.3.0/state.txt
\r
510 - /usr/share/man/man1/lighttpd.1.gz
\r
512 -------------------
\r
516 ----------- lighttpd-1.3.1-1 -----------
\r
520 ----------- lighttpd-1.3.0-1 -----------
\r
523 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
\r
524 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
\r
527 +------------------------------------------
528 +A fast, secure and flexible webserver
530 +Runtime requirements:
531 + cygwin-1.5.10 or newer
533 + libbz2_1-1.0.2 or newer
534 + libpcre0-4.5 or newer
535 + openssl-0.9.7d or newer
536 + zlib-1.2.1 or newer
539 + cygwin-1.5.10 or newer
540 + gcc-3.3.1-3 or newer
541 + binutils-20030901-1 or newer
551 + http://jan.kneschke.de/projects/lighttpd/
554 + http://jan.kneschke.de/projects/lighttpd/download
556 +------------------------------------
559 + unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
560 + if you use setup to install this src package, it will be
561 + unpacked under /usr/src automatically
563 + ./lighttpd-@VERSION@-<REL>.sh all
566 + /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
567 + /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
569 +Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
571 +-------------------------------------------
573 +Files included in the binary distribution:
575 + /etc/lighttpd/lighttpd.conf.default
576 + /usr/lib/cyglightcomp.dll
577 + /usr/lib/lighttpd/mod_access.dll
578 + /usr/lib/lighttpd/mod_accesslog.dll
579 + /usr/lib/lighttpd/mod_auth.dll
580 + /usr/lib/lighttpd/mod_cgi.dll
581 + /usr/lib/lighttpd/mod_compress.dll
582 + /usr/lib/lighttpd/mod_evhost.dll
583 + /usr/lib/lighttpd/mod_expire.dll
584 + /usr/lib/lighttpd/mod_fastcgi.dll
585 + /usr/lib/lighttpd/mod_httptls.dll
586 + /usr/lib/lighttpd/mod_maps.dll
587 + /usr/lib/lighttpd/mod_proxy.dll
588 + /usr/lib/lighttpd/mod_redirect.dll
589 + /usr/lib/lighttpd/mod_rewrite.dll
590 + /usr/lib/lighttpd/mod_rrdtool.dll
591 + /usr/lib/lighttpd/mod_secdownload.dll
592 + /usr/lib/lighttpd/mod_simple_vhost.dll
593 + /usr/lib/lighttpd/mod_ssi.dll
594 + /usr/lib/lighttpd/mod_status.dll
595 + /usr/lib/lighttpd/mod_usertrack.dll
596 + /usr/sbin/lighttpd.exe
597 + /usr/share/doc/Cygwin/lighttpd-1.3.0.README
598 + /usr/share/doc/lighttpd-1.3.0/accesslog.txt
599 + /usr/share/doc/lighttpd-1.3.0/authentification.txt
600 + /usr/share/doc/lighttpd-1.3.0/AUTHORS
601 + /usr/share/doc/lighttpd-1.3.0/cgi.txt
602 + /usr/share/doc/lighttpd-1.3.0/ChangeLog
603 + /usr/share/doc/lighttpd-1.3.0/compress.txt
604 + /usr/share/doc/lighttpd-1.3.0/configuration.txt
605 + /usr/share/doc/lighttpd-1.3.0/COPYING
606 + /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
607 + /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
608 + /usr/share/doc/lighttpd-1.3.0/features.txt
609 + /usr/share/doc/lighttpd-1.3.0/INSTALL
610 + /usr/share/doc/lighttpd-1.3.0/NEWS
611 + /usr/share/doc/lighttpd-1.3.0/performance.txt
612 + /usr/share/doc/lighttpd-1.3.0/plugins.txt
613 + /usr/share/doc/lighttpd-1.3.0/proxy.txt
614 + /usr/share/doc/lighttpd-1.3.0/README
615 + /usr/share/doc/lighttpd-1.3.0/redirect.txt
616 + /usr/share/doc/lighttpd-1.3.0/rewrite.txt
617 + /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
618 + /usr/share/doc/lighttpd-1.3.0/secdownload.txt
619 + /usr/share/doc/lighttpd-1.3.0/security.txt
620 + /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
621 + /usr/share/doc/lighttpd-1.3.0/skeleton.txt
622 + /usr/share/doc/lighttpd-1.3.0/ssi.txt
623 + /usr/share/doc/lighttpd-1.3.0/state.txt
624 + /usr/share/man/man1/lighttpd.1.gz
630 +---------- lighttpd-1.3.1-1 -----------
634 +---------- lighttpd-1.3.0-1 -----------
637 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
638 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
640 --- lighttpd-1.4.11/doc/Makefile.in 2006-03-07 14:20:57.000000000 +0200
641 +++ lighttpd-1.4.12/doc/Makefile.in 2006-07-11 21:48:12.000000000 +0300
643 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
644 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
647 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
649 am__aclocal_m4_deps = $(top_srcdir)/configure.in
650 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
652 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
653 +mkinstalldirs = $(install_sh) -d
654 CONFIG_HEADER = $(top_builddir)/config.h
660 LTLIBOBJS = @LTLIBOBJS@
661 -LUACONFIG = @LUACONFIG@
662 LUA_CFLAGS = @LUA_CFLAGS@
663 LUA_LIBS = @LUA_LIBS@
666 ac_ct_F77 = @ac_ct_F77@
667 ac_ct_RANLIB = @ac_ct_RANLIB@
668 ac_ct_STRIP = @ac_ct_STRIP@
669 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
670 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
671 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
672 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
673 --- lighttpd-1.4.11/doc/authentication.txt 2006-01-12 20:34:26.000000000 +0200
674 +++ lighttpd-1.4.12/doc/authentication.txt 2006-07-11 22:07:54.000000000 +0300
678 :Author: Jan Kneschke
680 -:Revision: $Revision$
682 +:Revision: $Revision$
685 The auth module provides ...
686 --- lighttpd-1.4.11/doc/compress.txt 2005-08-11 01:26:16.000000000 +0300
687 +++ lighttpd-1.4.12/doc/compress.txt 2006-07-11 22:07:54.000000000 +0300
691 Output compression reduces the network load and can improve the overall
692 -throughput of the webserver.
693 +throughput of the webserver. All major http-clients support compression by
694 +announcing it in the Accept-Encoding header. This is used to negotiate the
695 +most suitable compression method. We support deflate, gzip and bzip2.
697 -Only static content is supported up to now.
698 +deflate (RFC1950, RFC1951) and gzip (RFC1952) depend on zlib while bzip2
699 +depends on libbzip2. bzip2 is only supported by lynx and some other console
702 -The server negotiates automaticly which compression method is used.
703 -Supported are gzip, deflate, bzip.
704 +Currently we limit to compression support to static files.
709 +mod_compress can stored compressed files on disk to optimized the compression
710 +on a second request away. As soon as compress.cache-dir is set the files are
713 +The names of the cache files are made of the filename, the compression method
714 +and the etag associated to the file.
716 +Cleaning the cache is left to the user. A cron job deleting files older than
717 +10 days should do fine.
722 +The module limits the compression of files to files larger than 128 Byte and
723 +smaller than 128 MByte.
725 +The lower limit is set as small files tend to become larger by compressing due
726 +to the compression headers, the upper limit is set to work sensable with
727 +memory and cpu-time.
732 Default: not set, compress the file for every request
735 - mimetypes where might get compressed
736 + mimetypes which might get compressed
740 compress.filetype = ("text/plain", "text/html")
742 + Keep in mind that compressed JavaScript and CSS files are broken in some
747 +compress.max-file-size
748 + maximum size of the original file to be compressed kBytes.
750 + This is meant to protect the server against DoSing as compressing large
751 + (let's say 1Gbyte) takes a lot of time and would delay the whole operation
754 + There is a hard upper limit of 128Mbyte.
756 + Default: unlimited (== hard-limit of 128MByte)
758 Compressing Dynamic Content
759 ===========================
761 --- lighttpd-1.4.11/doc/configuration.txt 2006-03-09 02:10:40.000000000 +0200
762 +++ lighttpd-1.4.12/doc/configuration.txt 2006-07-11 22:07:54.000000000 +0300
766 :Author: Jan Kneschke
768 -:Revision: $Revision$
770 +:Revision: $Revision$
773 the layout of the configuration file
776 debug.log-request-handling
779 +debug.log-condition-handling
782 +debug.log-condition-cache-handling
783 + for developers only
785 --- lighttpd-1.4.11/doc/fastcgi.txt 2006-02-16 17:03:52.000000000 +0200
786 +++ lighttpd-1.4.12/doc/fastcgi.txt 2006-07-11 22:07:54.000000000 +0300
788 PHP can extract PATH_INFO from it (default: disabled)
789 :"disable-time": time to wait before a disabled backend is checked
791 - :"allow-x-send-file": controls if X-LIGHTTPD-send-file headers
793 + :"allow-x-send-file": controls if X-LIGHTTPD-send-file and X-Sendfile
794 + headers are allowed
798 --- lighttpd-1.4.11/doc/lighttpd.conf 2006-03-04 14:41:12.000000000 +0200
799 +++ lighttpd-1.4.12/doc/lighttpd.conf 2006-07-11 22:07:54.000000000 +0300
800 @@ -172,10 +172,11 @@
801 #dir-listing.activate = "enable"
804 -#debug.log-request-header = "enable"
805 -#debug.log-response-header = "enable"
806 -#debug.log-request-handling = "enable"
807 -#debug.log-file-not-found = "enable"
808 +#debug.log-request-header = "enable"
809 +#debug.log-response-header = "enable"
810 +#debug.log-request-handling = "enable"
811 +#debug.log-file-not-found = "enable"
812 +#debug.log-condition-handling = "enable"
814 ### only root can use these options
816 --- lighttpd-1.4.11/doc/performance.txt 2006-02-02 13:01:08.000000000 +0200
817 +++ lighttpd-1.4.12/doc/performance.txt 2006-07-11 22:07:54.000000000 +0300
820 server.stat-cache-engine = "fam" # either fam, simple or disabled
822 +See http://oss.sgi.com/projects/fam/faq.html for information about FAM.
823 +See http://www.gnome.org/~veillard/gamin/overview.html for information about gamin.
825 Platform-Specific Notes
826 =======================
827 --- lighttpd-1.4.11/doc/secdownload.txt 2005-12-20 15:58:58.000000000 +0200
828 +++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-11 22:07:54.000000000 +0300
830 $secret = "verysecret";
831 $uri_prefix = "/dl/";
834 + # filename, make sure it's started with a "/" or you'll get 404 in the browser
835 $f = "/secret-file.txt";
838 --- lighttpd-1.4.11/lighttpd.spec 2006-03-07 14:22:18.000000000 +0200
839 +++ lighttpd-1.4.12/lighttpd.spec 2006-07-11 22:07:58.000000000 +0300
841 Summary: A fast webserver with minimal memory-footprint (lighttpd)
846 Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
847 Packager: Jan Kneschke <jan@kneschke.de>
848 --- lighttpd-1.4.11/openwrt/Makefile.in 2006-03-07 14:20:58.000000000 +0200
849 +++ lighttpd-1.4.12/openwrt/Makefile.in 2006-07-11 21:48:12.000000000 +0300
851 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
852 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
855 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
857 am__aclocal_m4_deps = $(top_srcdir)/configure.in
858 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
860 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
861 +mkinstalldirs = $(install_sh) -d
862 CONFIG_HEADER = $(top_builddir)/config.h
863 CONFIG_CLEAN_FILES = control lighttpd.mk
868 LTLIBOBJS = @LTLIBOBJS@
869 -LUACONFIG = @LUACONFIG@
870 LUA_CFLAGS = @LUA_CFLAGS@
871 LUA_LIBS = @LUA_LIBS@
874 ac_ct_F77 = @ac_ct_F77@
875 ac_ct_RANLIB = @ac_ct_RANLIB@
876 ac_ct_STRIP = @ac_ct_STRIP@
877 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
878 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
879 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
880 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
881 --- lighttpd-1.4.11/openwrt/control 2006-03-07 14:22:19.000000000 +0200
882 +++ lighttpd-1.4.12/openwrt/control 2006-07-11 22:08:05.000000000 +0300
888 Maintainer: Jan Kneschke <jan@kneschke.de>
889 -Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.11.tar.gz
890 +Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.12.tar.gz
894 --- lighttpd-1.4.11/openwrt/lighttpd.mk 2006-03-07 14:22:19.000000000 +0200
895 +++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-11 22:08:05.000000000 +0300
898 # For this example we'll use a fairly simple package that compiles easily
899 # and has sources available for download at sourceforge
900 -LIGHTTPD=lighttpd-1.4.11
901 +LIGHTTPD=lighttpd-1.4.12
902 LIGHTTPD_TARGET=.built
903 LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
904 LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
905 --- lighttpd-1.4.11/src/Makefile.am 2006-03-07 14:20:20.000000000 +0200
906 +++ lighttpd-1.4.12/src/Makefile.am 2006-07-11 22:07:52.000000000 +0300
909 lib_LTLIBRARIES += mod_webdav.la
910 mod_webdav_la_SOURCES = mod_webdav.c
911 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
912 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
913 mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
914 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
915 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
917 lib_LTLIBRARIES += mod_cml.la
918 mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
919 --- lighttpd-1.4.11/src/Makefile.in 2006-03-07 14:21:02.000000000 +0200
920 +++ lighttpd-1.4.12/src/Makefile.in 2006-07-11 22:04:27.000000000 +0300
922 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
923 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
926 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
931 -SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) $(mod_cml_la_SOURCES) $(mod_compress_la_SOURCES) $(mod_dirlisting_la_SOURCES) $(mod_evasive_la_SOURCES) $(mod_evhost_la_SOURCES) $(mod_expire_la_SOURCES) $(mod_fastcgi_la_SOURCES) $(mod_flv_streaming_la_SOURCES) $(mod_indexfile_la_SOURCES) $(mod_mysql_vhost_la_SOURCES) $(mod_proxy_la_SOURCES) $(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) $(mod_rrdtool_la_SOURCES) $(mod_scgi_la_SOURCES) $(mod_secdownload_la_SOURCES) $(mod_setenv_la_SOURCES) $(mod_simple_vhost_la_SOURCES) $(mod_ssi_la_SOURCES) $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) $(lemon_SOURCES) $(lighttpd_SOURCES) $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
934 top_srcdir = @top_srcdir@
937 am__aclocal_m4_deps = $(top_srcdir)/configure.in
938 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
940 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
941 +mkinstalldirs = $(install_sh) -d
942 CONFIG_HEADER = $(top_builddir)/config.h
944 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
946 inet_ntop_cache.c crc32.c connections-glue.c configfile-glue.c \
947 http-header-glue.c network_write.c network_linux_sendfile.c \
948 network_freebsd_sendfile.c network_writev.c \
949 - network_solaris_sendfilev.c network_openssl.c splaytree.c
950 + network_solaris_sendfilev.c network_openssl.c splaytree.c \
951 + http_resp.c http_resp_parser.c
952 am__objects_1 = liblightcomp_la-buffer.lo liblightcomp_la-log.lo \
953 liblightcomp_la-keyvalue.lo liblightcomp_la-chunk.lo \
954 liblightcomp_la-http_chunk.lo liblightcomp_la-stream.lo \
956 liblightcomp_la-network_writev.lo \
957 liblightcomp_la-network_solaris_sendfilev.lo \
958 liblightcomp_la-network_openssl.lo \
959 - liblightcomp_la-splaytree.lo
960 + liblightcomp_la-splaytree.lo liblightcomp_la-http_resp.lo \
961 + liblightcomp_la-http_resp_parser.lo
962 @NO_RDYNAMIC_TRUE@am_liblightcomp_la_OBJECTS = $(am__objects_1)
963 liblightcomp_la_OBJECTS = $(am_liblightcomp_la_OBJECTS)
964 @NO_RDYNAMIC_TRUE@am_liblightcomp_la_rpath = -rpath $(libdir)
966 mod_simple_vhost_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
967 am_mod_simple_vhost_la_OBJECTS = mod_simple_vhost.lo
968 mod_simple_vhost_la_OBJECTS = $(am_mod_simple_vhost_la_OBJECTS)
969 +mod_sql_vhost_core_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
970 +am_mod_sql_vhost_core_la_OBJECTS = mod_sql_vhost_core.lo
971 +mod_sql_vhost_core_la_OBJECTS = $(am_mod_sql_vhost_core_la_OBJECTS)
972 mod_ssi_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
973 am_mod_ssi_la_OBJECTS = mod_ssi_exprparser.lo mod_ssi_expr.lo \
976 connections-glue.c configfile-glue.c http-header-glue.c \
977 network_write.c network_linux_sendfile.c \
978 network_freebsd_sendfile.c network_writev.c \
979 - network_solaris_sendfilev.c network_openssl.c splaytree.c
980 + network_solaris_sendfilev.c network_openssl.c splaytree.c \
981 + http_resp.c http_resp_parser.c
982 am__objects_2 = buffer.$(OBJEXT) log.$(OBJEXT) keyvalue.$(OBJEXT) \
983 chunk.$(OBJEXT) http_chunk.$(OBJEXT) stream.$(OBJEXT) \
984 fdevent.$(OBJEXT) stat_cache.$(OBJEXT) plugin.$(OBJEXT) \
986 network_linux_sendfile.$(OBJEXT) \
987 network_freebsd_sendfile.$(OBJEXT) network_writev.$(OBJEXT) \
988 network_solaris_sendfilev.$(OBJEXT) network_openssl.$(OBJEXT) \
989 - splaytree.$(OBJEXT)
990 + splaytree.$(OBJEXT) http_resp.$(OBJEXT) \
991 + http_resp_parser.$(OBJEXT)
992 @NO_RDYNAMIC_FALSE@am__objects_3 = $(am__objects_2)
993 am__objects_4 = server.$(OBJEXT) response.$(OBJEXT) \
994 connections.$(OBJEXT) network.$(OBJEXT) configfile.$(OBJEXT) \
996 $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
997 $(AM_CFLAGS) $(CFLAGS)
999 -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
1000 - $(AM_LDFLAGS) $(LDFLAGS) -o $@
1001 +LINK = $(LIBTOOL) --tag=CC --mode=link "$(CCLD)" $(AM_CFLAGS) \
1002 + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
1003 SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) \
1004 $(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) \
1005 $(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) \
1006 @@ -296,11 +301,12 @@
1007 $(mod_rewrite_la_SOURCES) $(mod_rrdtool_la_SOURCES) \
1008 $(mod_scgi_la_SOURCES) $(mod_secdownload_la_SOURCES) \
1009 $(mod_setenv_la_SOURCES) $(mod_simple_vhost_la_SOURCES) \
1010 - $(mod_ssi_la_SOURCES) $(mod_staticfile_la_SOURCES) \
1011 - $(mod_status_la_SOURCES) $(mod_trigger_b4_dl_la_SOURCES) \
1012 - $(mod_userdir_la_SOURCES) $(mod_usertrack_la_SOURCES) \
1013 - $(mod_webdav_la_SOURCES) $(lemon_SOURCES) $(lighttpd_SOURCES) \
1014 - $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
1015 + $(mod_sql_vhost_core_la_SOURCES) $(mod_ssi_la_SOURCES) \
1016 + $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) \
1017 + $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) \
1018 + $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) \
1019 + $(lemon_SOURCES) $(lighttpd_SOURCES) $(proc_open_SOURCES) \
1020 + $(spawn_fcgi_SOURCES)
1021 DIST_SOURCES = $(am__liblightcomp_la_SOURCES_DIST) \
1022 $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) \
1023 $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) \
1025 $(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) \
1026 $(mod_rrdtool_la_SOURCES) $(mod_scgi_la_SOURCES) \
1027 $(mod_secdownload_la_SOURCES) $(mod_setenv_la_SOURCES) \
1028 - $(mod_simple_vhost_la_SOURCES) $(mod_ssi_la_SOURCES) \
1029 + $(mod_simple_vhost_la_SOURCES) \
1030 + $(mod_sql_vhost_core_la_SOURCES) $(mod_ssi_la_SOURCES) \
1031 $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) \
1032 $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) \
1033 $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) \
1037 LTLIBOBJS = @LTLIBOBJS@
1038 -LUACONFIG = @LUACONFIG@
1039 LUA_CFLAGS = @LUA_CFLAGS@
1040 LUA_LIBS = @LUA_LIBS@
1043 ac_ct_F77 = @ac_ct_F77@
1044 ac_ct_RANLIB = @ac_ct_RANLIB@
1045 ac_ct_STRIP = @ac_ct_STRIP@
1046 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
1047 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
1048 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
1049 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
1051 network_write.c network_linux_sendfile.c \
1052 network_freebsd_sendfile.c network_writev.c \
1053 network_solaris_sendfilev.c network_openssl.c \
1055 + splaytree.c http_resp.c http_resp_parser.c
1057 src = server.c response.c connections.c network.c configfile.c \
1058 configparser.c request.c proc_open.c $(am__append_2)
1059 @@ -491,10 +498,11 @@
1060 #mod_httptls_la_LIBADD = $(common_libadd)
1061 lib_LTLIBRARIES = $(am__append_1) mod_flv_streaming.la mod_evasive.la \
1062 mod_webdav.la mod_cml.la mod_trigger_b4_dl.la \
1063 - mod_mysql_vhost.la mod_cgi.la mod_scgi.la mod_staticfile.la \
1064 - mod_dirlisting.la mod_indexfile.la mod_setenv.la mod_alias.la \
1065 - mod_userdir.la mod_rrdtool.la mod_usertrack.la mod_proxy.la \
1066 - mod_ssi.la mod_secdownload.la mod_expire.la mod_evhost.la \
1067 + mod_mysql_vhost.la mod_sql_vhost_core.la mod_cgi.la \
1068 + mod_scgi.la mod_staticfile.la mod_dirlisting.la \
1069 + mod_indexfile.la mod_setenv.la mod_alias.la mod_userdir.la \
1070 + mod_rrdtool.la mod_usertrack.la mod_proxy.la mod_ssi.la \
1071 + mod_secdownload.la mod_expire.la mod_evhost.la \
1072 mod_simple_vhost.la mod_fastcgi.la mod_access.la \
1073 mod_compress.la mod_auth.la mod_rewrite.la mod_redirect.la \
1074 mod_status.la mod_accesslog.la
1076 mod_evasive_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1077 mod_evasive_la_LIBADD = $(common_libadd)
1078 mod_webdav_la_SOURCES = mod_webdav.c
1079 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
1080 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
1081 mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1082 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
1083 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
1084 mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
1085 mod_cml_la_CFLAGS = $(AM_CFLAGS) $(LUA_CFLAGS)
1086 mod_cml_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1088 mod_mysql_vhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1089 mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
1090 mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
1091 +mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
1092 +mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1093 +mod_sql_vhost_core_la_LIBADD = $(common_libadd)
1094 mod_cgi_la_SOURCES = mod_cgi.c
1095 mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1096 mod_cgi_la_LIBADD = $(common_libadd)
1098 mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
1099 configparser.h mod_ssi_exprparser.h \
1100 sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
1101 - splaytree.h proc_open.h
1102 + splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h \
1103 + sys-files.h sys-process.h sys-strings.h
1105 lighttpd_SOURCES = $(src)
1106 lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS)
1108 $(LINK) -rpath $(libdir) $(mod_setenv_la_LDFLAGS) $(mod_setenv_la_OBJECTS) $(mod_setenv_la_LIBADD) $(LIBS)
1109 mod_simple_vhost.la: $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_DEPENDENCIES)
1110 $(LINK) -rpath $(libdir) $(mod_simple_vhost_la_LDFLAGS) $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_LIBADD) $(LIBS)
1111 +mod_sql_vhost_core.la: $(mod_sql_vhost_core_la_OBJECTS) $(mod_sql_vhost_core_la_DEPENDENCIES)
1112 + $(LINK) -rpath $(libdir) $(mod_sql_vhost_core_la_LDFLAGS) $(mod_sql_vhost_core_la_OBJECTS) $(mod_sql_vhost_core_la_LIBADD) $(LIBS)
1113 mod_ssi.la: $(mod_ssi_la_OBJECTS) $(mod_ssi_la_DEPENDENCIES)
1114 $(LINK) -rpath $(libdir) $(mod_ssi_la_LDFLAGS) $(mod_ssi_la_OBJECTS) $(mod_ssi_la_LIBADD) $(LIBS)
1115 mod_staticfile.la: $(mod_staticfile_la_OBJECTS) $(mod_staticfile_la_DEPENDENCIES)
1117 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_auth.Plo@am__quote@
1118 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_auth_digest.Plo@am__quote@
1119 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_chunk.Po@am__quote@
1120 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_resp.Po@am__quote@
1121 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_resp_parser.Po@am__quote@
1122 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_ntop_cache.Po@am__quote@
1123 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joblist.Po@am__quote@
1124 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyvalue.Po@am__quote@
1126 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_solaris_devpoll.Plo@am__quote@
1127 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http-header-glue.Plo@am__quote@
1128 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_chunk.Plo@am__quote@
1129 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_resp.Plo@am__quote@
1130 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_resp_parser.Plo@am__quote@
1131 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-inet_ntop_cache.Plo@am__quote@
1132 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-joblist.Plo@am__quote@
1133 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-keyvalue.Plo@am__quote@
1135 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_secure_download.Plo@am__quote@
1136 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_setenv.Plo@am__quote@
1137 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_simple_vhost.Plo@am__quote@
1138 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_sql_vhost_core.Plo@am__quote@
1139 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi.Plo@am__quote@
1140 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi_expr.Plo@am__quote@
1141 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi_exprparser.Plo@am__quote@
1142 @@ -1247,6 +1266,20 @@
1143 @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1144 @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -c -o liblightcomp_la-splaytree.lo `test -f 'splaytree.c' || echo '$(srcdir)/'`splaytree.c
1146 +liblightcomp_la-http_resp.lo: http_resp.c
1147 +@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -MT liblightcomp_la-http_resp.lo -MD -MP -MF "$(DEPDIR)/liblightcomp_la-http_resp.Tpo" -c -o liblightcomp_la-http_resp.lo `test -f 'http_resp.c' || echo '$(srcdir)/'`http_resp.c; \
1148 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/liblightcomp_la-http_resp.Tpo" "$(DEPDIR)/liblightcomp_la-http_resp.Plo"; else rm -f "$(DEPDIR)/liblightcomp_la-http_resp.Tpo"; exit 1; fi
1149 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='http_resp.c' object='liblightcomp_la-http_resp.lo' libtool=yes @AMDEPBACKSLASH@
1150 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1151 +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -c -o liblightcomp_la-http_resp.lo `test -f 'http_resp.c' || echo '$(srcdir)/'`http_resp.c
1153 +liblightcomp_la-http_resp_parser.lo: http_resp_parser.c
1154 +@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -MT liblightcomp_la-http_resp_parser.lo -MD -MP -MF "$(DEPDIR)/liblightcomp_la-http_resp_parser.Tpo" -c -o liblightcomp_la-http_resp_parser.lo `test -f 'http_resp_parser.c' || echo '$(srcdir)/'`http_resp_parser.c; \
1155 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/liblightcomp_la-http_resp_parser.Tpo" "$(DEPDIR)/liblightcomp_la-http_resp_parser.Plo"; else rm -f "$(DEPDIR)/liblightcomp_la-http_resp_parser.Tpo"; exit 1; fi
1156 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='http_resp_parser.c' object='liblightcomp_la-http_resp_parser.lo' libtool=yes @AMDEPBACKSLASH@
1157 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1158 +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -c -o liblightcomp_la-http_resp_parser.lo `test -f 'http_resp_parser.c' || echo '$(srcdir)/'`http_resp_parser.c
1160 mod_cml_la-mod_cml.lo: mod_cml.c
1161 @am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mod_cml_la_CFLAGS) $(CFLAGS) -MT mod_cml_la-mod_cml.lo -MD -MP -MF "$(DEPDIR)/mod_cml_la-mod_cml.Tpo" -c -o mod_cml_la-mod_cml.lo `test -f 'mod_cml.c' || echo '$(srcdir)/'`mod_cml.c; \
1162 @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mod_cml_la-mod_cml.Tpo" "$(DEPDIR)/mod_cml_la-mod_cml.Plo"; else rm -f "$(DEPDIR)/mod_cml_la-mod_cml.Tpo"; exit 1; fi
1163 @@ -1506,14 +1539,19 @@
1164 @CROSS_COMPILING_TRUE@mod_ssi_exprparser.c mod_ssi_exprparser.h:
1165 @CROSS_COMPILING_FALSE@configparser.y: lemon
1166 @CROSS_COMPILING_FALSE@mod_ssi_exprparser.y: lemon
1167 +@CROSS_COMPILING_FALSE@http_resp_parser.y: lemon
1169 @CROSS_COMPILING_FALSE@configparser.c configparser.h: configparser.y
1170 @CROSS_COMPILING_FALSE@ rm -f configparser.h
1171 -@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
1172 +@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
1174 +@CROSS_COMPILING_FALSE@http_resp_parser.c http_resp_parser.h: http_resp_parser.y
1175 +@CROSS_COMPILING_FALSE@ rm -f http_resp_parser.h
1176 +@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
1178 @CROSS_COMPILING_FALSE@mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y
1179 @CROSS_COMPILING_FALSE@ rm -f mod_ssi_exprparser.h
1180 -@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
1181 +@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
1183 configfile.c: configparser.h
1184 mod_ssi_expr.c: mod_ssi_exprparser.h
1185 --- lighttpd-1.4.11/src/array.c 2005-11-18 13:58:32.000000000 +0200
1186 +++ lighttpd-1.4.12/src/array.c 2006-07-11 22:07:51.000000000 +0300
1189 array *array_init(void) {
1193 a = calloc(1, sizeof(*a));
1197 a->next_power_of_2 = 1;
1204 void array_free(array *a) {
1209 if (!a->is_weakref) {
1210 for (i = 0; i < a->size; i++) {
1211 if (a->data[i]) a->data[i]->free(a->data[i]);
1216 if (a->data) free(a->data);
1217 if (a->sorted) free(a->sorted);
1223 void array_reset(array *a) {
1228 if (!a->is_weakref) {
1229 for (i = 0; i < a->used; i++) {
1230 a->data[i]->reset(a->data[i]);
1239 static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
1244 if (key == NULL) return -1;
1247 /* try to find the string */
1248 for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
1254 } else if (pos >= (int)a->used) {
1257 cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
1262 ndx = a->sorted[pos];
1263 @@ -110,46 +110,46 @@
1269 if (rndx) *rndx = pos;
1275 data_unset *array_get_element(array *a, const char *key) {
1279 if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
1280 /* found, leave here */
1283 return a->data[ndx];
1291 data_unset *array_get_unused_element(array *a, data_type_t t) {
1292 data_unset *ds = NULL;
1297 if (a->size == 0) return NULL;
1300 if (a->used == a->size) return NULL;
1302 if (a->data[a->used]) {
1303 ds = a->data[a->used];
1306 a->data[a->used] = NULL;
1313 /* replace or insert data, return the old one with the same key */
1314 data_unset *array_replace(array *a, data_unset *du) {
1318 if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
1319 array_insert_unique(a, du);
1321 @@ -164,13 +164,13 @@
1326 - /* generate unique index if neccesary */
1328 + /* generate unique index if necessary */
1329 if (str->key->used == 0 || str->is_index_key) {
1330 buffer_copy_long(str->key, a->unique_ndx++);
1331 str->is_index_key = 1;
1335 /* try to find the string */
1336 if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
1337 /* found, leave here */
1338 @@ -181,14 +181,14 @@
1347 if (a->used+1 > INT_MAX) {
1348 /* we can't handle more then INT_MAX entries: see array_get_index() */
1355 a->data = malloc(sizeof(*a->data) * a->size);
1356 @@ -204,27 +204,27 @@
1358 for (j = a->used; j < a->size; j++) a->data[j] = NULL;
1362 ndx = (int) a->used;
1365 a->data[a->used++] = str;
1371 buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
1375 - /* move everything on step to the right */
1378 + /* move everything one step to the right */
1380 memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
1385 a->sorted[pos] = ndx;
1388 if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
1405 array_print_indent(depth);
1406 fprintf(stderr, ")");
1412 @@ -323,47 +323,47 @@
1424 ds = data_string_init();
1425 buffer_copy_string(ds->key, "abc");
1426 buffer_copy_string(ds->value, "alfrag");
1429 array_insert_unique(a, (data_unset *)ds);
1432 ds = data_string_init();
1433 buffer_copy_string(ds->key, "abc");
1434 buffer_copy_string(ds->value, "hameplman");
1437 array_insert_unique(a, (data_unset *)ds);
1440 ds = data_string_init();
1441 buffer_copy_string(ds->key, "123");
1442 buffer_copy_string(ds->value, "alfrag");
1445 array_insert_unique(a, (data_unset *)ds);
1448 dc = data_count_init();
1449 buffer_copy_string(dc->key, "def");
1452 array_insert_unique(a, (data_unset *)dc);
1455 dc = data_count_init();
1456 buffer_copy_string(dc->key, "def");
1459 array_insert_unique(a, (data_unset *)dc);
1468 fprintf(stderr, "%d\n",
1469 buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
1475 --- lighttpd-1.4.11/src/array.h 2005-09-23 21:24:18.000000000 +0300
1476 +++ lighttpd-1.4.12/src/array.h 2006-07-11 22:07:51.000000000 +0300
1478 #define DATA_UNSET \
1481 - int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
1482 + int is_index_key; /* 1 if key is an array index (auto-generated keys) */ \
1483 struct data_unset *(*copy)(const struct data_unset *src); \
1484 void (* free)(struct data_unset *p); \
1485 void (* reset)(struct data_unset *p); \
1502 size_t next_power_of_2;
1503 int is_weakref; /* data is weakref, don't bother the data */
1532 COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP
1535 -/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
1536 +/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
1537 * for print: comp_key op string
1538 * for compare: comp cond string/regex
1541 typedef struct _data_config data_config;
1542 struct _data_config {
1557 int context_ndx; /* more or less like an id */
1561 /* for chaining only */
1578 @@ -120,13 +120,13 @@
1584 unsigned short port;
1591 int usage; /* fair-balancing needs the no. of connections active on this host */
1592 int last_used_ndx; /* round robin */
1594 --- lighttpd-1.4.11/src/base.h 2006-01-11 16:51:04.000000000 +0200
1595 +++ lighttpd-1.4.12/src/base.h 2006-07-11 22:07:51.000000000 +0300
1599 #include <sys/types.h>
1600 -#include <sys/time.h>
1601 #include <sys/stat.h>
1603 #ifdef HAVE_CONFIG_H
1605 #include "sys-socket.h"
1606 #include "splaytree.h"
1609 #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
1610 # define USE_OPENSSL
1611 -# include <openssl/ssl.h>
1612 +# include <openssl/ssl.h>
1620 -#ifndef O_LARGEFILE
1621 -# define O_LARGEFILE 0
1626 # define SIZE_MAX SIZE_T_MAX
1629 /* solaris and NetBSD 1.3.x again */
1630 #if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t))
1631 -# define uint32_t u_int32_t
1632 +//# define uint32_t u_int32_t
1633 +typedef unsigned __int32 uint32_t;
1639 #include "settings.h"
1641 -typedef enum { T_CONFIG_UNSET,
1647 +typedef enum { T_CONFIG_UNSET,
1654 } config_values_type_t;
1656 -typedef enum { T_CONFIG_SCOPE_UNSET,
1657 - T_CONFIG_SCOPE_SERVER,
1658 +typedef enum { T_CONFIG_SCOPE_UNSET,
1659 + T_CONFIG_SCOPE_SERVER,
1660 T_CONFIG_SCOPE_CONNECTION
1661 } config_scope_type_t;
1668 config_values_type_t type;
1669 config_scope_type_t scope;
1671 @@ -142,40 +137,40 @@
1672 /* the request-line */
1680 http_method_t http_method;
1681 http_version_t http_version;
1684 buffer *request_line;
1687 /* strings to the header */
1688 buffer *http_host; /* not alloced */
1689 const char *http_range;
1690 const char *http_content_type;
1691 const char *http_if_modified_since;
1692 const char *http_if_none_match;
1699 size_t content_length; /* returned by strtoul() */
1702 /* internal representation */
1703 int accept_encoding;
1711 off_t content_length;
1712 - int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */
1714 + int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
1721 HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
1722 } transfer_encoding;
1724 @@ -191,21 +186,21 @@
1727 buffer *basedir; /* path = "(basedir)(.*)" */
1730 buffer *doc_root; /* path = doc_root + rel_path */
1755 - splay_tree *files; /* the nodes of the tree are stat_cache_entry's */
1757 + splay_tree *files; /* the nodes of the tree are stat_cache_entries */
1759 buffer *dir_name; /* for building the dirname from the filename */
1761 splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */
1768 /* virtual-servers */
1769 buffer *document_root;
1770 buffer *server_name;
1773 buffer *dirlist_encoding;
1774 buffer *errorfile_prefix;
1777 unsigned short max_keep_alive_requests;
1778 unsigned short max_keep_alive_idle;
1779 unsigned short max_read_idle;
1780 @@ -244,16 +239,17 @@
1781 unsigned short use_xattr;
1782 unsigned short follow_symlink;
1783 unsigned short range_requests;
1789 unsigned short log_file_not_found;
1790 unsigned short log_request_header;
1791 unsigned short log_request_handling;
1792 unsigned short log_response_header;
1793 unsigned short log_condition_handling;
1796 + unsigned short log_condition_cache_handling;
1800 buffer *ssl_pemfile;
1801 buffer *ssl_ca_file;
1802 @@ -268,22 +264,22 @@
1804 unsigned short global_kbytes_per_second; /* */
1806 - off_t global_bytes_per_second_cnt;
1807 + off_t global_bytes_per_second_cnt;
1808 /* server-wide traffic-shaper
1811 * each context has the counter which is inited once
1812 - * a second by the global_kbytes_per_second config-var
1813 + * per second by the global_kbytes_per_second config-var
1815 * as soon as global_kbytes_per_second gets below 0
1816 * the connected conns are "offline" a little bit
1819 - * we somehow have to loose our "we are writable" signal
1820 + * we somehow have to lose our "we are writable" signal
1825 off_t *global_bytes_per_second_cnt_ptr; /* */
1831 @@ -291,18 +287,18 @@
1833 /* the order of the items should be the same as they are processed
1834 * read before write as we use this later */
1836 - CON_STATE_CONNECT,
1837 - CON_STATE_REQUEST_START,
1839 - CON_STATE_REQUEST_END,
1840 - CON_STATE_READ_POST,
1841 - CON_STATE_HANDLE_REQUEST,
1842 - CON_STATE_RESPONSE_START,
1844 - CON_STATE_RESPONSE_END,
1848 + CON_STATE_CONNECT,
1849 + CON_STATE_REQUEST_START,
1851 + CON_STATE_REQUEST_END,
1852 + CON_STATE_READ_POST,
1853 + CON_STATE_HANDLE_REQUEST,
1854 + CON_STATE_RESPONSE_START,
1856 + CON_STATE_RESPONSE_END,
1859 } connection_state_t;
1861 typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
1862 @@ -315,88 +311,88 @@
1865 connection_state_t state;
1869 time_t read_idle_ts;
1870 time_t close_timeout_ts;
1871 time_t write_request_ts;
1874 time_t connection_start;
1875 time_t request_start;
1878 struct timeval start_tv;
1881 size_t request_count; /* number of requests handled in this connection */
1882 size_t loops_per_request; /* to catch endless loops in a single request
1885 * used by mod_rewrite, mod_fastcgi, ... and others
1886 * this is self-protection
1890 int fd; /* the FD for this connection */
1891 int fde_ndx; /* index for the fdevent-handler */
1892 int ndx; /* reverse mapping to server->connection[ndx] */
1899 - int keep_alive; /* only request.c can enable it, all other just disable */
1902 + int keep_alive; /* only request.c can enable it, all others just disable */
1908 chunkqueue *write_queue; /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
1909 chunkqueue *read_queue; /* a small queue for low-level read ( HTTP request ) [ mem ] */
1910 chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/
1913 int traffic_limit_reached;
1916 off_t bytes_written; /* used by mod_accesslog, mod_rrd */
1917 off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */
1918 off_t bytes_read; /* used by mod_accesslog, mod_rrd */
1926 buffer *dst_addr_buf;
1929 buffer *parse_request;
1930 unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */
1935 - physical physical;
1936 + physical physical;
1943 buffer *authed_user;
1944 array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
1954 connection_type mode;
1957 void **plugin_ctx; /* plugin connection specific config */
1960 specific_config conf; /* global connection specific config */
1961 cond_cache_t *cond_cache;
1964 buffer *server_name;
1968 buffer *error_handler;
1969 int error_handler_saved_status;
1970 int in_error_handler;
1973 void *srv_socket; /* reference to the server-socket (typecast to server_socket) */
1979 @@ -439,39 +435,48 @@
1984 + NETWORK_STATUS_UNSET,
1985 + NETWORK_STATUS_SUCCESS,
1986 + NETWORK_STATUS_FATAL_ERROR,
1987 + NETWORK_STATUS_CONNECTION_CLOSE,
1988 + NETWORK_STATUS_WAIT_FOR_EVENT,
1989 + NETWORK_STATUS_INTERRUPTED
1990 +} network_status_t;
1993 unsigned short port;
1997 buffer *errorlog_file;
1998 unsigned short errorlog_use_syslog;
2001 unsigned short dont_daemonize;
2010 buffer *event_handler;
2013 buffer *modules_dir;
2014 buffer *network_backend;
2016 array *upload_tempdirs;
2019 unsigned short max_worker;
2020 unsigned short max_fds;
2021 unsigned short max_conns;
2022 unsigned short max_request_size;
2025 unsigned short log_request_header_on_error;
2026 unsigned short log_state_handling;
2028 - enum { STAT_CACHE_ENGINE_UNSET,
2029 - STAT_CACHE_ENGINE_NONE,
2030 - STAT_CACHE_ENGINE_SIMPLE,
2031 - STAT_CACHE_ENGINE_FAM
2033 + enum { STAT_CACHE_ENGINE_UNSET,
2034 + STAT_CACHE_ENGINE_NONE,
2035 + STAT_CACHE_ENGINE_SIMPLE,
2036 + STAT_CACHE_ENGINE_FAM
2037 } stat_cache_engine;
2038 unsigned short enable_cores;
2040 @@ -480,14 +485,14 @@
2046 buffer *ssl_pemfile;
2047 buffer *ssl_ca_file;
2048 unsigned short use_ipv6;
2049 unsigned short is_ssl;
2058 @@ -495,37 +500,37 @@
2061 server_socket **ptr;
2066 } server_socket_array;
2068 typedef struct server {
2069 server_socket_array srv_sockets;
2074 enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
2075 buffer *errorlog_buf;
2078 fdevents *ev, *ev_ins;
2081 buffer_plugin plugins;
2095 int max_fds; /* max possible fds */
2096 int cur_fds; /* currently used fds */
2097 int want_fds; /* waiting fds */
2098 int sockets_disabled;
2104 @@ -533,13 +538,13 @@
2105 buffer *response_header;
2106 buffer *response_range;
2110 buffer *tmp_chunk_len;
2113 buffer *empty_string; /* is necessary for cond_match */
2115 buffer *cond_check_buf;
2120 inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
2121 @@ -547,31 +552,31 @@
2122 mtime_cache_type mtime_cache[FILE_CACHE_MAX];
2129 time_t last_generated_date_ts;
2130 time_t last_generated_debug_ts;
2134 buffer *ts_debug_str;
2135 buffer *ts_date_str;
2140 array *config_touched;
2143 array *config_context;
2144 specific_config **config_storage;
2147 server_config srvconf;
2150 int config_deprecated;
2154 connections *joblist;
2155 connections *fdwaitqueue;
2158 stat_cache *stat_cache;
2161 @@ -588,18 +593,20 @@
2162 * fastcgi.backend.<key>.disconnects = ...
2167 fdevent_handler_t event_handler;
2169 - int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2170 - int (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2171 + network_status_t (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2172 + network_status_t (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2174 - int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2175 - int (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2176 + network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2177 + network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2187 --- lighttpd-1.4.11/src/buffer.c 2006-01-13 00:00:45.000000000 +0200
2188 +++ lighttpd-1.4.12/src/buffer.c 2006-07-11 22:07:52.000000000 +0300
2199 buffer* buffer_init(void) {
2203 b = malloc(sizeof(*b));
2225 void buffer_free(buffer *b) {
2228 void buffer_reset(buffer *b) {
2232 /* limit don't reuse buffer larger than ... bytes */
2233 if (b->size > BUFFER_MAX_REUSE_SIZE) {
2246 - * allocate (if neccessary) enough space for 'size' bytes and
2248 + * allocate (if necessary) enough space for 'size' bytes and
2249 * set the 'used' counter to 0
2254 #define BUFFER_PIECE_SIZE 64
2256 int buffer_prepare_copy(buffer *b, size_t size) {
2259 - if ((0 == b->size) ||
2261 + if ((0 == b->size) ||
2263 if (b->size) free(b->ptr);
2268 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
2270 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
2271 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2274 b->ptr = malloc(b->size);
2282 - * increase the internal buffer (if neccessary) to append another 'size' byte
2284 + * increase the internal buffer (if necessary) to append another 'size' byte
2285 * ->used isn't changed
2290 int buffer_prepare_append(buffer *b, size_t size) {
2297 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
2299 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
2300 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2303 b->ptr = malloc(b->size);
2306 } else if (b->used + size > b->size) {
2309 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
2311 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
2312 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2315 b->ptr = realloc(b->ptr, b->size);
2320 int buffer_copy_string(buffer *b, const char *s) {
2324 if (!s || !b) return -1;
2326 s_len = strlen(s) + 1;
2327 @@ -136,26 +136,26 @@
2329 int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
2330 if (!s || !b) return -1;
2332 - /* removed optimization as we have to keep the empty string
2334 + /* removed optimization as we have to keep the empty string
2335 * in some cases for the config handling
2338 * url.access-deny = ( "" )
2340 if (s_len == 0) return 0;
2343 buffer_prepare_copy(b, s_len + 1);
2346 memcpy(b->ptr, s, s_len);
2347 b->ptr[s_len] = '\0';
2348 b->used = s_len + 1;
2354 int buffer_copy_string_buffer(buffer *b, const buffer *src) {
2355 if (!src) return -1;
2358 if (src->used == 0) {
2361 @@ -201,10 +201,10 @@
2364 * append a string to the end of the buffer
2366 - * the resulting buffer is terminated with a '\0'
2367 - * s is treated as a un-terminated string (a \0 is handled a normal character)
2370 + * the resulting buffer is terminated with a '\0'
2371 + * s is treated as an un-terminated string (a \0 is handled as a normal character)
2374 * @param s the string
2375 * @param s_len size of the string (without the terminating \0)
2377 int buffer_append_string_buffer(buffer *b, const buffer *src) {
2378 if (!src) return -1;
2379 if (src->used == 0) return 0;
2382 return buffer_append_string_len(b, src->ptr, src->used - 1);
2387 int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
2388 if (!s || !b) return -1;
2394 return buffer_append_memory(b, s, s_len);
2397 @@ -402,46 +402,115 @@
2403 + * init the ptr buffer
2406 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer)
2408 + buffer_ptr *l = calloc(1, sizeof(buffer_ptr));
2415 + * free the buffer_array
2418 +void buffer_ptr_free(buffer_ptr *l)
2421 + buffer_ptr_clear(l);
2426 +void buffer_ptr_clear(buffer_ptr *l)
2428 + assert(NULL != l);
2430 + if (l->free && l->used) {
2432 + for (i = 0; i < l->used; i ++) {
2433 + l->free(l->ptr[i]);
2445 +void buffer_ptr_append(buffer_ptr* l, void *item)
2447 + assert(NULL != l);
2448 + if (l->ptr == NULL) {
2450 + l->ptr = (void **)malloc(sizeof(void *) * l->size);
2452 + else if (l->used == l->size) {
2454 + l->ptr = realloc(l->ptr, sizeof(void *) * l->size);
2456 + l->ptr[l->used++] = item;
2459 +void *buffer_ptr_pop(buffer_ptr* l)
2461 + assert(NULL != l && l->used > 0);
2462 + return l->ptr[--l->used];
2465 +void *buffer_ptr_top(buffer_ptr* l)
2467 + assert(NULL != l && l->used > 0);
2468 + return l->ptr[l->used-1];
2476 buffer_array* buffer_array_init(void) {
2480 b = malloc(sizeof(*b));
2492 void buffer_array_reset(buffer_array *b) {
2499 /* if they are too large, reduce them */
2500 for (i = 0; i < b->used; i++) {
2501 buffer_reset(b->ptr[i]);
2510 - * free the buffer_array
2512 + * free the buffer_array
2516 void buffer_array_free(buffer_array *b) {
2521 for (i = 0; i < b->size; i++) {
2522 if (b->ptr[i]) buffer_free(b->ptr[i]);
2526 buffer *buffer_array_append_get_buffer(buffer_array *b) {
2532 b->ptr = malloc(sizeof(*b->ptr) * b->size);
2533 @@ -467,13 +536,13 @@
2539 if (b->ptr[b->used] == NULL) {
2540 b->ptr[b->used] = buffer_init();
2544 b->ptr[b->used]->used = 0;
2547 return b->ptr[b->used++];
2550 @@ -482,23 +551,23 @@
2552 if (len == 0) return NULL;
2553 if (needle == NULL) return NULL;
2556 if (b->used < len) return NULL;
2559 for(i = 0; i < b->used - len; i++) {
2560 if (0 == memcmp(b->ptr + i, needle, len)) {
2569 buffer *buffer_init_string(const char *str) {
2570 buffer *b = buffer_init();
2573 buffer_copy_string(b, str);
2583 - * check if two buffer contain the same data
2585 + * check if two buffers contain the same data
2587 * HISTORY: this function was pretty much optimized, but didn't handled
2588 * alignment properly.
2590 @@ -522,100 +591,100 @@
2592 int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
2600 return buffer_is_equal(a, &b);
2603 /* simple-assumption:
2605 - * most parts are equal and doing a case conversion needs time
2608 + * most parts are equal and doing a case conversion takes time
2611 int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
2612 size_t ndx = 0, max_ndx;
2614 size_t mask = sizeof(*al) - 1;
2620 - /* is the alignment correct ? */
2622 + /* is the alignment correct? */
2623 if ( ((size_t)al & mask) == 0 &&
2624 ((size_t)bl & mask) == 0 ) {
2627 max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
2630 for (; ndx < max_ndx; ndx += sizeof(*al)) {
2631 if (*al != *bl) break;
2645 max_ndx = ((a_len < b_len) ? a_len : b_len);
2648 for (; ndx < max_ndx; ndx++) {
2649 char a1 = *a++, b1 = *b++;
2653 if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z'))
2655 else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z'))
2657 if ((a1 - b1) != 0) return (a1 - b1);
2669 * check if the rightmost bytes of the string are equal.
2676 int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
2677 /* no, len -> equal */
2678 if (len == 0) return 1;
2681 /* len > 0, but empty buffers -> not equal */
2682 if (b1->used == 0 || b2->used == 0) return 0;
2685 /* buffers too small -> not equal */
2686 - if (b1->used - 1 < len || b1->used - 1 < len) return 0;
2688 - if (0 == strncmp(b1->ptr + b1->used - 1 - len,
2689 + if (b1->used - 1 < len || b2->used - 1 < len) return 0;
2691 + if (0 == strncmp(b1->ptr + b1->used - 1 - len,
2692 b2->ptr + b2->used - 1 - len, len)) {
2700 int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
2705 if (in_len * 2 < in_len) return -1;
2708 buffer_prepare_copy(b, in_len * 2 + 1);
2711 for (i = 0; i < in_len; i++) {
2712 b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
2713 b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
2715 b->ptr[b->used++] = '\0';
2722 0 1 2 3 4 5 6 7 8 9 A B C D E F
2724 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2725 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2726 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2727 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, /* 20 - 2F space " # $ % & ' + , / */
2728 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
2729 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2731 0 1 2 3 4 5 6 7 8 9 A B C D E F
2733 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2734 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2735 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2736 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, /* 20 - 2F space " # $ % & ' + , / */
2737 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
2738 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2740 0 1 2 3 4 5 6 7 8 9 A B C D E F
2742 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2743 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2744 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2745 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
2746 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
2747 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2749 0 1 2 3 4 5 6 7 8 9 A B C D E F
2751 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2752 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2753 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2754 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
2755 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
2756 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2757 @@ -712,12 +781,12 @@
2758 0 1 2 3 4 5 6 7 8 9 A B C D E F
2760 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2761 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2762 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
2763 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
2764 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
2765 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
2766 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
2767 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2768 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
2769 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
2770 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
2771 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
2772 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
2773 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */
2774 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
2775 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
2776 @@ -734,13 +803,13 @@
2777 unsigned char *ds, *d;
2779 const char *map = NULL;
2782 if (!s || !b) return -1;
2785 if (b->ptr[b->used - 1] != '\0') {
2790 if (s_len == 0) return 0;
2793 @@ -760,12 +829,12 @@
2794 map = encoded_chars_hex;
2796 case ENCODING_UNSET:
2798 + return buffer_append_string_len(b, s, s_len);
2801 assert(map != NULL);
2803 - /* count to-be-encoded-characters */
2805 + /* count to-be-encoded characters */
2806 for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2815 buffer_prepare_append(b, d_len);
2818 for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2821 @@ -820,16 +889,16 @@
2825 - /* terminate buffer and calculate new length */
2826 + /* terminate buffer and calculate new length */
2827 b->ptr[b->used + d_len - 1] = '\0';
2836 -/* decodes url-special-chars inplace.
2837 +/* decodes url-special chars in-place.
2838 * replaces non-printable characters with '_'
2841 @@ -854,10 +923,10 @@
2842 low = hex2int(*(src + 2));
2844 high = (high << 4) | low;
2846 - /* map control-characters out */
2848 + /* map out control characters */
2849 if (high < 32 || high == 127) high = '_';
2856 * /abc/./xyz gets /abc/xyz
2857 * /abc//xyz gets /abc/xyz
2859 - * NOTE: src and dest can point to the same buffer, in which case,
2860 + * NOTE: src and dest can point to the same buffer, in which case
2861 * the operation is performed in-place.
2864 @@ -979,7 +1048,7 @@
2866 int light_isxdigit(int c) {
2867 if (light_isdigit(c)) return 1;
2871 return (c >= 'a' && c <= 'f');
2873 @@ -993,31 +1062,56 @@
2874 return light_isdigit(c) || light_isalpha(c);
2877 +#undef BUFFER_CTYPE_FUNC
2878 +#define BUFFER_CTYPE_FUNC(type) \
2879 + int buffer_is##type(buffer *b) { \
2881 + if (b->used < 2) return 0; \
2883 + len = b->used - 1; \
2884 + /* c-string only */ \
2885 + if (b->ptr[len] != '\0') { \
2888 + /* check on the whole string */ \
2889 + for (i = 0; i < len; i ++) { \
2890 + if (!light_is##type(b->ptr[i])) { \
2897 +BUFFER_CTYPE_FUNC(digit)
2898 +BUFFER_CTYPE_FUNC(xdigit)
2899 +BUFFER_CTYPE_FUNC(alpha)
2900 +BUFFER_CTYPE_FUNC(alnum)
2902 int buffer_to_lower(buffer *b) {
2906 if (b->used == 0) return 0;
2909 for (c = b->ptr; *c; c++) {
2910 if (*c >= 'A' && *c <= 'Z') {
2920 int buffer_to_upper(buffer *b) {
2924 if (b->used == 0) return 0;
2927 for (c = b->ptr; *c; c++) {
2928 if (*c >= 'a' && *c <= 'z') {
2936 --- lighttpd-1.4.11/src/buffer.h 2006-01-13 00:00:45.000000000 +0200
2937 +++ lighttpd-1.4.12/src/buffer.h 2006-07-11 22:07:52.000000000 +0300
2949 +typedef void (*buffer_ptr_free_t)(void *p);
2955 + buffer_ptr_free_t free;
2969 - size_t offset; /* input-pointer */
2971 - size_t used; /* output-pointer */
2973 + size_t offset; /* input pointer */
2975 + size_t used; /* output pointer */
2979 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer);
2980 +void buffer_ptr_free(buffer_ptr *b);
2981 +void buffer_ptr_clear(buffer_ptr *b);
2982 +void buffer_ptr_append(buffer_ptr *b, void *item);
2983 +void *buffer_ptr_pop(buffer_ptr *b);
2984 +void *buffer_ptr_top(buffer_ptr *b);
2986 buffer_array* buffer_array_init(void);
2987 void buffer_array_free(buffer_array *b);
2988 void buffer_array_reset(buffer_array *b);
2990 buffer* buffer_init_string(const char *str);
2991 void buffer_free(buffer *b);
2992 void buffer_reset(buffer *b);
2995 int buffer_prepare_copy(buffer *b, size_t size);
2996 int buffer_prepare_append(buffer *b, size_t size);
3002 - ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of a href */
3003 - ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus coding / too as %2F */
3004 - ENCODING_HTML, /* & becomes & and so on */
3005 + ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of an href */
3006 + ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus encoding "/" as "%2F" */
3007 + ENCODING_HTML, /* "&" becomes "&" and so on */
3008 ENCODING_MINIMAL_XML, /* minimal encoding for xml */
3009 ENCODING_HEX /* encode string as hex */
3010 } buffer_encoding_t;
3011 @@ -111,19 +128,21 @@
3012 int light_isalpha(int c);
3013 int light_isalnum(int c);
3015 +#define BUFFER_CTYPE_FUNC(type) int buffer_is##type(buffer *b);
3016 +BUFFER_CTYPE_FUNC(digit)
3017 +BUFFER_CTYPE_FUNC(xdigit)
3018 +BUFFER_CTYPE_FUNC(alpha)
3019 +BUFFER_CTYPE_FUNC(alnum)
3021 #define BUFFER_APPEND_STRING_CONST(x, y) \
3022 buffer_append_string_len(x, y, sizeof(y) - 1)
3024 #define BUFFER_COPY_STRING_CONST(x, y) \
3025 buffer_copy_string_len(x, y, sizeof(y) - 1)
3027 -#define BUFFER_APPEND_SLASH(x) \
3028 - if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); }
3030 #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
3031 #define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0
3034 #define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0)
3035 #define UNUSED(x) ( (void)(x) )
3037 --- lighttpd-1.4.11/src/chunk.c 2005-11-18 15:18:19.000000000 +0200
3038 +++ lighttpd-1.4.12/src/chunk.c 2006-07-11 22:07:51.000000000 +0300
3041 * the network chunk-API
3048 #include <sys/types.h>
3049 #include <sys/stat.h>
3050 -#include <sys/mman.h>
3054 -#include <unistd.h>
3062 +#include "sys-mmap.h"
3063 +#include "sys-files.h"
3065 chunkqueue *chunkqueue_init(void) {
3069 cq = calloc(1, sizeof(*cq));
3082 static chunk *chunk_init(void) {
3086 c = calloc(1, sizeof(*c));
3089 c->mem = buffer_init();
3090 c->file.name = buffer_init();
3092 c->file.mmap.start = MAP_FAILED;
3099 static void chunk_free(chunk *c) {
3103 buffer_free(c->mem);
3104 buffer_free(c->file.name);
3108 static void chunk_reset(chunk *c) {
3112 buffer_reset(c->mem);
3114 if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
3115 unlink(c->file.name->ptr);
3119 buffer_reset(c->file.name);
3121 if (c->file.fd != -1) {
3124 void chunkqueue_free(chunkqueue *cq) {
3131 for (c = cq->first; c; ) {
3138 for (c = cq->unused; c; ) {
3148 static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) {
3151 - /* check if we have a unused chunk */
3153 + /* check if we have an unused chunk */
3157 @@ -109,18 +110,18 @@
3159 cq->unused_chunks--;
3166 static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
3167 c->next = cq->first;
3171 if (cq->last == NULL) {
3179 @@ -129,19 +130,19 @@
3185 if (cq->first == NULL) {
3193 void chunkqueue_reset(chunkqueue *cq) {
3195 /* move everything to the unused queue */
3197 - /* mark all read written */
3199 + /* mark all read written */
3200 for (c = cq->first; c; c = c->next) {
3205 c->offset = c->file.length;
3212 @@ -162,93 +163,93 @@
3214 int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
3218 if (len == 0) return 0;
3221 c = chunkqueue_get_unused_chunk(cq);
3224 c->type = FILE_CHUNK;
3227 buffer_copy_string_buffer(c->file.name, fn);
3228 c->file.start = offset;
3229 c->file.length = len;
3233 chunkqueue_append_chunk(cq, c);
3239 int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
3243 if (mem->used == 0) return 0;
3246 c = chunkqueue_get_unused_chunk(cq);
3247 c->type = MEM_CHUNK;
3249 buffer_copy_string_buffer(c->mem, mem);
3252 chunkqueue_append_chunk(cq, c);
3258 int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
3262 if (mem->used == 0) return 0;
3265 c = chunkqueue_get_unused_chunk(cq);
3266 c->type = MEM_CHUNK;
3268 buffer_copy_string_buffer(c->mem, mem);
3271 chunkqueue_prepend_chunk(cq, c);
3277 int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
3281 if (len == 0) return 0;
3284 c = chunkqueue_get_unused_chunk(cq);
3285 c->type = MEM_CHUNK;
3287 buffer_copy_string_len(c->mem, mem, len - 1);
3290 chunkqueue_append_chunk(cq, c);
3296 buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
3300 c = chunkqueue_get_unused_chunk(cq);
3303 c->type = MEM_CHUNK;
3305 buffer_reset(c->mem);
3308 chunkqueue_prepend_chunk(cq, c);
3314 buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
3318 c = chunkqueue_get_unused_chunk(cq);
3321 c->type = MEM_CHUNK;
3323 buffer_reset(c->mem);
3326 chunkqueue_append_chunk(cq, c);
3333 chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
3335 buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
3338 c = chunkqueue_get_unused_chunk(cq);
3340 c->type = FILE_CHUNK;
3341 @@ -273,12 +274,12 @@
3344 /* we have several tempdirs, only if all of them fail we jump out */
3347 for (i = 0; i < cq->tempdirs->used; i++) {
3348 data_string *ds = (data_string *)cq->tempdirs->data[i];
3350 buffer_copy_string_buffer(template, ds->value);
3351 - BUFFER_APPEND_SLASH(template);
3352 + PATHNAME_APPEND_SLASH(template);
3353 BUFFER_APPEND_STRING_CONST(template, "lighttpd-upload-XXXXXX");
3355 if (-1 != (c->file.fd = mkstemp(template->ptr))) {
3357 chunkqueue_append_chunk(cq, c);
3359 buffer_free(template);
3366 off_t chunkqueue_length(chunkqueue *cq) {
3371 for (c = cq->first; c; c = c->next) {
3374 @@ -321,14 +322,14 @@
3383 off_t chunkqueue_written(chunkqueue *cq) {
3388 for (c = cq->first; c; c = c->next) {
3401 if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
3404 - if (c->offset == c->file.length) is_finished = 1;
3405 + if (c->offset == c->file.length) is_finished = 1;
3412 --- lighttpd-1.4.11/src/chunk.h 2005-11-01 09:32:21.000000000 +0200
3413 +++ lighttpd-1.4.12/src/chunk.h 2006-07-11 22:07:51.000000000 +0300
3416 typedef struct chunk {
3417 enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
3420 buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
3424 off_t length; /* octets to send from the starting offset */
3429 char *start; /* the start pointer of the mmap'ed area */
3430 size_t length; /* size of the mmap'ed area */
3431 - off_t offset; /* start is <n> octet away from the start of the file */
3432 + off_t offset; /* start is <n> octets away from the start of the file */
3435 - int is_temp; /* file is temporary and will be deleted if on cleanup */
3436 + int is_temp; /* file is temporary and will be deleted on cleanup */
3439 - off_t offset; /* octets sent from this chunk
3440 - the size of the chunk is either
3442 + off_t offset; /* octets sent from this chunk
3443 + the size of the chunk is either
3444 - mem-chunk: mem->used - 1
3445 - file-chunk: file.length
3458 size_t unused_chunks;
3460 --- lighttpd-1.4.11/src/configfile-glue.c 2006-03-03 20:14:56.000000000 +0200
3461 +++ lighttpd-1.4.12/src/configfile-glue.c 2006-07-11 22:07:51.000000000 +0300
3469 * are the external interface of lighttpd. The functions
3470 * are used by the server itself and the plugins.
3472 - * The main-goal is to have a small library in the end
3473 - * which is linked against both and which will define
3474 + * The main-goal is to have a small library in the end
3475 + * which is linked against both and which will define
3476 * the interface itself in the end.
3483 int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
3488 for (i = 0; cv[i].key; i++) {
3491 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3499 switch (cv[i].type) {
3500 case T_CONFIG_ARRAY:
3501 if (du->type == TYPE_ARRAY) {
3503 data_array *da = (data_array *)du;
3506 for (j = 0; j < da->value->used; j++) {
3507 if (da->value->data[j]->type == TYPE_STRING) {
3508 data_string *ds = data_string_init();
3511 buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
3512 if (!da->is_index_key) {
3513 /* the id's were generated automaticly, as we copy now we might have to renumber them
3514 - * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
3515 + * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
3516 * before mod_fastcgi and friends */
3517 buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
3521 array_insert_unique(cv[i].destination, (data_unset *)ds);
3523 - log_error_write(srv, __FILE__, __LINE__, "sssd",
3524 - "the key of and array can only be a string or a integer, variable:",
3525 - cv[i].key, "type:", da->value->data[j]->type);
3527 + log_error_write(srv, __FILE__, __LINE__, "sssd",
3528 + "the key of and array can only be a string or a integer, variable:",
3529 + cv[i].key, "type:", da->value->data[j]->type);
3535 log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
3541 case T_CONFIG_STRING:
3542 if (du->type == TYPE_STRING) {
3543 data_string *ds = (data_string *)du;
3546 buffer_copy_string_buffer(cv[i].destination, ds->value);
3547 + } else if (du->type == TYPE_INTEGER) {
3548 + data_integer *di = (data_integer *)du;
3550 + buffer_copy_long(cv[i].destination, di->value);
3552 log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
3560 case TYPE_INTEGER: {
3561 data_integer *di = (data_integer *)du;
3564 *((unsigned short *)(cv[i].destination)) = di->value;
3568 data_string *ds = (data_string *)du;
3571 + if (buffer_isdigit(ds->value)) {
3572 + *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
3576 log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
3582 @@ -100,19 +110,19 @@
3583 case T_CONFIG_BOOLEAN:
3584 if (du->type == TYPE_STRING) {
3585 data_string *ds = (data_string *)du;
3588 if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
3589 *((unsigned short *)(cv[i].destination)) = 1;
3590 } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
3591 *((unsigned short *)(cv[i].destination)) = 0;
3593 log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
3599 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
3607 case T_CONFIG_DEPRECATED:
3608 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
3611 srv->config_deprecated = 1;
3617 @@ -133,25 +143,25 @@
3618 int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
3623 for (i = 0; cv[i].key; i++) {
3624 data_string *touched;
3627 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3636 touched = data_string_init();
3639 buffer_copy_string(touched->value, "");
3640 buffer_copy_string_buffer(touched->key, du->key);
3643 array_insert_unique(srv->config_touched, (data_unset *)touched);
3647 return config_insert_values_internal(srv, ca, cv);
3650 @@ -191,25 +201,25 @@
3653 /* pass the rules */
3657 case COMP_HTTP_HOST: {
3658 char *ck_colon = NULL, *val_colon = NULL;
3661 if (!buffer_is_empty(con->uri.authority)) {
3666 * append server-port to the HTTP_POST if necessary
3670 l = con->uri.authority;
3674 case CONFIG_COND_NE:
3675 case CONFIG_COND_EQ:
3676 ck_colon = strchr(dc->string->ptr, ':');
3677 val_colon = strchr(l->ptr, ':');
3680 if (ck_colon == val_colon) {
3681 /* nothing to do with it */
3683 @@ -230,21 +240,21 @@
3688 + l = srv->empty_string;
3692 case COMP_HTTP_REMOTEIP: {
3694 - /* handle remoteip limitations
3696 + /* handle remoteip limitations
3698 * "10.0.0.1" is provided for all comparisions
3701 * only for == and != we support
3708 if ((dc->cond == CONFIG_COND_EQ ||
3709 dc->cond == CONFIG_COND_NE) &&
3710 (con->dst_addr.plain.sa_family == AF_INET) &&
3711 @@ -253,41 +263,48 @@
3714 struct in_addr val_inp;
3717 + if (con->conf.log_condition_handling) {
3718 + l = srv->empty_string;
3720 + log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
3721 + "(", l, ") compare to", dc->string);
3724 if (*(nm_slash+1) == '\0') {
3725 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
3728 return COND_RESULT_FALSE;
3732 nm_bits = strtol(nm_slash + 1, &err, 10);
3736 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
3739 return COND_RESULT_FALSE;
3743 /* take IP convert to the native */
3744 buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
3747 if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
3748 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3751 return COND_RESULT_FALSE;
3755 if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
3756 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3759 return COND_RESULT_FALSE;
3765 nm = htonl(~((1 << (32 - nm_bits)) - 1));
3768 if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
3769 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
3773 case COMP_HTTP_REFERER: {
3777 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
3782 return COND_RESULT_FALSE;
3787 if (con->conf.log_condition_handling) {
3788 log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key,
3789 @@ -346,10 +363,10 @@
3791 return COND_RESULT_FALSE;
3795 if (con->conf.log_condition_handling) {
3796 log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
3797 - "(", l, ") compare to ", dc->string);
3798 + "(", l, ") compare to", dc->string);
3801 case CONFIG_COND_NE:
3802 @@ -365,13 +382,13 @@
3803 case CONFIG_COND_MATCH: {
3804 cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
3809 #define elementsof(x) (sizeof(x) / sizeof(x[0]))
3811 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
3812 cache->matches, elementsof(cache->matches));
3815 cache->patterncount = n;
3817 cache->comp_value = l;
3824 return COND_RESULT_FALSE;
3828 cond_cache_t *caches = con->cond_cache;
3830 if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
3831 + if (con->conf.log_condition_handling) {
3832 + log_error_write(srv, __FILE__, __LINE__, "sds", "=== start of", dc->context_ndx, "condition block ===");
3834 if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
3837 @@ -409,11 +429,11 @@
3839 if (con->conf.log_condition_handling) {
3840 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3841 - "(uncached) result:",
3843 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3846 - if (con->conf.log_condition_handling) {
3847 + if (con->conf.log_condition_cache_handling) {
3848 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3850 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3854 int config_check_cond(server *srv, connection *con, data_config *dc) {
3855 - if (con->conf.log_condition_handling) {
3856 - log_error_write(srv, __FILE__, __LINE__, "s", "=== start of condition block ===");
3858 return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
3861 @@ -443,3 +460,85 @@
3865 +/* return <0 on error
3866 + * return 0-x if matched (and replaced)
3868 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result)
3872 + pcre_extra *extra;
3873 + const char *pattern;
3874 + size_t pattern_len;
3877 + pcre_keyvalue *kv;
3881 + for (i = 0; i < kvb->used; i++) {
3885 + extra = kv->key_extra;
3886 + pattern = kv->value->ptr;
3887 + pattern_len = kv->value->used - 1;
3889 + if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
3890 + if (n != PCRE_ERROR_NOMATCH) {
3894 + const char **list;
3895 + size_t start, end;
3899 + pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
3901 + /* search for $[0-9] */
3903 + buffer_reset(result);
3905 + start = 0; end = pattern_len;
3906 + for (k = 0; k < pattern_len; k++) {
3907 + if ((pattern[k] == '$' || pattern[k] == '%') &&
3908 + isdigit((unsigned char)pattern[k + 1])) {
3911 + size_t num = pattern[k + 1] - '0';
3915 + buffer_append_string_len(result, pattern + start, end - start);
3917 + if (pattern[k] == '$') {
3918 + /* n is always > 0 */
3919 + if (num < (size_t)n) {
3920 + buffer_append_string(result, list[num]);
3923 + config_append_cond_match_buffer(con, context, result, num);
3931 + buffer_append_string_len(result, pattern + start, pattern_len - start);
3939 + return PCRE_ERROR_NOMATCH;
3947 --- lighttpd-1.4.11/src/configfile.c 2006-02-15 14:26:42.000000000 +0200
3948 +++ lighttpd-1.4.12/src/configfile.c 2006-07-11 22:07:51.000000000 +0300
3953 -#include <unistd.h>
3962 -#include "license.h"
3965 #include "configparser.h"
3966 #include "configfile.h"
3967 #include "proc_open.h"
3969 +#include "sys-files.h"
3973 +#define PATH_MAX 64
3976 static int config_insert(server *srv) {
3979 buffer *stat_cache_string;
3981 - config_values_t cv[] = {
3983 + config_values_t cv[] = {
3984 { "server.bind", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 */
3985 { "server.errorlog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 */
3986 { "server.errorfile-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 */
3988 { "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
3989 { "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
3990 { "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */
3993 { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */
3994 { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */
3995 { "server.max-request-size", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
3997 { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
3998 { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */
3999 { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */
4002 { "server.max-read-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 20 */
4003 { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */
4004 { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */
4006 { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
4007 { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */
4008 { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 29 */
4011 { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */
4014 { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 31 */
4015 { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 32 */
4016 { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 33 */
4017 { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 34 */
4020 { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 35 */
4021 { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
4022 { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */
4023 { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 38 */
4026 { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 39 */
4027 { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
4028 { "server.stat-cache-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
4030 { "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 43 */
4031 { "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 44 */
4032 { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
4034 + { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 46 */
4036 { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4037 { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4038 { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4040 { "server.groupid", "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4041 { "server.use-keep-alive", "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4042 { "server.force-lower-case-files", "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4045 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
4051 cv[0].destination = srv->srvconf.bindhost;
4052 cv[1].destination = srv->srvconf.errorlog_file;
4053 @@ -102,33 +104,33 @@
4054 cv[4].destination = srv->srvconf.username;
4055 cv[5].destination = srv->srvconf.groupname;
4056 cv[6].destination = &(srv->srvconf.port);
4059 cv[9].destination = srv->srvconf.modules;
4060 cv[10].destination = srv->srvconf.event_handler;
4061 cv[11].destination = srv->srvconf.pid_file;
4064 cv[13].destination = &(srv->srvconf.max_worker);
4065 cv[23].destination = &(srv->srvconf.max_fds);
4066 cv[36].destination = &(srv->srvconf.log_request_header_on_error);
4067 cv[37].destination = &(srv->srvconf.log_state_handling);
4070 cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
4073 stat_cache_string = buffer_init();
4074 cv[41].destination = stat_cache_string;
4075 cv[43].destination = srv->srvconf.network_backend;
4076 cv[44].destination = srv->srvconf.upload_tempdirs;
4077 cv[45].destination = &(srv->srvconf.enable_cores);
4080 cv[42].destination = &(srv->srvconf.max_conns);
4081 cv[12].destination = &(srv->srvconf.max_request_size);
4082 srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
4084 assert(srv->config_storage);
4087 for (i = 0; i < srv->config_context->used; i++) {
4091 s = calloc(1, sizeof(specific_config));
4093 s->document_root = buffer_init();
4094 @@ -154,17 +156,18 @@
4095 s->global_kbytes_per_second = 0;
4096 s->global_bytes_per_second_cnt = 0;
4097 s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
4100 cv[2].destination = s->errorfile_prefix;
4103 cv[7].destination = s->server_tag;
4104 cv[8].destination = &(s->use_ipv6);
4110 cv[14].destination = s->document_root;
4111 cv[15].destination = &(s->force_lowercase_filenames);
4112 cv[16].destination = &(s->log_condition_handling);
4113 + cv[46].destination = &(s->log_condition_cache_handling);
4114 cv[17].destination = &(s->max_keep_alive_requests);
4115 cv[18].destination = s->server_name;
4116 cv[19].destination = &(s->max_keep_alive_idle);
4117 @@ -179,23 +182,23 @@
4118 cv[28].destination = s->mimetypes;
4119 cv[29].destination = s->ssl_pemfile;
4120 cv[30].destination = &(s->is_ssl);
4123 cv[31].destination = &(s->log_file_not_found);
4124 cv[32].destination = &(s->log_request_handling);
4125 cv[33].destination = &(s->log_response_header);
4126 cv[34].destination = &(s->log_request_header);
4129 cv[35].destination = &(s->allow_http11);
4130 cv[38].destination = s->ssl_ca_file;
4131 cv[40].destination = &(s->range_requests);
4134 srv->config_storage[i] = s;
4137 if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
4143 if (buffer_is_empty(stat_cache_string)) {
4144 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
4145 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
4146 @@ -205,22 +208,22 @@
4147 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
4148 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
4150 - log_error_write(srv, __FILE__, __LINE__, "sb",
4151 + log_error_write(srv, __FILE__, __LINE__, "sb",
4152 "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string);
4153 ret = HANDLER_ERROR;
4157 buffer_free(stat_cache_string);
4166 -#define PATCH(x) con->conf.x = s->x
4168 + con->conf.x = s->x
4169 int config_setup_connection(server *srv, connection *con) {
4170 specific_config *s = srv->config_storage[0];
4173 PATCH(allow_http11);
4175 PATCH(document_root);
4176 @@ -236,20 +239,21 @@
4177 PATCH(kbytes_per_second);
4178 PATCH(global_kbytes_per_second);
4179 PATCH(global_bytes_per_second_cnt);
4182 con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
4183 buffer_copy_string_buffer(con->server_name, s->server_name);
4186 PATCH(log_request_header);
4187 PATCH(log_response_header);
4188 PATCH(log_request_handling);
4189 PATCH(log_condition_handling);
4190 + PATCH(log_condition_cache_handling);
4191 PATCH(log_file_not_found);
4194 PATCH(range_requests);
4195 PATCH(force_lowercase_filenames);
4202 @@ -257,22 +261,22 @@
4204 int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
4208 /* skip the first, the global context */
4209 for (i = 1; i < srv->config_context->used; i++) {
4210 data_config *dc = (data_config *)srv->config_context->data[i];
4211 specific_config *s = srv->config_storage[i];
4215 if (comp != dc->comp) continue;
4218 /* condition didn't match */
4219 if (!config_check_cond(srv, con, dc)) continue;
4223 for (j = 0; j < dc->value->used; j++) {
4224 data_unset *du = dc->value->data[j];
4227 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
4228 PATCH(document_root);
4229 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
4230 @@ -315,11 +319,13 @@
4231 PATCH(log_response_header);
4232 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
4233 PATCH(log_condition_handling);
4234 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-cache-handling"))) {
4235 + PATCH(log_condition_cache_handling);
4236 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
4237 PATCH(log_file_not_found);
4238 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
4239 PATCH(allow_http11);
4240 - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
4241 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
4242 PATCH(force_lowercase_filenames);
4243 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
4244 PATCH(global_kbytes_per_second);
4254 @@ -336,15 +342,15 @@
4260 const buffer *source;
4276 if (0 != stream_open(&(t->s), t->file)) {
4277 - log_error_write(srv, __FILE__, __LINE__, "sbss",
4278 + log_error_write(srv, __FILE__, __LINE__, "sbss",
4279 "opening configfile ", t->file, "failed:", strerror(errno));
4280 buffer_free(t->file);
4283 t->size = t->s.size;
4292 static int config_skip_comment(tokenizer_t *t) {
4294 assert(t->input[t->offset] == '#');
4295 - for (i = 1; t->input[t->offset + i] &&
4296 + for (i = 1; t->input[t->offset + i] &&
4297 (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
4300 @@ -411,44 +417,44 @@
4301 static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
4306 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
4307 char c = t->input[t->offset];
4308 const char *start = NULL;
4315 if (t->input[t->offset + 1] == '>') {
4319 buffer_copy_string(token, "=>");
4322 tid = TK_ARRAY_ASSIGN;
4324 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4325 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4326 "source:", t->source,
4327 - "line:", t->line, "pos:", t->line_pos,
4328 + "line:", t->line, "pos:", t->line_pos,
4329 "use => for assignments in arrays");
4332 } else if (t->in_cond) {
4333 if (t->input[t->offset + 1] == '=') {
4337 buffer_copy_string(token, "==");
4341 } else if (t->input[t->offset + 1] == '~') {
4345 buffer_copy_string(token, "=~");
4350 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4351 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4352 "source:", t->source,
4353 - "line:", t->line, "pos:", t->line_pos,
4354 + "line:", t->line, "pos:", t->line_pos,
4355 "only =~ and == are allowed in the condition");
4358 @@ -456,51 +462,51 @@
4360 } else if (t->in_key) {
4364 buffer_copy_string_len(token, t->input + t->offset, 1);
4370 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4371 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4372 "source:", t->source,
4373 - "line:", t->line, "pos:", t->line_pos,
4374 + "line:", t->line, "pos:", t->line_pos,
4375 "unexpected equal-sign: =");
4384 if (t->input[t->offset + 1] == '=') {
4388 buffer_copy_string(token, "!=");
4392 } else if (t->input[t->offset + 1] == '~') {
4396 buffer_copy_string(token, "!~");
4401 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4402 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4403 "source:", t->source,
4404 - "line:", t->line, "pos:", t->line_pos,
4405 + "line:", t->line, "pos:", t->line_pos,
4406 "only !~ and != are allowed in the condition");
4412 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4413 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4414 "source:", t->source,
4415 - "line:", t->line, "pos:", t->line_pos,
4416 + "line:", t->line, "pos:", t->line_pos,
4417 "unexpected exclamation-marks: !");
4425 @@ -546,10 +552,10 @@
4427 if (t->in_brace > 0) {
4431 buffer_copy_string(token, "(COMMA)");
4438 @@ -557,70 +563,70 @@
4439 /* search for the terminating " */
4440 start = t->input + t->offset + 1;
4441 buffer_copy_string(token, "");
4444 for (i = 1; t->input[t->offset + i]; i++) {
4445 if (t->input[t->offset + i] == '\\' &&
4446 t->input[t->offset + i + 1] == '"') {
4449 buffer_append_string_len(token, start, t->input + t->offset + i - start);
4452 start = t->input + t->offset + i + 1;
4463 if (t->input[t->offset + i] == '"') {
4467 buffer_append_string_len(token, start, t->input + t->offset + i - start);
4474 if (t->input[t->offset + i] == '\0') {
4477 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4479 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4480 "source:", t->source,
4481 - "line:", t->line, "pos:", t->line_pos,
4482 + "line:", t->line, "pos:", t->line_pos,
4483 "missing closing quote");
4491 t->line_pos += i + 1;
4503 buffer_copy_string(token, "(");
4513 buffer_copy_string(token, ")");
4524 buffer_copy_string(token, "$");
4530 @@ -637,96 +643,88 @@
4539 buffer_copy_string(token, "{");
4552 buffer_copy_string(token, "}");
4564 buffer_copy_string(token, "[");
4577 buffer_copy_string(token, "]");
4582 t->line_pos += config_skip_comment(t);
4588 - for (i = 0; t->input[t->offset + i] &&
4589 + for (i = 0; t->input[t->offset + i] &&
4590 (isalpha((unsigned char)t->input[t->offset + i])
4594 if (i && t->input[t->offset + i]) {
4595 tid = TK_SRVVARNAME;
4596 buffer_copy_string_len(token, t->input + t->offset, i);
4603 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4604 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4605 "source:", t->source,
4606 - "line:", t->line, "pos:", t->line_pos,
4607 + "line:", t->line, "pos:", t->line_pos,
4608 "invalid character in condition");
4611 } else if (isdigit((unsigned char)c)) {
4612 /* take all digits */
4613 for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
4616 /* was there it least a digit ? */
4617 - if (i && t->input[t->offset + i]) {
4622 buffer_copy_string_len(token, t->input + t->offset, i);
4629 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4630 - "source:", t->source,
4631 - "line:", t->line, "pos:", t->line_pos,
4632 - "unexpected EOF");
4637 /* the key might consist of [-.0-9a-z] */
4638 - for (i = 0; t->input[t->offset + i] &&
4639 - (isalnum((unsigned char)t->input[t->offset + i]) ||
4640 + for (i = 0; t->input[t->offset + i] &&
4641 + (isalnum((unsigned char)t->input[t->offset + i]) ||
4642 t->input[t->offset + i] == '.' ||
4643 t->input[t->offset + i] == '_' || /* for env.* */
4644 t->input[t->offset + i] == '-'
4648 if (i && t->input[t->offset + i]) {
4649 buffer_copy_string_len(token, t->input + t->offset, i);
4652 if (strcmp(token->ptr, "include") == 0) {
4654 } else if (strcmp(token->ptr, "include_shell") == 0) {
4655 @@ -738,14 +736,14 @@
4665 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4666 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4667 "source:", t->source,
4668 - "line:", t->line, "pos:", t->line_pos,
4669 + "line:", t->line, "pos:", t->line_pos,
4670 "invalid character in variable name");
4673 @@ -753,16 +751,16 @@
4682 - log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
4683 + log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
4684 "source:", t->source,
4685 "line:", t->line, "pos:", t->line_pos,
4686 token, token->used - 1, tid);
4691 } else if (t->offset < t->size) {
4692 fprintf(stderr, "%s.%d: %d, %s\n",
4693 @@ -781,10 +779,11 @@
4694 pParser = configparserAlloc( malloc );
4695 lasttoken = buffer_init();
4696 token = buffer_init();
4698 while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
4699 buffer_copy_string_buffer(lasttoken, token);
4700 configparser(pParser, token_id, token, context);
4703 token = buffer_init();
4706 @@ -797,14 +796,14 @@
4709 configparserFree(pParser, free);
4713 - log_error_write(srv, __FILE__, __LINE__, "sb",
4714 + log_error_write(srv, __FILE__, __LINE__, "sb",
4715 "configfile parser failed:", lasttoken);
4716 } else if (context->ok == 0) {
4717 - log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
4718 + log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
4719 "source:", t->source,
4720 - "line:", t->line, "pos:", t->line_pos,
4721 + "line:", t->line, "pos:", t->line_pos,
4722 "parser failed somehow near here:", lasttoken);
4737 if (0 != stream_open(&s, filename)) {
4738 - log_error_write(srv, __FILE__, __LINE__, "sbss",
4739 + log_error_write(srv, __FILE__, __LINE__, "sbss",
4740 "opening configfile ", filename, "failed:", strerror(errno));
4744 char oldpwd[PATH_MAX];
4746 if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
4747 - log_error_write(srv, __FILE__, __LINE__, "s",
4748 + log_error_write(srv, __FILE__, __LINE__, "s",
4749 "cannot get cwd", strerror(errno));
4755 if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
4756 - log_error_write(srv, __FILE__, __LINE__, "sbss",
4757 + log_error_write(srv, __FILE__, __LINE__, "sbss",
4758 "opening", source, "failed:", strerror(errno));
4761 @@ -896,13 +895,12 @@
4762 static void context_init(server *srv, config_t *context) {
4765 - context->configs_stack = array_init();
4766 - context->configs_stack->is_weakref = 1;
4767 + context->configs_stack = buffer_ptr_init(NULL);
4768 context->basedir = buffer_init();
4771 static void context_free(config_t *context) {
4772 - array_free(context->configs_stack);
4773 + buffer_ptr_free(context->configs_stack);
4774 buffer_free(context->basedir);
4777 @@ -918,18 +916,15 @@
4778 context_init(srv, &context);
4779 context.all_configs = srv->config_context;
4788 + /* use the current dir as basedir for all other includes
4790 + pos = strrchr(fn, DIR_SEPERATOR);
4793 buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
4798 dc = data_config_init();
4799 buffer_copy_string(dc->key, "global");
4801 @@ -941,10 +936,10 @@
4802 /* default context */
4803 srv->config = dc->value;
4804 dpid = data_integer_init();
4805 - dpid->value = getpid();
4806 + dpid->value = /* getpid() */0;
4807 buffer_copy_string(dpid->key, "var.PID");
4808 array_insert_unique(srv->config, (data_unset *)dpid);
4811 dcwd = data_string_init();
4812 buffer_prepare_copy(dcwd->value, 1024);
4813 if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
4820 if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
4822 data_array *prepends;
4823 @@ -1026,22 +1021,23 @@
4824 buffer_copy_string(modules->key, "server.modules");
4825 array_insert_unique(srv->config, (data_unset *)modules);
4830 if (0 != config_insert(srv)) {
4839 int config_set_defaults(server *srv) {
4841 specific_config *s = srv->config_storage[0];
4842 struct stat st1, st2;
4844 - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4847 + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4849 /* - poll is most reliable
4850 * - select works everywhere
4851 * - linux-* are experimental
4852 @@ -1067,20 +1063,21 @@
4854 { FDEVENT_HANDLER_UNSET, NULL }
4858 - if (buffer_is_empty(s->document_root)) {
4859 - log_error_write(srv, __FILE__, __LINE__, "s",
4860 - "a default document-root has to be set");
4866 + if (buffer_is_empty(s->document_root)) {
4867 + log_error_write(srv, __FILE__, __LINE__, "s",
4868 + "a default document-root has to be set");
4873 if (buffer_is_empty(srv->srvconf.changeroot)) {
4874 - if (-1 == stat(s->document_root->ptr, &st1)) {
4875 - log_error_write(srv, __FILE__, __LINE__, "sb",
4876 + pathname_unix2local(s->document_root);
4877 + if (-1 == stat(s->document_root->ptr, &st1)) {
4878 + log_error_write(srv, __FILE__, __LINE__, "sbs",
4879 "base-docroot doesn't exist:",
4880 - s->document_root);
4881 + s->document_root, strerror(errno));
4885 @@ -1088,18 +1085,18 @@
4886 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
4887 buffer_append_string_buffer(srv->tmp_buf, s->document_root);
4889 - if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
4890 - log_error_write(srv, __FILE__, __LINE__, "sb",
4891 + if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
4892 + log_error_write(srv, __FILE__, __LINE__, "sb",
4893 "base-docroot doesn't exist:",
4902 - buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4904 - buffer_to_lower(srv->tmp_buf);
4905 + buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4907 + buffer_to_lower(srv->tmp_buf);
4909 if (0 == stat(srv->tmp_buf->ptr, &st1)) {
4911 @@ -1107,68 +1104,68 @@
4912 is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
4914 /* lower-case existed, check upper-case */
4915 - buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4916 + buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4918 - buffer_to_upper(srv->tmp_buf);
4919 + buffer_to_upper(srv->tmp_buf);
4921 /* we have to handle the special case that upper and lower-casing results in the same filename
4922 * as in server.document-root = "/" or "/12345/" */
4924 if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
4925 - /* lower-casing and upper-casing didn't result in
4926 - * an other filename, no need to stat(),
4927 + /* lower-casing and upper-casing didn't result in
4928 + * an other filename, no need to stat(),
4929 * just assume it is case-sensitive. */
4931 s->force_lowercase_filenames = 0;
4932 - } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
4933 + } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
4935 + /* upper case exists too, doesn't the FS handle this ? */
4937 + /* upper and lower have the same inode -> case-insensitve FS */
4939 + if (st1.st_ino == st2.st_ino) {
4940 + /* upper and lower have the same inode -> case-insensitve FS */
4942 + s->force_lowercase_filenames = 1;
4947 - /* upper case exists too, doesn't the FS handle this ? */
4949 - /* upper and lower have the same inode -> case-insensitve FS */
4951 - if (st1.st_ino == st2.st_ino) {
4952 - /* upper and lower have the same inode -> case-insensitve FS */
4954 - s->force_lowercase_filenames = 1;
4959 if (srv->srvconf.port == 0) {
4960 srv->srvconf.port = s->is_ssl ? 443 : 80;
4964 if (srv->srvconf.event_handler->used == 0) {
4965 /* choose a good default
4967 - * the event_handler list is sorted by 'goodness'
4969 + * the event_handler list is sorted by 'goodness'
4970 * taking the first available should be the best solution
4972 srv->event_handler = event_handlers[0].et;
4975 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4976 - log_error_write(srv, __FILE__, __LINE__, "s",
4977 + log_error_write(srv, __FILE__, __LINE__, "s",
4978 "sorry, there is no event handler for this system");
4989 for (i = 0; event_handlers[i].name; i++) {
4990 if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
4991 srv->event_handler = event_handlers[i].et;
4997 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4998 - log_error_write(srv, __FILE__, __LINE__, "sb",
4999 - "the selected event-handler in unknown or not supported:",
5000 + log_error_write(srv, __FILE__, __LINE__, "sb",
5001 + "the selected event-handler in unknown or not supported:",
5002 srv->srvconf.event_handler );
5008 @@ -1176,19 +1173,19 @@
5010 if (buffer_is_empty(s->ssl_pemfile)) {
5011 /* PEM file is require */
5013 - log_error_write(srv, __FILE__, __LINE__, "s",
5015 + log_error_write(srv, __FILE__, __LINE__, "s",
5016 "ssl.pemfile has to be set");
5022 - log_error_write(srv, __FILE__, __LINE__, "s",
5023 + log_error_write(srv, __FILE__, __LINE__, "s",
5024 "ssl support is missing, recompile with --with-openssl");
5034 --- lighttpd-1.4.11/src/configfile.h 2005-08-23 17:36:12.000000000 +0300
5035 +++ lighttpd-1.4.12/src/configfile.h 2006-07-11 22:07:51.000000000 +0300
5040 - array *configs_stack; /* to parse nested block */
5041 + buffer_ptr *configs_stack; /* to parse nested block */
5042 data_config *current; /* current started with { */
5045 --- lighttpd-1.4.11/src/configparser.c 2006-02-01 19:51:15.000000000 +0200
5046 +++ lighttpd-1.4.12/src/configparser.c 2006-07-11 22:08:02.000000000 +0300
5048 dc->parent = ctx->current;
5049 array_insert_unique(dc->parent->childs, (data_unset *)dc);
5051 - array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
5052 + buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
5056 static data_config *configparser_pop(config_t *ctx) {
5057 data_config *old = ctx->current;
5058 - ctx->current = (data_config *) array_pop(ctx->configs_stack);
5059 + ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
5063 /* return a copied variable */
5064 static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
5065 - if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
5068 - if (NULL != (env = getenv(key->ptr + 4))) {
5070 - ds = data_string_init();
5071 - buffer_append_string(ds->value, env);
5072 - return (data_unset *)ds;
5075 - fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
5086 - fprintf(stderr, "get var %s\n", key->ptr);
5087 + fprintf(stderr, "get var %s\n", key->ptr);
5089 - for (dc = ctx->current; dc; dc = dc->parent) {
5090 + for (dc = ctx->current; dc; dc = dc->parent) {
5092 - fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5093 - array_print(dc->value, 0);
5094 + fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5095 + array_print(dc->value, 0);
5097 - if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5098 - return du->copy(du);
5100 + if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5101 + return du->copy(du);
5103 - fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
5110 /* op1 is to be eat/return by this function, op1->key is not cared
5111 @@ -124,14 +106,14 @@
5115 -#line 128 "configparser.c"
5116 +#line 110 "configparser.c"
5117 /* Next is all token values, in a form suitable for use by makeheaders.
5118 ** This section will be null unless lemon is run with the -m switch.
5122 ** These constants (all generated automatically by the parser generator)
5123 ** specify the various kinds of tokens (terminals) that the parser
5127 ** Each symbol here is a terminal symbol in the grammar.
5130 ** and nonterminals. "int" is used otherwise.
5131 ** YYNOCODE is a number of type YYCODETYPE which corresponds
5132 ** to no legal terminal or nonterminal number. This
5133 -** number is used to fill in empty slots of the hash
5134 +** number is used to fill in empty slots of the hash
5136 ** YYFALLBACK If defined, this indicates that one or more tokens
5137 ** have fall-back values which should be used if the
5139 ** and nonterminal numbers. "unsigned char" is
5140 ** used if there are fewer than 250 rules and
5141 ** states combined. "int" is used otherwise.
5142 -** configparserTOKENTYPE is the data type used for minor tokens given
5143 +** configparserTOKENTYPE is the data type used for minor tokens given
5144 ** directly to the parser from the tokenizer.
5145 ** YYMINORTYPE is the data type used for all minor tokens.
5146 ** This is typically a union of many types, one of
5148 #define configparserARG_PDECL ,config_t *ctx
5149 #define configparserARG_FETCH config_t *ctx = yypParser->ctx
5150 #define configparserARG_STORE yypParser->ctx = ctx
5151 -#define YYNSTATE 62
5153 +#define YYNSTATE 63
5155 #define YYERRORSYMBOL 26
5156 #define YYERRSYMDT yy95
5157 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
5159 /* Next are that tables used to determine what action to take based on the
5160 ** current state and lookahead token. These tables are used to implement
5161 ** functions that take a state number and lookahead value and return an
5165 ** Suppose the action integer is N. Then the action is determined as
5168 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
5169 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
5170 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
5171 -** and that yy_default[S] should be used instead.
5172 +** and that yy_default[S] should be used instead.
5174 ** The formula above is for computing the action when the lookahead is
5175 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
5176 @@ -248,67 +230,69 @@
5177 ** yy_default[] Default action for each state.
5179 static YYACTIONTYPE yy_action[] = {
5180 - /* 0 */ 2, 3, 4, 5, 13, 14, 62, 15, 7, 44,
5181 - /* 10 */ 20, 86, 16, 45, 28, 48, 40, 10, 39, 25,
5182 - /* 20 */ 22, 49, 45, 8, 15, 102, 1, 20, 28, 18,
5183 - /* 30 */ 57, 59, 19, 25, 22, 39, 19, 61, 98, 45,
5184 - /* 40 */ 20, 6, 23, 24, 26, 28, 35, 57, 59, 12,
5185 - /* 50 */ 25, 22, 28, 27, 36, 87, 29, 25, 22, 33,
5186 - /* 60 */ 15, 30, 31, 20, 28, 38, 9, 17, 37, 25,
5187 - /* 70 */ 22, 39, 42, 43, 10, 45, 11, 53, 54, 55,
5188 - /* 80 */ 56, 28, 52, 57, 59, 34, 25, 22, 28, 27,
5189 - /* 90 */ 32, 88, 41, 25, 22, 33, 28, 48, 46, 28,
5190 - /* 100 */ 48, 25, 22, 58, 25, 22, 60, 21, 19, 47,
5191 - /* 110 */ 51, 50, 25, 22, 88, 88, 93,
5192 + /* 0 */ 2, 3, 4, 5, 13, 14, 63, 15, 7, 45,
5193 + /* 10 */ 20, 88, 16, 46, 28, 49, 41, 10, 40, 25,
5194 + /* 20 */ 22, 50, 46, 8, 15, 104, 1, 20, 28, 18,
5195 + /* 30 */ 58, 60, 6, 25, 22, 40, 47, 62, 11, 46,
5196 + /* 40 */ 20, 9, 23, 24, 26, 29, 89, 58, 60, 10,
5197 + /* 50 */ 17, 38, 28, 27, 37, 19, 30, 25, 22, 34,
5198 + /* 60 */ 15, 100, 20, 20, 23, 24, 26, 12, 19, 31,
5199 + /* 70 */ 32, 40, 19, 44, 43, 46, 95, 35, 90, 89,
5200 + /* 80 */ 28, 49, 42, 58, 60, 25, 22, 59, 28, 27,
5201 + /* 90 */ 33, 48, 52, 25, 22, 34, 28, 49, 51, 28,
5202 + /* 100 */ 36, 25, 22, 61, 25, 22, 89, 28, 39, 89,
5203 + /* 110 */ 89, 89, 25, 22, 54, 55, 56, 57, 89, 28,
5204 + /* 120 */ 53, 21, 89, 89, 25, 22, 25, 22,
5206 static YYCODETYPE yy_lookahead[] = {
5207 /* 0 */ 29, 30, 31, 32, 33, 34, 0, 1, 44, 38,
5208 /* 10 */ 4, 15, 41, 16, 35, 36, 45, 46, 12, 40,
5209 /* 20 */ 41, 42, 16, 15, 1, 27, 28, 4, 35, 36,
5210 - /* 30 */ 24, 25, 5, 40, 41, 12, 5, 14, 11, 16,
5211 - /* 40 */ 4, 1, 6, 7, 8, 35, 36, 24, 25, 28,
5212 - /* 50 */ 40, 41, 35, 36, 37, 15, 39, 40, 41, 42,
5213 - /* 60 */ 1, 9, 10, 4, 35, 36, 38, 2, 3, 40,
5214 - /* 70 */ 41, 12, 28, 14, 46, 16, 13, 20, 21, 22,
5215 - /* 80 */ 23, 35, 36, 24, 25, 11, 40, 41, 35, 36,
5216 - /* 90 */ 37, 13, 13, 40, 41, 42, 35, 36, 17, 35,
5217 - /* 100 */ 36, 40, 41, 42, 40, 41, 42, 35, 5, 18,
5218 - /* 110 */ 43, 19, 40, 41, 47, 47, 13,
5219 + /* 30 */ 24, 25, 1, 40, 41, 12, 17, 14, 13, 16,
5220 + /* 40 */ 4, 38, 6, 7, 8, 9, 15, 24, 25, 46,
5221 + /* 50 */ 2, 3, 35, 36, 37, 5, 39, 40, 41, 42,
5222 + /* 60 */ 1, 11, 4, 4, 6, 7, 8, 28, 5, 9,
5223 + /* 70 */ 10, 12, 5, 14, 28, 16, 13, 11, 13, 47,
5224 + /* 80 */ 35, 36, 13, 24, 25, 40, 41, 42, 35, 36,
5225 + /* 90 */ 37, 18, 43, 40, 41, 42, 35, 36, 19, 35,
5226 + /* 100 */ 36, 40, 41, 42, 40, 41, 47, 35, 36, 47,
5227 + /* 110 */ 47, 47, 40, 41, 20, 21, 22, 23, 47, 35,
5228 + /* 120 */ 36, 35, 47, 47, 40, 41, 40, 41,
5230 #define YY_SHIFT_USE_DFLT (-5)
5231 static signed char yy_shift_ofst[] = {
5232 - /* 0 */ -5, 6, -5, -5, -5, 40, -4, 8, -3, -5,
5233 - /* 10 */ 63, -5, 23, -5, -5, -5, 65, 36, 31, 36,
5234 - /* 20 */ -5, -5, -5, -5, -5, -5, 36, 27, -5, 52,
5235 - /* 30 */ -5, 36, -5, 74, 36, 31, -5, 36, 31, 78,
5236 - /* 40 */ 79, -5, 59, -5, -5, 81, 91, 36, 31, 92,
5237 - /* 50 */ 57, 36, 103, -5, -5, -5, -5, 36, -5, 36,
5239 + /* 0 */ -5, 6, -5, -5, -5, 31, -4, 8, -3, -5,
5240 + /* 10 */ 25, -5, 23, -5, -5, -5, 48, 58, 67, 58,
5241 + /* 20 */ -5, -5, -5, -5, -5, -5, 36, 50, -5, -5,
5242 + /* 30 */ 60, -5, 58, -5, 66, 58, 67, -5, 58, 67,
5243 + /* 40 */ 65, 69, -5, 59, -5, -5, 19, 73, 58, 67,
5244 + /* 50 */ 79, 94, 58, 63, -5, -5, -5, -5, 58, -5,
5245 + /* 60 */ 58, -5, -5,
5247 #define YY_REDUCE_USE_DFLT (-37)
5248 static signed char yy_reduce_ofst[] = {
5249 - /* 0 */ -2, -29, -37, -37, -37, -36, -37, -37, 28, -37,
5250 - /* 10 */ -37, 21, -29, -37, -37, -37, -37, -7, -37, 72,
5251 + /* 0 */ -2, -29, -37, -37, -37, -36, -37, -37, 3, -37,
5252 + /* 10 */ -37, 39, -29, -37, -37, -37, -37, -7, -37, 86,
5253 /* 20 */ -37, -37, -37, -37, -37, -37, 17, -37, -37, -37,
5254 - /* 30 */ -37, 53, -37, -37, 10, -37, -37, 29, -37, -37,
5255 - /* 40 */ -37, 44, -29, -37, -37, -37, -37, -21, -37, -37,
5256 - /* 50 */ 67, 46, -37, -37, -37, -37, -37, 61, -37, 64,
5257 - /* 60 */ -37, -37,
5258 + /* 30 */ -37, -37, 53, -37, -37, 64, -37, -37, 72, -37,
5259 + /* 40 */ -37, -37, 46, -29, -37, -37, -37, -37, -21, -37,
5260 + /* 50 */ -37, 49, 84, -37, -37, -37, -37, -37, 45, -37,
5261 + /* 60 */ 61, -37, -37,
5263 static YYACTIONTYPE yy_default[] = {
5264 - /* 0 */ 64, 101, 63, 65, 66, 101, 67, 101, 101, 90,
5265 - /* 10 */ 101, 64, 101, 68, 69, 70, 101, 101, 71, 101,
5266 - /* 20 */ 73, 74, 76, 77, 78, 79, 101, 84, 75, 101,
5267 - /* 30 */ 80, 82, 81, 101, 101, 85, 83, 101, 72, 101,
5268 - /* 40 */ 101, 64, 101, 89, 91, 101, 101, 101, 98, 101,
5269 - /* 50 */ 101, 101, 101, 94, 95, 96, 97, 101, 99, 101,
5271 + /* 0 */ 65, 103, 64, 66, 67, 103, 68, 103, 103, 92,
5272 + /* 10 */ 103, 65, 103, 69, 70, 71, 103, 103, 72, 103,
5273 + /* 20 */ 74, 75, 77, 78, 79, 80, 103, 86, 76, 81,
5274 + /* 30 */ 103, 82, 84, 83, 103, 103, 87, 85, 103, 73,
5275 + /* 40 */ 103, 103, 65, 103, 91, 93, 103, 103, 103, 100,
5276 + /* 50 */ 103, 103, 103, 103, 96, 97, 98, 99, 103, 101,
5277 + /* 60 */ 103, 102, 94,
5279 #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
5281 /* The next table maps tokens into fallback tokens. If a construct
5282 ** like the following:
5285 ** %fallback ID X Y Z.
5287 ** appears in the grammer, then ID becomes a fallback token for X, Y,
5288 @@ -359,10 +343,10 @@
5294 ** Turn parser tracing on by giving a stream to which to write the trace
5295 ** and a prompt to preface each trace message. Tracing is turned off
5296 -** by making either argument NULL
5297 +** by making either argument NULL
5303 /* For tracing shifts, the names of all terminals and nonterminals
5304 ** are required. The following table supplies these names */
5305 -static const char *yyTokenName[] = {
5306 +static const char *yyTokenName[] = {
5307 "$", "EOL", "ASSIGN", "APPEND",
5308 "LKEY", "PLUS", "STRING", "INTEGER",
5309 "LPARAN", "RPARAN", "COMMA", "ARRAY_ASSIGN",
5310 @@ -425,27 +409,28 @@
5311 /* 15 */ "value ::= STRING",
5312 /* 16 */ "value ::= INTEGER",
5313 /* 17 */ "value ::= array",
5314 - /* 18 */ "array ::= LPARAN aelements RPARAN",
5315 - /* 19 */ "aelements ::= aelements COMMA aelement",
5316 - /* 20 */ "aelements ::= aelements COMMA",
5317 - /* 21 */ "aelements ::= aelement",
5318 - /* 22 */ "aelement ::= expression",
5319 - /* 23 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5320 - /* 24 */ "eols ::= EOL",
5321 - /* 25 */ "eols ::=",
5322 - /* 26 */ "globalstart ::= GLOBAL",
5323 - /* 27 */ "global ::= globalstart LCURLY metalines RCURLY",
5324 - /* 28 */ "condlines ::= condlines eols ELSE condline",
5325 - /* 29 */ "condlines ::= condline",
5326 - /* 30 */ "condline ::= context LCURLY metalines RCURLY",
5327 - /* 31 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5328 - /* 32 */ "cond ::= EQ",
5329 - /* 33 */ "cond ::= MATCH",
5330 - /* 34 */ "cond ::= NE",
5331 - /* 35 */ "cond ::= NOMATCH",
5332 - /* 36 */ "stringop ::= expression",
5333 - /* 37 */ "include ::= INCLUDE stringop",
5334 - /* 38 */ "include_shell ::= INCLUDE_SHELL stringop",
5335 + /* 18 */ "array ::= LPARAN RPARAN",
5336 + /* 19 */ "array ::= LPARAN aelements RPARAN",
5337 + /* 20 */ "aelements ::= aelements COMMA aelement",
5338 + /* 21 */ "aelements ::= aelements COMMA",
5339 + /* 22 */ "aelements ::= aelement",
5340 + /* 23 */ "aelement ::= expression",
5341 + /* 24 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5342 + /* 25 */ "eols ::= EOL",
5343 + /* 26 */ "eols ::=",
5344 + /* 27 */ "globalstart ::= GLOBAL",
5345 + /* 28 */ "global ::= globalstart LCURLY metalines RCURLY",
5346 + /* 29 */ "condlines ::= condlines eols ELSE condline",
5347 + /* 30 */ "condlines ::= condline",
5348 + /* 31 */ "condline ::= context LCURLY metalines RCURLY",
5349 + /* 32 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5350 + /* 33 */ "cond ::= EQ",
5351 + /* 34 */ "cond ::= MATCH",
5352 + /* 35 */ "cond ::= NE",
5353 + /* 36 */ "cond ::= NOMATCH",
5354 + /* 37 */ "stringop ::= expression",
5355 + /* 38 */ "include ::= INCLUDE stringop",
5356 + /* 39 */ "include_shell ::= INCLUDE_SHELL stringop",
5366 ** This function allocates a new parser.
5367 ** The only argument is a pointer to a function which works like
5370 /* Here is inserted the actions which take place when a
5371 ** terminal or non-terminal is destroyed. This can happen
5372 ** when the symbol is popped from the stack during a
5373 - ** reduce or during error processing or when a parser is
5374 + ** reduce or during error processing or when a parser is
5375 ** being destroyed before it is finished parsing.
5377 ** Note: during a reduce, the only symbols destroyed are those
5378 @@ -528,44 +513,44 @@
5382 -#line 160 "./configparser.y"
5383 +#line 143 "./configparser.y"
5384 { buffer_free((yypminor->yy0)); }
5385 -#line 533 "configparser.c"
5386 +#line 518 "configparser.c"
5389 -#line 151 "./configparser.y"
5390 +#line 134 "./configparser.y"
5391 { (yypminor->yy41)->free((yypminor->yy41)); }
5392 -#line 538 "configparser.c"
5393 +#line 523 "configparser.c"
5396 -#line 152 "./configparser.y"
5397 +#line 135 "./configparser.y"
5398 { (yypminor->yy41)->free((yypminor->yy41)); }
5399 -#line 543 "configparser.c"
5400 +#line 528 "configparser.c"
5403 -#line 153 "./configparser.y"
5404 +#line 136 "./configparser.y"
5405 { (yypminor->yy41)->free((yypminor->yy41)); }
5406 -#line 548 "configparser.c"
5407 +#line 533 "configparser.c"
5410 -#line 154 "./configparser.y"
5411 +#line 137 "./configparser.y"
5412 { array_free((yypminor->yy40)); }
5413 -#line 553 "configparser.c"
5414 +#line 538 "configparser.c"
5417 -#line 155 "./configparser.y"
5418 +#line 138 "./configparser.y"
5419 { array_free((yypminor->yy40)); }
5420 -#line 558 "configparser.c"
5421 +#line 543 "configparser.c"
5424 -#line 156 "./configparser.y"
5425 +#line 139 "./configparser.y"
5426 { buffer_free((yypminor->yy43)); }
5427 -#line 563 "configparser.c"
5428 +#line 548 "configparser.c"
5431 -#line 157 "./configparser.y"
5432 +#line 140 "./configparser.y"
5433 { buffer_free((yypminor->yy43)); }
5434 -#line 568 "configparser.c"
5435 +#line 553 "configparser.c"
5437 default: break; /* If no destructor action specified: do nothing */
5445 ** Deallocate and destroy a parser. Destructors are all called for
5446 ** all stack elements before shutting the parser down.
5451 int stateno = pParser->yystack[pParser->yyidx].stateno;
5454 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
5455 i = yy_shift_ofst[stateno];
5456 if( i==YY_SHIFT_USE_DFLT ){
5460 int stateno = pParser->yystack[pParser->yyidx].stateno;
5463 i = yy_reduce_ofst[stateno];
5464 if( i==YY_REDUCE_USE_DFLT ){
5465 return yy_default[stateno];
5475 configparserARG_FETCH;
5476 yymsp = &yypParser->yystack[yypParser->yyidx];
5478 - if( yyTraceFILE && yyruleno>=0
5479 + if( yyTraceFILE && yyruleno>=0
5480 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
5481 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
5482 yyRuleName[yyruleno]);
5484 /* No destructor defined for global */
5487 -#line 134 "./configparser.y"
5488 +#line 116 "./configparser.y"
5489 { yymsp[-1].minor.yy78 = NULL; }
5490 -#line 837 "configparser.c"
5491 +#line 823 "configparser.c"
5492 yy_destructor(1,&yymsp[0].minor);
5495 @@ -847,10 +833,15 @@
5496 yy_destructor(1,&yymsp[0].minor);
5499 -#line 162 "./configparser.y"
5500 +#line 145 "./configparser.y"
5502 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5503 - if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5504 + if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5505 + fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5506 + ctx->current->context_ndx,
5507 + ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5509 + } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5510 array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5511 yymsp[0].minor.yy41 = NULL;
5513 @@ -864,16 +855,21 @@
5514 buffer_free(yymsp[-2].minor.yy43);
5515 yymsp[-2].minor.yy43 = NULL;
5517 -#line 867 "configparser.c"
5518 +#line 858 "configparser.c"
5519 yy_destructor(2,&yymsp[-1].minor);
5522 -#line 179 "./configparser.y"
5523 +#line 167 "./configparser.y"
5525 array *vars = ctx->current->value;
5528 - if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5529 + if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5530 + fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5531 + ctx->current->context_ndx,
5532 + ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5534 + } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5535 /* exists in current block */
5536 du = configparser_merge_data(du, yymsp[0].minor.yy41);
5539 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5540 array_replace(vars, du);
5542 + yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5543 } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) {
5544 du = configparser_merge_data(du, yymsp[0].minor.yy41);
5546 @@ -892,22 +889,20 @@
5547 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5548 array_insert_unique(ctx->current->value, du);
5550 + yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5552 - fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
5553 - ctx->current->context_ndx,
5554 - ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5556 + buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5557 + array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5559 buffer_free(yymsp[-2].minor.yy43);
5560 yymsp[-2].minor.yy43 = NULL;
5561 - yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5562 yymsp[0].minor.yy41 = NULL;
5564 -#line 906 "configparser.c"
5565 +#line 901 "configparser.c"
5566 yy_destructor(3,&yymsp[-1].minor);
5569 -#line 214 "./configparser.y"
5570 +#line 206 "./configparser.y"
5572 if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) {
5573 yygotominor.yy43 = buffer_init_string("var.");
5574 @@ -919,10 +914,10 @@
5575 yymsp[0].minor.yy0 = NULL;
5578 -#line 922 "configparser.c"
5579 +#line 917 "configparser.c"
5582 -#line 226 "./configparser.y"
5583 +#line 218 "./configparser.y"
5585 yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41);
5586 if (NULL == yygotominor.yy41) {
5587 @@ -932,21 +927,38 @@
5588 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5589 yymsp[0].minor.yy41 = NULL;
5591 -#line 935 "configparser.c"
5592 +#line 930 "configparser.c"
5593 yy_destructor(5,&yymsp[-1].minor);
5596 -#line 236 "./configparser.y"
5597 +#line 228 "./configparser.y"
5599 yygotominor.yy41 = yymsp[0].minor.yy41;
5600 yymsp[0].minor.yy41 = NULL;
5602 -#line 944 "configparser.c"
5603 +#line 939 "configparser.c"
5606 -#line 241 "./configparser.y"
5607 +#line 233 "./configparser.y"
5609 - yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43);
5610 + if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5613 + if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) {
5615 + ds = data_string_init();
5616 + buffer_append_string(ds->value, env);
5617 + yygotominor.yy41 = (data_unset *)ds;
5620 + yygotominor.yy41 = NULL;
5621 + fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4);
5624 + } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) {
5625 + fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr);
5628 if (!yygotominor.yy41) {
5629 /* make a dummy so it won't crash */
5630 yygotominor.yy41 = (data_unset *)data_string_init();
5631 @@ -954,50 +966,59 @@
5632 buffer_free(yymsp[0].minor.yy43);
5633 yymsp[0].minor.yy43 = NULL;
5635 -#line 957 "configparser.c"
5636 +#line 969 "configparser.c"
5639 -#line 251 "./configparser.y"
5640 +#line 260 "./configparser.y"
5642 yygotominor.yy41 = (data_unset *)data_string_init();
5643 buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
5644 buffer_free(yymsp[0].minor.yy0);
5645 yymsp[0].minor.yy0 = NULL;
5647 -#line 967 "configparser.c"
5648 +#line 979 "configparser.c"
5651 -#line 258 "./configparser.y"
5652 +#line 267 "./configparser.y"
5654 yygotominor.yy41 = (data_unset *)data_integer_init();
5655 ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
5656 buffer_free(yymsp[0].minor.yy0);
5657 yymsp[0].minor.yy0 = NULL;
5659 -#line 977 "configparser.c"
5660 +#line 989 "configparser.c"
5663 -#line 264 "./configparser.y"
5664 +#line 273 "./configparser.y"
5666 yygotominor.yy41 = (data_unset *)data_array_init();
5667 array_free(((data_array *)(yygotominor.yy41))->value);
5668 ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
5669 yymsp[0].minor.yy40 = NULL;
5671 -#line 987 "configparser.c"
5672 +#line 999 "configparser.c"
5675 -#line 270 "./configparser.y"
5676 +#line 279 "./configparser.y"
5678 + yygotominor.yy40 = array_init();
5680 +#line 1006 "configparser.c"
5681 + yy_destructor(8,&yymsp[-1].minor);
5682 + yy_destructor(9,&yymsp[0].minor);
5685 +#line 282 "./configparser.y"
5687 yygotominor.yy40 = yymsp[-1].minor.yy40;
5688 yymsp[-1].minor.yy40 = NULL;
5690 -#line 995 "configparser.c"
5691 +#line 1016 "configparser.c"
5692 yy_destructor(8,&yymsp[-2].minor);
5693 yy_destructor(9,&yymsp[0].minor);
5696 -#line 275 "./configparser.y"
5698 +#line 287 "./configparser.y"
5700 if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
5701 NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
5702 @@ -1014,37 +1035,37 @@
5703 yygotominor.yy40 = yymsp[-2].minor.yy40;
5704 yymsp[-2].minor.yy40 = NULL;
5706 -#line 1017 "configparser.c"
5707 +#line 1038 "configparser.c"
5708 yy_destructor(10,&yymsp[-1].minor);
5711 -#line 292 "./configparser.y"
5713 +#line 304 "./configparser.y"
5715 yygotominor.yy40 = yymsp[-1].minor.yy40;
5716 yymsp[-1].minor.yy40 = NULL;
5718 -#line 1026 "configparser.c"
5719 +#line 1047 "configparser.c"
5720 yy_destructor(10,&yymsp[0].minor);
5723 -#line 297 "./configparser.y"
5725 +#line 309 "./configparser.y"
5727 yygotominor.yy40 = array_init();
5728 array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
5729 yymsp[0].minor.yy41 = NULL;
5731 -#line 1036 "configparser.c"
5732 +#line 1057 "configparser.c"
5735 -#line 303 "./configparser.y"
5737 +#line 315 "./configparser.y"
5739 yygotominor.yy41 = yymsp[0].minor.yy41;
5740 yymsp[0].minor.yy41 = NULL;
5742 -#line 1044 "configparser.c"
5743 +#line 1065 "configparser.c"
5746 -#line 307 "./configparser.y"
5748 +#line 319 "./configparser.y"
5750 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5751 buffer_free(yymsp[-2].minor.yy43);
5752 @@ -1053,27 +1074,27 @@
5753 yygotominor.yy41 = yymsp[0].minor.yy41;
5754 yymsp[0].minor.yy41 = NULL;
5756 -#line 1056 "configparser.c"
5757 +#line 1077 "configparser.c"
5758 yy_destructor(11,&yymsp[-1].minor);
5761 - yy_destructor(1,&yymsp[0].minor);
5764 + yy_destructor(1,&yymsp[0].minor);
5767 -#line 319 "./configparser.y"
5770 +#line 331 "./configparser.y"
5773 dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
5775 configparser_push(ctx, dc, 0);
5777 -#line 1072 "configparser.c"
5778 +#line 1093 "configparser.c"
5779 yy_destructor(12,&yymsp[0].minor);
5782 -#line 326 "./configparser.y"
5784 +#line 338 "./configparser.y"
5788 @@ -1082,16 +1103,16 @@
5790 assert(cur && ctx->current);
5792 - yygotominor.yy0 = cur;
5793 + yygotominor.yy78 = cur;
5795 -#line 1087 "configparser.c"
5796 +#line 1108 "configparser.c"
5797 /* No destructor defined for globalstart */
5798 yy_destructor(13,&yymsp[-2].minor);
5799 /* No destructor defined for metalines */
5800 yy_destructor(14,&yymsp[0].minor);
5803 -#line 337 "./configparser.y"
5805 +#line 349 "./configparser.y"
5807 assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx);
5808 yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
5809 @@ -1100,20 +1121,20 @@
5810 yymsp[-3].minor.yy78 = NULL;
5811 yymsp[0].minor.yy78 = NULL;
5813 -#line 1103 "configparser.c"
5814 +#line 1124 "configparser.c"
5815 /* No destructor defined for eols */
5816 yy_destructor(15,&yymsp[-1].minor);
5819 -#line 346 "./configparser.y"
5821 +#line 358 "./configparser.y"
5823 yygotominor.yy78 = yymsp[0].minor.yy78;
5824 yymsp[0].minor.yy78 = NULL;
5826 -#line 1113 "configparser.c"
5827 +#line 1134 "configparser.c"
5830 -#line 351 "./configparser.y"
5832 +#line 363 "./configparser.y"
5836 @@ -1124,14 +1145,14 @@
5838 yygotominor.yy78 = cur;
5840 -#line 1127 "configparser.c"
5841 +#line 1148 "configparser.c"
5842 /* No destructor defined for context */
5843 yy_destructor(13,&yymsp[-2].minor);
5844 /* No destructor defined for metalines */
5845 yy_destructor(14,&yymsp[0].minor);
5848 -#line 362 "./configparser.y"
5850 +#line 374 "./configparser.y"
5853 buffer *b, *rvalue, *op;
5854 @@ -1266,45 +1287,45 @@
5855 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5856 yymsp[0].minor.yy41 = NULL;
5858 -#line 1269 "configparser.c"
5859 +#line 1290 "configparser.c"
5860 yy_destructor(16,&yymsp[-6].minor);
5861 yy_destructor(18,&yymsp[-4].minor);
5862 yy_destructor(19,&yymsp[-2].minor);
5865 -#line 496 "./configparser.y"
5867 +#line 508 "./configparser.y"
5869 yygotominor.yy27 = CONFIG_COND_EQ;
5871 -#line 1279 "configparser.c"
5872 +#line 1300 "configparser.c"
5873 yy_destructor(20,&yymsp[0].minor);
5876 -#line 499 "./configparser.y"
5878 +#line 511 "./configparser.y"
5880 yygotominor.yy27 = CONFIG_COND_MATCH;
5882 -#line 1287 "configparser.c"
5883 +#line 1308 "configparser.c"
5884 yy_destructor(21,&yymsp[0].minor);
5887 -#line 502 "./configparser.y"
5889 +#line 514 "./configparser.y"
5891 yygotominor.yy27 = CONFIG_COND_NE;
5893 -#line 1295 "configparser.c"
5894 +#line 1316 "configparser.c"
5895 yy_destructor(22,&yymsp[0].minor);
5898 -#line 505 "./configparser.y"
5900 +#line 517 "./configparser.y"
5902 yygotominor.yy27 = CONFIG_COND_NOMATCH;
5904 -#line 1303 "configparser.c"
5905 +#line 1324 "configparser.c"
5906 yy_destructor(23,&yymsp[0].minor);
5909 -#line 509 "./configparser.y"
5911 +#line 521 "./configparser.y"
5913 yygotominor.yy43 = NULL;
5915 @@ -1321,10 +1342,10 @@
5916 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5917 yymsp[0].minor.yy41 = NULL;
5919 -#line 1324 "configparser.c"
5920 +#line 1345 "configparser.c"
5923 -#line 526 "./configparser.y"
5925 +#line 538 "./configparser.y"
5928 if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5929 @@ -1334,11 +1355,11 @@
5930 yymsp[0].minor.yy43 = NULL;
5933 -#line 1337 "configparser.c"
5934 +#line 1358 "configparser.c"
5935 yy_destructor(24,&yymsp[-1].minor);
5938 -#line 536 "./configparser.y"
5940 +#line 548 "./configparser.y"
5943 if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5944 @@ -1348,7 +1369,7 @@
5945 yymsp[0].minor.yy43 = NULL;
5948 -#line 1351 "configparser.c"
5949 +#line 1372 "configparser.c"
5950 yy_destructor(25,&yymsp[-1].minor);
5953 @@ -1378,11 +1399,11 @@
5954 while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
5955 /* Here code is inserted which will be executed whenever the
5957 -#line 125 "./configparser.y"
5958 +#line 107 "./configparser.y"
5962 -#line 1385 "configparser.c"
5963 +#line 1406 "configparser.c"
5964 configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
5967 @@ -1489,7 +1510,7 @@
5968 #ifdef YYERRORSYMBOL
5969 /* A syntax error has occurred.
5970 ** The response to an error depends upon whether or not the
5971 - ** grammar defines an error token "ERROR".
5972 + ** grammar defines an error token "ERROR".
5974 ** This is what we do if the grammar does define ERROR:
5976 --- lighttpd-1.4.11/src/configparser.y 2006-01-26 18:46:25.000000000 +0200
5977 +++ lighttpd-1.4.12/src/configparser.y 2006-07-11 22:07:53.000000000 +0300
5979 dc->parent = ctx->current;
5980 array_insert_unique(dc->parent->childs, (data_unset *)dc);
5982 - array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
5983 + buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
5987 static data_config *configparser_pop(config_t *ctx) {
5988 data_config *old = ctx->current;
5989 - ctx->current = (data_config *) array_pop(ctx->configs_stack);
5990 + ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
5994 /* return a copied variable */
5995 static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
5996 - if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
5999 - if (NULL != (env = getenv(key->ptr + 4))) {
6001 - ds = data_string_init();
6002 - buffer_append_string(ds->value, env);
6003 - return (data_unset *)ds;
6006 - fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
6017 - fprintf(stderr, "get var %s\n", key->ptr);
6018 + fprintf(stderr, "get var %s\n", key->ptr);
6020 - for (dc = ctx->current; dc; dc = dc->parent) {
6021 + for (dc = ctx->current; dc; dc = dc->parent) {
6023 - fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
6024 - array_print(dc->value, 0);
6025 + fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
6026 + array_print(dc->value, 0);
6028 - if (NULL != (du = array_get_element(dc->value, key->ptr))) {
6029 - return du->copy(du);
6031 + if (NULL != (du = array_get_element(dc->value, key->ptr))) {
6032 + return du->copy(du);
6034 - fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
6041 /* op1 is to be eat/return by this function, op1->key is not cared
6043 %type aelement {data_unset *}
6044 %type condline {data_config *}
6045 %type condlines {data_config *}
6046 +%type global {data_config *}
6047 %type aelements {array *}
6048 %type array {array *}
6049 %type key {buffer *}
6050 @@ -161,7 +144,12 @@
6052 varline ::= key(A) ASSIGN expression(B). {
6053 buffer_copy_string_buffer(B->key, A);
6054 - if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
6055 + if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
6056 + fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
6057 + ctx->current->context_ndx,
6058 + ctx->current->key->ptr, A->ptr);
6060 + } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
6061 array_insert_unique(ctx->current->value, B);
6064 @@ -180,7 +168,12 @@
6065 array *vars = ctx->current->value;
6068 - if (NULL != (du = array_get_element(vars, A->ptr))) {
6069 + if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
6070 + fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
6071 + ctx->current->context_ndx,
6072 + ctx->current->key->ptr, A->ptr);
6074 + } else if (NULL != (du = array_get_element(vars, A->ptr))) {
6075 /* exists in current block */
6076 du = configparser_merge_data(du, B);
6079 buffer_copy_string_buffer(du->key, A);
6080 array_replace(vars, du);
6083 } else if (NULL != (du = configparser_get_variable(ctx, A))) {
6084 du = configparser_merge_data(du, B);
6086 @@ -199,15 +193,13 @@
6087 buffer_copy_string_buffer(du->key, A);
6088 array_insert_unique(ctx->current->value, du);
6092 - fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
6093 - ctx->current->context_ndx,
6094 - ctx->current->key->ptr, A->ptr);
6096 + buffer_copy_string_buffer(B->key, A);
6097 + array_insert_unique(ctx->current->value, B);
6105 @@ -239,7 +231,24 @@
6108 value(A) ::= key(B). {
6109 - A = configparser_get_variable(ctx, B);
6110 + if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
6113 + if (NULL != (env = getenv(B->ptr + 4))) {
6115 + ds = data_string_init();
6116 + buffer_append_string(ds->value, env);
6117 + A = (data_unset *)ds;
6121 + fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
6124 + } else if (NULL == (A = configparser_get_variable(ctx, B))) {
6125 + fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
6129 /* make a dummy so it won't crash */
6130 A = (data_unset *)data_string_init();
6132 ((data_array *)(A))->value = B;
6135 +array(A) ::= LPARAN RPARAN. {
6138 array(A) ::= LPARAN aelements(B) RPARAN. {
6141 --- lighttpd-1.4.11/src/connections-glue.c 2005-09-12 10:04:23.000000000 +0300
6142 +++ lighttpd-1.4.12/src/connections-glue.c 2006-07-11 22:07:51.000000000 +0300
6144 case CON_STATE_REQUEST_END: return "req-end";
6145 case CON_STATE_RESPONSE_START: return "resp-start";
6146 case CON_STATE_RESPONSE_END: return "resp-end";
6147 - default: return "(unknown)";
6148 + default: return "(unknown)";
6153 case CON_STATE_REQUEST_END: return "Q";
6154 case CON_STATE_RESPONSE_START: return "s";
6155 case CON_STATE_RESPONSE_END: return "S";
6156 - default: return "x";
6157 + default: return "x";
6161 int connection_set_state(server *srv, connection *con, connection_state_t state) {
6171 --- lighttpd-1.4.11/src/connections.c 2006-03-05 22:14:53.000000000 +0200
6172 +++ lighttpd-1.4.12/src/connections.c 2006-07-11 22:07:51.000000000 +0300
6177 -#include <unistd.h>
6182 #include "inet_ntop_cache.h"
6185 -# include <openssl/ssl.h>
6186 -# include <openssl/err.h>
6187 +# include <openssl/ssl.h>
6188 +# include <openssl/err.h>
6191 #ifdef HAVE_SYS_FILIO_H
6195 #include "sys-socket.h"
6196 +#include "sys-files.h"
6201 static connection *connections_get_new_connection(server *srv) {
6202 connections *conns = srv->conns;
6206 if (conns->size == 0) {
6210 } else if (conns->size == conns->used) {
6212 conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
6215 for (i = conns->used; i < conns->size; i++) {
6216 conns->ptr[i] = connection_init(srv);
6220 connection_reset(srv, conns->ptr[conns->used]);
6223 fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
6224 for (i = 0; i < conns->used + 1; i++) {
6225 fprintf(stderr, "%d ", conns->ptr[i]->fd);
6227 fprintf(stderr, "\n");
6232 conns->ptr[conns->used]->ndx = conns->used;
6233 return conns->ptr[conns->used++];
6237 connections *conns = srv->conns;
6241 if (con == NULL) return -1;
6244 if (-1 == con->ndx) return -1;
6250 /* not last element */
6253 if (i != conns->used - 1) {
6254 temp = conns->ptr[i];
6255 conns->ptr[i] = conns->ptr[conns->used - 1];
6256 conns->ptr[conns->used - 1] = temp;
6259 conns->ptr[i]->ndx = i;
6260 conns->ptr[conns->used - 1]->ndx = -1;
6269 fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
6270 @@ -104,25 +104,23 @@
6271 fprintf(stderr, "%d ", conns->ptr[i]->fd);
6273 fprintf(stderr, "\n");
6279 int connection_close(server *srv, connection *con) {
6281 server_socket *srv_sock = con->srv_socket;
6286 if (srv_sock->is_ssl) {
6287 if (con->ssl) SSL_free(con->ssl);
6293 fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
6294 fdevent_unregister(srv->ev, con->fd);
6297 if (closesocket(con->fd)) {
6298 log_error_write(srv, __FILE__, __LINE__, "sds",
6299 "(warning) close:", con->fd, strerror(errno));
6300 @@ -133,207 +131,96 @@
6301 "(warning) close:", con->fd, strerror(errno));
6308 log_error_write(srv, __FILE__, __LINE__, "sd",
6309 "closed()", con->fd);
6313 connection_del(srv, con);
6314 connection_set_state(srv, con, CON_STATE_CONNECT);
6321 static void dump_packet(const unsigned char *data, size_t len) {
6325 if (len == 0) return;
6328 for (i = 0; i < len; i++) {
6329 if (i % 16 == 0) fprintf(stderr, " ");
6332 fprintf(stderr, "%02x ", data[i]);
6335 if ((i + 1) % 16 == 0) {
6336 fprintf(stderr, " ");
6337 for (j = 0; j <= i % 16; j++) {
6341 if (i-15+j >= len) break;
6347 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6351 fprintf(stderr, "\n");
6356 if (len % 16 != 0) {
6357 for (j = i % 16; j < 16; j++) {
6358 fprintf(stderr, " ");
6362 fprintf(stderr, " ");
6363 for (j = i & ~0xf; j < len; j++) {
6368 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6370 fprintf(stderr, "\n");
6375 -static int connection_handle_read(server *srv, connection *con) {
6380 - server_socket *srv_sock = con->srv_socket;
6383 - b = chunkqueue_get_append_buffer(con->read_queue);
6384 - buffer_prepare_copy(b, 4096);
6385 +static network_status_t connection_handle_read(server *srv, connection *con) {
6386 + off_t oldlen, newlen;
6389 - if (srv_sock->is_ssl) {
6390 - len = SSL_read(con->ssl, b->ptr, b->size - 1);
6392 - if (ioctl(con->fd, FIONREAD, &toread)) {
6393 - log_error_write(srv, __FILE__, __LINE__, "sd",
6394 - "unexpected end-of-file:",
6398 - buffer_prepare_copy(b, toread);
6399 + oldlen = chunkqueue_length(con->read_queue);
6401 - len = read(con->fd, b->ptr, b->size - 1);
6403 -#elif defined(__WIN32)
6404 - len = recv(con->fd, b->ptr, b->size - 1, 0);
6406 - if (ioctl(con->fd, FIONREAD, &toread)) {
6407 - log_error_write(srv, __FILE__, __LINE__, "sd",
6408 - "unexpected end-of-file:",
6412 - buffer_prepare_copy(b, toread);
6414 - len = read(con->fd, b->ptr, b->size - 1);
6418 - con->is_readable = 0;
6421 - if (srv_sock->is_ssl) {
6424 - switch ((r = SSL_get_error(con->ssl, len))) {
6425 - case SSL_ERROR_WANT_READ:
6427 - case SSL_ERROR_SYSCALL:
6429 - * man SSL_get_error()
6431 - * SSL_ERROR_SYSCALL
6432 - * Some I/O error occurred. The OpenSSL error queue may contain more
6433 - * information on the error. If the error queue is empty (i.e.
6434 - * ERR_get_error() returns 0), ret can be used to find out more about
6435 - * the error: If ret == 0, an EOF was observed that violates the
6436 - * protocol. If ret == -1, the underlying BIO reported an I/O error
6437 - * (for socket I/O on Unix systems, consult errno for details).
6440 - while((ssl_err = ERR_get_error())) {
6441 - /* get all errors from the error-queue */
6442 - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
6443 - r, ERR_error_string(ssl_err, NULL));
6445 + switch(network_read_chunkqueue(srv, con, con->read_queue)) {
6446 + case NETWORK_STATUS_SUCCESS:
6448 + case NETWORK_STATUS_WAIT_FOR_EVENT:
6449 + con->is_readable = 0;
6450 + return NETWORK_STATUS_WAIT_FOR_EVENT;
6451 + case NETWORK_STATUS_INTERRUPTED:
6452 + con->is_readable = 1;
6453 + return NETWORK_STATUS_WAIT_FOR_EVENT;
6454 + case NETWORK_STATUS_CONNECTION_CLOSE:
6456 + con->is_readable = 0;
6457 + return NETWORK_STATUS_CONNECTION_CLOSE;
6458 + case NETWORK_STATUS_FATAL_ERROR:
6459 + con->is_readable = 0;
6461 + connection_set_state(srv, con, CON_STATE_ERROR);
6462 + return NETWORK_STATUS_FATAL_ERROR;
6470 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
6477 - case SSL_ERROR_ZERO_RETURN:
6478 - /* clean shutdown on the remote side */
6481 - /* FIXME: later */
6484 - /* fall thourgh */
6486 - while((ssl_err = ERR_get_error())) {
6487 - /* get all errors from the error-queue */
6488 - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
6489 - r, ERR_error_string(ssl_err, NULL));
6494 - if (errno == EAGAIN) return 0;
6495 - if (errno == EINTR) {
6496 - /* we have been interrupted before we could read */
6497 - con->is_readable = 1;
6501 - if (errno != ECONNRESET) {
6502 - /* expected for keep-alive */
6503 - log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6507 - if (errno == EAGAIN) return 0;
6508 - if (errno == EINTR) {
6509 - /* we have been interrupted before we could read */
6510 - con->is_readable = 1;
6514 - if (errno != ECONNRESET) {
6515 - /* expected for keep-alive */
6516 - log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6519 - connection_set_state(srv, con, CON_STATE_ERROR);
6522 - } else if (len == 0) {
6523 - con->is_readable = 0;
6524 - /* the other end close the connection -> KEEP-ALIVE */
6529 - } else if ((size_t)len < b->size - 1) {
6530 - /* we got less then expected, wait for the next fd-event */
6532 - con->is_readable = 0;
6536 - b->ptr[b->used++] = '\0';
6538 - con->bytes_read += len;
6540 - dump_packet(b->ptr, len);
6544 + newlen = chunkqueue_length(con->read_queue);
6546 + con->bytes_read += (newlen - oldlen);
6548 + return NETWORK_STATUS_SUCCESS;
6551 static int connection_handle_write_prepare(server *srv, connection *con) {
6553 case HTTP_METHOD_GET:
6554 case HTTP_METHOD_POST:
6555 case HTTP_METHOD_HEAD:
6557 case HTTP_METHOD_PUT:
6558 case HTTP_METHOD_MKCOL:
6559 case HTTP_METHOD_DELETE:
6560 @@ -350,12 +238,14 @@
6561 case HTTP_METHOD_MOVE:
6562 case HTTP_METHOD_PROPFIND:
6563 case HTTP_METHOD_PROPPATCH:
6564 + case HTTP_METHOD_LOCK:
6565 + case HTTP_METHOD_UNLOCK:
6567 case HTTP_METHOD_OPTIONS:
6569 * 400 is coming from the request-parser BEFORE uri.path is set
6570 - * 403 is from the response handler when noone else catched it
6572 + * 403 is from the response handler when noone else catched it
6575 if (con->uri.path->used &&
6576 con->uri.path->ptr[0] != '*') {
6577 @@ -381,55 +271,58 @@
6583 if (con->http_status == 0) {
6584 con->http_status = 403;
6588 switch(con->http_status) {
6589 case 400: /* class: header + custom body */
6605 if (con->mode != DIRECT) break;
6608 con->file_finished = 0;
6611 buffer_reset(con->physical.path);
6614 /* try to send static errorfile */
6615 if (!buffer_is_empty(con->conf.errorfile_prefix)) {
6616 stat_cache_entry *sce = NULL;
6619 buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
6620 buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
6623 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
6624 con->file_finished = 1;
6627 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
6628 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
6632 - if (!con->file_finished) {
6634 + if (!con->file_finished) {
6638 buffer_reset(con->physical.path);
6641 con->file_finished = 1;
6642 b = chunkqueue_get_append_buffer(con->write_queue);
6645 /* build default error-page */
6646 - buffer_copy_string(b,
6647 + buffer_copy_string(b,
6648 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
6649 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
6650 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
6652 buffer_append_long(b, con->http_status);
6653 buffer_append_string(b, " - ");
6654 buffer_append_string(b, get_http_status_name(con->http_status));
6657 buffer_append_string(b,
6660 @@ -448,12 +341,12 @@
6661 buffer_append_long(b, con->http_status);
6662 buffer_append_string(b, " - ");
6663 buffer_append_string(b, get_http_status_name(con->http_status));
6665 - buffer_append_string(b,"</h1>\n"
6667 + buffer_append_string(b,"</h1>\n"
6673 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
6676 @@ -463,10 +356,10 @@
6682 case 206: /* write_queue is already prepared */
6683 con->file_finished = 1;
6687 case 205: /* class: header only */
6689 @@ -474,19 +367,19 @@
6690 /* disable chunked encoding again as we have no body */
6691 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
6692 chunkqueue_reset(con->write_queue);
6695 con->file_finished = 1;
6701 if (con->file_finished) {
6702 - /* we have all the content and chunked encoding is not used, set a content-length */
6704 - if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6705 + /* we have all the content and chunked encoding is not used, set a content-length */
6707 + if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6708 (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
6709 buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
6712 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
6715 @@ -495,74 +388,77 @@
6716 ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
6717 con->keep_alive = 0;
6721 if (0 == (con->parsed_response & HTTP_CONNECTION)) {
6722 /* (f)cgi did'nt send Connection: header
6727 if (((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) &&
6728 (con->parsed_response & HTTP_CONTENT_LENGTH) == 0) {
6729 /* without content_length, no keep-alive */
6732 con->keep_alive = 0;
6735 /* a subrequest disable keep-alive although the client wanted it */
6736 if (con->keep_alive && !con->response.keep_alive) {
6737 con->keep_alive = 0;
6740 /* FIXME: we have to drop the Connection: Header from the subrequest */
6746 if (con->request.http_method == HTTP_METHOD_HEAD) {
6747 chunkqueue_reset(con->write_queue);
6750 http_response_write_header(srv, con);
6756 static int connection_handle_write(server *srv, connection *con) {
6757 - switch(network_write_chunkqueue(srv, con, con->write_queue)) {
6759 + switch(network_write_chunkqueue(srv, con, con->write_queue)) {
6760 + case NETWORK_STATUS_SUCCESS:
6761 if (con->file_finished) {
6762 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
6763 joblist_append(srv, con);
6766 - case -1: /* error on our side */
6767 + case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
6768 log_error_write(srv, __FILE__, __LINE__, "sd",
6769 "connection closed: write failed on fd", con->fd);
6770 connection_set_state(srv, con, CON_STATE_ERROR);
6771 joblist_append(srv, con);
6773 - case -2: /* remote close */
6774 + case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
6775 connection_set_state(srv, con, CON_STATE_ERROR);
6776 joblist_append(srv, con);
6779 + case NETWORK_STATUS_WAIT_FOR_EVENT:
6780 con->is_writable = 0;
6783 /* not finished yet -> WRITE */
6785 + case NETWORK_STATUS_INTERRUPTED:
6786 + con->is_writable = 1;
6788 + case NETWORK_STATUS_UNSET:
6798 connection *connection_init(server *srv) {
6804 con = calloc(1, sizeof(*con));
6810 @@ -573,32 +469,32 @@
6813 con->x = buffer_init();
6817 CLEAN(request.request_line);
6818 CLEAN(request.request);
6819 CLEAN(request.pathinfo);
6822 CLEAN(request.orig_uri);
6826 CLEAN(uri.authority);
6828 CLEAN(uri.path_raw);
6832 CLEAN(physical.doc_root);
6833 CLEAN(physical.path);
6834 CLEAN(physical.basedir);
6835 CLEAN(physical.rel_path);
6836 CLEAN(physical.etag);
6837 CLEAN(parse_request);
6842 CLEAN(error_handler);
6843 CLEAN(dst_addr_buf);
6847 con->write_queue = chunkqueue_init();
6848 con->read_queue = chunkqueue_init();
6849 @@ -608,26 +504,26 @@
6850 con->request.headers = array_init();
6851 con->response.headers = array_init();
6852 con->environment = array_init();
6855 /* init plugin specific connection structures */
6858 con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
6861 con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
6862 config_setup_connection(srv, con);
6868 void connections_free(server *srv) {
6869 connections *conns = srv->conns;
6874 for (i = 0; i < conns->size; i++) {
6875 connection *con = conns->ptr[i];
6878 connection_reset(srv, con);
6881 chunkqueue_free(con->write_queue);
6882 chunkqueue_free(con->read_queue);
6883 chunkqueue_free(con->request_content_queue);
6884 @@ -637,27 +533,27 @@
6887 buffer_free(con->x);
6891 CLEAN(request.request_line);
6892 CLEAN(request.request);
6893 CLEAN(request.pathinfo);
6896 CLEAN(request.orig_uri);
6900 CLEAN(uri.authority);
6902 CLEAN(uri.path_raw);
6906 CLEAN(physical.doc_root);
6907 CLEAN(physical.path);
6908 CLEAN(physical.basedir);
6909 CLEAN(physical.etag);
6910 CLEAN(physical.rel_path);
6911 CLEAN(parse_request);
6916 CLEAN(error_handler);
6917 @@ -665,97 +561,97 @@
6919 free(con->plugin_ctx);
6920 free(con->cond_cache);
6931 int connection_reset(server *srv, connection *con) {
6935 plugins_call_connection_reset(srv, con);
6938 con->is_readable = 1;
6939 con->is_writable = 1;
6940 con->http_status = 0;
6941 con->file_finished = 0;
6942 con->file_started = 0;
6943 con->got_response = 0;
6946 con->parsed_response = 0;
6949 con->bytes_written = 0;
6950 con->bytes_written_cur_second = 0;
6951 con->bytes_read = 0;
6952 con->bytes_header = 0;
6953 con->loops_per_request = 0;
6956 con->request.http_method = HTTP_METHOD_UNSET;
6957 con->request.http_version = HTTP_VERSION_UNSET;
6960 con->request.http_if_modified_since = NULL;
6961 con->request.http_if_none_match = NULL;
6964 con->response.keep_alive = 0;
6965 con->response.content_length = -1;
6966 con->response.transfer_encoding = 0;
6973 if (con->x) buffer_reset(con->x);
6977 CLEAN(request.request_line);
6978 CLEAN(request.pathinfo);
6979 CLEAN(request.request);
6982 CLEAN(request.orig_uri);
6986 CLEAN(uri.authority);
6988 CLEAN(uri.path_raw);
6992 CLEAN(physical.doc_root);
6993 CLEAN(physical.path);
6994 CLEAN(physical.basedir);
6995 CLEAN(physical.rel_path);
6996 CLEAN(physical.etag);
6999 CLEAN(parse_request);
7004 CLEAN(error_handler);
7010 - if (con->x) con->x->used = 0;
7012 + if (con->x) con->x->used = 0;
7018 con->request.x = NULL;
7023 CLEAN(http_content_type);
7025 con->request.content_length = 0;
7028 array_reset(con->request.headers);
7029 array_reset(con->response.headers);
7030 array_reset(con->environment);
7033 chunkqueue_reset(con->write_queue);
7034 chunkqueue_reset(con->request_content_queue);
7036 - /* the plugins should cleanup themself */
7037 + /* the plugins should cleanup themself */
7038 for (i = 0; i < srv->plugins.used; i++) {
7039 plugin *p = ((plugin **)(srv->plugins.ptr))[i];
7040 plugin_data *pd = p->data;
7043 con->plugin_ctx[pd->id] = NULL;
7047 #if COND_RESULT_UNSET
7048 for (i = srv->config_context->used - 1; i >= 0; i --) {
7049 con->cond_cache[i].result = COND_RESULT_UNSET;
7050 @@ -777,56 +673,56 @@
7052 memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
7056 con->header_len = 0;
7057 con->in_error_handler = 0;
7060 config_setup_connection(srv, con);
7068 - * search for \r\n\r\n
7071 + * search for \r\n\r\n
7073 * this is a special 32bit version which is using a sliding window for
7074 - * the comparisions
7076 + * the comparisions
7085 * cmpbuf: abcd != cdef
7086 * cmpbuf: bcde != cdef
7087 * cmpbuf: cdef == cdef -> return &c
7089 - * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
7091 + * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
7092 * maintain cmpbuf and rnrn
7097 char *buffer_search_rnrn(buffer *b) {
7098 uint32_t cmpbuf, rnrn;
7103 if (b->used < 4) return NULL;
7106 rnrn = ('\r' << 24) | ('\n' << 16) |
7107 ('\r' << 8) | ('\n' << 0);
7110 cmpbuf = (b->ptr[0] << 24) | (b->ptr[1] << 16) |
7111 (b->ptr[2] << 8) | (b->ptr[3] << 0);
7115 for (i = 0; i < b->used - 4; i++) {
7116 if (cmpbuf == rnrn) return cp - 4;
7119 cmpbuf = (cmpbuf << 8 | *(cp++)) & 0xffffffff;
7126 @@ -840,22 +736,25 @@
7128 chunkqueue *cq = con->read_queue;
7129 chunkqueue *dst_cq = con->request_content_queue;
7132 if (con->is_readable) {
7133 con->read_idle_ts = srv->cur_ts;
7136 switch(connection_handle_read(srv, con)) {
7138 + case NETWORK_STATUS_FATAL_ERROR:
7141 + case NETWORK_STATUS_CONNECTION_CLOSE:
7142 /* remote side closed the connection
7143 * if we still have content, handle it, if not leave here */
7145 if (cq->first == cq->last &&
7146 - cq->first->mem->used == 0) {
7147 + (NULL == cq->first ||
7148 + cq->first->mem->used == 0)) {
7150 /* conn-closed, leave here */
7151 connection_set_state(srv, con, CON_STATE_ERROR);
7157 @@ -891,14 +790,14 @@
7158 /* the last node was empty */
7159 if (c->next == NULL) {
7171 /* nothing to handle */
7172 if (cq->first == NULL) return 0;
7174 @@ -906,25 +805,26 @@
7175 case CON_STATE_READ:
7176 /* prepare con->request.request */
7180 /* check if we need the full package */
7181 if (con->request.request->used == 0) {
7185 b.ptr = c->mem->ptr + c->offset;
7186 b.used = c->mem->used - c->offset;
7189 if (NULL != (h_term = buffer_search_rnrn(&b))) {
7191 * - copy everything incl. the terminator to request.request
7194 - buffer_copy_string_len(con->request.request,
7197 + buffer_copy_string_len(con->request.request,
7199 h_term - b.ptr + 4);
7202 /* the buffer has been read up to the terminator */
7203 c->offset += h_term - b.ptr + 4;
7206 /* not found, copy everything */
7207 buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
7208 @@ -932,14 +832,14 @@
7211 /* have to take care of overlapping header terminators */
7214 size_t l = con->request.request->used - 2;
7215 char *s = con->request.request->ptr;
7219 b.ptr = c->mem->ptr + c->offset;
7220 b.used = c->mem->used - c->offset;
7223 if (con->request.request->used - 1 > 3 &&
7227 c->mem->ptr[0] == '\n') {
7228 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
7232 h_term = con->request.request->ptr;
7233 } else if (con->request.request->used - 1 > 2 &&
7236 c->mem->ptr[1] == '\n') {
7237 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
7241 h_term = con->request.request->ptr;
7242 } else if (con->request.request->used - 1 > 1 &&
7244 @@ -968,17 +868,17 @@
7245 c->mem->ptr[2] == '\n') {
7246 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3);
7250 h_term = con->request.request->ptr;
7251 } else if (NULL != (h_term = buffer_search_string_len(&b, "\r\n\r\n", 4))) {
7253 * - copy everything incl. the terminator to request.request
7256 - buffer_append_string_len(con->request.request,
7257 - c->mem->ptr + c->offset,
7259 + buffer_append_string_len(con->request.request,
7260 + c->mem->ptr + c->offset,
7261 c->offset + h_term - b.ptr + 4);
7264 /* the buffer has been read up to the terminator */
7265 c->offset += h_term - b.ptr + 4;
7267 @@ -999,16 +899,16 @@
7268 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7271 - case CON_STATE_READ_POST:
7272 + case CON_STATE_READ_POST:
7273 for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
7274 off_t weWant, weHave, toRead;
7277 weWant = con->request.content_length - dst_cq->bytes_in;
7280 assert(c->mem->used);
7283 weHave = c->mem->used - c->offset - 1;
7286 toRead = weHave > weWant ? weWant : weHave;
7288 /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
7289 @@ -1017,13 +917,13 @@
7290 /* copy everything to max 1Mb sized tempfiles */
7293 - * if the last chunk is
7294 + * if the last chunk is
7295 * - smaller than 1Mb (size < 1Mb)
7296 * - not read yet (offset == 0)
7299 - * -> create a new chunk
7301 + * -> create a new chunk
7306 @@ -1056,14 +956,14 @@
7307 /* we have a chunk, let's write to it */
7309 if (dst_c->file.fd == -1) {
7310 - /* we don't have file to write to,
7311 + /* we don't have file to write to,
7312 * EACCES might be one reason.
7314 * Instead of sending 500 we send 413 and say the request is too large
7317 log_error_write(srv, __FILE__, __LINE__, "sbs",
7318 - "denying upload as opening to temp-file for upload failed:",
7319 + "denying upload as opening to temp-file for upload failed:",
7320 dst_c->file.name, strerror(errno));
7322 con->http_status = 413; /* Request-Entity too large */
7323 @@ -1074,15 +974,15 @@
7326 if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
7327 - /* write failed for some reason ... disk full ? */
7328 + /* write failed for some reason ... disk full ? */
7329 log_error_write(srv, __FILE__, __LINE__, "sbs",
7330 - "denying upload as writing to file failed:",
7331 + "denying upload as writing to file failed:",
7332 dst_c->file.name, strerror(errno));
7335 con->http_status = 413; /* Request-Entity too large */
7336 con->keep_alive = 0;
7337 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7340 close(dst_c->file.fd);
7341 dst_c->file.fd = -1;
7343 @@ -1090,7 +990,7 @@
7346 dst_c->file.length += toRead;
7349 if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
7350 /* we read everything, close the chunk */
7351 close(dst_c->file.fd);
7352 @@ -1102,7 +1002,7 @@
7353 b = chunkqueue_get_append_buffer(dst_cq);
7354 buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
7358 c->offset += toRead;
7359 dst_cq->bytes_in += toRead;
7361 @@ -1111,7 +1011,7 @@
7362 if (dst_cq->bytes_in == (off_t)con->request.content_length) {
7363 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7370 @@ -1123,9 +1023,9 @@
7371 handler_t connection_handle_fdevent(void *s, void *context, int revents) {
7372 server *srv = (server *)s;
7373 connection *con = context;
7376 joblist_append(srv, con);
7379 if (revents & FDEVENT_IN) {
7380 con->is_readable = 1;
7382 @@ -1136,19 +1036,19 @@
7383 con->is_writable = 1;
7384 /* we don't need the event twice */
7390 if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
7391 /* looks like an error */
7394 /* FIXME: revents = 0x19 still means that we should read from the queue */
7395 if (revents & FDEVENT_HUP) {
7396 if (con->state == CON_STATE_CLOSE) {
7397 con->close_timeout_ts = 0;
7399 /* sigio reports the wrong event here
7401 - * there was no HUP at all
7403 + * there was no HUP at all
7405 #ifdef USE_LINUX_SIGIO
7406 if (srv->ev->in_sigio == 1) {
7407 @@ -1160,32 +1060,39 @@
7409 connection_set_state(srv, con, CON_STATE_ERROR);
7414 } else if (revents & FDEVENT_ERR) {
7415 #ifndef USE_LINUX_SIGIO
7416 log_error_write(srv, __FILE__, __LINE__, "sd",
7417 "connection closed: poll() -> ERR", con->fd);
7420 connection_set_state(srv, con, CON_STATE_ERROR);
7422 log_error_write(srv, __FILE__, __LINE__, "sd",
7423 "connection closed: poll() -> ???", revents);
7429 if (con->state == CON_STATE_READ ||
7430 con->state == CON_STATE_READ_POST) {
7431 connection_handle_read_state(srv, con);
7433 + * if SSL_read() is not readin in the full packet we won't get
7434 + * a fdevent as the low-level has already fetched everything.
7436 + * we have to call the state-engine to read the rest of the packet
7438 + if (con->is_readable) joblist_append(srv, con);
7442 if (con->state == CON_STATE_WRITE &&
7443 !chunkqueue_is_empty(con->write_queue) &&
7447 if (-1 == connection_handle_write(srv, con)) {
7448 connection_set_state(srv, con, CON_STATE_ERROR);
7451 log_error_write(srv, __FILE__, __LINE__, "ds",
7453 "handle write failed.");
7454 @@ -1193,30 +1100,30 @@
7455 con->write_request_ts = srv->cur_ts;
7460 if (con->state == CON_STATE_CLOSE) {
7461 /* flush the read buffers */
7465 if (ioctl(con->fd, FIONREAD, &b)) {
7466 log_error_write(srv, __FILE__, __LINE__, "ss",
7467 "ioctl() failed", strerror(errno));
7473 log_error_write(srv, __FILE__, __LINE__, "sdd",
7474 "CLOSE-read()", con->fd, b);
7478 read(con->fd, buf, sizeof(buf));
7480 /* nothing to read */
7483 con->close_timeout_ts = 0;
7488 return HANDLER_FINISHED;
7491 @@ -1229,63 +1136,68 @@
7494 /* accept it and register the fd */
7497 cnt_len = sizeof(cnt_addr);
7499 if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
7501 + errno = WSAGetLastError();
7503 if ((errno != EAGAIN) &&
7504 + (errno != EWOULDBLOCK) &&
7506 - log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
7507 + log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), srv_socket->fd);
7517 /* ok, we have the connection, register it */
7519 log_error_write(srv, __FILE__, __LINE__, "sd",
7525 con = connections_get_new_connection(srv);
7531 gettimeofday(&(con->start_tv), NULL);
7534 fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
7537 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7540 con->connection_start = srv->cur_ts;
7541 con->dst_addr = cnt_addr;
7542 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
7543 con->srv_socket = srv_socket;
7546 if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
7547 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
7548 + connection_close(srv, con);
7552 /* connect FD to SSL */
7553 if (srv_socket->is_ssl) {
7554 if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
7555 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7556 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7557 ERR_error_string(ERR_get_error(), NULL));
7559 + connection_close(srv, con);
7564 SSL_set_accept_state(con->ssl);
7568 if (1 != (SSL_set_fd(con->ssl, cnt))) {
7569 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7570 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7571 ERR_error_string(ERR_get_error(), NULL));
7572 + connection_close(srv, con);
7576 @@ -1300,10 +1212,10 @@
7578 server_socket *srv_sock = con->srv_socket;
7582 if (srv->srvconf.log_state_handling) {
7583 - log_error_write(srv, __FILE__, __LINE__, "sds",
7585 + log_error_write(srv, __FILE__, __LINE__, "sds",
7588 connection_get_state(con->state));
7590 @@ -1311,91 +1223,91 @@
7592 size_t ostate = con->state;
7596 switch (con->state) {
7597 case CON_STATE_REQUEST_START: /* transient */
7598 if (srv->srvconf.log_state_handling) {
7599 - log_error_write(srv, __FILE__, __LINE__, "sds",
7600 + log_error_write(srv, __FILE__, __LINE__, "sds",
7601 "state for fd", con->fd, connection_get_state(con->state));
7605 con->request_start = srv->cur_ts;
7606 con->read_idle_ts = srv->cur_ts;
7609 con->request_count++;
7610 con->loops_per_request = 0;
7613 connection_set_state(srv, con, CON_STATE_READ);
7617 case CON_STATE_REQUEST_END: /* transient */
7618 if (srv->srvconf.log_state_handling) {
7619 - log_error_write(srv, __FILE__, __LINE__, "sds",
7620 + log_error_write(srv, __FILE__, __LINE__, "sds",
7621 "state for fd", con->fd, connection_get_state(con->state));
7625 if (http_request_parse(srv, con)) {
7626 /* we have to read some data from the POST request */
7629 connection_set_state(srv, con, CON_STATE_READ_POST);
7635 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7639 case CON_STATE_HANDLE_REQUEST:
7642 * the request is parsed
7645 * decided what to do with the request
7655 if (srv->srvconf.log_state_handling) {
7656 - log_error_write(srv, __FILE__, __LINE__, "sds",
7657 + log_error_write(srv, __FILE__, __LINE__, "sds",
7658 "state for fd", con->fd, connection_get_state(con->state));
7662 switch (r = http_response_prepare(srv, con)) {
7663 case HANDLER_FINISHED:
7664 if (con->http_status == 404 ||
7665 con->http_status == 403) {
7666 /* 404 error-handler */
7668 - if (con->in_error_handler == 0 &&
7670 + if (con->in_error_handler == 0 &&
7671 (!buffer_is_empty(con->conf.error_handler) ||
7672 !buffer_is_empty(con->error_handler))) {
7673 /* call error-handler */
7676 con->error_handler_saved_status = con->http_status;
7677 con->http_status = 0;
7680 if (buffer_is_empty(con->error_handler)) {
7681 buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
7683 buffer_copy_string_buffer(con->request.uri, con->error_handler);
7685 buffer_reset(con->physical.path);
7688 con->in_error_handler = 1;
7691 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7696 } else if (con->in_error_handler) {
7697 /* error-handler is a 404 */
7700 /* continue as normal, status is the same */
7701 - log_error_write(srv, __FILE__, __LINE__, "sb",
7702 + log_error_write(srv, __FILE__, __LINE__, "sb",
7703 "Warning: Either the error-handler returned status 404 or the error-handler itself was not found:", con->request.uri);
7704 - log_error_write(srv, __FILE__, __LINE__, "sd",
7705 + log_error_write(srv, __FILE__, __LINE__, "sd",
7706 "returning the original status", con->error_handler_saved_status);
7707 - log_error_write(srv, __FILE__, __LINE__, "s",
7708 + log_error_write(srv, __FILE__, __LINE__, "s",
7709 "If this is a rails app: check your production.log");
7710 con->http_status = con->error_handler_saved_status;
7712 @@ -1403,26 +1315,26 @@
7713 /* error-handler is back and has generated content */
7714 /* if Status: was set, take it otherwise use 200 */
7718 if (con->http_status == 0) con->http_status = 200;
7721 /* we have something to send, go on */
7722 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
7724 case HANDLER_WAIT_FOR_FD:
7728 fdwaitqueue_append(srv, con);
7731 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7735 case HANDLER_COMEBACK:
7737 case HANDLER_WAIT_FOR_EVENT:
7738 /* come back here */
7739 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7744 /* something went wrong */
7745 @@ -1432,44 +1344,44 @@
7746 log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
7752 case CON_STATE_RESPONSE_START:
7755 * the decision is done
7756 * - create the HTTP-Response-Header
7762 if (srv->srvconf.log_state_handling) {
7763 - log_error_write(srv, __FILE__, __LINE__, "sds",
7764 + log_error_write(srv, __FILE__, __LINE__, "sds",
7765 "state for fd", con->fd, connection_get_state(con->state));
7769 if (-1 == connection_handle_write_prepare(srv, con)) {
7770 connection_set_state(srv, con, CON_STATE_ERROR);
7777 connection_set_state(srv, con, CON_STATE_WRITE);
7779 case CON_STATE_RESPONSE_END: /* transient */
7780 /* log the request */
7783 if (srv->srvconf.log_state_handling) {
7784 - log_error_write(srv, __FILE__, __LINE__, "sds",
7785 + log_error_write(srv, __FILE__, __LINE__, "sds",
7786 "state for fd", con->fd, connection_get_state(con->state));
7790 plugins_call_handle_request_done(srv, con);
7796 if (con->keep_alive) {
7797 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7802 con->request_start = srv->cur_ts;
7803 con->read_idle_ts = srv->cur_ts;
7805 @@ -1482,7 +1394,7 @@
7806 log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
7812 if (srv_sock->is_ssl) {
7813 switch (SSL_shutdown(con->ssl)) {
7814 @@ -1490,44 +1402,44 @@
7818 - /* wait for fd-event
7820 + /* wait for fd-event
7822 * FIXME: wait for fdevent and call SSL_shutdown again
7830 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7831 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7832 ERR_error_string(ERR_get_error(), NULL));
7836 connection_close(srv, con);
7843 connection_reset(srv, con);
7847 case CON_STATE_CONNECT:
7848 if (srv->srvconf.log_state_handling) {
7849 - log_error_write(srv, __FILE__, __LINE__, "sds",
7850 + log_error_write(srv, __FILE__, __LINE__, "sds",
7851 "state for fd", con->fd, connection_get_state(con->state));
7855 chunkqueue_reset(con->read_queue);
7858 con->request_count = 0;
7862 case CON_STATE_CLOSE:
7863 if (srv->srvconf.log_state_handling) {
7864 - log_error_write(srv, __FILE__, __LINE__, "sds",
7865 + log_error_write(srv, __FILE__, __LINE__, "sds",
7866 "state for fd", con->fd, connection_get_state(con->state));
7870 if (con->keep_alive) {
7871 if (ioctl(con->fd, FIONREAD, &b)) {
7872 log_error_write(srv, __FILE__, __LINE__, "ss",
7873 @@ -1537,43 +1449,43 @@
7875 log_error_write(srv, __FILE__, __LINE__, "sdd",
7876 "CLOSE-read()", con->fd, b);
7880 read(con->fd, buf, sizeof(buf));
7882 /* nothing to read */
7885 con->close_timeout_ts = 0;
7888 con->close_timeout_ts = 0;
7892 if (srv->cur_ts - con->close_timeout_ts > 1) {
7893 connection_close(srv, con);
7896 if (srv->srvconf.log_state_handling) {
7897 - log_error_write(srv, __FILE__, __LINE__, "sd",
7898 + log_error_write(srv, __FILE__, __LINE__, "sd",
7899 "connection closed for fd", con->fd);
7905 case CON_STATE_READ_POST:
7906 case CON_STATE_READ:
7907 if (srv->srvconf.log_state_handling) {
7908 - log_error_write(srv, __FILE__, __LINE__, "sds",
7909 + log_error_write(srv, __FILE__, __LINE__, "sds",
7910 "state for fd", con->fd, connection_get_state(con->state));
7914 connection_handle_read_state(srv, con);
7916 case CON_STATE_WRITE:
7917 if (srv->srvconf.log_state_handling) {
7918 - log_error_write(srv, __FILE__, __LINE__, "sds",
7919 + log_error_write(srv, __FILE__, __LINE__, "sds",
7920 "state for fd", con->fd, connection_get_state(con->state));
7924 /* only try to write if we have something in the queue */
7925 if (!chunkqueue_is_empty(con->write_queue)) {
7927 @@ -1593,10 +1505,10 @@
7928 con->write_request_ts = srv->cur_ts;
7934 case CON_STATE_ERROR: /* transient */
7937 /* even if the connection was drop we still have to write it to the access log */
7938 if (con->http_status) {
7939 plugins_call_handle_request_done(srv, con);
7940 @@ -1612,19 +1524,19 @@
7941 SSL_shutdown(con->ssl);
7944 - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
7945 - SSL_get_error(con->ssl, ret),
7946 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
7947 + SSL_get_error(con->ssl, ret),
7948 ERR_error_string(ERR_get_error(), NULL));
7958 - log_error_write(srv, __FILE__, __LINE__, "sd",
7959 - "emergency exit: direct",
7960 + log_error_write(srv, __FILE__, __LINE__, "sd",
7961 + "emergency exit: direct",
7965 @@ -1639,35 +1551,35 @@
7971 connection_reset(srv, con);
7974 /* close the connection */
7975 if ((con->keep_alive == 1) &&
7976 (0 == shutdown(con->fd, SHUT_WR))) {
7977 con->close_timeout_ts = srv->cur_ts;
7978 connection_set_state(srv, con, CON_STATE_CLOSE);
7981 if (srv->srvconf.log_state_handling) {
7982 - log_error_write(srv, __FILE__, __LINE__, "sd",
7983 + log_error_write(srv, __FILE__, __LINE__, "sd",
7984 "shutdown for fd", con->fd);
7987 connection_close(srv, con);
7991 con->keep_alive = 0;
7999 - log_error_write(srv, __FILE__, __LINE__, "sdd",
8000 + log_error_write(srv, __FILE__, __LINE__, "sdd",
8001 "unknown state:", con->fd, con->state);
8010 } else if (ostate == con->state) {
8011 @@ -1676,12 +1588,12 @@
8014 if (srv->srvconf.log_state_handling) {
8015 - log_error_write(srv, __FILE__, __LINE__, "sds",
8017 + log_error_write(srv, __FILE__, __LINE__, "sds",
8020 connection_get_state(con->state));
8024 switch(con->state) {
8025 case CON_STATE_READ_POST:
8026 case CON_STATE_READ:
8027 @@ -1689,11 +1601,11 @@
8028 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
8030 case CON_STATE_WRITE:
8031 - /* request write-fdevent only if we really need it
8032 + /* request write-fdevent only if we really need it
8033 * - if we have data to write
8034 - * - if the socket is not writable yet
8035 + * - if the socket is not writable yet
8037 - if (!chunkqueue_is_empty(con->write_queue) &&
8038 + if (!chunkqueue_is_empty(con->write_queue) &&
8039 (con->is_writable == 0) &&
8040 (con->traffic_limit_reached == 0)) {
8041 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
8042 --- lighttpd-1.4.11/src/crc32.h 2005-09-30 20:18:59.000000000 +0300
8043 +++ lighttpd-1.4.12/src/crc32.h 2006-07-11 22:07:53.000000000 +0300
8047 #include <sys/types.h>
8048 +#include <stdlib.h>
8050 #if defined HAVE_STDINT_H
8053 #include <inttypes.h>
8057 +#define uint32_t unsigned __int32
8060 uint32_t generate_crc32c(char *string, size_t length);
8063 --- lighttpd-1.4.11/src/data_array.c 2005-08-23 17:36:12.000000000 +0300
8064 +++ lighttpd-1.4.12/src/data_array.c 2006-07-11 22:07:52.000000000 +0300
8067 static void data_array_free(data_unset *d) {
8068 data_array *ds = (data_array *)d;
8071 buffer_free(ds->key);
8072 array_free(ds->value);
8078 static void data_array_reset(data_unset *d) {
8079 data_array *ds = (data_array *)d;
8082 /* reused array elements */
8083 buffer_reset(ds->key);
8084 array_reset(ds->value);
8096 data_array *data_array_init(void) {
8100 ds = calloc(1, sizeof(*ds));
8103 ds->key = buffer_init();
8104 ds->value = array_init();
8107 ds->copy = data_array_copy;
8108 ds->free = data_array_free;
8109 ds->reset = data_array_reset;
8110 ds->insert_dup = data_array_insert_dup;
8111 ds->print = data_array_print;
8112 ds->type = TYPE_ARRAY;
8117 --- lighttpd-1.4.11/src/data_config.c 2005-08-17 12:53:19.000000000 +0300
8118 +++ lighttpd-1.4.12/src/data_config.c 2006-07-11 22:07:51.000000000 +0300
8121 static void data_config_free(data_unset *d) {
8122 data_config *ds = (data_config *)d;
8125 buffer_free(ds->key);
8126 buffer_free(ds->op);
8127 buffer_free(ds->comp_key);
8130 array_free(ds->value);
8131 array_free(ds->childs);
8134 if (ds->string) buffer_free(ds->string);
8136 if (ds->regex) pcre_free(ds->regex);
8137 if (ds->regex_study) pcre_free(ds->regex_study);
8144 static void data_config_reset(data_unset *d) {
8145 data_config *ds = (data_config *)d;
8148 /* reused array elements */
8149 buffer_reset(ds->key);
8150 buffer_reset(ds->comp_key);
8153 static int data_config_insert_dup(data_unset *dst, data_unset *src) {
8164 array *a = (array *)ds->value;
8169 if (0 == ds->context_ndx) {
8170 fprintf(stderr, "config {\n");
8172 @@ -117,22 +117,22 @@
8174 data_config *data_config_init(void) {
8178 ds = calloc(1, sizeof(*ds));
8181 ds->key = buffer_init();
8182 ds->op = buffer_init();
8183 ds->comp_key = buffer_init();
8184 ds->value = array_init();
8185 ds->childs = array_init();
8186 ds->childs->is_weakref = 1;
8189 ds->copy = data_config_copy;
8190 ds->free = data_config_free;
8191 ds->reset = data_config_reset;
8192 ds->insert_dup = data_config_insert_dup;
8193 ds->print = data_config_print;
8194 ds->type = TYPE_CONFIG;
8199 --- lighttpd-1.4.11/src/data_count.c 2005-08-23 17:36:12.000000000 +0300
8200 +++ lighttpd-1.4.12/src/data_count.c 2006-07-11 22:07:51.000000000 +0300
8203 static void data_count_free(data_unset *d) {
8204 data_count *ds = (data_count *)d;
8207 buffer_free(ds->key);
8213 static void data_count_reset(data_unset *d) {
8214 data_count *ds = (data_count *)d;
8217 buffer_reset(ds->key);
8223 static int data_count_insert_dup(data_unset *dst, data_unset *src) {
8224 data_count *ds_dst = (data_count *)dst;
8225 data_count *ds_src = (data_count *)src;
8228 ds_dst->count += ds_src->count;
8237 static void data_count_print(const data_unset *d, int depth) {
8238 data_count *ds = (data_count *)d;
8242 fprintf(stderr, "count(%d)", ds->count);
8246 data_count *data_count_init(void) {
8250 ds = calloc(1, sizeof(*ds));
8253 ds->key = buffer_init();
8257 ds->copy = data_count_copy;
8258 ds->free = data_count_free;
8259 ds->reset = data_count_reset;
8260 ds->insert_dup = data_count_insert_dup;
8261 ds->print = data_count_print;
8262 ds->type = TYPE_COUNT;
8267 --- lighttpd-1.4.11/src/data_fastcgi.c 2005-08-23 17:36:12.000000000 +0300
8268 +++ lighttpd-1.4.12/src/data_fastcgi.c 2006-07-11 22:07:53.000000000 +0300
8271 static void data_fastcgi_free(data_unset *d) {
8272 data_fastcgi *ds = (data_fastcgi *)d;
8275 buffer_free(ds->key);
8276 buffer_free(ds->host);
8282 static void data_fastcgi_reset(data_unset *d) {
8283 data_fastcgi *ds = (data_fastcgi *)d;
8286 buffer_reset(ds->key);
8287 buffer_reset(ds->host);
8292 static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
8301 static void data_fastcgi_print(const data_unset *d, int depth) {
8302 data_fastcgi *ds = (data_fastcgi *)d;
8306 fprintf(stderr, "fastcgi(%s)", ds->host->ptr);
8310 data_fastcgi *data_fastcgi_init(void) {
8314 ds = calloc(1, sizeof(*ds));
8317 ds->key = buffer_init();
8318 ds->host = buffer_init();
8320 ds->is_disabled = 0;
8323 ds->copy = data_fastcgi_copy;
8324 ds->free = data_fastcgi_free;
8325 ds->reset = data_fastcgi_reset;
8326 ds->insert_dup = data_fastcgi_insert_dup;
8327 ds->print = data_fastcgi_print;
8328 ds->type = TYPE_FASTCGI;
8333 --- lighttpd-1.4.11/src/data_integer.c 2005-08-23 17:36:12.000000000 +0300
8334 +++ lighttpd-1.4.12/src/data_integer.c 2006-07-11 22:07:51.000000000 +0300
8337 static void data_integer_free(data_unset *d) {
8338 data_integer *ds = (data_integer *)d;
8341 buffer_free(ds->key);
8347 static void data_integer_reset(data_unset *d) {
8348 data_integer *ds = (data_integer *)d;
8351 /* reused integer elements */
8352 buffer_reset(ds->key);
8356 static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
8368 data_integer *data_integer_init(void) {
8372 ds = calloc(1, sizeof(*ds));
8375 ds->key = buffer_init();
8379 ds->copy = data_integer_copy;
8380 ds->free = data_integer_free;
8381 ds->reset = data_integer_reset;
8382 ds->insert_dup = data_integer_insert_dup;
8383 ds->print = data_integer_print;
8384 ds->type = TYPE_INTEGER;
8389 --- lighttpd-1.4.11/src/data_string.c 2005-08-23 17:36:12.000000000 +0300
8390 +++ lighttpd-1.4.12/src/data_string.c 2006-07-11 22:07:53.000000000 +0300
8393 static void data_string_free(data_unset *d) {
8394 data_string *ds = (data_string *)d;
8397 buffer_free(ds->key);
8398 buffer_free(ds->value);
8404 static void data_string_reset(data_unset *d) {
8405 data_string *ds = (data_string *)d;
8408 /* reused array elements */
8409 buffer_reset(ds->key);
8410 buffer_reset(ds->value);
8412 static int data_string_insert_dup(data_unset *dst, data_unset *src) {
8413 data_string *ds_dst = (data_string *)dst;
8414 data_string *ds_src = (data_string *)src;
8417 if (ds_dst->value->used) {
8418 buffer_append_string(ds_dst->value, ", ");
8419 buffer_append_string_buffer(ds_dst->value, ds_src->value);
8421 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8431 static int data_response_insert_dup(data_unset *dst, data_unset *src) {
8432 data_string *ds_dst = (data_string *)dst;
8433 data_string *ds_src = (data_string *)src;
8436 if (ds_dst->value->used) {
8437 buffer_append_string(ds_dst->value, "\r\n");
8438 buffer_append_string_buffer(ds_dst->value, ds_dst->key);
8441 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8453 data_string *data_string_init(void) {
8457 ds = calloc(1, sizeof(*ds));
8461 ds->key = buffer_init();
8462 ds->value = buffer_init();
8465 ds->copy = data_string_copy;
8466 ds->free = data_string_free;
8467 ds->reset = data_string_reset;
8468 ds->insert_dup = data_string_insert_dup;
8469 ds->print = data_string_print;
8470 ds->type = TYPE_STRING;
8476 data_string *data_response_init(void) {
8480 ds = data_string_init();
8481 ds->insert_dup = data_response_insert_dup;
8486 --- lighttpd-1.4.11/src/etag.c 2005-08-11 01:26:40.000000000 +0300
8487 +++ lighttpd-1.4.12/src/etag.c 2006-07-11 22:07:51.000000000 +0300
8489 buffer_append_off_t(etag, st->st_size);
8490 buffer_append_string_len(etag, CONST_STR_LEN("-"));
8491 buffer_append_long(etag, st->st_mtime);
8497 int etag_mutate(buffer *mut, buffer *etag) {
8501 for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
8505 buffer_copy_string_len(mut, CONST_STR_LEN("\""));
8506 buffer_append_long(mut, h);
8507 buffer_append_string_len(mut, CONST_STR_LEN("\""));
8512 --- lighttpd-1.4.11/src/etag.h 2005-08-11 01:26:40.000000000 +0300
8513 +++ lighttpd-1.4.12/src/etag.h 2006-07-11 22:07:51.000000000 +0300
8516 #include <sys/types.h>
8517 #include <sys/stat.h>
8518 -#include <unistd.h>
8522 int etag_is_equal(buffer *etag, const char *matches);
8523 int etag_create(buffer *etag, struct stat *st);
8524 int etag_mutate(buffer *mut, buffer *etag);
8529 --- lighttpd-1.4.11/src/fastcgi.h 2005-08-11 01:26:40.000000000 +0300
8530 +++ lighttpd-1.4.12/src/fastcgi.h 2006-07-11 22:07:51.000000000 +0300
8536 * Defines for the FastCGI protocol.
8541 - unsigned char type;
8542 + unsigned char type;
8543 unsigned char reserved[7];
8544 } FCGI_UnknownTypeBody;
8546 --- lighttpd-1.4.11/src/fdevent.c 2005-11-15 10:51:05.000000000 +0200
8547 +++ lighttpd-1.4.12/src/fdevent.c 2006-07-11 22:07:53.000000000 +0300
8550 #include "settings.h"
8552 -#include <unistd.h>
8557 #include "fdevent.h"
8560 +#include "sys-socket.h"
8562 fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
8566 ev = calloc(1, sizeof(*ev));
8567 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
8568 ev->maxfds = maxfds;
8572 case FDEVENT_HANDLER_POLL:
8573 if (0 != fdevent_poll_init(ev)) {
8574 - fprintf(stderr, "%s.%d: event-handler poll failed\n",
8575 + fprintf(stderr, "%s.%d: event-handler poll failed\n",
8576 __FILE__, __LINE__);
8582 case FDEVENT_HANDLER_SELECT:
8583 if (0 != fdevent_select_init(ev)) {
8584 - fprintf(stderr, "%s.%d: event-handler select failed\n",
8585 + fprintf(stderr, "%s.%d: event-handler select failed\n",
8586 __FILE__, __LINE__);
8590 case FDEVENT_HANDLER_LINUX_RTSIG:
8591 if (0 != fdevent_linux_rtsig_init(ev)) {
8592 - fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8593 + fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8594 __FILE__, __LINE__);
8598 case FDEVENT_HANDLER_LINUX_SYSEPOLL:
8599 if (0 != fdevent_linux_sysepoll_init(ev)) {
8600 - fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8601 + fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8602 __FILE__, __LINE__);
8606 case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
8607 if (0 != fdevent_solaris_devpoll_init(ev)) {
8608 - fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8609 + fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8610 __FILE__, __LINE__);
8614 case FDEVENT_HANDLER_FREEBSD_KQUEUE:
8615 if (0 != fdevent_freebsd_kqueue_init(ev)) {
8616 - fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8617 + fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8618 __FILE__, __LINE__);
8623 - fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
8624 + fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
8625 __FILE__, __LINE__);
8629 void fdevent_free(fdevents *ev) {
8634 if (ev->free) ev->free(ev);
8637 for (i = 0; i < ev->maxfds; i++) {
8638 if (ev->fdarray[i]) free(ev->fdarray[i]);
8646 int fdevent_reset(fdevents *ev) {
8647 if (ev->reset) return ev->reset(ev);
8653 fdnode *fdnode_init() {
8657 fdn = calloc(1, sizeof(*fdn));
8660 @@ -106,12 +107,12 @@
8662 int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
8666 fdn = fdnode_init();
8667 fdn->handler = handler;
8672 ev->fdarray[fd] = fdn;
8675 @@ -121,31 +122,31 @@
8678 fdn = ev->fdarray[fd];
8684 ev->fdarray[fd] = NULL;
8690 int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
8691 int fde = fde_ndx ? *fde_ndx : -1;
8694 if (ev->event_del) fde = ev->event_del(ev, fde, fd);
8697 if (fde_ndx) *fde_ndx = fde;
8703 int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
8704 int fde = fde_ndx ? *fde_ndx : -1;
8707 if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
8710 if (fde_ndx) *fde_ndx = fde;
8716 @@ -156,38 +157,43 @@
8718 int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
8719 if (ev->event_get_revent == NULL) SEGFAULT();
8722 return ev->event_get_revent(ev, ndx);
8725 int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
8726 if (ev->event_get_fd == NULL) SEGFAULT();
8729 return ev->event_get_fd(ev, ndx);
8732 fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
8733 if (ev->fdarray[fd] == NULL) SEGFAULT();
8734 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8737 return ev->fdarray[fd]->handler;
8740 void * fdevent_get_context(fdevents *ev, int fd) {
8741 if (ev->fdarray[fd] == NULL) SEGFAULT();
8742 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8745 return ev->fdarray[fd]->ctx;
8748 int fdevent_fcntl_set(fdevents *ev, int fd) {
8753 /* close fd on exec (cgi) */
8754 fcntl(fd, F_SETFD, FD_CLOEXEC);
8756 if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
8759 return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
8760 +#elif defined _WIN32
8761 + return ioctlsocket(fd, FIONBIO, &i);
8767 int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
8768 if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
8774 --- lighttpd-1.4.11/src/fdevent.h 2005-09-27 11:26:33.000000000 +0300
8775 +++ lighttpd-1.4.12/src/fdevent.h 2006-07-11 22:07:51.000000000 +0300
8777 # include <sys/epoll.h>
8780 -/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
8781 +/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
8782 * under /usr/include/sys/ */
8783 #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
8789 # include <sys/poll.h>
8791 # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
8793 # include <signal.h>
8798 +# define HAVE_SELECT
8800 #if defined HAVE_SELECT
8803 # include <winsock2.h>
8807 #define FDEVENT_HUP BV(4)
8808 #define FDEVENT_NVAL BV(5)
8810 -typedef enum { FD_EVENT_TYPE_UNSET = -1,
8811 - FD_EVENT_TYPE_CONNECTION,
8812 - FD_EVENT_TYPE_FCGI_CONNECTION,
8813 - FD_EVENT_TYPE_DIRWATCH,
8814 - FD_EVENT_TYPE_CGI_CONNECTION
8815 +typedef enum { FD_EVENT_TYPE_UNSET = -1,
8816 + FD_EVENT_TYPE_CONNECTION,
8817 + FD_EVENT_TYPE_FCGI_CONNECTION,
8818 + FD_EVENT_TYPE_DIRWATCH,
8819 + FD_EVENT_TYPE_CGI_CONNECTION
8822 -typedef enum { FDEVENT_HANDLER_UNSET,
8823 +typedef enum { FDEVENT_HANDLER_UNSET,
8824 FDEVENT_HANDLER_SELECT,
8825 FDEVENT_HANDLER_POLL,
8826 FDEVENT_HANDLER_LINUX_RTSIG,
8830 * a mapping from fd to connection structure
8835 int fd; /**< the fd */
8836 @@ -98,41 +100,41 @@
8847 * array of unused fd's
8852 typedef struct _fdnode {
8853 fdevent_handler handler;
8858 struct _fdnode *prev, *next;
8870 * fd-event handler for select(), poll() and rt-signals on Linux 2.4
8874 typedef struct fdevents {
8875 fdevent_handler_t type;
8882 #ifdef USE_LINUX_SIGIO
8885 @@ -146,21 +148,21 @@
8888 struct pollfd *pollfds;
8899 fd_set select_write;
8900 fd_set select_error;
8903 fd_set select_set_read;
8904 fd_set select_set_write;
8905 fd_set select_set_error;
8910 #ifdef USE_SOLARIS_DEVPOLL
8911 @@ -177,16 +179,16 @@
8913 int (*reset)(struct fdevents *ev);
8914 void (*free)(struct fdevents *ev);
8917 int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events);
8918 int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
8919 int (*event_get_revent)(struct fdevents *ev, size_t ndx);
8920 int (*event_get_fd)(struct fdevents *ev, size_t ndx);
8923 int (*event_next_fdndx)(struct fdevents *ev, int ndx);
8926 int (*poll)(struct fdevents *ev, int timeout_ms);
8929 int (*fcntl_set)(struct fdevents *ev, int fd);
8932 --- lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c 2005-09-01 10:46:24.000000000 +0300
8933 +++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c 2006-07-11 22:07:51.000000000 +0300
8935 #include <sys/types.h>
8937 -#include <unistd.h>
8956 ret = kevent(ev->kq_fd,
8965 if (filter == EVFILT_READ) {
8966 bitset_set_bit(ev->kq_bevents, fd);
8969 } else if (e == EVFILT_WRITE) {
8970 events |= FDEVENT_OUT;
8974 e = ev->kq_results[ndx].flags;
8977 @@ -152,10 +151,10 @@
8978 if (-1 == (ev->kq_fd = kqueue())) {
8979 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8980 __FILE__, __LINE__, strerror(errno));
8991 if (-1 == (ev->kq_fd = kqueue())) {
8992 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8993 __FILE__, __LINE__, strerror(errno));
8999 --- lighttpd-1.4.11/src/fdevent_linux_rtsig.c 2005-11-21 19:56:11.000000000 +0200
9000 +++ lighttpd-1.4.12/src/fdevent_linux_rtsig.c 2006-07-11 22:07:53.000000000 +0300
9002 #include <sys/types.h>
9004 -#include <unistd.h>
9010 static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) {
9011 if (fde_ndx < 0) return -1;
9014 if ((size_t)fde_ndx >= ev->used) {
9015 fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used);
9020 if (ev->pollfds[fde_ndx].fd == fd) {
9024 ev->pollfds[k].fd = -1;
9026 bitset_clear_bit(ev->sigbset, fd);
9029 if (ev->unused.size == 0) {
9030 ev->unused.size = 16;
9031 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9033 ev->unused.size += 16;
9034 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9038 ev->unused.ptr[ev->unused.used++] = k;
9040 fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd);
9051 static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
9055 if (ev->used == 0) return 0;
9056 if (ev->unused.used != 0) return 0;
9059 for (j = ev->used - 1; j + 1 > 0; j--) {
9060 if (ev->pollfds[j].fd == -1) ev->used--;
9070 if (fde_ndx != -1) {
9071 if (ev->pollfds[fde_ndx].fd == fd) {
9072 ev->pollfds[fde_ndx].events = events;
9077 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9082 if (ev->unused.used > 0) {
9083 int k = ev->unused.ptr[--ev->unused.used];
9086 ev->pollfds[k].fd = fd;
9087 ev->pollfds[k].events = events;
9089 bitset_set_bit(ev->sigbset, fd);
9094 if (ev->size == 0) {
9095 @@ -102,12 +101,12 @@
9097 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9101 ev->pollfds[ev->used].fd = fd;
9102 ev->pollfds[ev->used].events = events;
9104 bitset_set_bit(ev->sigbset, fd);
9110 @@ -115,20 +114,20 @@
9111 static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
9117 fdevent_linux_rtsig_event_compress(ev);
9124 ts.tv_sec = timeout_ms / 1000;
9125 ts.tv_nsec = (timeout_ms % 1000) * 1000000;
9126 r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
9131 if (errno == EAGAIN) return 0;
9134 } else if (r == SIGIO) {
9135 struct sigaction act;
9138 /* re-enable the signal queue */
9139 act.sa_handler = SIG_DFL;
9140 sigaction(ev->signum, &act, NULL);
9144 r = poll(ev->pollfds, ev->used, timeout_ms);
9146 @@ -162,12 +161,12 @@
9147 if (ev->siginfo.si_band == POLLERR) {
9148 fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno));
9153 fprintf(stderr, "+\n");
9158 return ev->siginfo.si_band & 0x3f;
9160 if (ndx >= ev->used) {
9161 @@ -188,13 +187,13 @@
9163 static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
9164 static pid_t pid = 0;
9167 if (pid == 0) pid = getpid();
9170 if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
9173 if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
9176 return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
9179 @@ -205,12 +204,12 @@
9185 i = (ndx < 0) ? 0 : ndx + 1;
9186 for (; i < ev->used; i++) {
9187 if (ev->pollfds[i].revents) break;
9194 @@ -219,34 +218,34 @@
9195 ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
9197 ev->x = fdevent_linux_rtsig_##x;
9208 SET(event_next_fdndx);
9211 SET(event_get_revent);
9214 ev->signum = SIGRTMIN + 1;
9217 sigemptyset(&(ev->sigset));
9218 sigaddset(&(ev->sigset), ev->signum);
9219 sigaddset(&(ev->sigset), SIGIO);
9220 if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) {
9221 fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9222 __FILE__, __LINE__, strerror(errno));
9231 ev->sigbset = bitset_init(ev->maxfds);
9237 --- lighttpd-1.4.11/src/fdevent_linux_sysepoll.c 2005-09-30 20:29:27.000000000 +0300
9238 +++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c 2006-07-11 22:07:53.000000000 +0300
9240 #include <sys/types.h>
9242 -#include <unistd.h>
9247 #include "settings.h"
9250 +#include "sys-files.h"
9252 #ifdef USE_LINUX_EPOLL
9253 static void fdevent_linux_sysepoll_free(fdevents *ev) {
9254 close(ev->epoll_fd);
9257 static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9258 struct epoll_event ep;
9261 if (fde_ndx < 0) return -1;
9264 memset(&ep, 0, sizeof(ep));
9271 if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
9272 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9287 static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9288 struct epoll_event ep;
9292 if (fde_ndx == -1) add = 1;
9295 memset(&ep, 0, sizeof(ep));
9301 if (events & FDEVENT_IN) ep.events |= EPOLLIN;
9302 if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
9310 ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
9317 if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
9318 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9333 static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
9337 e = ev->epoll_events[ndx].events;
9338 if (e & EPOLLIN) events |= FDEVENT_IN;
9339 if (e & EPOLLOUT) events |= FDEVENT_OUT;
9340 if (e & EPOLLERR) events |= FDEVENT_ERR;
9341 if (e & EPOLLHUP) events |= FDEVENT_HUP;
9342 if (e & EPOLLPRI) events |= FDEVENT_PRI;
9350 fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
9354 return ev->epoll_events[ndx].data.fd;
9357 static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
9363 i = (ndx < 0) ? 0 : ndx + 1;
9369 @@ -116,17 +117,17 @@
9370 ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
9372 ev->x = fdevent_linux_sysepoll_##x;
9383 SET(event_next_fdndx);
9385 SET(event_get_revent);
9388 if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
9389 fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9390 __FILE__, __LINE__, strerror(errno));
9393 fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9394 __FILE__, __LINE__);
9400 --- lighttpd-1.4.11/src/fdevent_poll.c 2005-11-18 13:59:16.000000000 +0200
9401 +++ lighttpd-1.4.12/src/fdevent_poll.c 2006-07-11 22:07:53.000000000 +0300
9403 #include <sys/types.h>
9405 -#include <unistd.h>
9411 static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
9412 if (fde_ndx < 0) return -1;
9415 if ((size_t)fde_ndx >= ev->used) {
9416 fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used);
9421 if (ev->pollfds[fde_ndx].fd == fd) {
9425 ev->pollfds[k].fd = -1;
9426 /* ev->pollfds[k].events = 0; */
9427 /* ev->pollfds[k].revents = 0; */
9430 if (ev->unused.size == 0) {
9431 ev->unused.size = 16;
9432 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9434 ev->unused.size += 16;
9435 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9439 ev->unused.ptr[ev->unused.used++] = k;
9449 static int fdevent_poll_event_compress(fdevents *ev) {
9453 if (ev->used == 0) return 0;
9454 if (ev->unused.used != 0) return 0;
9457 for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
9464 static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9468 if (fde_ndx != -1) {
9469 if (ev->pollfds[fde_ndx].fd == fd) {
9470 ev->pollfds[fde_ndx].events = events;
9475 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9480 if (ev->unused.used > 0) {
9481 int k = ev->unused.ptr[--ev->unused.used];
9484 ev->pollfds[k].fd = fd;
9485 ev->pollfds[k].events = events;
9490 if (ev->size == 0) {
9493 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9497 ev->pollfds[ev->used].fd = fd;
9498 ev->pollfds[ev->used].events = events;
9504 @@ -109,12 +108,12 @@
9506 if (ndx >= ev->used) {
9507 fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used);
9517 if (ev->pollfds[ndx].revents & POLLNVAL) {
9518 /* should never happen */
9521 if (poll_r & POLLHUP) r |= FDEVENT_HUP;
9522 if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
9523 if (poll_r & POLLPRI) r |= FDEVENT_PRI;
9526 return ev->pollfds[ndx].revents;
9529 @@ -141,12 +140,12 @@
9531 static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
9535 i = (ndx < 0) ? 0 : ndx + 1;
9536 for (; i < ev->used; i++) {
9537 if (ev->pollfds[i].revents) break;
9544 @@ -154,17 +153,17 @@
9545 ev->type = FDEVENT_HANDLER_POLL;
9547 ev->x = fdevent_poll_##x;
9558 SET(event_next_fdndx);
9560 SET(event_get_revent);
9566 --- lighttpd-1.4.11/src/fdevent_select.c 2005-08-31 11:12:46.000000000 +0300
9567 +++ lighttpd-1.4.12/src/fdevent_select.c 2006-07-11 22:07:53.000000000 +0300
9569 -#include <sys/time.h>
9570 #include <sys/types.h>
9572 -#include <unistd.h>
9581 #include "fdevent.h"
9582 #include "settings.h"
9585 +#include "sys-socket.h"
9589 static int fdevent_select_reset(fdevents *ev) {
9593 /* we should be protected by max-fds, but you never know */
9595 assert(fd < FD_SETSIZE);
9598 if (events & FDEVENT_IN) {
9599 FD_SET(fd, &(ev->select_set_read));
9601 FD_SET(fd, &(ev->select_set_write));
9603 FD_SET(fd, &(ev->select_set_error));
9606 if (fd > ev->select_max_fd) ev->select_max_fd = fd;
9612 static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
9616 tv.tv_sec = timeout_ms / 1000;
9617 tv.tv_usec = (timeout_ms % 1000) * 1000;
9620 ev->select_read = ev->select_set_read;
9621 ev->select_write = ev->select_set_write;
9622 ev->select_error = ev->select_set_error;
9625 return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
9628 static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
9632 if (FD_ISSET(ndx, &(ev->select_read))) {
9633 revents |= FDEVENT_IN;
9636 if (FD_ISSET(ndx, &(ev->select_error))) {
9637 revents |= FDEVENT_ERR;
9646 static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
9650 i = (ndx < 0) ? 0 : ndx + 1;
9653 for (; i < ev->select_max_fd + 1; i++) {
9654 if (FD_ISSET(i, &(ev->select_read))) break;
9655 if (FD_ISSET(i, &(ev->select_write))) break;
9656 if (FD_ISSET(i, &(ev->select_error))) break;
9663 @@ -108,17 +111,17 @@
9664 ev->type = FDEVENT_HANDLER_SELECT;
9666 ev->x = fdevent_select_##x;
9677 SET(event_next_fdndx);
9679 SET(event_get_revent);
9685 --- lighttpd-1.4.11/src/fdevent_solaris_devpoll.c 2005-09-01 10:45:26.000000000 +0300
9686 +++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c 2006-07-11 22:07:51.000000000 +0300
9688 #include <sys/types.h>
9690 -#include <unistd.h>
9696 static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9700 if (fde_ndx < 0) return -1;
9704 pfd.events = POLLREMOVE;
9708 if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9709 - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9710 - __FILE__, __LINE__,
9711 + fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9712 + __FILE__, __LINE__,
9713 fd, strerror(errno));
9723 static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9728 if (fde_ndx == -1) add = 1;
9732 pfd.events = events;
9736 if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9737 - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9738 - __FILE__, __LINE__,
9739 + fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9740 + __FILE__, __LINE__,
9741 fd, strerror(errno));
9751 static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
9752 struct dvpoll dopoll;
9756 dopoll.dp_timeout = timeout_ms;
9757 dopoll.dp_nfds = ev->maxfds;
9758 dopoll.dp_fds = ev->devpollfds;
9761 ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
9769 static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
9775 i = (last_ndx < 0) ? 0 : last_ndx + 1;
9781 @@ -117,20 +116,20 @@
9782 ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
9784 ev->x = fdevent_solaris_devpoll_##x;
9796 SET(event_next_fdndx);
9798 SET(event_get_revent);
9801 ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
9804 if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
9805 fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9806 __FILE__, __LINE__, strerror(errno));
9809 fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9810 __FILE__, __LINE__);
9816 --- lighttpd-1.4.11/src/http-header-glue.c 2006-02-08 15:31:36.000000000 +0200
9817 +++ lighttpd-1.4.12/src/http-header-glue.c 2006-07-11 22:07:53.000000000 +0300
9819 # ifdef HAVE_STRUCT_SOCKADDR_STORAGE
9820 static size_t get_sa_len(const struct sockaddr *addr) {
9821 switch (addr->sa_family) {
9826 return (sizeof (struct sockaddr_in));
9832 return (sizeof (struct sockaddr_in6));
9837 return (sizeof (struct sockaddr));
9842 # define SA_LEN(addr) (get_sa_len(addr))
9845 int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9851 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
9854 buffer_copy_string_len(ds->key, key, keylen);
9855 buffer_copy_string_len(ds->value, value, vallen);
9858 array_insert_unique(con->response.headers, (data_unset *)ds);
9864 int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9870 /* if there already is a key by this name overwrite the value */
9871 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
9872 buffer_copy_string(ds->value, value);
9879 return response_header_insert(srv, con, key, keylen, value, vallen);
9882 int http_response_redirect_to_directory(server *srv, connection *con) {
9889 if (con->conf.is_ssl) {
9890 buffer_copy_string(o, "https://");
9892 @@ -123,36 +123,36 @@
9895 socklen_t our_addr_len;
9898 our_addr_len = sizeof(our_addr);
9901 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
9902 con->http_status = 500;
9905 log_error_write(srv, __FILE__, __LINE__, "ss",
9906 "can't get sockname", strerror(errno));
9916 /* Lookup name: secondly try to get hostname for bind address */
9917 switch(our_addr.plain.sa_family) {
9920 - if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
9921 - SA_LEN((const struct sockaddr *)&our_addr.ipv6),
9922 + if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
9923 + SA_LEN((const struct sockaddr *)&our_addr.ipv6),
9924 hbuf, sizeof(hbuf), NULL, 0, 0)) {
9927 char dst[INET6_ADDRSTRLEN];
9930 log_error_write(srv, __FILE__, __LINE__,
9931 "SSSS", "NOTICE: getnameinfo failed: ",
9932 strerror(errno), ", using ip-address instead");
9934 - buffer_append_string(o,
9935 - inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
9937 + buffer_append_string(o,
9938 + inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
9941 buffer_append_string(o, hbuf);
9943 log_error_write(srv, __FILE__, __LINE__,
9944 "SdSS", "NOTICE: gethostbyaddr failed: ",
9945 h_errno, ", using ip-address instead");
9948 buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
9950 buffer_append_string(o, he->h_name);
9951 @@ -173,12 +173,12 @@
9953 log_error_write(srv, __FILE__, __LINE__,
9954 "S", "ERROR: unsupported address-type");
9961 - if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
9963 + if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
9964 (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
9965 buffer_append_string(o, ":");
9966 buffer_append_long(o, srv->srvconf.port);
9967 @@ -190,41 +190,41 @@
9968 buffer_append_string(o, "?");
9969 buffer_append_string_buffer(o, con->uri.query);
9973 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
9976 con->http_status = 301;
9977 con->file_finished = 1;
9986 buffer * strftime_cache_get(server *srv, time_t last_mod) {
9991 for (i = 0; i < FILE_CACHE_MAX; i++) {
9992 /* found cache-entry */
9993 if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;
9996 /* found empty slot */
9997 if (srv->mtime_cache[i].mtime == 0) break;
10001 if (i == FILE_CACHE_MAX) {
10006 srv->mtime_cache[i].mtime = last_mod;
10007 buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
10008 tm = gmtime(&(srv->mtime_cache[i].mtime));
10009 - srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
10010 + srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
10011 srv->mtime_cache[i].str->size - 1,
10012 "%a, %d %b %Y %H:%M:%S GMT", tm);
10013 srv->mtime_cache[i].str->used++;
10016 return srv->mtime_cache[i].str;
10019 @@ -239,56 +239,60 @@
10020 * request. That is, if no entity tags match, then the server MUST NOT
10021 * return a 304 (Not Modified) response.
10025 /* last-modified handling */
10026 if (con->request.http_if_none_match) {
10027 if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) {
10028 - if (con->request.http_method == HTTP_METHOD_GET ||
10029 + if (con->request.http_method == HTTP_METHOD_GET ||
10030 con->request.http_method == HTTP_METHOD_HEAD) {
10033 /* check if etag + last-modified */
10034 if (con->request.http_if_modified_since) {
10039 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
10040 used_len = strlen(con->request.http_if_modified_since);
10042 used_len = semicolon - con->request.http_if_modified_since;
10046 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
10047 con->http_status = 304;
10048 return HANDLER_FINISHED;
10050 +#ifdef HAVE_STRPTIME
10051 char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
10052 + time_t t_header, t_file;
10055 - /* convert to timestamp */
10056 - if (used_len < sizeof(buf)) {
10057 - time_t t_header, t_file;
10060 - strncpy(buf, con->request.http_if_modified_since, used_len);
10061 - buf[used_len] = '\0';
10063 - strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10064 - t_header = mktime(&tm);
10066 - strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10067 - t_file = mktime(&tm);
10069 - if (t_file > t_header) {
10070 - con->http_status = 304;
10071 - return HANDLER_FINISHED;
10074 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
10075 - "DEBUG: Last-Modified check failed as the received timestamp was too long:",
10076 + /* check if we can safely copy the string */
10077 + if (used_len >= sizeof(buf)) {
10078 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
10079 + "DEBUG: Last-Modified check failed as the received timestamp was too long:",
10080 con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
10083 con->http_status = 412;
10084 return HANDLER_FINISHED;
10088 + strncpy(buf, con->request.http_if_modified_since, used_len);
10089 + buf[used_len] = '\0';
10091 + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10092 + t_header = mktime(&tm);
10094 + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10095 + t_file = mktime(&tm);
10097 + if (t_file > t_header) return HANDLER_GO_ON;
10099 + con->http_status = 304;
10100 + return HANDLER_FINISHED;
10102 + return HANDLER_GO_ON;
10106 con->http_status = 304;
10107 @@ -302,16 +306,41 @@
10108 } else if (con->request.http_if_modified_since) {
10113 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
10114 used_len = strlen(con->request.http_if_modified_since);
10116 used_len = semicolon - con->request.http_if_modified_since;
10120 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
10121 con->http_status = 304;
10122 return HANDLER_FINISHED;
10124 +#ifdef HAVE_STRPTIME
10125 + char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
10126 + time_t t_header, t_file;
10129 + /* convert to timestamp */
10130 + if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
10132 + strncpy(buf, con->request.http_if_modified_since, used_len);
10133 + buf[used_len] = '\0';
10135 + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10136 + t_header = mktime(&tm);
10138 + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10139 + t_file = mktime(&tm);
10141 + if (t_file > t_header) return HANDLER_GO_ON;
10143 + con->http_status = 304;
10144 + return HANDLER_FINISHED;
10146 + return HANDLER_GO_ON;
10151 --- lighttpd-1.4.11/src/http_auth.c 2006-02-01 13:02:52.000000000 +0200
10152 +++ lighttpd-1.4.12/src/http_auth.c 2006-07-11 22:07:53.000000000 +0300
10154 #include <string.h>
10157 -#include <unistd.h>
10160 #include "server.h"
10161 @@ -31,23 +30,14 @@
10162 #include "http_auth_digest.h"
10163 #include "stream.h"
10165 +#include "sys-strings.h"
10168 # include <openssl/md5.h>
10175 -#include <security/pam_appl.h>
10176 -#include <security/pam_misc.h>
10178 -static struct pam_conv conv = {
10184 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
10186 static const char base64_pad = '=';
10187 @@ -75,25 +65,25 @@
10188 unsigned char *result;
10193 size_t in_len = strlen(in);
10196 buffer_prepare_copy(out, in_len);
10199 result = (unsigned char *)out->ptr;
10203 /* run through the whole string, converting as we go */
10204 for (i = 0; i < in_len; i++) {
10208 if (ch == '\0') break;
10211 if (ch == base64_pad) break;
10214 ch = base64_reverse_table[ch];
10215 if (ch < 0) continue;
10220 result[j] = ch << 2;
10221 @@ -125,168 +115,168 @@
10233 static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
10237 if (!username->used|| !realm->used) return -1;
10240 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10245 if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
10248 if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) {
10249 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno));
10259 while (f_line - f.start != f.size) {
10260 char *f_user, *f_pwd, *e, *f_realm;
10261 size_t u_len, pwd_len, r_len;
10271 - * user:realm:md5(user:realm:password)
10273 + * user:realm:md5(user:realm:password)
10277 if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10278 - log_error_write(srv, __FILE__, __LINE__, "sbs",
10279 - "parsed error in", p->conf.auth_htdigest_userfile,
10280 + log_error_write(srv, __FILE__, __LINE__, "sbs",
10281 + "parsed error in", p->conf.auth_htdigest_userfile,
10282 "expected 'username:realm:hashed password'");
10292 if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) {
10293 - log_error_write(srv, __FILE__, __LINE__, "sbs",
10294 - "parsed error in", p->conf.auth_plain_userfile,
10295 + log_error_write(srv, __FILE__, __LINE__, "sbs",
10296 + "parsed error in", p->conf.auth_plain_userfile,
10297 "expected 'username:realm:hashed password'");
10307 /* get pointers to the fields */
10308 - u_len = f_realm - f_user;
10309 + u_len = f_realm - f_user;
10311 r_len = f_pwd - f_realm;
10315 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10316 pwd_len = e - f_pwd;
10318 pwd_len = f.size - (f_pwd - f.start);
10322 if (username->used - 1 == u_len &&
10323 (realm->used - 1 == r_len) &&
10324 (0 == strncmp(username->ptr, f_user, u_len)) &&
10325 (0 == strncmp(realm->ptr, f_realm, r_len))) {
10329 buffer_copy_string_len(password, f_pwd, pwd_len);
10346 } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
10347 p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10353 auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
10356 if (buffer_is_empty(auth_fn)) return -1;
10359 if (0 != stream_open(&f, auth_fn)) {
10360 - log_error_write(srv, __FILE__, __LINE__, "sbss",
10361 + log_error_write(srv, __FILE__, __LINE__, "sbss",
10362 "opening plain-userfile", auth_fn, "failed:", strerror(errno));
10372 while (f_line - f.start != f.size) {
10373 char *f_user, *f_pwd, *e;
10374 size_t u_len, pwd_len;
10385 * user:crypted passwd
10389 if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10390 - log_error_write(srv, __FILE__, __LINE__, "sbs",
10391 - "parsed error in", auth_fn,
10392 + log_error_write(srv, __FILE__, __LINE__, "sbs",
10393 + "parsed error in", auth_fn,
10394 "expected 'username:hashed password'");
10404 /* get pointers to the fields */
10405 - u_len = f_pwd - f_user;
10406 + u_len = f_pwd - f_user;
10410 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10411 pwd_len = e - f_pwd;
10413 pwd_len = f.size - (f_pwd - f.start);
10417 if (username->used - 1 == u_len &&
10418 (0 == strncmp(username->ptr, f_user, u_len))) {
10422 buffer_copy_string_len(password, f_pwd, pwd_len);
10439 } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10449 @@ -296,7 +286,7 @@
10451 data_string *require;
10458 @@ -304,12 +294,12 @@
10459 /* search auth-directives for path */
10460 for (i = 0; i < p->conf.auth_require->used; i++) {
10461 if (p->conf.auth_require->data[i]->key->used == 0) continue;
10464 if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
10470 if (i == p->conf.auth_require->used) {
10473 @@ -317,72 +307,72 @@
10474 req = ((data_array *)(p->conf.auth_require->data[i]))->value;
10476 require = (data_string *)array_get_element(req, "require");
10479 /* if we get here, the user we got a authed user */
10480 if (0 == strcmp(require->value->ptr, "valid-user")) {
10485 /* user=name1|group=name3|host=name4 */
10488 /* seperate the string by | */
10490 log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
10495 username_len = username ? strlen(username) : 0;
10498 r = rules = require->value->ptr;
10503 const char *k, *v, *e;
10504 int k_len, v_len, r_len;
10507 e = strchr(r, '|');
10513 r_len = strlen(rules) - (r - rules);
10517 /* from r to r + r_len is a rule */
10520 if (0 == strncmp(r, "valid-user", r_len)) {
10521 - log_error_write(srv, __FILE__, __LINE__, "sb",
10522 + log_error_write(srv, __FILE__, __LINE__, "sb",
10523 "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules",
10529 /* search for = in the rules */
10530 if (NULL == (eq = strchr(r, '='))) {
10531 - log_error_write(srv, __FILE__, __LINE__, "sb",
10532 - "parsing the 'require' section in 'auth.require' failed: a = is missing",
10533 + log_error_write(srv, __FILE__, __LINE__, "sb",
10534 + "parsing the 'require' section in 'auth.require' failed: a = is missing",
10540 /* = out of range */
10541 if (eq > r + r_len) {
10542 - log_error_write(srv, __FILE__, __LINE__, "sb",
10543 + log_error_write(srv, __FILE__, __LINE__, "sb",
10544 "parsing the 'require' section in 'auth.require' failed: = out of range",
10552 /* the part before the = is user|group|host */
10558 v_len = r_len - k_len - 1;
10562 if (0 == strncmp(k, "user", k_len)) {
10565 username_len == v_len &&
10566 0 == strncmp(username, v, v_len)) {
10568 @@ -404,19 +394,19 @@
10569 log_error_write(srv, __FILE__, __LINE__, "s", "unknown key");
10579 log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
10590 * @param password password-string from the auth-backend
10591 * @param pw password-string from the client
10593 @@ -426,16 +416,16 @@
10596 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10601 - * user:realm:md5(user:realm:password)
10603 + * user:realm:md5(user:realm:password)
10613 MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1);
10614 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10615 @@ -443,24 +433,24 @@
10616 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10617 MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
10618 MD5_Final(HA1, &Md5Ctx);
10624 if (0 == strcmp(password->ptr, a1)) {
10627 - } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
10629 + } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
10633 size_t salt_len = 0;
10639 * user:crypted password
10645 * CRYPT_STD_DES 2-character (Default)
10646 * CRYPT_EXT_DES 9-character
10647 @@ -478,7 +468,7 @@
10649 } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
10650 char *dollar = NULL;
10653 if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
10654 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10656 @@ -495,7 +485,7 @@
10657 strncpy(salt, password->ptr, salt_len);
10659 salt[salt_len] = '\0';
10662 crypted = crypt(pw, salt);
10664 if (0 == strcmp(password->ptr, crypted)) {
10665 @@ -503,40 +493,13 @@
10667 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10671 - } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10674 + } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10675 if (0 == strcmp(password->ptr, pw)) {
10678 - } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) {
10680 - pam_handle_t *pamh=NULL;
10683 - retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
10685 - if (retval == PAM_SUCCESS)
10686 - retval = pam_authenticate(pamh, 0); /* is user really user? */
10688 - if (retval == PAM_SUCCESS)
10689 - retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
10691 - /* This is where we have been authorized or not. */
10693 - if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
10695 - log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
10698 - if (retval == PAM_SUCCESS) {
10699 - log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
10702 - log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
10705 - } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10706 + } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10709 LDAPMessage *lm, *first;
10710 @@ -544,45 +507,45 @@
10712 char *attrs[] = { LDAP_NO_ATTRS, NULL };
10716 /* for now we stay synchronous */
10721 * 1. connect anonymously (done in plugin init)
10722 * 2. get DN for uid = username
10723 * 3. auth against ldap server
10724 * 4. (optional) check a field
10734 * we have to protect us againt username which modifies out filter in
10739 for (i = 0; i < username->used - 1; i++) {
10740 char c = username->ptr[i];
10746 - log_error_write(srv, __FILE__, __LINE__, "sbd",
10748 + log_error_write(srv, __FILE__, __LINE__, "sbd",
10749 "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
10762 buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
10763 buffer_append_string_buffer(p->ldap_filter, username);
10764 buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post);
10770 if (p->conf.ldap == NULL ||
10771 LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
10772 @@ -590,71 +553,71 @@
10774 if (LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
10776 - log_error_write(srv, __FILE__, __LINE__, "sssb",
10777 + log_error_write(srv, __FILE__, __LINE__, "sssb",
10778 "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
10786 if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
10787 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10797 if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
10798 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10814 if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) {
10815 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
10820 ret = LDAP_VERSION3;
10821 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
10822 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10825 ldap_unbind_s(ldap);
10832 if (p->conf.auth_ldap_starttls == 1) {
10833 if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL, NULL))) {
10834 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
10837 ldap_unbind_s(ldap);
10846 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
10847 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10850 ldap_unbind_s(ldap);
10858 ldap_unbind_s(ldap);
10861 /* everything worked, good, access granted */
10867 @@ -664,65 +627,65 @@
10868 int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
10869 buffer *username, *password;
10873 data_string *realm;
10876 realm = (data_string *)array_get_element(req, "realm");
10879 username = buffer_init();
10880 password = buffer_init();
10883 base64_decode(username, realm_str);
10886 /* r2 == user:password */
10887 if (NULL == (pw = strchr(username->ptr, ':'))) {
10888 buffer_free(username);
10891 log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
10901 username->used = pw - username->ptr;
10904 /* copy password to r1 */
10905 if (http_auth_get_password(srv, p, username, realm->value, password)) {
10906 buffer_free(username);
10907 buffer_free(password);
10910 log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed");
10917 /* password doesn't match */
10918 if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
10919 log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
10922 buffer_free(username);
10923 buffer_free(password);
10930 /* value is our allow-rules */
10931 if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
10932 buffer_free(username);
10933 buffer_free(password);
10936 log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
10943 /* remember the username */
10944 buffer_copy_string_buffer(p->auth_user, username);
10947 buffer_free(username);
10948 buffer_free(password);
10954 @@ -735,7 +698,7 @@
10955 int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
10963 @@ -745,18 +708,18 @@
10970 const char *m = NULL;
10972 buffer *password, *b, *username_buf, *realm_buf;
10983 /* init pointers */
10985 @@ -771,11 +734,11 @@
10988 { S("response=") },
10996 dkv[0].ptr = &username;
10997 dkv[1].ptr = &realm;
10998 dkv[2].ptr = &nonce;
10999 @@ -786,24 +749,24 @@
11001 dkv[8].ptr = &respons;
11008 for (i = 0; dkv[i].key; i++) {
11009 *(dkv[i].ptr) = NULL;
11015 if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST &&
11016 p->conf.auth_backend != AUTH_BACKEND_PLAIN) {
11017 - log_error_write(srv, __FILE__, __LINE__, "s",
11018 + log_error_write(srv, __FILE__, __LINE__, "s",
11019 "digest: unsupported backend (only htdigest or plain)");
11026 b = buffer_init_string(realm_str);
11029 /* parse credentials from client */
11030 for (c = b->ptr; *c; c++) {
11031 /* skip whitespaces */
11032 @@ -812,18 +775,18 @@
11034 for (i = 0; dkv[i].key; i++) {
11035 if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) {
11036 - if ((c[dkv[i].key_len] == '"') &&
11037 + if ((c[dkv[i].key_len] == '"') &&
11038 (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) {
11039 /* value with "..." */
11040 *(dkv[i].ptr) = c + dkv[i].key_len + 1;
11045 } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) {
11046 /* value without "...", terminated by ',' */
11047 *(dkv[i].ptr) = c + dkv[i].key_len;
11053 /* value without "...", terminated by EOL */
11054 @@ -833,7 +796,7 @@
11060 if (p->conf.auth_debug > 1) {
11061 log_error_write(srv, __FILE__, __LINE__, "ss", "username", username);
11062 log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm);
11063 @@ -845,22 +808,22 @@
11064 log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc);
11065 log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons);
11069 /* check if everything is transmitted */
11075 (qop && (!nc || !cnonce)) ||
11077 /* missing field */
11079 - log_error_write(srv, __FILE__, __LINE__, "s",
11081 + log_error_write(srv, __FILE__, __LINE__, "s",
11082 "digest: missing field");
11086 - m = get_http_method_name(con->request.http_method);
11087 + m = get_http_method_name(con->request.http_method);
11089 /* password-string == HA1 */
11090 password = buffer_init();
11091 @@ -873,10 +836,10 @@
11092 buffer_free(realm_buf);
11097 buffer_free(username_buf);
11098 buffer_free(realm_buf);
11101 if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
11102 /* generate password from plain-text */
11104 @@ -890,16 +853,16 @@
11106 /* transform the 32-byte-hex-md5 to a 16-byte-md5 */
11107 for (i = 0; i < HASHLEN; i++) {
11108 - HA1[i] = hex2int(password->ptr[i*2]) << 4;
11109 - HA1[i] |= hex2int(password->ptr[i*2+1]);
11110 + HA1[i] = hex2int(password->ptr[i*2]) << 4;
11111 + HA1[i] |= hex2int(password->ptr[i*2+1]);
11114 /* we already check that above */
11119 buffer_free(password);
11123 strcasecmp(algorithm, "md5-sess") == 0) {
11125 @@ -910,9 +873,9 @@
11126 MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
11127 MD5_Final(HA1, &Md5Ctx);
11134 /* calculate H(A2) */
11136 MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
11137 @@ -924,7 +887,7 @@
11139 MD5_Final(HA2, &Md5Ctx);
11140 CvtHex(HA2, HA2Hex);
11143 /* calculate response */
11145 MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN);
11146 @@ -942,39 +905,39 @@
11147 MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN);
11148 MD5_Final(RespHash, &Md5Ctx);
11149 CvtHex(RespHash, a2);
11152 if (0 != strcmp(a2, respons)) {
11153 /* digest not ok */
11156 if (p->conf.auth_debug) {
11157 - log_error_write(srv, __FILE__, __LINE__, "sss",
11158 + log_error_write(srv, __FILE__, __LINE__, "sss",
11159 "digest: digest mismatch", a2, respons);
11162 - log_error_write(srv, __FILE__, __LINE__, "sss",
11164 + log_error_write(srv, __FILE__, __LINE__, "sss",
11165 "digest: auth failed for", username, "wrong password");
11173 /* value is our allow-rules */
11174 if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
11177 - log_error_write(srv, __FILE__, __LINE__, "s",
11179 + log_error_write(srv, __FILE__, __LINE__, "s",
11180 "digest: rules did match");
11187 /* remember the username */
11188 buffer_copy_string(p->auth_user, username);
11194 if (p->conf.auth_debug) {
11195 - log_error_write(srv, __FILE__, __LINE__, "s",
11196 + log_error_write(srv, __FILE__, __LINE__, "s",
11197 "digest: auth ok");
11200 @@ -985,23 +948,23 @@
11208 /* generate shared-secret */
11210 MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
11211 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
11214 /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
11215 ltostr(hh, srv->cur_ts);
11216 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
11217 ltostr(hh, rand());
11218 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
11221 MD5_Final(h, &Md5Ctx);
11229 --- lighttpd-1.4.11/src/http_auth.h 2005-08-14 17:12:31.000000000 +0300
11230 +++ lighttpd-1.4.12/src/http_auth.h 2006-07-11 22:07:53.000000000 +0300
11235 -typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN,
11236 - AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD,
11237 - AUTH_BACKEND_HTDIGEST, AUTH_BACKEND_PAM } auth_backend_t;
11239 + AUTH_BACKEND_UNSET,
11240 + AUTH_BACKEND_PLAIN,
11241 + AUTH_BACKEND_LDAP,
11242 + AUTH_BACKEND_HTPASSWD,
11243 + AUTH_BACKEND_HTDIGEST
11248 array *auth_require;
11251 buffer *auth_plain_groupfile;
11252 buffer *auth_plain_userfile;
11255 buffer *auth_htdigest_userfile;
11256 buffer *auth_htpasswd_userfile;
11259 buffer *auth_backend_conf;
11262 buffer *auth_ldap_hostname;
11263 buffer *auth_ldap_basedn;
11264 buffer *auth_ldap_binddn;
11265 @@ -32,15 +36,15 @@
11266 buffer *auth_ldap_filter;
11267 buffer *auth_ldap_cafile;
11268 unsigned short auth_ldap_starttls;
11271 unsigned short auth_debug;
11275 auth_backend_t auth_backend;
11282 buffer *ldap_filter_pre;
11283 buffer *ldap_filter_post;
11285 @@ -49,15 +53,15 @@
11294 buffer *ldap_filter;
11298 mod_auth_plugin_config **config_storage;
11301 mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
11302 } mod_auth_plugin_data;
11304 --- lighttpd-1.4.11/src/http_auth_digest.h 2006-01-05 00:54:01.000000000 +0200
11305 +++ lighttpd-1.4.12/src/http_auth_digest.h 2006-07-11 22:07:53.000000000 +0300
11315 --- lighttpd-1.4.11/src/http_chunk.c 2005-08-11 01:26:50.000000000 +0300
11316 +++ lighttpd-1.4.12/src/http_chunk.c 2006-07-11 22:07:53.000000000 +0300
11319 * the HTTP chunk-API
11326 #include <sys/types.h>
11329 #include <stdlib.h>
11331 -#include <unistd.h>
11335 @@ -23,19 +22,19 @@
11336 static int http_chunk_append_len(server *srv, connection *con, size_t len) {
11337 size_t i, olen = len, j;
11341 b = srv->tmp_chunk_len;
11345 buffer_copy_string(b, "0");
11347 for (i = 0; i < 8 && len; i++) {
11352 /* i is the number of hex digits we have */
11353 buffer_prepare_copy(b, i + 1);
11356 for (j = i-1, len = olen; j+1 > 0; j--) {
11357 b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
11359 @@ -43,61 +42,61 @@
11361 b->ptr[b->used++] = '\0';
11365 buffer_append_string(b, "\r\n");
11366 chunkqueue_append_buffer(con->write_queue, b);
11373 int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
11377 if (!con) return -1;
11380 cq = con->write_queue;
11383 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11384 http_chunk_append_len(srv, con, len);
11388 chunkqueue_append_file(cq, fn, offset, len);
11391 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
11392 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11399 int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
11403 if (!con) return -1;
11406 cq = con->write_queue;
11409 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11410 http_chunk_append_len(srv, con, mem->used - 1);
11414 chunkqueue_append_buffer(cq, mem);
11417 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
11418 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11425 int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
11429 if (!con) return -1;
11432 cq = con->write_queue;
11436 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11437 http_chunk_append_len(srv, con, 0);
11438 @@ -107,17 +106,17 @@
11444 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11445 http_chunk_append_len(srv, con, len - 1);
11449 chunkqueue_append_mem(cq, mem, len);
11452 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11453 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11460 @@ -125,9 +124,9 @@
11461 off_t http_chunkqueue_length(server *srv, connection *con) {
11463 log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
11470 return chunkqueue_length(con->write_queue);
11472 --- lighttpd-1.4.11/src/http_resp.c 1970-01-01 03:00:00.000000000 +0300
11473 +++ lighttpd-1.4.12/src/http_resp.c 2006-07-11 22:07:53.000000000 +0300
11475 +#include <string.h>
11476 +#include <stdlib.h>
11477 +#include <stdio.h>
11478 +#include <assert.h>
11480 +#include "http_resp.h"
11481 +#include "http_resp_parser.h"
11483 +/* declare prototypes for the parser */
11484 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t));
11485 +void http_resp_parserFree(void *p, void (*freeProc)(void*));
11486 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt);
11487 +void http_resp_parser(void *, int, buffer *, http_resp_ctx_t *);
11492 + chunk *c; /* current chunk in the chunkqueue */
11493 + size_t offset; /* current offset in current chunk */
11496 + size_t lookup_offset;
11499 + int is_statusline;
11500 +} http_resp_tokenizer_t;
11502 +http_resp *http_response_init(void) {
11503 + http_resp *resp = calloc(1, sizeof(*resp));
11505 + resp->reason = buffer_init();
11506 + resp->headers = array_init();
11511 +void http_response_reset(http_resp *resp) {
11512 + if (!resp) return;
11514 + buffer_reset(resp->reason);
11515 + array_reset(resp->headers);
11519 +void http_response_free(http_resp *resp) {
11520 + if (!resp) return;
11522 + buffer_free(resp->reason);
11523 + array_free(resp->headers);
11528 +static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11529 + if (t->offset == t->c->mem->used - 1) {
11530 + /* end of chunk, open next chunk */
11532 + if (!t->c->next) return -1;
11534 + t->c = t->c->next;
11538 + *c = t->c->mem->ptr[t->offset++];
11540 + t->lookup_offset = t->offset;
11541 + t->lookup_c = t->c;
11543 + //fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
11548 +static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11549 + if (t->lookup_offset == t->lookup_c->mem->used - 1) {
11550 + /* end of chunk, open next chunk */
11552 + if (!t->lookup_c->next) return -1;
11554 + t->lookup_c = t->lookup_c->next;
11555 + t->lookup_offset = 0;
11558 + *c = t->lookup_c->mem->ptr[t->lookup_offset++];
11560 + //fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
11567 +static int http_resp_tokenizer(
11568 + http_resp_tokenizer_t *t,
11575 + /* push the token to the parser */
11577 + while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
11591 + if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11596 + t->c = t->lookup_c;
11597 + t->offset = t->lookup_offset;
11599 + t->is_statusline = 0;
11602 + fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__);
11609 + t->is_statusline = 0;
11614 + while (c >= 32 && c != 127 && c != 255) {
11615 + if (t->is_statusline) {
11616 + if (c == ':') {t->is_statusline = 0; break; } /* this is not a status line by a real header */
11617 + if (c == 32) break; /* the space is a splitter in the statusline */
11620 + if (c == ':') break; /* the : is the splitter between key and value */
11623 + if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11626 + if (t->c == t->lookup_c &&
11627 + t->offset == t->lookup_offset + 1) {
11629 + fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__);
11635 + /* the lookup points to the first invalid char */
11636 + t->lookup_offset--;
11638 + /* no overlapping string */
11639 + if (t->c == t->lookup_c) {
11640 + buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
11642 + /* first chunk */
11643 + buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
11645 + /* chunks in the middle */
11646 + for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
11647 + buffer_append_string_buffer(token, t->c->mem);
11648 + t->offset = t->c->mem->used - 1;
11652 + buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
11655 + t->offset = t->lookup_offset;
11670 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
11671 + http_resp_tokenizer_t t;
11672 + void *pParser = NULL;
11673 + int token_id = 0;
11674 + buffer *token = NULL;
11675 + http_resp_ctx_t context;
11676 + parse_status_t ret = PARSE_UNSET;
11677 + int last_token_id = 0;
11681 + t.offset = t.c->offset;
11683 + t.is_statusline = 1;
11686 + context.errmsg = buffer_init();
11687 + context.resp = resp;
11689 + pParser = http_resp_parserAlloc( malloc );
11690 + token = buffer_init();
11691 + /* http_resp_parserTrace(stderr, "http-response: "); */
11693 + while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) {
11694 + http_resp_parser(pParser, token_id, token, &context);
11696 + token = buffer_init();
11698 + if (last_token_id == TK_CRLF &&
11699 + token_id == TK_CRLF) break;
11701 + last_token_id = token_id;
11704 + /* oops, the parser failed */
11705 + if (context.ok == 0) {
11706 + ret = PARSE_ERROR;
11708 + fprintf(stderr, "%s.%d: parsing failed at: ...%20s\r\n",
11709 + __FILE__, __LINE__, t.c->mem->ptr + t.offset);
11712 + http_resp_parser(pParser, 0, token, &context);
11713 + http_resp_parserFree(pParser, free );
11715 + if (context.ok == 0) {
11716 + /* we are missing the some tokens */
11718 + if (ret == PARSE_UNSET) ret = PARSE_NEED_MORE;
11722 + for (c = cq->first; c != t.c; c = c->next) {
11723 + c->offset = c->mem->used - 1;
11726 + c->offset = t.offset;
11728 + ret = PARSE_SUCCESS;
11731 + buffer_free(token);
11736 --- lighttpd-1.4.11/src/http_resp.h 1970-01-01 03:00:00.000000000 +0300
11737 +++ lighttpd-1.4.12/src/http_resp.h 2006-07-11 22:07:53.000000000 +0300
11739 +#ifndef _HTTP_RESP_H_
11740 +#define _HTTP_RESP_H_
11742 +#include "array.h"
11743 +#include "chunk.h"
11753 + int protocol; /* http/1.0, http/1.1 */
11754 + int status; /* e.g. 200 */
11755 + buffer *reason; /* e.g. Ok */
11764 +} http_resp_ctx_t;
11766 +http_resp *http_response_init(void);
11767 +void http_response_free(http_resp *resp);
11768 +void http_response_reset(http_resp *resp);
11770 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
11773 --- lighttpd-1.4.11/src/http_resp_parser.c 1970-01-01 03:00:00.000000000 +0300
11774 +++ lighttpd-1.4.12/src/http_resp_parser.c 2006-07-11 22:08:02.000000000 +0300
11776 +/* Driver template for the LEMON parser generator.
11777 +** The author disclaims copyright to this source code.
11779 +/* First off, code is include which follows the "include" declaration
11780 +** in the input file. */
11781 +#include <stdio.h>
11782 +#line 6 "./http_resp_parser.y"
11784 +#include <assert.h>
11785 +#include <string.h>
11786 +#include "http_resp.h"
11787 +#include "keyvalue.h"
11788 +#include "array.h"
11790 +#line 16 "http_resp_parser.c"
11791 +/* Next is all token values, in a form suitable for use by makeheaders.
11792 +** This section will be null unless lemon is run with the -m switch.
11795 +** These constants (all generated automatically by the parser generator)
11796 +** specify the various kinds of tokens (terminals) that the parser
11799 +** Each symbol here is a terminal symbol in the grammar.
11801 +/* Make sure the INTERFACE macro is defined.
11804 +# define INTERFACE 1
11806 +/* The next thing included is series of defines which control
11807 +** various aspects of the generated parser.
11808 +** YYCODETYPE is the data type used for storing terminal
11809 +** and nonterminal numbers. "unsigned char" is
11810 +** used if there are fewer than 250 terminals
11811 +** and nonterminals. "int" is used otherwise.
11812 +** YYNOCODE is a number of type YYCODETYPE which corresponds
11813 +** to no legal terminal or nonterminal number. This
11814 +** number is used to fill in empty slots of the hash
11816 +** YYFALLBACK If defined, this indicates that one or more tokens
11817 +** have fall-back values which should be used if the
11818 +** original value of the token will not parse.
11819 +** YYACTIONTYPE is the data type used for storing terminal
11820 +** and nonterminal numbers. "unsigned char" is
11821 +** used if there are fewer than 250 rules and
11822 +** states combined. "int" is used otherwise.
11823 +** http_resp_parserTOKENTYPE is the data type used for minor tokens given
11824 +** directly to the parser from the tokenizer.
11825 +** YYMINORTYPE is the data type used for all minor tokens.
11826 +** This is typically a union of many types, one of
11827 +** which is http_resp_parserTOKENTYPE. The entry in the union
11828 +** for base tokens is called "yy0".
11829 +** YYSTACKDEPTH is the maximum depth of the parser's stack.
11830 +** http_resp_parserARG_SDECL A static variable declaration for the %extra_argument
11831 +** http_resp_parserARG_PDECL A parameter declaration for the %extra_argument
11832 +** http_resp_parserARG_STORE Code to store %extra_argument into yypParser
11833 +** http_resp_parserARG_FETCH Code to extract %extra_argument from yypParser
11834 +** YYNSTATE the combined number of states.
11835 +** YYNRULE the number of rules in the grammar
11836 +** YYERRORSYMBOL is the code number of the error symbol. If not
11837 +** defined, then do no error processing.
11840 +#define YYCODETYPE unsigned char
11841 +#define YYNOCODE 12
11842 +#define YYACTIONTYPE unsigned char
11843 +#define http_resp_parserTOKENTYPE buffer *
11845 + http_resp_parserTOKENTYPE yy0;
11847 + data_string * yy9;
11852 +#define YYSTACKDEPTH 100
11853 +#define http_resp_parserARG_SDECL http_resp_ctx_t *ctx;
11854 +#define http_resp_parserARG_PDECL ,http_resp_ctx_t *ctx
11855 +#define http_resp_parserARG_FETCH http_resp_ctx_t *ctx = yypParser->ctx
11856 +#define http_resp_parserARG_STORE yypParser->ctx = ctx
11857 +#define YYNSTATE 19
11859 +#define YYERRORSYMBOL 4
11860 +#define YYERRSYMDT yy23
11861 +#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
11862 +#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
11863 +#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
11865 +/* Next are that tables used to determine what action to take based on the
11866 +** current state and lookahead token. These tables are used to implement
11867 +** functions that take a state number and lookahead value and return an
11868 +** action integer.
11870 +** Suppose the action integer is N. Then the action is determined as
11873 +** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
11874 +** token onto the stack and goto state N.
11876 +** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
11878 +** N == YYNSTATE+YYNRULE A syntax error has occurred.
11880 +** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
11882 +** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
11883 +** slots in the yy_action[] table.
11885 +** The action table is constructed as a single large table named yy_action[].
11886 +** Given state S and lookahead X, the action is computed as
11888 +** yy_action[ yy_shift_ofst[S] + X ]
11890 +** If the index value yy_shift_ofst[S]+X is out of range or if the value
11891 +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
11892 +** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
11893 +** and that yy_default[S] should be used instead.
11895 +** The formula above is for computing the action when the lookahead is
11896 +** a terminal symbol. If the lookahead is a non-terminal (as occurs after
11897 +** a reduce action) then the yy_reduce_ofst[] array is used in place of
11898 +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
11899 +** YY_SHIFT_USE_DFLT.
11901 +** The following are the tables generated in this section:
11903 +** yy_action[] A single table containing all actions.
11904 +** yy_lookahead[] A table containing the lookahead for each entry in
11905 +** yy_action. Used to detect hash collisions.
11906 +** yy_shift_ofst[] For each state, the offset into yy_action for
11907 +** shifting terminals.
11908 +** yy_reduce_ofst[] For each state, the offset into yy_action for
11909 +** shifting non-terminals after a reduce.
11910 +** yy_default[] Default action for each state.
11912 +static YYACTIONTYPE yy_action[] = {
11913 + /* 0 */ 8, 29, 18, 1, 14, 2, 4, 11, 15, 12,
11914 + /* 10 */ 14, 13, 4, 21, 5, 19, 3, 5, 6, 7,
11915 + /* 20 */ 9, 17, 16, 4, 20, 22, 22, 10,
11917 +static YYCODETYPE yy_lookahead[] = {
11918 + /* 0 */ 5, 6, 2, 8, 9, 1, 2, 1, 2, 8,
11919 + /* 10 */ 9, 1, 2, 2, 3, 0, 9, 3, 2, 1,
11920 + /* 20 */ 7, 2, 2, 2, 0, 2, 11, 10,
11922 +#define YY_SHIFT_USE_DFLT (-1)
11923 +static signed char yy_shift_ofst[] = {
11924 + /* 0 */ 0, 4, 15, -1, 14, 16, 18, -1, 19, 20,
11925 + /* 10 */ 6, 21, 10, 24, -1, -1, -1, 23, 11,
11927 +#define YY_REDUCE_USE_DFLT (-6)
11928 +static signed char yy_reduce_ofst[] = {
11929 + /* 0 */ -5, 7, -6, -6, -6, -6, -6, -6, 13, 17,
11930 + /* 10 */ -6, 1, 7, -6, -6, -6, -6, -6, -6,
11932 +static YYACTIONTYPE yy_default[] = {
11933 + /* 0 */ 28, 28, 28, 25, 28, 28, 28, 27, 28, 28,
11934 + /* 10 */ 28, 28, 28, 28, 26, 24, 23, 28, 28,
11936 +#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
11938 +/* The next table maps tokens into fallback tokens. If a construct
11939 +** like the following:
11941 +** %fallback ID X Y Z.
11943 +** appears in the grammer, then ID becomes a fallback token for X, Y,
11944 +** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
11945 +** but it does not parse, the type of the token is changed to ID and
11946 +** the parse is retried before an error is thrown.
11949 +static const YYCODETYPE yyFallback[] = {
11951 +#endif /* YYFALLBACK */
11953 +/* The following structure represents a single element of the
11954 +** parser's stack. Information stored includes:
11956 +** + The state number for the parser at this level of the stack.
11958 +** + The value of the token stored at this level of the stack.
11959 +** (In other words, the "major" token.)
11961 +** + The semantic value stored at this level of the stack. This is
11962 +** the information used by the action routines in the grammar.
11963 +** It is sometimes called the "minor" token.
11965 +struct yyStackEntry {
11966 + int stateno; /* The state-number */
11967 + int major; /* The major token value. This is the code
11968 + ** number for the token at this stack level */
11969 + YYMINORTYPE minor; /* The user-supplied minor token value. This
11970 + ** is the value of the token */
11972 +typedef struct yyStackEntry yyStackEntry;
11974 +/* The state of the parser is completely contained in an instance of
11975 +** the following structure */
11977 + int yyidx; /* Index of top element in stack */
11978 + int yyerrcnt; /* Shifts left before out of the error */
11979 + http_resp_parserARG_SDECL /* A place to hold %extra_argument */
11980 + yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
11982 +typedef struct yyParser yyParser;
11985 +#include <stdio.h>
11986 +static FILE *yyTraceFILE = 0;
11987 +static char *yyTracePrompt = 0;
11988 +#endif /* NDEBUG */
11992 +** Turn parser tracing on by giving a stream to which to write the trace
11993 +** and a prompt to preface each trace message. Tracing is turned off
11994 +** by making either argument NULL
11998 +** <li> A FILE* to which trace output should be written.
11999 +** If NULL, then tracing is turned off.
12000 +** <li> A prefix string written at the beginning of every
12001 +** line of trace output. If NULL, then tracing is
12008 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt){
12009 + yyTraceFILE = TraceFILE;
12010 + yyTracePrompt = zTracePrompt;
12011 + if( yyTraceFILE==0 ) yyTracePrompt = 0;
12012 + else if( yyTracePrompt==0 ) yyTraceFILE = 0;
12014 +#endif /* NDEBUG */
12017 +/* For tracing shifts, the names of all terminals and nonterminals
12018 +** are required. The following table supplies these names */
12019 +static const char *yyTokenName[] = {
12020 + "$", "CRLF", "STRING", "COLON",
12021 + "error", "protocol", "response_hdr", "number",
12022 + "headers", "header", "reason",
12024 +#endif /* NDEBUG */
12027 +/* For tracing reduce actions, the names of all rules are required.
12029 +static const char *yyRuleName[] = {
12030 + /* 0 */ "response_hdr ::= headers CRLF",
12031 + /* 1 */ "response_hdr ::= protocol number reason CRLF headers CRLF",
12032 + /* 2 */ "protocol ::= STRING",
12033 + /* 3 */ "number ::= STRING",
12034 + /* 4 */ "reason ::= STRING",
12035 + /* 5 */ "reason ::= reason STRING",
12036 + /* 6 */ "headers ::= headers header",
12037 + /* 7 */ "headers ::= header",
12038 + /* 8 */ "header ::= STRING COLON STRING CRLF",
12040 +#endif /* NDEBUG */
12043 +** This function returns the symbolic name associated with a token
12046 +const char *http_resp_parserTokenName(int tokenType){
12048 + if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
12049 + return yyTokenName[tokenType];
12051 + return "Unknown";
12059 +** This function allocates a new parser.
12060 +** The only argument is a pointer to a function which works like
12064 +** A pointer to the function used to allocate memory.
12067 +** A pointer to a parser. This pointer is used in subsequent calls
12068 +** to http_resp_parser and http_resp_parserFree.
12070 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t)){
12071 + yyParser *pParser;
12072 + pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
12074 + pParser->yyidx = -1;
12079 +/* The following function deletes the value associated with a
12080 +** symbol. The symbol can be either a terminal or nonterminal.
12081 +** "yymajor" is the symbol code, and "yypminor" is a pointer to
12084 +static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
12085 + switch( yymajor ){
12086 + /* Here is inserted the actions which take place when a
12087 + ** terminal or non-terminal is destroyed. This can happen
12088 + ** when the symbol is popped from the stack during a
12089 + ** reduce or during error processing or when a parser is
12090 + ** being destroyed before it is finished parsing.
12092 + ** Note: during a reduce, the only symbols destroyed are those
12093 + ** which appear on the RHS of the rule, but which are not used
12094 + ** inside the C code.
12099 +#line 23 "./http_resp_parser.y"
12100 +{ buffer_free((yypminor->yy0)); }
12101 +#line 326 "http_resp_parser.c"
12103 + default: break; /* If no destructor action specified: do nothing */
12108 +** Pop the parser's stack once.
12110 +** If there is a destructor routine associated with the token which
12111 +** is popped from the stack, then call it.
12113 +** Return the major token number for the symbol popped.
12115 +static int yy_pop_parser_stack(yyParser *pParser){
12116 + YYCODETYPE yymajor;
12117 + yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
12119 + if( pParser->yyidx<0 ) return 0;
12121 + if( yyTraceFILE && pParser->yyidx>=0 ){
12122 + fprintf(yyTraceFILE,"%sPopping %s\n",
12124 + yyTokenName[yytos->major]);
12127 + yymajor = yytos->major;
12128 + yy_destructor( yymajor, &yytos->minor);
12129 + pParser->yyidx--;
12134 +** Deallocate and destroy a parser. Destructors are all called for
12135 +** all stack elements before shutting the parser down.
12139 +** <li> A pointer to the parser. This should be a pointer
12140 +** obtained from http_resp_parserAlloc.
12141 +** <li> A pointer to a function used to reclaim memory obtained
12145 +void http_resp_parserFree(
12146 + void *p, /* The parser to be deleted */
12147 + void (*freeProc)(void*) /* Function used to reclaim memory */
12149 + yyParser *pParser = (yyParser*)p;
12150 + if( pParser==0 ) return;
12151 + while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
12152 + (*freeProc)((void*)pParser);
12156 +** Find the appropriate action for a parser given the terminal
12157 +** look-ahead token iLookAhead.
12159 +** If the look-ahead token is YYNOCODE, then check to see if the action is
12160 +** independent of the look-ahead. If it is, return the action, otherwise
12161 +** return YY_NO_ACTION.
12163 +static int yy_find_shift_action(
12164 + yyParser *pParser, /* The parser */
12165 + int iLookAhead /* The look-ahead token */
12168 + int stateno = pParser->yystack[pParser->yyidx].stateno;
12170 + /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
12171 + i = yy_shift_ofst[stateno];
12172 + if( i==YY_SHIFT_USE_DFLT ){
12173 + return yy_default[stateno];
12175 + if( iLookAhead==YYNOCODE ){
12176 + return YY_NO_ACTION;
12179 + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
12181 + int iFallback; /* Fallback token */
12182 + if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
12183 + && (iFallback = yyFallback[iLookAhead])!=0 ){
12185 + if( yyTraceFILE ){
12186 + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
12187 + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
12190 + return yy_find_shift_action(pParser, iFallback);
12193 + return yy_default[stateno];
12195 + return yy_action[i];
12200 +** Find the appropriate action for a parser given the non-terminal
12201 +** look-ahead token iLookAhead.
12203 +** If the look-ahead token is YYNOCODE, then check to see if the action is
12204 +** independent of the look-ahead. If it is, return the action, otherwise
12205 +** return YY_NO_ACTION.
12207 +static int yy_find_reduce_action(
12208 + yyParser *pParser, /* The parser */
12209 + int iLookAhead /* The look-ahead token */
12212 + int stateno = pParser->yystack[pParser->yyidx].stateno;
12214 + i = yy_reduce_ofst[stateno];
12215 + if( i==YY_REDUCE_USE_DFLT ){
12216 + return yy_default[stateno];
12218 + if( iLookAhead==YYNOCODE ){
12219 + return YY_NO_ACTION;
12222 + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
12223 + return yy_default[stateno];
12225 + return yy_action[i];
12230 +** Perform a shift action.
12232 +static void yy_shift(
12233 + yyParser *yypParser, /* The parser to be shifted */
12234 + int yyNewState, /* The new state to shift in */
12235 + int yyMajor, /* The major token to shift in */
12236 + YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */
12238 + yyStackEntry *yytos;
12239 + yypParser->yyidx++;
12240 + if( yypParser->yyidx>=YYSTACKDEPTH ){
12241 + http_resp_parserARG_FETCH;
12242 + yypParser->yyidx--;
12244 + if( yyTraceFILE ){
12245 + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
12248 + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12249 + /* Here code is inserted which will execute if the parser
12250 + ** stack every overflows */
12251 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument var */
12254 + yytos = &yypParser->yystack[yypParser->yyidx];
12255 + yytos->stateno = yyNewState;
12256 + yytos->major = yyMajor;
12257 + yytos->minor = *yypMinor;
12259 + if( yyTraceFILE && yypParser->yyidx>0 ){
12261 + fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
12262 + fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
12263 + for(i=1; i<=yypParser->yyidx; i++)
12264 + fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
12265 + fprintf(yyTraceFILE,"\n");
12270 +/* The following table contains information about every rule that
12271 +** is used during the reduce.
12274 + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
12275 + unsigned char nrhs; /* Number of right-hand side symbols in the rule */
12276 +} yyRuleInfo[] = {
12288 +static void yy_accept(yyParser*); /* Forward Declaration */
12291 +** Perform a reduce action and the shift that must immediately
12292 +** follow the reduce.
12294 +static void yy_reduce(
12295 + yyParser *yypParser, /* The parser */
12296 + int yyruleno /* Number of the rule by which to reduce */
12298 + int yygoto; /* The next state */
12299 + int yyact; /* The next action */
12300 + YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
12301 + yyStackEntry *yymsp; /* The top of the parser's stack */
12302 + int yysize; /* Amount to pop the stack */
12303 + http_resp_parserARG_FETCH;
12304 + yymsp = &yypParser->yystack[yypParser->yyidx];
12306 + if( yyTraceFILE && yyruleno>=0
12307 + && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
12308 + fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
12309 + yyRuleName[yyruleno]);
12311 +#endif /* NDEBUG */
12313 + switch( yyruleno ){
12314 + /* Beginning here are the reduction cases. A typical example
12317 + ** #line <lineno> <grammarfile>
12318 + ** { ... } // User supplied code
12319 + ** #line <lineno> <thisfile>
12323 +#line 26 "./http_resp_parser.y"
12325 + http_resp *resp = ctx->resp;
12328 + resp->protocol = HTTP_VERSION_UNSET;
12330 + buffer_copy_string(resp->reason, ""); /* no reason */
12331 + array_free(resp->headers);
12332 + resp->headers = yymsp[-1].minor.yy12;
12334 + if (NULL == (ds = (data_string *)array_get_element(yymsp[-1].minor.yy12, "Status"))) {
12335 + resp->status = 0;
12338 + resp->status = strtol(ds->value->ptr, &err, 10);
12340 + if (*err != '\0') {
12341 + buffer_copy_string(ctx->errmsg, "expected a number: ");
12342 + buffer_append_string_buffer(ctx->errmsg, ds->value);
12349 + yymsp[-1].minor.yy12 = NULL;
12351 +#line 576 "http_resp_parser.c"
12352 + yy_destructor(1,&yymsp[0].minor);
12355 +#line 54 "./http_resp_parser.y"
12357 + http_resp *resp = ctx->resp;
12359 + resp->status = yymsp[-4].minor.yy20;
12360 + resp->protocol = yymsp[-5].minor.yy20;
12361 + buffer_copy_string_buffer(resp->reason, yymsp[-3].minor.yy0);
12363 + array_free(resp->headers);
12365 + resp->headers = yymsp[-1].minor.yy12;
12367 + yymsp[-1].minor.yy12 = NULL;
12369 +#line 594 "http_resp_parser.c"
12370 + yy_destructor(1,&yymsp[-2].minor);
12371 + yy_destructor(1,&yymsp[0].minor);
12374 +#line 68 "./http_resp_parser.y"
12376 + if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.0"))) {
12377 + yygotominor.yy20 = HTTP_VERSION_1_0;
12378 + } else if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.1"))) {
12379 + yygotominor.yy20 = HTTP_VERSION_1_1;
12381 + buffer_copy_string(ctx->errmsg, "unknown protocol: ");
12382 + buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12387 +#line 612 "http_resp_parser.c"
12390 +#line 81 "./http_resp_parser.y"
12393 + yygotominor.yy20 = strtol(yymsp[0].minor.yy0->ptr, &err, 10);
12395 + if (*err != '\0') {
12396 + buffer_copy_string(ctx->errmsg, "expected a number: ");
12397 + buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12402 +#line 627 "http_resp_parser.c"
12405 +#line 93 "./http_resp_parser.y"
12407 + buffer_copy_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12409 +#line 634 "http_resp_parser.c"
12412 +#line 97 "./http_resp_parser.y"
12414 + yygotominor.yy0 = yymsp[-1].minor.yy0;
12416 + buffer_append_string(yygotominor.yy0, " ");
12417 + buffer_append_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12419 + yymsp[-1].minor.yy0 = NULL;
12421 +#line 646 "http_resp_parser.c"
12424 +#line 106 "./http_resp_parser.y"
12426 + yygotominor.yy12 = yymsp[-1].minor.yy12;
12428 + array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12430 + yymsp[-1].minor.yy12 = NULL;
12432 +#line 657 "http_resp_parser.c"
12435 +#line 114 "./http_resp_parser.y"
12437 + yygotominor.yy12 = array_init();
12439 + array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12441 +#line 666 "http_resp_parser.c"
12444 +#line 119 "./http_resp_parser.y"
12446 + yygotominor.yy9 = data_string_init();
12448 + buffer_copy_string_buffer(yygotominor.yy9->key, yymsp[-3].minor.yy0);
12449 + buffer_copy_string_buffer(yygotominor.yy9->value, yymsp[-1].minor.yy0);
12451 +#line 676 "http_resp_parser.c"
12452 + yy_destructor(3,&yymsp[-2].minor);
12453 + yy_destructor(1,&yymsp[0].minor);
12456 + yygoto = yyRuleInfo[yyruleno].lhs;
12457 + yysize = yyRuleInfo[yyruleno].nrhs;
12458 + yypParser->yyidx -= yysize;
12459 + yyact = yy_find_reduce_action(yypParser,yygoto);
12460 + if( yyact < YYNSTATE ){
12461 + yy_shift(yypParser,yyact,yygoto,&yygotominor);
12462 + }else if( yyact == YYNSTATE + YYNRULE + 1 ){
12463 + yy_accept(yypParser);
12468 +** The following code executes when the parse fails
12470 +static void yy_parse_failed(
12471 + yyParser *yypParser /* The parser */
12473 + http_resp_parserARG_FETCH;
12475 + if( yyTraceFILE ){
12476 + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
12479 + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12480 + /* Here code is inserted which will be executed whenever the
12481 + ** parser fails */
12482 +#line 14 "./http_resp_parser.y"
12486 +#line 711 "http_resp_parser.c"
12487 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12491 +** The following code executes when a syntax error first occurs.
12493 +static void yy_syntax_error(
12494 + yyParser *yypParser, /* The parser */
12495 + int yymajor, /* The major type of the error token */
12496 + YYMINORTYPE yyminor /* The minor type of the error token */
12498 + http_resp_parserARG_FETCH;
12499 +#define TOKEN (yyminor.yy0)
12500 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12504 +** The following is executed when the parser accepts
12506 +static void yy_accept(
12507 + yyParser *yypParser /* The parser */
12509 + http_resp_parserARG_FETCH;
12511 + if( yyTraceFILE ){
12512 + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
12515 + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12516 + /* Here code is inserted which will be executed whenever the
12517 + ** parser accepts */
12518 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12521 +/* The main parser program.
12522 +** The first argument is a pointer to a structure obtained from
12523 +** "http_resp_parserAlloc" which describes the current state of the parser.
12524 +** The second argument is the major token number. The third is
12525 +** the minor token. The fourth optional argument is whatever the
12526 +** user wants (and specified in the grammar) and is available for
12527 +** use by the action routines.
12531 +** <li> A pointer to the parser (an opaque structure.)
12532 +** <li> The major token number.
12533 +** <li> The minor token number.
12534 +** <li> An option argument of a grammar-specified type.
12540 +void http_resp_parser(
12541 + void *yyp, /* The parser */
12542 + int yymajor, /* The major token code number */
12543 + http_resp_parserTOKENTYPE yyminor /* The value for the token */
12544 + http_resp_parserARG_PDECL /* Optional %extra_argument parameter */
12546 + YYMINORTYPE yyminorunion;
12547 + int yyact; /* The parser action. */
12548 + int yyendofinput; /* True if we are at the end of input */
12549 + int yyerrorhit = 0; /* True if yymajor has invoked an error */
12550 + yyParser *yypParser; /* The parser */
12552 + /* (re)initialize the parser, if necessary */
12553 + yypParser = (yyParser*)yyp;
12554 + if( yypParser->yyidx<0 ){
12555 + if( yymajor==0 ) return;
12556 + yypParser->yyidx = 0;
12557 + yypParser->yyerrcnt = -1;
12558 + yypParser->yystack[0].stateno = 0;
12559 + yypParser->yystack[0].major = 0;
12561 + yyminorunion.yy0 = yyminor;
12562 + yyendofinput = (yymajor==0);
12563 + http_resp_parserARG_STORE;
12566 + if( yyTraceFILE ){
12567 + fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
12572 + yyact = yy_find_shift_action(yypParser,yymajor);
12573 + if( yyact<YYNSTATE ){
12574 + yy_shift(yypParser,yyact,yymajor,&yyminorunion);
12575 + yypParser->yyerrcnt--;
12576 + if( yyendofinput && yypParser->yyidx>=0 ){
12579 + yymajor = YYNOCODE;
12581 + }else if( yyact < YYNSTATE + YYNRULE ){
12582 + yy_reduce(yypParser,yyact-YYNSTATE);
12583 + }else if( yyact == YY_ERROR_ACTION ){
12586 + if( yyTraceFILE ){
12587 + fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
12590 +#ifdef YYERRORSYMBOL
12591 + /* A syntax error has occurred.
12592 + ** The response to an error depends upon whether or not the
12593 + ** grammar defines an error token "ERROR".
12595 + ** This is what we do if the grammar does define ERROR:
12597 + ** * Call the %syntax_error function.
12599 + ** * Begin popping the stack until we enter a state where
12600 + ** it is legal to shift the error symbol, then shift
12601 + ** the error symbol.
12603 + ** * Set the error count to three.
12605 + ** * Begin accepting and shifting new tokens. No new error
12606 + ** processing will occur until three tokens have been
12607 + ** shifted successfully.
12610 + if( yypParser->yyerrcnt<0 ){
12611 + yy_syntax_error(yypParser,yymajor,yyminorunion);
12613 + yymx = yypParser->yystack[yypParser->yyidx].major;
12614 + if( yymx==YYERRORSYMBOL || yyerrorhit ){
12616 + if( yyTraceFILE ){
12617 + fprintf(yyTraceFILE,"%sDiscard input token %s\n",
12618 + yyTracePrompt,yyTokenName[yymajor]);
12621 + yy_destructor(yymajor,&yyminorunion);
12622 + yymajor = YYNOCODE;
12625 + yypParser->yyidx >= 0 &&
12626 + yymx != YYERRORSYMBOL &&
12627 + (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
12629 + yy_pop_parser_stack(yypParser);
12631 + if( yypParser->yyidx < 0 || yymajor==0 ){
12632 + yy_destructor(yymajor,&yyminorunion);
12633 + yy_parse_failed(yypParser);
12634 + yymajor = YYNOCODE;
12635 + }else if( yymx!=YYERRORSYMBOL ){
12637 + u2.YYERRSYMDT = 0;
12638 + yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
12641 + yypParser->yyerrcnt = 3;
12643 +#else /* YYERRORSYMBOL is not defined */
12644 + /* This is what we do if the grammar does not define ERROR:
12646 + ** * Report an error message, and throw away the input token.
12648 + ** * If the input token is $, then fail the parse.
12650 + ** As before, subsequent error messages are suppressed until
12651 + ** three input tokens have been successfully shifted.
12653 + if( yypParser->yyerrcnt<=0 ){
12654 + yy_syntax_error(yypParser,yymajor,yyminorunion);
12656 + yypParser->yyerrcnt = 3;
12657 + yy_destructor(yymajor,&yyminorunion);
12658 + if( yyendofinput ){
12659 + yy_parse_failed(yypParser);
12661 + yymajor = YYNOCODE;
12664 + yy_accept(yypParser);
12665 + yymajor = YYNOCODE;
12667 + }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
12670 --- lighttpd-1.4.11/src/inet_ntop_cache.c 2005-08-11 01:26:38.000000000 +0300
12671 +++ lighttpd-1.4.12/src/inet_ntop_cache.c 2006-07-11 22:07:52.000000000 +0300
12673 #include "sys-socket.h"
12675 const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
12679 for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
12680 if (srv->inet_ntop_cache[i].ts != 0) {
12681 @@ -20,31 +20,31 @@
12682 srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
12683 /* IPv4 found in cache */
12692 if (i == INET_NTOP_CACHE_MAX) {
12693 /* not found in cache */
12697 - inet_ntop(addr->plain.sa_family,
12698 - addr->plain.sa_family == AF_INET6 ?
12699 + inet_ntop(addr->plain.sa_family,
12700 + addr->plain.sa_family == AF_INET6 ?
12701 (const void *) &(addr->ipv6.sin6_addr) :
12702 (const void *) &(addr->ipv4.sin_addr),
12703 srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
12706 srv->inet_ntop_cache[i].ts = srv->cur_ts;
12707 srv->inet_ntop_cache[i].family = addr->plain.sa_family;
12710 if (srv->inet_ntop_cache[i].family == AF_INET) {
12711 srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
12712 } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
12713 memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
12718 return srv->inet_ntop_cache[i].b2;
12721 --- lighttpd-1.4.11/src/joblist.c 2005-08-11 01:26:41.000000000 +0300
12722 +++ lighttpd-1.4.12/src/joblist.c 2006-07-11 22:07:51.000000000 +0300
12725 int joblist_append(server *srv, connection *con) {
12726 if (con->in_joblist) return 0;
12729 if (srv->joblist->size == 0) {
12730 srv->joblist->size = 16;
12731 srv->joblist->ptr = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
12732 @@ -15,15 +15,15 @@
12733 srv->joblist->size += 16;
12734 srv->joblist->ptr = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
12738 srv->joblist->ptr[srv->joblist->used++] = con;
12744 void joblist_free(server *srv, connections *joblist) {
12748 free(joblist->ptr);
12751 @@ -31,14 +31,14 @@
12752 connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
12759 if (fdwaitqueue->used == 0) return NULL;
12762 con = fdwaitqueue->ptr[0];
12765 memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
12772 srv->fdwaitqueue->size += 16;
12773 srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
12777 srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
12783 --- lighttpd-1.4.11/src/keyvalue.c 2006-03-02 16:08:06.000000000 +0200
12784 +++ lighttpd-1.4.12/src/keyvalue.c 2006-07-11 22:07:51.000000000 +0300
12786 { 504, "Gateway Timeout" },
12787 { 505, "HTTP Version Not Supported" },
12788 { 507, "Insufficient Storage" }, /* WebDAV */
12790 + { 509, "Bandwidth Limit exceeded" },
12795 @@ -102,12 +103,12 @@
12796 { 501, "501.html" },
12797 { 503, "503.html" },
12798 { 505, "505.html" },
12805 -const char *keyvalue_get_value(keyvalue *kv, int k) {
12806 +const char *keyvalue_get_value(keyvalue *kv, int k) {
12808 for (i = 0; kv[i].value; i++) {
12809 if (kv[i].key == k) return kv[i].value;
12810 @@ -115,7 +116,7 @@
12814 -int keyvalue_get_key(keyvalue *kv, const char *s) {
12815 +int keyvalue_get_key(keyvalue *kv, const char *s) {
12817 for (i = 0; kv[i].value; i++) {
12818 if (0 == strcmp(kv[i].value, s)) return kv[i].key;
12819 @@ -125,9 +126,9 @@
12821 keyvalue_buffer *keyvalue_buffer_init(void) {
12822 keyvalue_buffer *kvb;
12825 kvb = calloc(1, sizeof(*kvb));
12831 @@ -135,49 +136,49 @@
12833 if (kvb->size == 0) {
12837 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12840 for(i = 0; i < kvb->size; i++) {
12841 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12843 } else if (kvb->used == kvb->size) {
12847 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12850 for(i = kvb->used; i < kvb->size; i++) {
12851 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12856 kvb->kv[kvb->used]->key = key;
12857 kvb->kv[kvb->used]->value = strdup(value);
12866 void keyvalue_buffer_free(keyvalue_buffer *kvb) {
12870 for (i = 0; i < kvb->size; i++) {
12871 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12876 if (kvb->kv) free(kvb->kv);
12883 s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
12884 s_keyvalue_buffer *kvb;
12887 kvb = calloc(1, sizeof(*kvb));
12893 @@ -186,50 +187,50 @@
12894 if (kvb->size == 0) {
12899 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12902 for(i = 0; i < kvb->size; i++) {
12903 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12905 } else if (kvb->used == kvb->size) {
12909 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12912 for(i = kvb->used; i < kvb->size; i++) {
12913 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12918 kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
12919 kvb->kv[kvb->used]->value = strdup(value);
12928 void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
12932 for (i = 0; i < kvb->size; i++) {
12933 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12934 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12939 if (kvb->kv) free(kvb->kv);
12946 httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
12947 httpauth_keyvalue_buffer *kvb;
12950 kvb = calloc(1, sizeof(*kvb));
12956 @@ -237,42 +238,42 @@
12958 if (kvb->size == 0) {
12962 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12965 for(i = 0; i < kvb->size; i++) {
12966 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12968 } else if (kvb->used == kvb->size) {
12972 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12975 for(i = kvb->used; i < kvb->size; i++) {
12976 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12981 kvb->kv[kvb->used]->key = strdup(key);
12982 kvb->kv[kvb->used]->realm = strdup(realm);
12983 kvb->kv[kvb->used]->type = type;
12992 void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
12996 for (i = 0; i < kvb->size; i++) {
12997 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12998 if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
13003 if (kvb->kv) free(kvb->kv);
13009 @@ -306,9 +307,9 @@
13011 pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
13012 pcre_keyvalue_buffer *kvb;
13015 kvb = calloc(1, sizeof(*kvb));
13021 @@ -319,46 +320,46 @@
13027 if (!key) return -1;
13030 if (kvb->size == 0) {
13035 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
13038 for(i = 0; i < kvb->size; i++) {
13039 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13041 } else if (kvb->used == kvb->size) {
13045 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13048 for(i = kvb->used; i < kvb->size; i++) {
13049 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13054 kv = kvb->kv[kvb->used];
13055 if (NULL == (kv->key = pcre_compile(key,
13056 0, &errptr, &erroff, NULL))) {
13059 fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
13063 - if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
13064 + if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
13070 kv->value = buffer_init_string(value);
13079 @@ -380,9 +381,9 @@
13080 if (kv->value) buffer_free(kv->value);
13085 if (kvb->kv) free(kvb->kv);
13091 --- lighttpd-1.4.11/src/keyvalue.h 2006-03-02 16:08:06.000000000 +0200
13092 +++ lighttpd-1.4.12/src/keyvalue.h 2006-07-11 22:07:52.000000000 +0300
13098 - HTTP_METHOD_UNSET = -1,
13100 - HTTP_METHOD_POST,
13101 - HTTP_METHOD_HEAD,
13102 - HTTP_METHOD_OPTIONS,
13104 + HTTP_METHOD_UNSET = -1,
13106 + HTTP_METHOD_POST,
13107 + HTTP_METHOD_HEAD,
13108 + HTTP_METHOD_OPTIONS,
13109 HTTP_METHOD_PROPFIND, /* WebDAV */
13110 - HTTP_METHOD_MKCOL,
13112 - HTTP_METHOD_DELETE,
13113 - HTTP_METHOD_COPY,
13114 - HTTP_METHOD_MOVE,
13115 - HTTP_METHOD_PROPPATCH,
13116 + HTTP_METHOD_MKCOL,
13118 + HTTP_METHOD_DELETE,
13119 + HTTP_METHOD_COPY,
13120 + HTTP_METHOD_MOVE,
13121 + HTTP_METHOD_PROPPATCH,
13122 HTTP_METHOD_REPORT, /* DeltaV */
13123 HTTP_METHOD_CHECKOUT,
13124 HTTP_METHOD_CHECKIN,
13125 @@ -39,13 +39,13 @@
13143 pcre_extra *key_extra;
13157 httpauth_type type;
13158 } httpauth_keyvalue;
13159 --- lighttpd-1.4.11/src/lemon.c 2005-09-01 00:21:34.000000000 +0300
13160 +++ lighttpd-1.4.12/src/lemon.c 2006-07-11 22:07:51.000000000 +0300
13161 @@ -579,7 +579,7 @@
13164 /* Find a precedence symbol of every rule in the grammar.
13167 ** Those rules which have a precedence symbol coded in the input
13168 ** grammar using the "[symbol]" construct will already have the
13169 ** rp->precsym field filled. Other rules take as their precedence
13170 @@ -869,7 +869,7 @@
13171 cfp->status = INCOMPLETE;
13178 for(i=0; i<lemp->nstate; i++){
13179 @@ -900,7 +900,7 @@
13183 - /* Add all of the reduce actions
13184 + /* Add all of the reduce actions
13185 ** A reduce action is added for each element of the followset of
13186 ** a configuration which has its dot at the extreme right.
13188 @@ -1017,7 +1017,7 @@
13189 apx->type = RD_RESOLVED;
13194 apx->type==SH_RESOLVED ||
13195 apx->type==RD_RESOLVED ||
13196 apx->type==CONFLICT ||
13197 @@ -1350,7 +1350,7 @@
13198 OptInit(argv,options,stderr);
13200 printf("Lemon version 1.0\n");
13204 if( OptNArgs() < 1 ){
13205 fprintf(stderr,"Exactly one filename argument is required.\n");
13206 @@ -2031,7 +2031,7 @@
13210 - rp = (struct rule *)malloc( sizeof(struct rule) +
13211 + rp = (struct rule *)malloc( sizeof(struct rule) +
13212 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
13214 ErrorMsg(psp->filename,psp->tokenlineno,
13215 @@ -2546,7 +2546,7 @@
13219 -/* Duplicate the input file without comments and without actions
13220 +/* Duplicate the input file without comments and without actions
13223 struct lemon *lemp;
13224 @@ -2822,7 +2822,7 @@
13225 PRIVATE FILE *tplt_open(lemp)
13226 struct lemon *lemp;
13233 @@ -2930,7 +2930,7 @@
13239 ** Generate code which executes when the rule "rp" is reduced. Write
13240 ** the code to "out". Make sure lineno stays up-to-date.
13242 @@ -3384,7 +3384,7 @@
13244 /* Output the yy_shift_ofst[] table */
13245 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
13246 - fprintf(out, "static %s yy_shift_ofst[] = {\n",
13247 + fprintf(out, "static %s yy_shift_ofst[] = {\n",
13248 minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
13250 for(i=j=0; i<n; i++){
13251 @@ -3405,7 +3405,7 @@
13253 /* Output the yy_reduce_ofst[] table */
13254 fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
13255 - fprintf(out, "static %s yy_reduce_ofst[] = {\n",
13256 + fprintf(out, "static %s yy_reduce_ofst[] = {\n",
13257 minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
13259 for(i=j=0; i<n; i++){
13260 @@ -3480,7 +3480,7 @@
13261 tplt_xfer(lemp->name,in,out,&lineno);
13263 /* Generate code which executes every time a symbol is popped from
13264 - ** the stack while processing errors or while destroying the parser.
13265 + ** the stack while processing errors or while destroying the parser.
13266 ** (In other words, generate the %destructor actions)
13268 if( lemp->tokendest ){
13269 @@ -3522,7 +3522,7 @@
13270 tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
13271 tplt_xfer(lemp->name,in,out,&lineno);
13273 - /* Generate the table of rule information
13274 + /* Generate the table of rule information
13276 ** Note: This code depends on the fact that rules are number
13277 ** sequentually beginning with 0.
13278 @@ -3589,7 +3589,7 @@
13279 for(i=1; i<lemp->nterminal; i++){
13280 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
13287 @@ -3630,7 +3630,7 @@
13293 /* Do not make a default if the number of rules to default
13294 ** is not at least 2 */
13295 if( nbest<2 ) continue;
13296 @@ -3781,7 +3781,7 @@
13300 - x1a->tbl = (x1node*)malloc(
13301 + x1a->tbl = (x1node*)malloc(
13302 (sizeof(x1node) + sizeof(x1node*))*1024 );
13305 @@ -3943,7 +3943,7 @@
13309 - x2a->tbl = (x2node*)malloc(
13310 + x2a->tbl = (x2node*)malloc(
13311 (sizeof(x2node) + sizeof(x2node*))*128 );
13314 @@ -4149,7 +4149,7 @@
13318 - x3a->tbl = (x3node*)malloc(
13319 + x3a->tbl = (x3node*)malloc(
13320 (sizeof(x3node) + sizeof(x3node*))*128 );
13323 @@ -4295,7 +4295,7 @@
13327 - x4a->tbl = (x4node*)malloc(
13328 + x4a->tbl = (x4node*)malloc(
13329 (sizeof(x4node) + sizeof(x4node*))*64 );
13332 --- lighttpd-1.4.11/src/lempar.c 2005-08-11 01:26:40.000000000 +0300
13333 +++ lighttpd-1.4.12/src/lempar.c 2006-07-11 22:07:51.000000000 +0300
13335 /* Next is all token values, in a form suitable for use by makeheaders.
13336 ** This section will be null unless lemon is run with the -m switch.
13340 ** These constants (all generated automatically by the parser generator)
13341 ** specify the various kinds of tokens (terminals) that the parser
13345 ** Each symbol here is a terminal symbol in the grammar.
13348 ** and nonterminals. "int" is used otherwise.
13349 ** YYNOCODE is a number of type YYCODETYPE which corresponds
13350 ** to no legal terminal or nonterminal number. This
13351 -** number is used to fill in empty slots of the hash
13352 +** number is used to fill in empty slots of the hash
13354 ** YYFALLBACK If defined, this indicates that one or more tokens
13355 ** have fall-back values which should be used if the
13357 ** and nonterminal numbers. "unsigned char" is
13358 ** used if there are fewer than 250 rules and
13359 ** states combined. "int" is used otherwise.
13360 -** ParseTOKENTYPE is the data type used for minor tokens given
13361 +** ParseTOKENTYPE is the data type used for minor tokens given
13362 ** directly to the parser from the tokenizer.
13363 ** YYMINORTYPE is the data type used for all minor tokens.
13364 ** This is typically a union of many types, one of
13366 /* Next are that tables used to determine what action to take based on the
13367 ** current state and lookahead token. These tables are used to implement
13368 ** functions that take a state number and lookahead value and return an
13369 -** action integer.
13370 +** action integer.
13372 ** Suppose the action integer is N. Then the action is determined as
13375 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
13376 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
13377 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
13378 -** and that yy_default[S] should be used instead.
13379 +** and that yy_default[S] should be used instead.
13381 ** The formula above is for computing the action when the lookahead is
13382 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
13383 @@ -111,7 +111,7 @@
13385 /* The next table maps tokens into fallback tokens. If a construct
13386 ** like the following:
13389 ** %fallback ID X Y Z.
13391 ** appears in the grammer, then ID becomes a fallback token for X, Y,
13392 @@ -163,10 +163,10 @@
13393 #endif /* NDEBUG */
13398 ** Turn parser tracing on by giving a stream to which to write the trace
13399 ** and a prompt to preface each trace message. Tracing is turned off
13400 -** by making either argument NULL
13401 +** by making either argument NULL
13405 @@ -191,7 +191,7 @@
13407 /* For tracing shifts, the names of all terminals and nonterminals
13408 ** are required. The following table supplies these names */
13409 -static const char *yyTokenName[] = {
13410 +static const char *yyTokenName[] = {
13413 #endif /* NDEBUG */
13414 @@ -220,7 +220,7 @@
13420 ** This function allocates a new parser.
13421 ** The only argument is a pointer to a function which works like
13423 @@ -251,7 +251,7 @@
13424 /* Here is inserted the actions which take place when a
13425 ** terminal or non-terminal is destroyed. This can happen
13426 ** when the symbol is popped from the stack during a
13427 - ** reduce or during error processing or when a parser is
13428 + ** reduce or during error processing or when a parser is
13429 ** being destroyed before it is finished parsing.
13431 ** Note: during a reduce, the only symbols destroyed are those
13432 @@ -289,7 +289,7 @@
13438 ** Deallocate and destroy a parser. Destructors are all called for
13439 ** all stack elements before shutting the parser down.
13441 @@ -325,7 +325,7 @@
13444 int stateno = pParser->yystack[pParser->yyidx].stateno;
13447 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
13448 i = yy_shift_ofst[stateno];
13449 if( i==YY_SHIFT_USE_DFLT ){
13450 @@ -369,7 +369,7 @@
13453 int stateno = pParser->yystack[pParser->yyidx].stateno;
13456 i = yy_reduce_ofst[stateno];
13457 if( i==YY_REDUCE_USE_DFLT ){
13458 return yy_default[stateno];
13459 @@ -455,7 +455,7 @@
13461 yymsp = &yypParser->yystack[yypParser->yyidx];
13463 - if( yyTraceFILE && yyruleno>=0
13464 + if( yyTraceFILE && yyruleno>=0
13465 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
13466 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
13467 yyRuleName[yyruleno]);
13468 @@ -608,7 +608,7 @@
13469 #ifdef YYERRORSYMBOL
13470 /* A syntax error has occurred.
13471 ** The response to an error depends upon whether or not the
13472 - ** grammar defines an error token "ERROR".
13473 + ** grammar defines an error token "ERROR".
13475 ** This is what we do if the grammar does define ERROR:
13477 --- lighttpd-1.4.11/src/log.c 2005-11-07 15:01:35.000000000 +0200
13478 +++ lighttpd-1.4.12/src/log.c 2006-07-11 22:07:53.000000000 +0300
13483 -#include <unistd.h>
13484 +//#include <unistd.h>
13485 #include <string.h>
13486 #include <stdlib.h>
13489 #include "config.h"
13493 +#undef HAVE_SYSLOG_H
13496 #ifdef HAVE_SYSLOG_H
13497 #include <syslog.h>
13503 +#include "sys-files.h"
13505 #ifdef HAVE_VALGRIND_VALGRIND_H
13506 #include <valgrind/valgrind.h>
13508 @@ -31,38 +37,38 @@
13509 # define O_LARGEFILE 0
13514 * open the errorlog
13517 * we have 3 possibilities:
13518 * - stderr (default)
13524 * if the open failed, report to the user and die
13529 int log_error_open(server *srv) {
13531 int close_stderr = 1;
13534 #ifdef HAVE_SYSLOG_H
13535 /* perhaps someone wants to use syslog() */
13536 openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
13538 srv->errorlog_mode = ERRORLOG_STDERR;
13541 if (srv->srvconf.errorlog_use_syslog) {
13542 srv->errorlog_mode = ERRORLOG_SYSLOG;
13543 } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
13544 const char *logfile = srv->srvconf.errorlog_file->ptr;
13547 if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13548 - log_error_write(srv, __FILE__, __LINE__, "SSSS",
13549 + log_error_write(srv, __FILE__, __LINE__, "SSSS",
13550 "opening errorlog '", logfile,
13551 "' failed: ", strerror(errno));
13557 @@ -71,15 +77,15 @@
13559 srv->errorlog_mode = ERRORLOG_FILE;
13563 log_error_write(srv, __FILE__, __LINE__, "s", "server started");
13566 #ifdef HAVE_VALGRIND_VALGRIND_H
13567 /* don't close stderr for debugging purposes if run in valgrind */
13568 if (RUNNING_ON_VALGRIND) close_stderr = 0;
13570 if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
13573 /* move stderr to /dev/null */
13574 if (close_stderr &&
13575 -1 != (fd = open("/dev/null", O_WRONLY))) {
13576 @@ -90,33 +96,33 @@
13582 * open the errorlog
13585 * if the open failed, report to the user and die
13586 * if no filename is given, use syslog instead
13591 int log_error_cycle(server *srv) {
13592 /* only cycle if we are not in syslog-mode */
13595 if (srv->errorlog_mode == ERRORLOG_FILE) {
13596 const char *logfile = srv->srvconf.errorlog_file->ptr;
13597 /* already check of opening time */
13603 if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13604 /* write to old log */
13605 - log_error_write(srv, __FILE__, __LINE__, "SSSSS",
13606 + log_error_write(srv, __FILE__, __LINE__, "SSSSS",
13607 "cycling errorlog '", logfile,
13608 "' failed: ", strerror(errno),
13609 ", falling back to syslog()");
13612 close(srv->errorlog_fd);
13613 srv->errorlog_fd = -1;
13614 -#ifdef HAVE_SYSLOG_H
13615 +#ifdef HAVE_SYSLOG_H
13616 srv->errorlog_mode = ERRORLOG_SYSLOG;
13619 @@ -125,15 +131,15 @@
13620 srv->errorlog_fd = new_fd;
13625 log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
13631 int log_error_close(server *srv) {
13632 log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
13635 switch(srv->errorlog_mode) {
13636 case ERRORLOG_FILE:
13637 close(srv->errorlog_fd);
13638 @@ -146,13 +152,13 @@
13639 case ERRORLOG_STDERR:
13647 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
13651 switch(srv->errorlog_mode) {
13652 case ERRORLOG_FILE:
13653 case ERRORLOG_STDERR:
13654 @@ -161,7 +167,7 @@
13655 buffer_prepare_copy(srv->ts_debug_str, 255);
13656 strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
13657 srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
13660 srv->last_generated_debug_ts = srv->cur_ts;
13663 @@ -173,19 +179,19 @@
13664 BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
13669 buffer_append_string(srv->errorlog_buf, filename);
13670 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ".");
13671 buffer_append_long(srv->errorlog_buf, line);
13672 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") ");
13677 for(va_start(ap, fmt); *fmt; fmt++) {
13685 case 's': /* string */
13686 s = va_arg(ap, char *);
13687 @@ -227,7 +233,7 @@
13696 @@ -236,7 +242,7 @@
13702 switch(srv->errorlog_mode) {
13703 case ERRORLOG_FILE:
13704 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13705 @@ -246,11 +252,13 @@
13706 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13707 write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
13709 +#ifdef HAVE_SYSLOG_H
13710 case ERRORLOG_SYSLOG:
13711 syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
13720 --- lighttpd-1.4.11/src/log.h 2005-08-11 01:26:36.000000000 +0300
13721 +++ lighttpd-1.4.12/src/log.h 2006-07-11 22:07:53.000000000 +0300
13723 int log_error_close(server *srv);
13724 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
13725 int log_error_cycle(server *srv);
13729 --- lighttpd-1.4.11/src/md5.h 2005-11-17 16:20:40.000000000 +0200
13730 +++ lighttpd-1.4.12/src/md5.h 2006-07-11 22:07:53.000000000 +0300
13732 # include <inttypes.h>
13736 +#define UINT4 unsigned __int32
13737 +#define UINT2 unsigned __int16
13738 +#define POINTER unsigned char *
13740 #define UINT4 uint32_t
13741 #define UINT2 uint16_t
13742 #define POINTER unsigned char *
13747 --- lighttpd-1.4.11/src/mod_access.c 2006-01-14 19:44:54.000000000 +0200
13748 +++ lighttpd-1.4.12/src/mod_access.c 2006-07-11 22:07:53.000000000 +0300
13749 @@ -8,126 +8,125 @@
13751 #include "plugin.h"
13753 +#include "sys-strings.h"
13756 array *access_deny;
13763 plugin_config **config_storage;
13765 - plugin_config conf;
13767 + plugin_config conf;
13770 INIT_FUNC(mod_access_init) {
13774 p = calloc(1, sizeof(*p));
13780 FREE_FUNC(mod_access_free) {
13781 plugin_data *p = p_d;
13786 if (!p) return HANDLER_GO_ON;
13789 if (p->config_storage) {
13791 for (i = 0; i < srv->config_context->used; i++) {
13792 plugin_config *s = p->config_storage[i];
13795 array_free(s->access_deny);
13800 free(p->config_storage);
13807 return HANDLER_GO_ON;
13810 SETDEFAULTS_FUNC(mod_access_set_defaults) {
13811 plugin_data *p = p_d;
13814 - config_values_t cv[] = {
13816 + config_values_t cv[] = {
13817 { "url.access-deny", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
13818 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
13822 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
13825 for (i = 0; i < srv->config_context->used; i++) {
13829 s = calloc(1, sizeof(plugin_config));
13830 s->access_deny = array_init();
13833 cv[0].destination = s->access_deny;
13836 p->config_storage[i] = s;
13839 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
13840 return HANDLER_ERROR;
13845 return HANDLER_GO_ON;
13848 -#define PATCH(x) \
13849 - p->conf.x = s->x;
13850 static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
13852 plugin_config *s = p->config_storage[0];
13854 - PATCH(access_deny);
13856 + PATCH_OPTION(access_deny);
13858 /* skip the first, the global context */
13859 for (i = 1; i < srv->config_context->used; i++) {
13860 data_config *dc = (data_config *)srv->config_context->data[i];
13861 s = p->config_storage[i];
13864 /* condition didn't match */
13865 if (!config_check_cond(srv, con, dc)) continue;
13869 for (j = 0; j < dc->value->used; j++) {
13870 data_unset *du = dc->value->data[j];
13873 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
13874 - PATCH(access_deny);
13875 + PATCH_OPTION(access_deny);
13885 URIHANDLER_FUNC(mod_access_uri_handler) {
13886 plugin_data *p = p_d;
13891 if (con->uri.path->used == 0) return HANDLER_GO_ON;
13894 mod_access_patch_connection(srv, con, p);
13897 s_len = con->uri.path->used - 1;
13900 for (k = 0; k < p->conf.access_deny->used; k++) {
13901 data_string *ds = (data_string *)p->conf.access_deny->data[k];
13902 int ct_len = ds->value->used - 1;
13905 if (ct_len > s_len) continue;
13908 if (ds->value->used == 0) continue;
13910 /* if we have a case-insensitive FS we have to lower-case the URI here too */
13911 @@ -135,18 +134,18 @@
13912 if (con->conf.force_lowercase_filenames) {
13913 if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13914 con->http_status = 403;
13917 return HANDLER_FINISHED;
13920 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13921 con->http_status = 403;
13924 return HANDLER_FINISHED;
13931 return HANDLER_GO_ON;
13933 @@ -155,13 +154,13 @@
13934 int mod_access_plugin_init(plugin *p) {
13935 p->version = LIGHTTPD_VERSION_ID;
13936 p->name = buffer_init_string("access");
13939 p->init = mod_access_init;
13940 p->set_defaults = mod_access_set_defaults;
13941 p->handle_uri_clean = mod_access_uri_handler;
13942 p->cleanup = mod_access_free;
13950 --- lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200
13951 +++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-11 22:07:53.000000000 +0300
13954 #include <stdlib.h>
13955 #include <string.h>
13956 -#include <fcntl.h>
13957 -#include <unistd.h>
13958 +#include <fcntl.h> /* only the defines on windows */
13963 #include "inet_ntop_cache.h"
13965 #include "sys-socket.h"
13966 +#include "sys-files.h"
13968 #ifdef HAVE_SYSLOG_H
13969 # include <syslog.h>
13977 FORMAT_UNSUPPORTED,
13981 FORMAT_BYTES_OUT_NO_HEADER,
13985 FORMAT_REMOTE_ADDR,
13988 @@ -59,20 +59,20 @@
13989 FORMAT_CONNECTION_STATUS,
13994 FORMAT_RESPONSE_HEADER
14003 * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
14008 -const format_mapping fmap[] =
14010 +const format_mapping fmap[] =
14012 { '%', FORMAT_PERCENT },
14013 { 'h', FORMAT_REMOTE_HOST },
14014 { 'l', FORMAT_REMOTE_IDENT },
14016 { 's', FORMAT_STATUS },
14017 { 'b', FORMAT_BYTES_OUT_NO_HEADER },
14018 { 'i', FORMAT_HEADER },
14021 { 'a', FORMAT_REMOTE_ADDR },
14022 { 'A', FORMAT_LOCAL_ADDR },
14023 { 'B', FORMAT_BYTES_OUT_NO_HEADER },
14024 @@ -103,23 +103,23 @@
14025 { 'X', FORMAT_CONNECTION_STATUS },
14026 { 'I', FORMAT_BYTES_IN },
14027 { 'O', FORMAT_BYTES_OUT },
14030 { 'o', FORMAT_RESPONSE_HEADER },
14033 { '\0', FORMAT_UNSET }
14038 enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
14046 format_field **ptr;
14052 @@ -128,39 +128,39 @@
14053 buffer *access_logfile;
14055 unsigned short use_syslog;
14061 time_t last_generated_accesslog_ts;
14062 time_t *last_generated_accesslog_ts_ptr;
14067 buffer *access_logbuffer;
14068 buffer *ts_accesslog_str;
14071 format_fields *parsed_format;
14078 plugin_config **config_storage;
14079 - plugin_config conf;
14080 + plugin_config conf;
14083 INIT_FUNC(mod_accesslog_init) {
14087 p = calloc(1, sizeof(*p));
14093 int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
14094 size_t i, j, k = 0, start = 0;
14097 for (i = 0; i < format->used - 1; i++) {
14100 switch(format->ptr[i]) {
14103 @@ -173,19 +173,19 @@
14104 fields->size += 16;
14105 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14109 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14110 fields->ptr[fields->used]->type = FIELD_STRING;
14111 fields->ptr[fields->used]->string = buffer_init();
14114 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14123 /* we need a new field */
14126 if (fields->size == 0) {
14129 @@ -194,43 +194,43 @@
14130 fields->size += 16;
14131 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14135 /* search for the terminating command */
14136 switch (format->ptr[i+1]) {
14142 for (j = 0; fmap[j].key != '\0'; j++) {
14143 if (fmap[j].key != format->ptr[i+2]) continue;
14149 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14150 fields->ptr[fields->used]->type = FIELD_FORMAT;
14151 fields->ptr[fields->used]->field = fmap[j].type;
14152 fields->ptr[fields->used]->string = NULL;
14162 if (fmap[j].key == '\0') {
14163 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14173 /* go forward to } */
14176 for (k = i+2; k < format->used - 1; k++) {
14177 if (format->ptr[k] == '}') break;
14181 if (k == format->used - 1) {
14182 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14184 @@ -239,62 +239,62 @@
14185 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14190 for (j = 0; fmap[j].key != '\0'; j++) {
14191 if (fmap[j].key != format->ptr[k+1]) continue;
14197 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14198 fields->ptr[fields->used]->type = FIELD_FORMAT;
14199 fields->ptr[fields->used]->field = fmap[j].type;
14200 fields->ptr[fields->used]->string = buffer_init();
14203 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
14213 if (fmap[j].key == '\0') {
14214 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14224 for (j = 0; fmap[j].key != '\0'; j++) {
14225 if (fmap[j].key != format->ptr[i+1]) continue;
14231 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14232 fields->ptr[fields->used]->type = FIELD_FORMAT;
14233 fields->ptr[fields->used]->field = fmap[j].type;
14234 fields->ptr[fields->used]->string = NULL;
14244 if (fmap[j].key == '\0') {
14245 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14263 /* copy the string */
14264 if (fields->size == 0) {
14265 @@ -305,32 +305,32 @@
14266 fields->size += 16;
14267 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14271 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14272 fields->ptr[fields->used]->type = FIELD_STRING;
14273 fields->ptr[fields->used]->string = buffer_init();
14276 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14286 FREE_FUNC(mod_accesslog_free) {
14287 plugin_data *p = p_d;
14291 if (!p) return HANDLER_GO_ON;
14294 if (p->config_storage) {
14297 for (i = 0; i < srv->config_context->used; i++) {
14298 plugin_config *s = p->config_storage[i];
14303 if (s->access_logbuffer->used) {
14304 if (s->use_syslog) {
14305 # ifdef HAVE_SYSLOG_H
14306 @@ -342,14 +342,14 @@
14307 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14312 if (s->log_access_fd != -1) close(s->log_access_fd);
14315 buffer_free(s->ts_accesslog_str);
14316 buffer_free(s->access_logbuffer);
14317 buffer_free(s->format);
14318 buffer_free(s->access_logfile);
14321 if (s->parsed_format) {
14323 for (j = 0; j < s->parsed_format->used; j++) {
14324 @@ -359,36 +359,36 @@
14325 free(s->parsed_format->ptr);
14326 free(s->parsed_format);
14334 free(p->config_storage);
14341 return HANDLER_GO_ON;
14344 SETDEFAULTS_FUNC(log_access_open) {
14345 plugin_data *p = p_d;
14348 - config_values_t cv[] = {
14350 + config_values_t cv[] = {
14351 { "accesslog.filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14352 { "accesslog.use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
14353 { "accesslog.format", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14354 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14358 if (!p) return HANDLER_ERROR;
14361 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14364 for (i = 0; i < srv->config_context->used; i++) {
14368 s = calloc(1, sizeof(plugin_config));
14369 s->access_logfile = buffer_init();
14370 s->format = buffer_init();
14371 @@ -397,44 +397,44 @@
14372 s->log_access_fd = -1;
14373 s->last_generated_accesslog_ts = 0;
14374 s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
14379 cv[0].destination = s->access_logfile;
14380 cv[1].destination = &(s->use_syslog);
14381 cv[2].destination = s->format;
14384 p->config_storage[i] = s;
14387 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14388 return HANDLER_ERROR;
14392 if (i == 0 && buffer_is_empty(s->format)) {
14393 /* set a default logfile string */
14396 buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
14403 if (s->format->used) {
14404 s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
14407 if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
14409 - log_error_write(srv, __FILE__, __LINE__, "sb",
14410 + log_error_write(srv, __FILE__, __LINE__, "sb",
14411 "parsing accesslog-definition failed:", s->format);
14413 return HANDLER_ERROR;
14418 for (j = 0; j < s->parsed_format->used; j++) {
14419 switch (s->parsed_format->ptr[j]->type) {
14421 - log_error_write(srv, __FILE__, __LINE__, "ssds",
14422 + log_error_write(srv, __FILE__, __LINE__, "ssds",
14423 "config:", "format", s->parsed_format->ptr[j]->field,
14424 - s->parsed_format->ptr[j]->string ?
14425 + s->parsed_format->ptr[j]->string ?
14426 s->parsed_format->ptr[j]->string->ptr : "" );
14429 @@ -446,52 +446,52 @@
14435 if (s->use_syslog) {
14436 /* ignore the next checks */
14441 if (buffer_is_empty(s->access_logfile)) continue;
14444 if (s->access_logfile->ptr[0] == '|') {
14446 /* create write pipe and spawn process */
14453 if (pipe(to_log_fds)) {
14454 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
14455 return HANDLER_ERROR;
14460 switch (pid = fork()) {
14466 close(STDIN_FILENO);
14467 dup2(to_log_fds[0], STDIN_FILENO);
14468 close(to_log_fds[0]);
14470 close(to_log_fds[1]);
14473 /* we don't need the client socket */
14474 for (i = 3; i < 256; i++) {
14478 - /* exec the log-process (skip the | )
14481 + /* exec the log-process (skip the | )
14486 execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
14488 - log_error_write(srv, __FILE__, __LINE__, "sss",
14489 - "spawning log-process failed: ", strerror(errno),
14490 + log_error_write(srv, __FILE__, __LINE__, "sss",
14491 + "spawning log-process failed: ", strerror(errno),
14492 s->access_logfile->ptr + 1);
14498 @@ -500,27 +500,28 @@
14501 close(to_log_fds[0]);
14504 s->log_access_fd = to_log_fds[1];
14512 - } else if (-1 == (s->log_access_fd =
14513 + } else if (-1 == (s->log_access_fd =
14514 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14516 - log_error_write(srv, __FILE__, __LINE__, "ssb",
14517 - "opening access-log failed:",
14519 + log_error_write(srv, __FILE__, __LINE__, "ssb",
14520 + "opening access-log failed:",
14521 strerror(errno), s->access_logfile);
14524 return HANDLER_ERROR;
14527 fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
14533 return HANDLER_GO_ON;
14536 @@ -529,7 +530,7 @@
14539 if (!p->config_storage) return HANDLER_GO_ON;
14542 for (i = 0; i < srv->config_context->used; i++) {
14543 plugin_config *s = p->config_storage[i];
14545 @@ -544,90 +545,87 @@
14546 } else if (s->log_access_fd != -1) {
14547 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14551 buffer_reset(s->access_logbuffer);
14555 if (s->use_syslog == 0 &&
14556 !buffer_is_empty(s->access_logfile) &&
14557 s->access_logfile->ptr[0] != '|') {
14560 close(s->log_access_fd);
14562 - if (-1 == (s->log_access_fd =
14564 + if (-1 == (s->log_access_fd =
14565 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14568 log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
14571 return HANDLER_ERROR;
14577 return HANDLER_GO_ON;
14580 -#define PATCH(x) \
14581 - p->conf.x = s->x;
14582 static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
14584 plugin_config *s = p->config_storage[0];
14586 - PATCH(access_logfile);
14588 - PATCH(log_access_fd);
14589 - PATCH(last_generated_accesslog_ts_ptr);
14590 - PATCH(access_logbuffer);
14591 - PATCH(ts_accesslog_str);
14592 - PATCH(parsed_format);
14593 - PATCH(use_syslog);
14596 + PATCH_OPTION(access_logfile);
14597 + PATCH_OPTION(format);
14598 + PATCH_OPTION(log_access_fd);
14599 + PATCH_OPTION(last_generated_accesslog_ts_ptr);
14600 + PATCH_OPTION(access_logbuffer);
14601 + PATCH_OPTION(ts_accesslog_str);
14602 + PATCH_OPTION(parsed_format);
14603 + PATCH_OPTION(use_syslog);
14605 /* skip the first, the global context */
14606 for (i = 1; i < srv->config_context->used; i++) {
14607 data_config *dc = (data_config *)srv->config_context->data[i];
14608 s = p->config_storage[i];
14611 /* condition didn't match */
14612 if (!config_check_cond(srv, con, dc)) continue;
14616 for (j = 0; j < dc->value->used; j++) {
14617 data_unset *du = dc->value->data[j];
14620 if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
14621 - PATCH(access_logfile);
14622 - PATCH(log_access_fd);
14623 - PATCH(last_generated_accesslog_ts_ptr);
14624 - PATCH(access_logbuffer);
14625 - PATCH(ts_accesslog_str);
14626 + PATCH_OPTION(access_logfile);
14627 + PATCH_OPTION(log_access_fd);
14628 + PATCH_OPTION(last_generated_accesslog_ts_ptr);
14629 + PATCH_OPTION(access_logbuffer);
14630 + PATCH_OPTION(ts_accesslog_str);
14631 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
14633 - PATCH(parsed_format);
14634 + PATCH_OPTION(format);
14635 + PATCH_OPTION(parsed_format);
14636 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
14637 - PATCH(use_syslog);
14638 + PATCH_OPTION(use_syslog);
14648 REQUESTDONE_FUNC(log_access_write) {
14649 plugin_data *p = p_d;
14658 mod_accesslog_patch_connection(srv, con, p);
14661 b = p->conf.access_logbuffer;
14662 if (b->used == 0) {
14663 buffer_copy_string(b, "");
14667 for (j = 0; j < p->conf.parsed_format->used; j++) {
14668 switch(p->conf.parsed_format->ptr[j]->type) {
14670 @@ -636,14 +634,14 @@
14672 switch(p->conf.parsed_format->ptr[j]->field) {
14673 case FORMAT_TIMESTAMP:
14676 /* cache the generated timestamp */
14677 if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
14679 #if defined(HAVE_STRUCT_TM_GMTOFF)
14680 long scd, hrs, min;
14684 buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
14685 #if defined(HAVE_STRUCT_TM_GMTOFF)
14686 # ifdef HAVE_LOCALTIME_R
14687 @@ -653,17 +651,17 @@
14688 strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S ", localtime_r(&(srv->cur_ts)));
14690 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14693 buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
14696 scd = abs(tm.tm_gmtoff);
14698 min = (scd % 3600) / 60;
14702 if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14703 buffer_append_long(p->conf.ts_accesslog_str, hrs);
14706 if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14707 buffer_append_long(p->conf.ts_accesslog_str, min);
14708 BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]");
14709 @@ -676,20 +674,20 @@
14711 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14715 *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
14720 buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
14724 case FORMAT_REMOTE_HOST:
14727 /* handle inet_ntop cache */
14730 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
14734 case FORMAT_REMOTE_IDENT:
14736 @@ -710,10 +708,10 @@
14737 case FORMAT_STATUS:
14738 buffer_append_long(b, con->http_status);
14742 case FORMAT_BYTES_OUT_NO_HEADER:
14743 if (con->bytes_written > 0) {
14744 - buffer_append_off_t(b,
14745 + buffer_append_off_t(b,
14746 con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
14748 BUFFER_APPEND_STRING_CONST(b, "-");
14749 @@ -772,7 +770,7 @@
14752 case FORMAT_REQUEST_PROTOCOL:
14753 - buffer_append_string(b,
14754 + buffer_append_string(b,
14755 con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
14757 case FORMAT_REQUEST_METHOD:
14758 @@ -801,7 +799,7 @@
14759 { 'D', FORMAT_TIME_USED_MS },
14760 { 'e', FORMAT_ENV },
14767 @@ -809,7 +807,7 @@
14773 BUFFER_APPEND_STRING_CONST(b, "\n");
14775 if (p->conf.use_syslog || /* syslog doesn't cache */
14776 @@ -828,7 +826,7 @@
14782 return HANDLER_GO_ON;
14785 @@ -836,15 +834,15 @@
14786 int mod_accesslog_plugin_init(plugin *p) {
14787 p->version = LIGHTTPD_VERSION_ID;
14788 p->name = buffer_init_string("accesslog");
14791 p->init = mod_accesslog_init;
14792 p->set_defaults= log_access_open;
14793 p->cleanup = mod_accesslog_free;
14796 p->handle_request_done = log_access_write;
14797 p->handle_sighup = log_access_cycle;
14805 --- lighttpd-1.4.11/src/mod_alias.c 2006-03-01 23:18:51.000000000 +0200
14806 +++ lighttpd-1.4.12/src/mod_alias.c 2006-07-11 22:07:51.000000000 +0300
14808 #include "buffer.h"
14810 #include "plugin.h"
14811 +#include "sys-strings.h"
14813 /* plugin config for all request/connections */
14815 @@ -16,44 +17,44 @@
14821 plugin_config **config_storage;
14823 - plugin_config conf;
14825 + plugin_config conf;
14828 /* init the plugin data */
14829 INIT_FUNC(mod_alias_init) {
14833 p = calloc(1, sizeof(*p));
14843 /* detroy the plugin data */
14844 FREE_FUNC(mod_alias_free) {
14845 plugin_data *p = p_d;
14848 if (!p) return HANDLER_GO_ON;
14851 if (p->config_storage) {
14855 for (i = 0; i < srv->config_context->used; i++) {
14856 plugin_config *s = p->config_storage[i];
14859 array_free(s->alias);
14864 free(p->config_storage);
14871 return HANDLER_GO_ON;
14874 @@ -62,25 +63,25 @@
14875 SETDEFAULTS_FUNC(mod_alias_set_defaults) {
14876 plugin_data *p = p_d;
14879 - config_values_t cv[] = {
14881 + config_values_t cv[] = {
14882 { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
14883 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14887 if (!p) return HANDLER_ERROR;
14890 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14893 for (i = 0; i < srv->config_context->used; i++) {
14897 s = calloc(1, sizeof(plugin_config));
14898 - s->alias = array_init();
14899 + s->alias = array_init();
14900 cv[0].destination = s->alias;
14903 p->config_storage[i] = s;
14906 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14907 return HANDLER_ERROR;
14909 @@ -110,76 +111,73 @@
14915 return HANDLER_GO_ON;
14918 -#define PATCH(x) \
14919 - p->conf.x = s->x;
14920 static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
14922 plugin_config *s = p->config_storage[0];
14927 + PATCH_OPTION(alias);
14929 /* skip the first, the global context */
14930 for (i = 1; i < srv->config_context->used; i++) {
14931 data_config *dc = (data_config *)srv->config_context->data[i];
14932 s = p->config_storage[i];
14935 /* condition didn't match */
14936 if (!config_check_cond(srv, con, dc)) continue;
14940 for (j = 0; j < dc->value->used; j++) {
14941 data_unset *du = dc->value->data[j];
14944 if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
14946 + PATCH_OPTION(alias);
14956 PHYSICALPATH_FUNC(mod_alias_physical_handler) {
14957 plugin_data *p = p_d;
14958 int uri_len, basedir_len;
14963 if (con->physical.path->used == 0) return HANDLER_GO_ON;
14966 mod_alias_patch_connection(srv, con, p);
14969 /* not to include the tailing slash */
14970 basedir_len = (con->physical.basedir->used - 1) - 1;
14971 uri_len = con->physical.path->used - 1 - basedir_len;
14972 uri_ptr = con->physical.path->ptr + basedir_len;
14975 for (k = 0; k < p->conf.alias->used; k++) {
14976 data_string *ds = (data_string *)p->conf.alias->data[k];
14977 int alias_len = ds->key->used - 1;
14980 if (alias_len > uri_len) continue;
14981 if (ds->key->used == 0) continue;
14984 if (0 == (con->conf.force_lowercase_filenames ?
14985 strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
14986 strncmp(uri_ptr, ds->key->ptr, alias_len))) {
14990 buffer_copy_string_buffer(con->physical.basedir, ds->value);
14991 buffer_copy_string_buffer(srv->tmp_buf, ds->value);
14992 buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
14993 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
14996 return HANDLER_GO_ON;
15002 return HANDLER_GO_ON;
15004 @@ -189,13 +187,13 @@
15005 int mod_alias_plugin_init(plugin *p) {
15006 p->version = LIGHTTPD_VERSION_ID;
15007 p->name = buffer_init_string("alias");
15010 p->init = mod_alias_init;
15011 p->handle_physical= mod_alias_physical_handler;
15012 p->set_defaults = mod_alias_set_defaults;
15013 p->cleanup = mod_alias_free;
15021 --- lighttpd-1.4.11/src/mod_auth.c 2006-02-15 20:01:31.000000000 +0200
15022 +++ lighttpd-1.4.12/src/mod_auth.c 2006-07-11 22:07:53.000000000 +0300
15023 @@ -5,168 +5,167 @@
15024 #include <string.h>
15027 -#include <unistd.h>
15029 #include "plugin.h"
15030 #include "http_auth.h"
15032 #include "response.h"
15034 +#include "sys-strings.h"
15035 +#include "sys-files.h"
15037 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
15041 * the basic and digest auth framework
15044 * - config handling
15045 * - protocol handling
15048 - * http_auth_digest.c
15052 + * http_auth_digest.c
15057 INIT_FUNC(mod_auth_init) {
15058 mod_auth_plugin_data *p;
15061 p = calloc(1, sizeof(*p));
15064 p->tmp_buf = buffer_init();
15067 p->auth_user = buffer_init();
15069 p->ldap_filter = buffer_init();
15076 FREE_FUNC(mod_auth_free) {
15077 mod_auth_plugin_data *p = p_d;
15082 if (!p) return HANDLER_GO_ON;
15085 buffer_free(p->tmp_buf);
15086 buffer_free(p->auth_user);
15088 buffer_free(p->ldap_filter);
15092 if (p->config_storage) {
15094 for (i = 0; i < srv->config_context->used; i++) {
15095 mod_auth_plugin_config *s = p->config_storage[i];
15101 array_free(s->auth_require);
15102 buffer_free(s->auth_plain_groupfile);
15103 buffer_free(s->auth_plain_userfile);
15104 buffer_free(s->auth_htdigest_userfile);
15105 buffer_free(s->auth_htpasswd_userfile);
15106 buffer_free(s->auth_backend_conf);
15109 buffer_free(s->auth_ldap_hostname);
15110 buffer_free(s->auth_ldap_basedn);
15111 buffer_free(s->auth_ldap_binddn);
15112 buffer_free(s->auth_ldap_bindpw);
15113 buffer_free(s->auth_ldap_filter);
15114 buffer_free(s->auth_ldap_cafile);
15118 buffer_free(s->ldap_filter_pre);
15119 buffer_free(s->ldap_filter_post);
15122 if (s->ldap) ldap_unbind_s(s->ldap);
15128 free(p->config_storage);
15135 return HANDLER_GO_ON;
15138 -#define PATCH(x) \
15139 - p->conf.x = s->x;
15140 static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
15142 mod_auth_plugin_config *s = p->config_storage[0];
15144 - PATCH(auth_backend);
15145 - PATCH(auth_plain_groupfile);
15146 - PATCH(auth_plain_userfile);
15147 - PATCH(auth_htdigest_userfile);
15148 - PATCH(auth_htpasswd_userfile);
15149 - PATCH(auth_require);
15150 - PATCH(auth_debug);
15151 - PATCH(auth_ldap_hostname);
15152 - PATCH(auth_ldap_basedn);
15153 - PATCH(auth_ldap_binddn);
15154 - PATCH(auth_ldap_bindpw);
15155 - PATCH(auth_ldap_filter);
15156 - PATCH(auth_ldap_cafile);
15157 - PATCH(auth_ldap_starttls);
15158 + PATCH_OPTION(auth_backend);
15159 + PATCH_OPTION(auth_plain_groupfile);
15160 + PATCH_OPTION(auth_plain_userfile);
15161 + PATCH_OPTION(auth_htdigest_userfile);
15162 + PATCH_OPTION(auth_htpasswd_userfile);
15163 + PATCH_OPTION(auth_require);
15164 + PATCH_OPTION(auth_debug);
15165 + PATCH_OPTION(auth_ldap_hostname);
15166 + PATCH_OPTION(auth_ldap_basedn);
15167 + PATCH_OPTION(auth_ldap_binddn);
15168 + PATCH_OPTION(auth_ldap_bindpw);
15169 + PATCH_OPTION(auth_ldap_filter);
15170 + PATCH_OPTION(auth_ldap_cafile);
15171 + PATCH_OPTION(auth_ldap_starttls);
15174 - PATCH(ldap_filter_pre);
15175 - PATCH(ldap_filter_post);
15176 + PATCH_OPTION(ldap);
15177 + PATCH_OPTION(ldap_filter_pre);
15178 + PATCH_OPTION(ldap_filter_post);
15182 /* skip the first, the global context */
15183 for (i = 1; i < srv->config_context->used; i++) {
15184 data_config *dc = (data_config *)srv->config_context->data[i];
15185 s = p->config_storage[i];
15188 /* condition didn't match */
15189 if (!config_check_cond(srv, con, dc)) continue;
15193 for (j = 0; j < dc->value->used; j++) {
15194 data_unset *du = dc->value->data[j];
15197 if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
15198 - PATCH(auth_backend);
15199 + PATCH_OPTION(auth_backend);
15200 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
15201 - PATCH(auth_plain_groupfile);
15202 + PATCH_OPTION(auth_plain_groupfile);
15203 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
15204 - PATCH(auth_plain_userfile);
15205 + PATCH_OPTION(auth_plain_userfile);
15206 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
15207 - PATCH(auth_htdigest_userfile);
15208 + PATCH_OPTION(auth_htdigest_userfile);
15209 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
15210 - PATCH(auth_htpasswd_userfile);
15211 + PATCH_OPTION(auth_htpasswd_userfile);
15212 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
15213 - PATCH(auth_require);
15214 + PATCH_OPTION(auth_require);
15215 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
15216 - PATCH(auth_debug);
15217 + PATCH_OPTION(auth_debug);
15218 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
15219 - PATCH(auth_ldap_hostname);
15220 + PATCH_OPTION(auth_ldap_hostname);
15223 - PATCH(ldap_filter_pre);
15224 - PATCH(ldap_filter_post);
15225 + PATCH_OPTION(ldap);
15226 + PATCH_OPTION(ldap_filter_pre);
15227 + PATCH_OPTION(ldap_filter_post);
15229 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
15230 - PATCH(auth_ldap_basedn);
15231 + PATCH_OPTION(auth_ldap_basedn);
15232 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
15233 - PATCH(auth_ldap_filter);
15234 + PATCH_OPTION(auth_ldap_filter);
15235 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
15236 - PATCH(auth_ldap_cafile);
15237 + PATCH_OPTION(auth_ldap_cafile);
15238 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
15239 - PATCH(auth_ldap_starttls);
15240 + PATCH_OPTION(auth_ldap_starttls);
15250 static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
15252 @@ -175,22 +174,22 @@
15254 mod_auth_plugin_data *p = p_d;
15258 /* select the right config */
15259 mod_auth_patch_connection(srv, con, p);
15262 if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
15272 /* do we have to ask for auth ? */
15276 auth_satisfied = 0;
15279 /* search auth-directives for path */
15280 for (k = 0; k < p->conf.auth_require->used; k++) {
15281 buffer *req = p->conf.auth_require->data[k]->key;
15282 @@ -212,31 +211,31 @@
15288 /* nothing to do for us */
15289 if (auth_required == 0) return HANDLER_GO_ON;
15292 req = ((data_array *)(p->conf.auth_require->data[k]))->value;
15295 /* try to get Authorization-header */
15298 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
15299 http_authorization = ds->value->ptr;
15303 if (ds && ds->value && ds->value->used) {
15305 data_string *method;
15308 method = (data_string *)array_get_element(req, "method");
15311 /* parse auth-header */
15312 if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
15313 int auth_type_len = auth_realm - http_authorization;
15316 if ((auth_type_len == 5) &&
15317 (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
15320 if (0 == strcmp(method->value->ptr, "basic")) {
15321 auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
15323 @@ -245,43 +244,43 @@
15324 if (0 == strcmp(method->value->ptr, "digest")) {
15325 if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
15326 con->http_status = 400;
15329 /* a field was missing */
15332 return HANDLER_FINISHED;
15336 - log_error_write(srv, __FILE__, __LINE__, "ss",
15337 + log_error_write(srv, __FILE__, __LINE__, "ss",
15338 "unknown authentification type:",
15339 http_authorization);
15345 if (!auth_satisfied) {
15346 data_string *method, *realm;
15347 method = (data_string *)array_get_element(req, "method");
15348 realm = (data_string *)array_get_element(req, "realm");
15351 con->http_status = 401;
15354 if (0 == strcmp(method->value->ptr, "basic")) {
15355 buffer_copy_string(p->tmp_buf, "Basic realm=\"");
15356 buffer_append_string_buffer(p->tmp_buf, realm->value);
15357 buffer_append_string(p->tmp_buf, "\"");
15360 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15361 } else if (0 == strcmp(method->value->ptr, "digest")) {
15363 http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
15366 buffer_copy_string(p->tmp_buf, "Digest realm=\"");
15367 buffer_append_string_buffer(p->tmp_buf, realm->value);
15368 buffer_append_string(p->tmp_buf, "\", nonce=\"");
15369 buffer_append_string(p->tmp_buf, hh);
15370 buffer_append_string(p->tmp_buf, "\", qop=\"auth\"");
15373 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15376 @@ -289,18 +288,18 @@
15377 return HANDLER_FINISHED;
15379 /* the REMOTE_USER header */
15382 buffer_copy_string_buffer(con->authed_user, p->auth_user);
15386 return HANDLER_GO_ON;
15389 SETDEFAULTS_FUNC(mod_auth_set_defaults) {
15390 mod_auth_plugin_data *p = p_d;
15393 - config_values_t cv[] = {
15395 + config_values_t cv[] = {
15396 { "auth.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15397 { "auth.backend.plain.groupfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15398 { "auth.backend.plain.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15399 @@ -317,7 +316,7 @@
15400 { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
15401 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
15405 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15407 for (i = 0; i < srv->config_context->used; i++) {
15408 @@ -325,14 +324,14 @@
15414 s = calloc(1, sizeof(mod_auth_plugin_config));
15415 s->auth_plain_groupfile = buffer_init();
15416 s->auth_plain_userfile = buffer_init();
15417 s->auth_htdigest_userfile = buffer_init();
15418 s->auth_htpasswd_userfile = buffer_init();
15419 s->auth_backend_conf = buffer_init();
15422 s->auth_ldap_hostname = buffer_init();
15423 s->auth_ldap_basedn = buffer_init();
15424 s->auth_ldap_binddn = buffer_init();
15425 @@ -341,15 +340,15 @@
15426 s->auth_ldap_cafile = buffer_init();
15427 s->auth_ldap_starttls = 0;
15431 s->auth_require = array_init();
15435 s->ldap_filter_pre = buffer_init();
15436 s->ldap_filter_post = buffer_init();
15441 cv[0].destination = s->auth_backend_conf;
15442 cv[1].destination = s->auth_plain_groupfile;
15443 cv[2].destination = s->auth_plain_userfile;
15444 @@ -364,14 +363,14 @@
15445 cv[11].destination = s->auth_htdigest_userfile;
15446 cv[12].destination = s->auth_htpasswd_userfile;
15447 cv[13].destination = &(s->auth_debug);
15450 p->config_storage[i] = s;
15451 ca = ((data_config *)srv->config_context->data[i])->value;
15454 if (0 != config_insert_values_global(srv, ca, cv)) {
15455 return HANDLER_ERROR;
15459 if (s->auth_backend_conf->used) {
15460 if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
15461 s->auth_backend = AUTH_BACKEND_HTPASSWD;
15462 @@ -383,31 +382,31 @@
15463 s->auth_backend = AUTH_BACKEND_LDAP;
15465 log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
15468 return HANDLER_ERROR;
15472 /* no auth.require for this section */
15473 if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
15476 if (da->type != TYPE_ARRAY) continue;
15479 for (n = 0; n < da->value->used; n++) {
15481 data_array *da_file = (data_array *)da->value->data[n];
15482 const char *method, *realm, *require;
15485 if (da->value->data[n]->type != TYPE_ARRAY) {
15486 - log_error_write(srv, __FILE__, __LINE__, "ss",
15487 - "auth.require should contain an array as in:",
15488 + log_error_write(srv, __FILE__, __LINE__, "ss",
15489 + "auth.require should contain an array as in:",
15490 "auth.require = ( \"...\" => ( ..., ...) )");
15492 return HANDLER_ERROR;
15496 method = realm = require = NULL;
15499 for (m = 0; m < da_file->value->used; m++) {
15500 if (da_file->value->data[m]->type == TYPE_STRING) {
15501 if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
15502 @@ -417,8 +416,8 @@
15503 } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
15504 require = ((data_string *)(da_file->value->data[m]))->value->ptr;
15506 - log_error_write(srv, __FILE__, __LINE__, "ssbs",
15507 - "the field is unknown in:",
15508 + log_error_write(srv, __FILE__, __LINE__, "ssbs",
15509 + "the field is unknown in:",
15510 "auth.require = ( \"...\" => ( ..., -> \"",
15511 da_file->value->data[m]->key,
15512 "\" <- => \"...\" ) )");
15513 @@ -426,19 +425,19 @@
15514 return HANDLER_ERROR;
15517 - log_error_write(srv, __FILE__, __LINE__, "ssbs",
15518 - "a string was expected for:",
15519 + log_error_write(srv, __FILE__, __LINE__, "ssbs",
15520 + "a string was expected for:",
15521 "auth.require = ( \"...\" => ( ..., -> \"",
15522 da_file->value->data[m]->key,
15523 "\" <- => \"...\" ) )");
15526 return HANDLER_ERROR;
15531 if (method == NULL) {
15532 - log_error_write(srv, __FILE__, __LINE__, "ss",
15533 - "the require field is missing in:",
15534 + log_error_write(srv, __FILE__, __LINE__, "ss",
15535 + "the require field is missing in:",
15536 "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
15537 return HANDLER_ERROR;
15539 @@ -450,60 +449,60 @@
15540 return HANDLER_ERROR;
15545 if (realm == NULL) {
15546 - log_error_write(srv, __FILE__, __LINE__, "ss",
15547 - "the require field is missing in:",
15548 + log_error_write(srv, __FILE__, __LINE__, "ss",
15549 + "the require field is missing in:",
15550 "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
15551 return HANDLER_ERROR;
15555 if (require == NULL) {
15556 - log_error_write(srv, __FILE__, __LINE__, "ss",
15557 - "the require field is missing in:",
15558 + log_error_write(srv, __FILE__, __LINE__, "ss",
15559 + "the require field is missing in:",
15560 "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
15561 return HANDLER_ERROR;
15565 if (method && realm && require) {
15570 a = data_array_init();
15571 buffer_copy_string_buffer(a->key, da_file->key);
15574 ds = data_string_init();
15577 buffer_copy_string(ds->key, "method");
15578 buffer_copy_string(ds->value, method);
15581 array_insert_unique(a->value, (data_unset *)ds);
15584 ds = data_string_init();
15587 buffer_copy_string(ds->key, "realm");
15588 buffer_copy_string(ds->value, realm);
15591 array_insert_unique(a->value, (data_unset *)ds);
15594 ds = data_string_init();
15597 buffer_copy_string(ds->key, "require");
15598 buffer_copy_string(ds->value, require);
15601 array_insert_unique(a->value, (data_unset *)ds);
15604 array_insert_unique(s->auth_require, (data_unset *)a);
15609 switch(s->auth_backend) {
15610 case AUTH_BACKEND_PLAIN:
15611 if (s->auth_plain_userfile->used) {
15614 if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) {
15615 - log_error_write(srv, __FILE__, __LINE__, "sbss",
15616 + log_error_write(srv, __FILE__, __LINE__, "sbss",
15617 "opening auth.backend.plain.userfile:", s->auth_plain_userfile,
15618 "failed:", strerror(errno));
15619 return HANDLER_ERROR;
15620 @@ -516,7 +515,7 @@
15623 if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) {
15624 - log_error_write(srv, __FILE__, __LINE__, "sbss",
15625 + log_error_write(srv, __FILE__, __LINE__, "sbss",
15626 "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile,
15627 "failed:", strerror(errno));
15628 return HANDLER_ERROR;
15629 @@ -529,7 +528,7 @@
15632 if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) {
15633 - log_error_write(srv, __FILE__, __LINE__, "sbss",
15634 + log_error_write(srv, __FILE__, __LINE__, "sbss",
15635 "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile,
15636 "failed:", strerror(errno));
15637 return HANDLER_ERROR;
15638 @@ -554,75 +553,75 @@
15639 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
15644 if (s->auth_ldap_basedn->used == 0) {
15645 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
15648 return HANDLER_ERROR;
15653 if (s->auth_ldap_filter->used) {
15660 if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
15661 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
15664 return HANDLER_ERROR;
15668 buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
15669 buffer_copy_string(s->ldap_filter_post, dollar+1);
15673 if (s->auth_ldap_hostname->used) {
15674 if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
15675 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
15678 return HANDLER_ERROR;
15682 ret = LDAP_VERSION3;
15683 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
15684 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15687 return HANDLER_ERROR;
15690 if (s->auth_ldap_starttls) {
15691 - /* if no CA file is given, it is ok, as we will use encryption
15692 + /* if no CA file is given, it is ok, as we will use encryption
15693 * if the server requires a CAfile it will tell us */
15694 if (!buffer_is_empty(s->auth_ldap_cafile)) {
15695 - if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
15696 + if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
15697 s->auth_ldap_cafile->ptr))) {
15698 - log_error_write(srv, __FILE__, __LINE__, "ss",
15699 + log_error_write(srv, __FILE__, __LINE__, "ss",
15700 "Loading CA certificate failed:", ldap_err2string(ret));
15703 return HANDLER_ERROR;
15708 if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL, NULL))) {
15709 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
15712 return HANDLER_ERROR;
15720 if (s->auth_ldap_binddn->used) {
15721 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
15722 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15725 return HANDLER_ERROR;
15728 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
15729 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15732 return HANDLER_ERROR;
15735 @@ -641,8 +640,8 @@
15736 p->set_defaults = mod_auth_set_defaults;
15737 p->handle_uri_clean = mod_auth_uri_handler;
15738 p->cleanup = mod_auth_free;
15746 --- lighttpd-1.4.11/src/mod_cgi.c 2006-02-22 15:15:10.000000000 +0200
15747 +++ lighttpd-1.4.12/src/mod_cgi.c 2006-07-11 22:07:51.000000000 +0300
15749 #include <sys/types.h>
15751 -#include <winsock2.h>
15753 -#include <sys/socket.h>
15754 -#include <sys/wait.h>
15755 -#include <sys/mman.h>
15757 -#include <netinet/in.h>
15759 -#include <arpa/inet.h>
15762 -#include <unistd.h>
15764 #include <stdlib.h>
15765 #include <string.h>
15766 -#include <fdevent.h>
15767 #include <signal.h>
15769 #include <assert.h>
15771 #include "connections.h"
15772 #include "joblist.h"
15773 #include "http_chunk.h"
15774 +#include "fdevent.h"
15776 #include "plugin.h"
15778 +#include "sys-files.h"
15779 +#include "sys-mmap.h"
15780 +#include "sys-socket.h"
15781 +#include "sys-strings.h"
15782 +#include "sys-process.h"
15784 #ifdef HAVE_SYS_FILIO_H
15785 # include <sys/filio.h>
15787 @@ -40,11 +34,12 @@
15801 @@ -58,23 +53,23 @@
15804 buffer_pid_t cgi_pid;
15808 buffer *parse_response;
15811 plugin_config **config_storage;
15813 - plugin_config conf;
15815 + plugin_config conf;
15821 int fde_ndx; /* index into the fd-event buffer */
15824 connection *remote_conn; /* dumb pointer */
15825 plugin_data *plugin_data; /* dumb pointer */
15829 buffer *response_header;
15831 @@ -83,17 +78,17 @@
15832 handler_ctx *hctx = calloc(1, sizeof(*hctx));
15837 hctx->response = buffer_init();
15838 hctx->response_header = buffer_init();
15844 static void cgi_handler_ctx_free(handler_ctx *hctx) {
15845 buffer_free(hctx->response);
15846 buffer_free(hctx->response_header);
15852 @@ -101,14 +96,14 @@
15854 INIT_FUNC(mod_cgi_init) {
15858 p = calloc(1, sizeof(*p));
15863 p->tmp_buf = buffer_init();
15864 p->parse_response = buffer_init();
15870 @@ -116,62 +111,62 @@
15871 FREE_FUNC(mod_cgi_free) {
15872 plugin_data *p = p_d;
15873 buffer_pid_t *r = &(p->cgi_pid);
15879 if (p->config_storage) {
15881 for (i = 0; i < srv->config_context->used; i++) {
15882 plugin_config *s = p->config_storage[i];
15885 array_free(s->cgi);
15890 free(p->config_storage);
15895 if (r->ptr) free(r->ptr);
15898 buffer_free(p->tmp_buf);
15899 buffer_free(p->parse_response);
15905 return HANDLER_GO_ON;
15908 SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
15909 plugin_data *p = p_d;
15912 - config_values_t cv[] = {
15914 + config_values_t cv[] = {
15915 { "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15916 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
15919 if (!p) return HANDLER_ERROR;
15922 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15925 for (i = 0; i < srv->config_context->used; i++) {
15929 s = calloc(1, sizeof(plugin_config));
15933 s->cgi = array_init();
15936 cv[0].destination = s->cgi;
15939 p->config_storage[i] = s;
15942 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
15943 return HANDLER_ERROR;
15948 return HANDLER_GO_ON;
15951 @@ -180,13 +175,13 @@
15954 buffer_pid_t *r = &(p->cgi_pid);
15959 for (i = 0; i < r->used; i++) {
15960 if (r->ptr[i] > m) m = r->ptr[i];
15964 if (r->size == 0) {
15966 r->ptr = malloc(sizeof(*r->ptr) * r->size);
15967 @@ -194,31 +189,31 @@
15969 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
15973 r->ptr[r->used++] = pid;
15979 static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
15981 buffer_pid_t *r = &(p->cgi_pid);
15986 for (i = 0; i < r->used; i++) {
15987 if (r->ptr[i] == pid) break;
15991 if (i != r->used) {
15995 if (i != r->used - 1) {
15996 r->ptr[i] = r->ptr[r->used - 1];
16005 @@ -226,32 +221,32 @@
16014 buffer_copy_string_buffer(p->parse_response, in);
16016 - for (s = p->parse_response->ptr;
16017 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
16019 + for (s = p->parse_response->ptr;
16020 + NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
16021 s = ns + (eol == EOL_RN ? 2 : 1), line++) {
16022 const char *key, *value;
16032 0 == strncmp(s, "HTTP/1.", 7)) {
16033 /* non-parsed header ... we parse them anyway */
16036 if ((s[7] == '1' ||
16040 /* after the space should be a status code for us */
16043 status = strtol(s+9, NULL, 10);
16046 if (con->http_status >= 100 &&
16047 con->http_status < 1000) {
16048 /* we expected 3 digits and didn't got them */
16049 @@ -260,27 +255,27 @@
16056 if (NULL == (value = strchr(s, ':'))) {
16057 /* we expect: "<key>: <value>\r\n" */
16062 key_len = value - key;
16067 while (*value == ' ' || *value == '\t') value++;
16070 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
16071 ds = data_response_init();
16073 buffer_copy_string_len(ds->key, key, key_len);
16074 buffer_copy_string(ds->value, value);
16077 array_insert_unique(con->response.headers, (data_unset *)ds);
16082 if (0 == strncasecmp(key, "Date", key_len)) {
16083 @@ -315,13 +310,13 @@
16089 /* CGI/1.1 rev 03 - 7.2.1.2 */
16090 if ((con->parsed_response & HTTP_LOCATION) &&
16091 !(con->parsed_response & HTTP_STATUS)) {
16092 con->http_status = 302;
16099 @@ -329,10 +324,10 @@
16100 static int cgi_demux_response(server *srv, handler_ctx *hctx) {
16101 plugin_data *p = hctx->plugin_data;
16102 connection *con = hctx->remote_conn;
16109 buffer_prepare_copy(hctx->response, 1024);
16110 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
16111 if (errno == EAGAIN || errno == EINTR) {
16112 @@ -343,125 +338,125 @@
16113 log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
16114 return FDEVENT_HANDLED_ERROR;
16119 /* read finished */
16122 con->file_finished = 1;
16125 /* send final chunk */
16126 http_chunk_append_mem(srv, con, NULL, 0);
16127 joblist_append(srv, con);
16130 return FDEVENT_HANDLED_FINISHED;
16134 hctx->response->ptr[n] = '\0';
16135 hctx->response->used = n+1;
16138 /* split header from body */
16141 if (con->file_started == 0) {
16144 int header_end = 0;
16145 int cp, eol = EOL_UNSET;
16149 buffer_append_string_buffer(hctx->response_header, hctx->response);
16152 /* nph (non-parsed headers) */
16153 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
16156 /* search for the \r\n\r\n or \n\n in the string */
16157 for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
16158 if (*c == ':') in_header = 1;
16159 else if (*c == '\n') {
16160 if (in_header == 0) {
16161 /* got a response without a response header */
16170 if (eol == EOL_UNSET) eol = EOL_N;
16173 if (*(c+1) == '\n') {
16179 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
16180 if (in_header == 0) {
16181 /* got a response without a response header */
16190 if (eol == EOL_UNSET) eol = EOL_RN;
16194 - *(c+2) == '\r' &&
16195 + *(c+2) == '\r' &&
16212 /* no header, but a body */
16215 if (con->request.http_version == HTTP_VERSION_1_1) {
16216 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
16220 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16221 joblist_append(srv, con);
16223 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
16224 size_t blen = hctx->response_header->used - hlen - 1;
16227 /* a small hack: terminate after at the second \r */
16228 hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
16229 hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
16232 /* parse the response header */
16233 cgi_response_parse(srv, con, p, hctx->response_header, eol);
16236 /* enable chunked-transfer-encoding */
16237 if (con->request.http_version == HTTP_VERSION_1_1 &&
16238 !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
16239 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
16243 if ((hctx->response->used != hlen) && blen > 0) {
16244 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
16245 joblist_append(srv, con);
16250 con->file_started = 1;
16253 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
16254 joblist_append(srv, con);
16260 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
16265 return FDEVENT_HANDLED_NOT_FINISHED;
16268 @@ -470,45 +465,46 @@
16274 if (NULL == hctx) return HANDLER_GO_ON;
16277 p = hctx->plugin_data;
16278 con = hctx->remote_conn;
16281 if (con->mode != p->id) return HANDLER_GO_ON;
16287 /* the connection to the browser went away, but we still have a connection
16288 - * to the CGI script
16289 + * to the CGI script
16291 * close cgi-connection
16295 if (hctx->fd != -1) {
16296 /* close connection to the cgi-script */
16297 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16298 fdevent_unregister(srv->ev, hctx->fd);
16301 if (close(hctx->fd)) {
16302 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16307 hctx->fde_ndx = -1;
16314 con->plugin_ctx[p->id] = NULL;
16317 /* is this a good idea ? */
16318 cgi_handler_ctx_free(hctx);
16321 /* if waitpid hasn't been called by response.c yet, do it here */
16323 /* check if the CGI-script is already gone */
16325 switch(waitpid(pid, &status, WNOHANG)) {
16327 /* not finished yet */
16328 @@ -519,19 +515,19 @@
16331 if (errno == EINTR) break;
16334 - * errno == ECHILD happens if _subrequest catches the process-status before
16337 + * errno == ECHILD happens if _subrequest catches the process-status before
16338 * we have read the response of the cgi process
16342 * -> WAIT_FOR_EVENT
16344 * -> we get here with waitpid == ECHILD
16348 if (errno == ECHILD) return HANDLER_GO_ON;
16351 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16352 return HANDLER_ERROR;
16354 @@ -541,13 +537,13 @@
16355 con->http_status = 500;
16356 con->mode = DIRECT;
16360 if (WIFEXITED(status)) {
16362 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
16367 return HANDLER_GO_ON;
16369 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
16370 @@ -555,20 +551,20 @@
16371 return HANDLER_GO_ON;
16378 kill(pid, SIGTERM);
16381 /* cgi-script is still alive, queue the PID for removal */
16382 cgi_pid_add(srv, p, pid);
16386 return HANDLER_GO_ON;
16389 static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
16390 plugin_data *p = p_d;
16393 return cgi_connection_close(srv, con->plugin_ctx[p->id]);
16396 @@ -577,43 +573,43 @@
16397 server *srv = (server *)s;
16398 handler_ctx *hctx = ctx;
16399 connection *con = hctx->remote_conn;
16402 joblist_append(srv, con);
16405 if (hctx->fd == -1) {
16406 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
16409 return HANDLER_ERROR;
16413 if (revents & FDEVENT_IN) {
16414 switch (cgi_demux_response(srv, hctx)) {
16415 case FDEVENT_HANDLED_NOT_FINISHED:
16417 case FDEVENT_HANDLED_FINISHED:
16422 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
16424 cgi_connection_close(srv, hctx);
16426 - /* if we get a IN|HUP and have read everything don't exec the close twice */
16428 + /* if we get a IN|HUP and have read everything don't exec the close twice */
16429 return HANDLER_FINISHED;
16430 case FDEVENT_HANDLED_ERROR:
16431 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
16432 con->http_status = 500;
16433 con->mode = DIRECT;
16436 log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
16442 if (revents & FDEVENT_OUT) {
16443 /* nothing to do */
16447 /* perhaps this issue is already handled */
16448 if (revents & FDEVENT_HUP) {
16449 /* check if we still have a unfinished header package which is a body in reality */
16450 @@ -623,54 +619,54 @@
16451 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16452 joblist_append(srv, con);
16456 if (con->file_finished == 0) {
16457 http_chunk_append_mem(srv, con, NULL, 0);
16458 joblist_append(srv, con);
16462 con->file_finished = 1;
16465 if (chunkqueue_is_empty(con->write_queue)) {
16466 /* there is nothing left to write */
16467 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
16469 /* used the write-handler to finish the request on demand */
16476 log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
16480 /* rtsigs didn't liked the close */
16481 cgi_connection_close(srv, hctx);
16482 } else if (revents & FDEVENT_ERR) {
16483 con->file_finished = 1;
16486 /* kill all connections to the cgi process */
16487 cgi_connection_close(srv, hctx);
16489 log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
16492 return HANDLER_ERROR;
16496 return HANDLER_FINISHED;
16500 static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
16504 if (!key || !val) return -1;
16507 dst = malloc(key_len + val_len + 3);
16508 memcpy(dst, key, key_len);
16509 dst[key_len] = '=';
16510 /* add the \0 from the value */
16511 memcpy(dst + key_len + 1, val, val_len + 1);
16514 if (env->size == 0) {
16516 env->ptr = malloc(env->size * sizeof(*env->ptr));
16517 @@ -678,45 +674,45 @@
16519 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
16523 env->ptr[env->used++] = dst;
16529 static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
16534 char b2[INET6_ADDRSTRLEN + 1];
16539 int from_cgi_fds[2];
16547 if (cgi_handler->used > 1) {
16548 /* stat the exec file */
16549 if (-1 == (stat(cgi_handler->ptr, &st))) {
16550 - log_error_write(srv, __FILE__, __LINE__, "sbss",
16551 + log_error_write(srv, __FILE__, __LINE__, "sbss",
16552 "stat for cgi-handler", cgi_handler,
16553 "failed:", strerror(errno));
16559 if (pipe(to_cgi_fds)) {
16560 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16565 if (pipe(from_cgi_fds)) {
16566 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16572 switch (pid = fork()) {
16574 @@ -730,22 +726,22 @@
16577 server_socket *srv_sock = con->srv_socket;
16580 /* move stdout to from_cgi_fd[1] */
16581 close(STDOUT_FILENO);
16582 dup2(from_cgi_fds[1], STDOUT_FILENO);
16583 close(from_cgi_fds[1]);
16585 close(from_cgi_fds[0]);
16588 /* move the stdin to to_cgi_fd[0] */
16589 close(STDIN_FILENO);
16590 dup2(to_cgi_fds[0], STDIN_FILENO);
16591 close(to_cgi_fds[0]);
16593 close(to_cgi_fds[1]);
16598 * this is not nice, but it works
16600 * we feed the stderr of the CGI to our errorlog, if possible
16601 @@ -754,20 +750,20 @@
16602 close(STDERR_FILENO);
16603 dup2(srv->errorlog_fd, STDERR_FILENO);
16607 /* create environment */
16613 cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
16615 if (!buffer_is_empty(con->server_name)) {
16616 cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
16619 - s = inet_ntop(srv_sock->addr.plain.sa_family,
16620 - srv_sock->addr.plain.sa_family == AF_INET6 ?
16621 + s = inet_ntop(srv_sock->addr.plain.sa_family,
16622 + srv_sock->addr.plain.sa_family == AF_INET6 ?
16623 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16624 (const void *) &(srv_sock->addr.ipv4.sin_addr),
16626 @@ -779,10 +775,10 @@
16627 cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
16629 s = get_http_version_name(con->request.http_version);
16632 cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
16638 ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
16640 @@ -790,10 +786,10 @@
16643 cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
16647 - s = inet_ntop(srv_sock->addr.plain.sa_family,
16648 - srv_sock->addr.plain.sa_family == AF_INET6 ?
16649 + s = inet_ntop(srv_sock->addr.plain.sa_family,
16650 + srv_sock->addr.plain.sa_family == AF_INET6 ?
16651 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16652 (const void *) &(srv_sock->addr.ipv4.sin_addr),
16654 @@ -811,15 +807,18 @@
16655 cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
16656 if (!buffer_is_empty(con->uri.query)) {
16657 cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
16659 + /* set a empty QUERY_STRING */
16660 + cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
16662 if (!buffer_is_empty(con->request.orig_uri)) {
16663 cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
16670 - s = inet_ntop(con->dst_addr.plain.sa_family,
16671 - con->dst_addr.plain.sa_family == AF_INET6 ?
16672 + s = inet_ntop(con->dst_addr.plain.sa_family,
16673 + con->dst_addr.plain.sa_family == AF_INET6 ?
16674 (const void *) &(con->dst_addr.ipv6.sin6_addr) :
16675 (const void *) &(con->dst_addr.ipv4.sin_addr),
16677 @@ -828,7 +827,7 @@
16679 cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
16684 ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
16686 @@ -836,19 +835,19 @@
16689 cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
16692 if (!buffer_is_empty(con->authed_user)) {
16693 cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
16694 CONST_BUF_LEN(con->authed_user));
16698 /* request.content_length < SSIZE_MAX, see request.c */
16699 ltostr(buf, con->request.content_length);
16700 cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
16701 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
16702 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
16703 cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
16707 if (NULL != (s = getenv("LD_PRELOAD"))) {
16708 cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
16709 @@ -863,24 +862,24 @@
16710 cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
16715 for (n = 0; n < con->request.headers->used; n++) {
16719 ds = (data_string *)con->request.headers->data[n];
16722 if (ds->value->used && ds->key->used) {
16726 buffer_reset(p->tmp_buf);
16729 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
16730 buffer_copy_string(p->tmp_buf, "HTTP_");
16731 p->tmp_buf->used--; /* strip \0 after HTTP_ */
16735 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16738 for (j = 0; j < ds->key->used - 1; j++) {
16740 if (light_isalpha(ds->key->ptr[j])) {
16741 @@ -893,46 +892,46 @@
16742 p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
16744 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16747 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16752 for (n = 0; n < con->environment->used; n++) {
16756 ds = (data_string *)con->environment->data[n];
16759 if (ds->value->used && ds->key->used) {
16763 buffer_reset(p->tmp_buf);
16766 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16769 for (j = 0; j < ds->key->used - 1; j++) {
16770 - p->tmp_buf->ptr[p->tmp_buf->used++] =
16771 - isalpha((unsigned char)ds->key->ptr[j]) ?
16772 + p->tmp_buf->ptr[p->tmp_buf->used++] =
16773 + isalpha((unsigned char)ds->key->ptr[j]) ?
16774 toupper((unsigned char)ds->key->ptr[j]) : '_';
16776 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16779 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16784 if (env.size == env.used) {
16786 env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
16790 env.ptr[env.used] = NULL;
16795 args = malloc(sizeof(*args) * argc);
16799 if (cgi_handler->used > 1) {
16800 args[i++] = cgi_handler->ptr;
16802 @@ -942,7 +941,7 @@
16803 /* search for the last / */
16804 if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
16808 /* change to the physical directory */
16809 if (-1 == chdir(con->physical.path->ptr)) {
16810 log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
16811 @@ -954,12 +953,12 @@
16812 for (i = 3; i < 256; i++) {
16813 if (i != srv->errorlog_fd) close(i);
16818 execve(args[0], args, env.ptr);
16821 log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
16827 @@ -974,11 +973,11 @@
16829 close(from_cgi_fds[1]);
16830 close(to_cgi_fds[0]);
16833 if (con->request.content_length) {
16834 chunkqueue *cq = con->request_content_queue;
16838 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
16840 /* there is content to send */
16841 @@ -993,16 +992,16 @@
16842 if (-1 == c->file.fd && /* open the file if not already open */
16843 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
16844 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
16847 close(from_cgi_fds[0]);
16848 close(to_cgi_fds[1]);
16852 c->file.mmap.length = c->file.length;
16855 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
16856 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
16857 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
16858 strerror(errno), c->file.name, c->file.fd);
16860 close(from_cgi_fds[0]);
16861 @@ -1012,7 +1011,7 @@
16867 /* chunk_reset() or chunk_free() will cleanup for us */
16870 @@ -1020,7 +1019,7 @@
16873 con->http_status = 507;
16878 con->http_status = 403;
16879 @@ -1033,7 +1032,7 @@
16882 con->http_status = 507;
16887 con->http_status = 403;
16888 @@ -1056,103 +1055,100 @@
16891 close(to_cgi_fds[1]);
16894 /* register PID and wait for them asyncronously */
16896 buffer_reset(con->physical.path);
16899 hctx = cgi_handler_ctx_init();
16902 hctx->remote_conn = con;
16903 hctx->plugin_data = p;
16905 hctx->fd = from_cgi_fds[0];
16906 hctx->fde_ndx = -1;
16909 con->plugin_ctx[p->id] = hctx;
16912 fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
16913 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
16916 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
16917 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
16920 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16921 fdevent_unregister(srv->ev, hctx->fd);
16924 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
16930 cgi_handler_ctx_free(hctx);
16933 con->plugin_ctx[p->id] = NULL;
16951 -#define PATCH(x) \
16952 - p->conf.x = s->x;
16953 static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
16955 plugin_config *s = p->config_storage[0];
16960 + PATCH_OPTION(cgi);
16962 /* skip the first, the global context */
16963 for (i = 1; i < srv->config_context->used; i++) {
16964 data_config *dc = (data_config *)srv->config_context->data[i];
16965 s = p->config_storage[i];
16968 /* condition didn't match */
16969 if (!config_check_cond(srv, con, dc)) continue;
16973 for (j = 0; j < dc->value->used; j++) {
16974 data_unset *du = dc->value->data[j];
16977 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
16979 + PATCH_OPTION(cgi);
16989 URIHANDLER_FUNC(cgi_is_handled) {
16991 plugin_data *p = p_d;
16992 buffer *fn = con->physical.path;
16995 if (fn->used == 0) return HANDLER_GO_ON;
16998 mod_cgi_patch_connection(srv, con, p);
17001 s_len = fn->used - 1;
17004 for (k = 0; k < p->conf.cgi->used; k++) {
17005 data_string *ds = (data_string *)p->conf.cgi->data[k];
17006 size_t ct_len = ds->key->used - 1;
17009 if (ds->key->used == 0) continue;
17010 if (s_len < ct_len) continue;
17013 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
17014 if (cgi_create_env(srv, con, p, ds->value)) {
17015 con->http_status = 500;
17018 buffer_reset(con->physical.path);
17019 return HANDLER_FINISHED;
17021 @@ -1160,7 +1156,7 @@
17027 return HANDLER_GO_ON;
17030 @@ -1168,11 +1164,11 @@
17031 plugin_data *p = p_d;
17033 /* the trigger handle only cares about lonely PID which we have to wait for */
17037 for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
17041 switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
17043 /* not finished yet */
17044 @@ -1182,7 +1178,7 @@
17047 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
17050 return HANDLER_ERROR;
17053 @@ -1193,16 +1189,16 @@
17055 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
17059 cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
17060 - /* del modified the buffer structure
17061 + /* del modified the buffer structure
17062 * and copies the last entry to the current one
17063 * -> recheck the current index
17070 return HANDLER_GO_ON;
17073 @@ -1210,15 +1206,15 @@
17075 plugin_data *p = p_d;
17076 handler_ctx *hctx = con->plugin_ctx[p->id];
17079 if (con->mode != p->id) return HANDLER_GO_ON;
17080 if (NULL == hctx) return HANDLER_GO_ON;
17084 log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
17087 if (hctx->pid == 0) return HANDLER_FINISHED;
17090 switch(waitpid(hctx->pid, &status, WNOHANG)) {
17092 /* we only have for events here if we don't have the header yet,
17093 @@ -1228,61 +1224,61 @@
17094 return HANDLER_WAIT_FOR_EVENT;
17096 if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
17099 if (errno == ECHILD && con->file_started == 0) {
17101 - * second round but still not response
17102 + * second round but still not response
17104 - return HANDLER_WAIT_FOR_EVENT;
17105 + return HANDLER_WAIT_FOR_EVENT;
17109 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
17110 con->mode = DIRECT;
17111 con->http_status = 500;
17117 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
17118 fdevent_unregister(srv->ev, hctx->fd);
17121 if (close(hctx->fd)) {
17122 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
17126 cgi_handler_ctx_free(hctx);
17129 con->plugin_ctx[p->id] = NULL;
17132 return HANDLER_FINISHED;
17134 - /* cgi process exited cleanly
17136 - * check if we already got the response
17137 + /* cgi process exited cleanly
17139 + * check if we already got the response
17143 if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
17146 if (WIFEXITED(status)) {
17149 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
17152 con->mode = DIRECT;
17153 con->http_status = 500;
17162 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
17163 fdevent_unregister(srv->ev, hctx->fd);
17166 if (close(hctx->fd)) {
17167 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
17171 cgi_handler_ctx_free(hctx);
17174 con->plugin_ctx[p->id] = NULL;
17175 return HANDLER_FINISHED;
17177 @@ -1306,8 +1302,8 @@
17178 p->init = mod_cgi_init;
17179 p->cleanup = mod_cgi_free;
17180 p->set_defaults = mod_fastcgi_set_defaults;
17188 --- lighttpd-1.4.11/src/mod_cml.c 2006-01-30 13:51:48.000000000 +0200
17189 +++ lighttpd-1.4.12/src/mod_cml.c 2006-07-11 22:07:51.000000000 +0300
17191 #include <stdlib.h>
17192 #include <string.h>
17194 -#include <unistd.h>
17197 #include "buffer.h"
17198 @@ -20,50 +19,50 @@
17199 /* init the plugin data */
17200 INIT_FUNC(mod_cml_init) {
17204 p = calloc(1, sizeof(*p));
17207 p->basedir = buffer_init();
17208 p->baseurl = buffer_init();
17209 p->trigger_handler = buffer_init();
17215 /* detroy the plugin data */
17216 FREE_FUNC(mod_cml_free) {
17217 plugin_data *p = p_d;
17222 if (!p) return HANDLER_GO_ON;
17225 if (p->config_storage) {
17227 for (i = 0; i < srv->config_context->used; i++) {
17228 plugin_config *s = p->config_storage[i];
17231 buffer_free(s->ext);
17234 buffer_free(s->mc_namespace);
17235 buffer_free(s->power_magnet);
17236 array_free(s->mc_hosts);
17239 #if defined(HAVE_MEMCACHE_H)
17240 if (s->mc) mc_free(s->mc);
17246 free(p->config_storage);
17250 buffer_free(p->trigger_handler);
17251 buffer_free(p->basedir);
17252 buffer_free(p->baseurl);
17258 return HANDLER_GO_ON;
17261 @@ -72,22 +71,22 @@
17262 SETDEFAULTS_FUNC(mod_cml_set_defaults) {
17263 plugin_data *p = p_d;
17266 - config_values_t cv[] = {
17268 + config_values_t cv[] = {
17269 { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
17270 { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
17271 { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
17272 { "cml.power-magnet", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
17273 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
17277 if (!p) return HANDLER_ERROR;
17280 p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
17283 for (i = 0; i < srv->config_context->used; i++) {
17287 s = malloc(sizeof(plugin_config));
17288 s->ext = buffer_init();
17289 s->mc_hosts = array_init();
17290 @@ -96,87 +95,84 @@
17291 #if defined(HAVE_MEMCACHE_H)
17296 cv[0].destination = s->ext;
17297 cv[1].destination = s->mc_hosts;
17298 cv[2].destination = s->mc_namespace;
17299 cv[3].destination = s->power_magnet;
17302 p->config_storage[i] = s;
17305 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
17306 return HANDLER_ERROR;
17310 if (s->mc_hosts->used) {
17311 #if defined(HAVE_MEMCACHE_H)
17316 for (k = 0; k < s->mc_hosts->used; k++) {
17317 data_string *ds = (data_string *)s->mc_hosts->data[k];
17320 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
17321 - log_error_write(srv, __FILE__, __LINE__, "sb",
17322 - "connection to host failed:",
17323 + log_error_write(srv, __FILE__, __LINE__, "sb",
17324 + "connection to host failed:",
17328 return HANDLER_ERROR;
17332 - log_error_write(srv, __FILE__, __LINE__, "s",
17333 + log_error_write(srv, __FILE__, __LINE__, "s",
17334 "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
17335 return HANDLER_ERROR;
17341 return HANDLER_GO_ON;
17344 -#define PATCH(x) \
17345 - p->conf.x = s->x;
17346 static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
17348 plugin_config *s = p->config_storage[0];
17352 + PATCH_OPTION(ext);
17353 #if defined(HAVE_MEMCACHE_H)
17355 + PATCH_OPTION(mc);
17357 - PATCH(mc_namespace);
17358 - PATCH(power_magnet);
17360 + PATCH_OPTION(mc_namespace);
17361 + PATCH_OPTION(power_magnet);
17363 /* skip the first, the global context */
17364 for (i = 1; i < srv->config_context->used; i++) {
17365 data_config *dc = (data_config *)srv->config_context->data[i];
17366 s = p->config_storage[i];
17369 /* condition didn't match */
17370 if (!config_check_cond(srv, con, dc)) continue;
17374 for (j = 0; j < dc->value->used; j++) {
17375 data_unset *du = dc->value->data[j];
17378 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
17380 + PATCH_OPTION(ext);
17381 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
17382 #if defined(HAVE_MEMCACHE_H)
17384 + PATCH_OPTION(mc);
17386 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
17387 - PATCH(mc_namespace);
17388 + PATCH_OPTION(mc_namespace);
17389 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
17390 - PATCH(power_magnet);
17391 + PATCH_OPTION(power_magnet);
17401 int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
17403 @@ -187,57 +183,57 @@
17405 buffer_copy_string_buffer(b, con->uri.path);
17406 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17410 b->used = c - b->ptr + 2;
17416 buffer_copy_string_buffer(b, con->physical.path);
17417 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17421 b->used = c - b->ptr + 2;
17427 /* prepare variables
17429 * - get-param-based
17433 return cache_parse_lua(srv, con, p, cml_file);
17438 URIHANDLER_FUNC(mod_cml_power_magnet) {
17439 plugin_data *p = p_d;
17442 mod_cml_patch_connection(srv, con, p);
17445 buffer_reset(p->basedir);
17446 buffer_reset(p->baseurl);
17447 buffer_reset(p->trigger_handler);
17449 if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
17455 * cml.power-magnet = server.docroot + "/rewrite.cml"
17457 * is called on EACH request, take the original REQUEST_URI and modifies the
17458 - * request header as neccesary.
17459 + * request header as neccesary.
17462 * if file_exists("/maintainance.html") {
17463 * output_include = ( "/maintainance.html" )
17464 - * return CACHE_HIT
17465 + * return CACHE_HIT
17468 * as we only want to rewrite HTML like requests we should cover it in a conditional
17473 switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
17474 @@ -266,20 +262,20 @@
17476 URIHANDLER_FUNC(mod_cml_is_handled) {
17477 plugin_data *p = p_d;
17480 if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
17483 mod_cml_patch_connection(srv, con, p);
17486 buffer_reset(p->basedir);
17487 buffer_reset(p->baseurl);
17488 buffer_reset(p->trigger_handler);
17490 if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
17493 if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
17494 return HANDLER_GO_ON;
17498 switch(cache_call_lua(srv, con, p, con->physical.path)) {
17500 @@ -311,15 +307,15 @@
17501 int mod_cml_plugin_init(plugin *p) {
17502 p->version = LIGHTTPD_VERSION_ID;
17503 p->name = buffer_init_string("cache");
17506 p->init = mod_cml_init;
17507 p->cleanup = mod_cml_free;
17508 p->set_defaults = mod_cml_set_defaults;
17511 p->handle_subrequest_start = mod_cml_is_handled;
17512 p->handle_physical = mod_cml_power_magnet;
17520 --- lighttpd-1.4.11/src/mod_cml.h 2006-01-30 13:51:35.000000000 +0200
17521 +++ lighttpd-1.4.12/src/mod_cml.h 2006-07-11 22:07:51.000000000 +0300
17522 @@ -16,10 +16,10 @@
17529 buffer *mc_namespace;
17530 -#if defined(HAVE_MEMCACHE_H)
17531 +#if defined(HAVE_MEMCACHE_H)
17532 struct memcache *mc;
17534 buffer *power_magnet;
17535 @@ -27,15 +27,15 @@
17545 buffer *trigger_handler;
17548 plugin_config **config_storage;
17550 - plugin_config conf;
17552 + plugin_config conf;
17555 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
17556 --- lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200
17557 +++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-11 22:07:52.000000000 +0300
17559 #include <stdlib.h>
17560 #include <string.h>
17562 -#include <unistd.h>
17563 -#include <dirent.h>
17567 #include "buffer.h"
17570 #include "plugin.h"
17571 #include "response.h"
17572 +#include "sys-files.h"
17574 #include "mod_cml.h"
17575 #include "mod_cml_funcs.h"
17585 @@ -42,29 +42,29 @@
17588 int n = lua_gettop(L);
17593 b.size = sizeof(hex);
17597 lua_pushstring(L, "md5: expected one argument");
17602 if (!lua_isstring(L, 1)) {
17603 lua_pushstring(L, "md5: argument has to be a string");
17609 MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
17610 MD5_Final(HA1, &Md5Ctx);
17613 buffer_copy_string_hex(&b, (char *)HA1, 16);
17616 lua_pushstring(L, b.ptr);
17622 @@ -72,37 +72,37 @@
17623 int f_file_mtime(lua_State *L) {
17625 int n = lua_gettop(L);
17629 lua_pushstring(L, "file_mtime: expected one argument");
17634 if (!lua_isstring(L, 1)) {
17635 lua_pushstring(L, "file_mtime: argument has to be a string");
17640 if (-1 == stat(lua_tostring(L, 1), &st)) {
17646 lua_pushnumber(L, st.st_mtime);
17653 int f_dir_files_iter(lua_State *L) {
17658 d = lua_touserdata(L, lua_upvalueindex(1));
17661 if (NULL == (de = readdir(d))) {
17668 lua_pushstring(L, de->d_name);
17669 @@ -113,75 +113,75 @@
17670 int f_dir_files(lua_State *L) {
17672 int n = lua_gettop(L);
17676 lua_pushstring(L, "dir_files: expected one argument");
17681 if (!lua_isstring(L, 1)) {
17682 lua_pushstring(L, "dir_files: argument has to be a string");
17686 - /* check if there is a valid DIR handle on the stack */
17688 + /* check if there is a valid DIR handle on the stack */
17689 if (NULL == (d = opendir(lua_tostring(L, 1)))) {
17695 /* push d into registry */
17696 lua_pushlightuserdata(L, d);
17697 lua_pushcclosure(L, f_dir_files_iter, 1);
17704 int f_file_isreg(lua_State *L) {
17706 int n = lua_gettop(L);
17710 lua_pushstring(L, "file_isreg: expected one argument");
17715 if (!lua_isstring(L, 1)) {
17716 lua_pushstring(L, "file_isreg: argument has to be a string");
17721 if (-1 == stat(lua_tostring(L, 1), &st)) {
17727 lua_pushnumber(L, S_ISREG(st.st_mode));
17733 int f_file_isdir(lua_State *L) {
17735 int n = lua_gettop(L);
17739 lua_pushstring(L, "file_isreg: expected one argument");
17744 if (!lua_isstring(L, 1)) {
17745 lua_pushstring(L, "file_isreg: argument has to be a string");
17750 if (-1 == stat(lua_tostring(L, 1), &st)) {
17756 lua_pushnumber(L, S_ISDIR(st.st_mode));
17762 @@ -192,33 +192,33 @@
17764 int n = lua_gettop(L);
17765 struct memcache *mc;
17768 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17769 lua_pushstring(L, "where is my userdata ?");
17774 mc = lua_touserdata(L, lua_upvalueindex(1));
17778 lua_pushstring(L, "expected one argument");
17783 if (!lua_isstring(L, 1)) {
17784 lua_pushstring(L, "argument has to be a string");
17788 - if (NULL == (r = mc_aget(mc,
17790 + if (NULL == (r = mc_aget(mc,
17791 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17794 lua_pushboolean(L, 0);
17802 lua_pushboolean(L, 1);
17805 @@ -226,74 +226,74 @@
17806 int f_memcache_get_string(lua_State *L) {
17808 int n = lua_gettop(L);
17811 struct memcache *mc;
17814 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17815 lua_pushstring(L, "where is my userdata ?");
17820 mc = lua_touserdata(L, lua_upvalueindex(1));
17826 lua_pushstring(L, "expected one argument");
17831 if (!lua_isstring(L, 1)) {
17832 lua_pushstring(L, "argument has to be a string");
17836 - if (NULL == (r = mc_aget(mc,
17838 + if (NULL == (r = mc_aget(mc,
17839 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17845 lua_pushstring(L, r);
17854 int f_memcache_get_long(lua_State *L) {
17856 int n = lua_gettop(L);
17859 struct memcache *mc;
17862 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17863 lua_pushstring(L, "where is my userdata ?");
17868 mc = lua_touserdata(L, lua_upvalueindex(1));
17874 lua_pushstring(L, "expected one argument");
17879 if (!lua_isstring(L, 1)) {
17880 lua_pushstring(L, "argument has to be a string");
17884 - if (NULL == (r = mc_aget(mc,
17886 + if (NULL == (r = mc_aget(mc,
17887 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17893 lua_pushnumber(L, strtol(r, NULL, 10));
17902 --- lighttpd-1.4.11/src/mod_cml_lua.c 2006-01-30 13:56:40.000000000 +0200
17903 +++ lighttpd-1.4.12/src/mod_cml_lua.c 2006-07-11 22:07:53.000000000 +0300
17916 #include <lualib.h>
17917 +#include <lauxlib.h>
17921 @@ -39,11 +40,11 @@
17923 static const char * load_file(lua_State *L, void *data, size_t *size) {
17930 if (rm->done) return 0;
17933 *size = rm->st.size;
17935 return rm->st.start;
17936 @@ -51,47 +52,47 @@
17938 static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
17942 lua_pushstring(L, varname);
17945 curelem = lua_gettop(L);
17946 lua_gettable(L, LUA_GLOBALSINDEX);
17949 /* it should be a table */
17950 if (!lua_isstring(L, curelem)) {
17951 lua_settop(L, curelem - 1);
17958 buffer_copy_string(b, lua_tostring(L, curelem));
17964 assert(curelem - 1 == lua_gettop(L));
17970 static int lua_to_c_is_table(lua_State *L, const char *varname) {
17974 lua_pushstring(L, varname);
17977 curelem = lua_gettop(L);
17978 lua_gettable(L, LUA_GLOBALSINDEX);
17981 /* it should be a table */
17982 if (!lua_istable(L, curelem)) {
17983 lua_settop(L, curelem - 1);
17990 lua_settop(L, curelem - 1);
17993 assert(curelem - 1 == lua_gettop(L));
18000 lua_pushlstring(L, key, key_len);
18001 lua_pushlstring(L, val, val_len);
18002 lua_settable(L, tbl);
18008 @@ -108,21 +109,21 @@
18011 char *key = NULL, *val = NULL;
18017 /* we need the \0 */
18018 for (i = 0; i < qrystr->used; i++) {
18019 switch(qrystr->ptr[i]) {
18022 val = qrystr->ptr + i + 1;
18025 qrystr->ptr[i] = '\0';
18034 case '\0': /* fin symbol */
18035 @@ -131,19 +132,19 @@
18037 /* terminate the value */
18038 qrystr->ptr[i] = '\0';
18040 - c_to_lua_push(L, tbl,
18042 + c_to_lua_push(L, tbl,
18048 key = qrystr->ptr + i + 1;
18059 @@ -151,21 +152,21 @@
18065 if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
18066 data_string *ds = (data_string *)d;
18067 size_t key = 0, value = 0;
18068 size_t is_key = 1, is_sid = 0;
18073 if (!DATA_IS_STRING(d)) return -1;
18074 if (ds->value->used == 0) return -1;
18077 if (ds->value->ptr[0] == '\0' ||
18078 ds->value->ptr[0] == '=' ||
18079 ds->value->ptr[0] == ';') return -1;
18082 buffer_reset(p->session_id);
18083 for (i = 0; i < ds->value->used; i++) {
18084 switch(ds->value->ptr[i]) {
18085 @@ -176,16 +177,16 @@
18098 buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
18105 @@ -204,48 +205,43 @@
18115 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
18120 buffer *b = buffer_init();
18121 int header_tbl = 0;
18125 stream_open(&rm.st, fn);
18128 /* push the lua file to the interpreter and see what happends */
18132 - luaopen_table(L);
18133 - luaopen_string(L);
18137 + L = luaL_newstate();
18138 + luaL_openlibs(L);
18140 /* register functions */
18141 lua_register(L, "md5", f_crypto_md5);
18142 lua_register(L, "file_mtime", f_file_mtime);
18143 lua_register(L, "file_isreg", f_file_isreg);
18144 lua_register(L, "file_isdir", f_file_isreg);
18145 lua_register(L, "dir_files", f_dir_files);
18148 #ifdef HAVE_MEMCACHE_H
18149 lua_pushliteral(L, "memcache_get_long");
18150 lua_pushlightuserdata(L, p->conf.mc);
18151 lua_pushcclosure(L, f_memcache_get_long, 1);
18152 lua_settable(L, LUA_GLOBALSINDEX);
18155 lua_pushliteral(L, "memcache_get_string");
18156 lua_pushlightuserdata(L, p->conf.mc);
18157 lua_pushcclosure(L, f_memcache_get_string, 1);
18158 lua_settable(L, LUA_GLOBALSINDEX);
18161 lua_pushliteral(L, "memcache_exists");
18162 lua_pushlightuserdata(L, p->conf.mc);
18163 lua_pushcclosure(L, f_memcache_exists, 1);
18164 @@ -255,11 +251,11 @@
18165 lua_pushliteral(L, "request");
18167 lua_settable(L, LUA_GLOBALSINDEX);
18170 lua_pushliteral(L, "request");
18171 header_tbl = lua_gettop(L);
18172 lua_gettable(L, LUA_GLOBALSINDEX);
18175 c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
18176 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
18177 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
18178 @@ -267,84 +263,84 @@
18179 if (!buffer_is_empty(con->request.pathinfo)) {
18180 c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
18184 c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
18185 c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
18188 /* register GET parameter */
18189 lua_pushliteral(L, "get");
18191 lua_settable(L, LUA_GLOBALSINDEX);
18194 lua_pushliteral(L, "get");
18195 header_tbl = lua_gettop(L);
18196 lua_gettable(L, LUA_GLOBALSINDEX);
18199 buffer_copy_string_buffer(b, con->uri.query);
18200 cache_export_get_params(L, header_tbl, b);
18203 - /* 2 default constants */
18204 + /* 2 default constants */
18205 lua_pushliteral(L, "CACHE_HIT");
18206 lua_pushboolean(L, 0);
18207 lua_settable(L, LUA_GLOBALSINDEX);
18210 lua_pushliteral(L, "CACHE_MISS");
18211 lua_pushboolean(L, 1);
18212 lua_settable(L, LUA_GLOBALSINDEX);
18215 /* load lua program */
18216 if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
18217 log_error_write(srv, __FILE__, __LINE__, "s",
18218 lua_tostring(L,-1));
18225 /* get return value */
18226 ret = (int)lua_tonumber(L, -1);
18229 - /* fetch the data from lua */
18231 + /* fetch the data from lua */
18232 lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
18235 if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
18236 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
18241 /* up to now it is a cache-hit, check if all files exist */
18248 if (!lua_to_c_is_table(L, "output_include")) {
18249 log_error_write(srv, __FILE__, __LINE__, "s",
18250 "output_include is missing or not a table");
18258 lua_pushstring(L, "output_include");
18261 curelem = lua_gettop(L);
18262 lua_gettable(L, LUA_GLOBALSINDEX);
18264 /* HOW-TO build a etag ?
18265 - * as we don't just have one file we have to take the stat()
18266 + * as we don't just have one file we have to take the stat()
18267 * from all base files, merge them and build the etag from
18271 * The mtime of the content is the mtime of the freshest base file
18277 lua_pushnil(L); /* first key */
18278 while (lua_next(L, curelem) != 0) {
18279 stat_cache_entry *sce = NULL;
18280 /* key' is at index -2 and value' at index -1 */
18283 if (lua_isstring(L, -1)) {
18284 const char *s = lua_tostring(L, -1);
18286 @@ -364,18 +360,18 @@
18287 /* a file is missing, call the handler to generate it */
18288 if (!buffer_is_empty(p->trigger_handler)) {
18289 ret = 1; /* cache-miss */
18292 log_error_write(srv, __FILE__, __LINE__, "s",
18293 "a file is missing, calling handler");
18298 /* handler not set -> 500 */
18302 log_error_write(srv, __FILE__, __LINE__, "s",
18303 "a file missing and no handler set");
18309 @@ -393,12 +389,12 @@
18315 lua_pop(L, 1); /* removes value'; keeps key' for next iteration */
18319 lua_settop(L, curelem - 1);
18324 char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
18325 @@ -410,9 +406,9 @@
18327 /* no Last-Modified specified */
18328 if ((mtime) && (NULL == ds)) {
18331 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
18334 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
18337 @@ -428,9 +424,9 @@
18343 if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
18344 - /* ok, the client already has our content,
18345 + /* ok, the client already has our content,
18346 * no need to send it again */
18348 chunkqueue_reset(con->write_queue);
18349 @@ -440,24 +436,24 @@
18350 chunkqueue_reset(con->write_queue);
18355 if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
18357 buffer_copy_string_buffer(con->uri.path, p->baseurl);
18358 buffer_append_string_buffer(con->uri.path, p->trigger_handler);
18361 buffer_copy_string_buffer(con->physical.path, p->basedir);
18362 buffer_append_string_buffer(con->physical.path, p->trigger_handler);
18365 chunkqueue_reset(con->write_queue);
18373 stream_close(&rm.st);
18377 return ret /* cache-error */;
18380 --- lighttpd-1.4.11/src/mod_compress.c 2005-11-18 13:49:14.000000000 +0200
18381 +++ lighttpd-1.4.12/src/mod_compress.c 2006-07-11 22:07:53.000000000 +0300
18383 #include <sys/stat.h>
18386 -#include <unistd.h>
18388 #include <stdlib.h>
18389 #include <string.h>
18391 #include "buffer.h"
18392 #include "response.h"
18393 #include "stat_cache.h"
18394 +#include "http_chunk.h"
18396 #include "plugin.h"
18401 #include "sys-mmap.h"
18402 +#include "sys-files.h"
18404 /* request: accept-encoding */
18405 #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
18406 @@ -55,97 +56,127 @@
18412 plugin_config **config_storage;
18413 - plugin_config conf;
18414 + plugin_config conf;
18417 INIT_FUNC(mod_compress_init) {
18421 p = calloc(1, sizeof(*p));
18424 p->ofn = buffer_init();
18425 p->b = buffer_init();
18431 FREE_FUNC(mod_compress_free) {
18432 plugin_data *p = p_d;
18437 if (!p) return HANDLER_GO_ON;
18440 buffer_free(p->ofn);
18444 if (p->config_storage) {
18446 for (i = 0; i < srv->config_context->used; i++) {
18447 plugin_config *s = p->config_storage[i];
18452 array_free(s->compress);
18453 buffer_free(s->compress_cache_dir);
18458 free(p->config_storage);
18467 return HANDLER_GO_ON;
18470 +void mkdir_recursive(const char *dir) {
18472 + char dir_copy[256];
18473 + char *p = dir_copy;
18475 + if (!dir || !dir[0])
18478 + strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
18480 + while ((p = strchr(p + 1, '/')) != NULL) {
18483 + if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
18489 + mkdir(dir, 0700);
18492 SETDEFAULTS_FUNC(mod_compress_setdefaults) {
18493 plugin_data *p = p_d;
18496 - config_values_t cv[] = {
18498 + config_values_t cv[] = {
18499 { "compress.cache-dir", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
18500 { "compress.filetype", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
18501 { "compress.max-filesize", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
18502 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
18506 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
18509 for (i = 0; i < srv->config_context->used; i++) {
18513 s = calloc(1, sizeof(plugin_config));
18514 s->compress_cache_dir = buffer_init();
18515 s->compress = array_init();
18516 s->compress_max_filesize = 0;
18519 cv[0].destination = s->compress_cache_dir;
18520 cv[1].destination = s->compress;
18521 cv[2].destination = &(s->compress_max_filesize);
18524 p->config_storage[i] = s;
18527 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18528 return HANDLER_ERROR;
18532 if (!buffer_is_empty(s->compress_cache_dir)) {
18534 if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18535 - log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
18537 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
18538 s->compress_cache_dir, strerror(errno));
18540 - return HANDLER_ERROR;
18541 + mkdir_recursive(s->compress_cache_dir->ptr);
18543 + if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18545 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
18546 + s->compress_cache_dir, strerror(errno));
18548 + return HANDLER_ERROR;
18555 return HANDLER_GO_ON;
18561 @@ -153,32 +184,32 @@
18574 - if (Z_OK != deflateInit2(&z,
18576 + if (Z_OK != deflateInit2(&z,
18577 Z_DEFAULT_COMPRESSION,
18580 -MAX_WBITS, /* supress zlib-header */
18582 Z_DEFAULT_STRATEGY)) {
18587 z.next_in = (unsigned char *)start;
18588 z.avail_in = st_size;
18594 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
18597 /* write gzip header */
18600 c = (unsigned char *)p->b->ptr;
18603 @@ -190,24 +221,24 @@
18604 c[7] = (mtime >> 24) & 0xff;
18605 c[8] = 0x00; /* extra flags */
18606 c[9] = 0x03; /* UNIX */
18610 z.next_out = (unsigned char *)p->b->ptr + p->b->used;
18611 z.avail_out = p->b->size - p->b->used - 8;
18615 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18622 p->b->used += z.total_out;
18625 crc = generate_crc32c(start, st_size);
18628 c = (unsigned char *)p->b->ptr + p->b->used;
18631 c[0] = (crc >> 0) & 0xff;
18632 c[1] = (crc >> 8) & 0xff;
18633 c[2] = (crc >> 16) & 0xff;
18634 @@ -221,51 +252,51 @@
18635 if (Z_OK != deflateEnd(&z)) {
18643 static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18654 - if (Z_OK != deflateInit2(&z,
18656 + if (Z_OK != deflateInit2(&z,
18657 Z_DEFAULT_COMPRESSION,
18660 -MAX_WBITS, /* supress zlib-header */
18662 Z_DEFAULT_STRATEGY)) {
18668 z.avail_in = st_size;
18672 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
18675 z.next_out = (unsigned char *)p->b->ptr;
18676 z.avail_out = p->b->size;
18680 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18687 p->b->used += z.total_out;
18690 if (Z_OK != deflateEnd(&z)) {
18698 @@ -274,48 +305,48 @@
18700 static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18711 - if (BZ_OK != BZ2_bzCompressInit(&bz,
18713 + if (BZ_OK != BZ2_bzCompressInit(&bz,
18714 9, /* blocksize = 900k */
18716 0)) { /* workFactor: default */
18721 bz.next_in = (char *)start;
18722 bz.avail_in = st_size;
18723 bz.total_in_lo32 = 0;
18724 bz.total_in_hi32 = 0;
18727 buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
18730 bz.next_out = p->b->ptr;
18731 bz.avail_out = p->b->size;
18732 bz.total_out_lo32 = 0;
18733 bz.total_out_hi32 = 0;
18736 if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
18737 BZ2_bzCompressEnd(&bz);
18742 /* file is too large for now */
18743 if (bz.total_out_hi32) return -1;
18747 p->b->used = bz.total_out_lo32;
18750 if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
18758 @@ -326,47 +357,50 @@
18760 const char *filename = fn->ptr;
18763 + stat_cache_entry *compressed_sce = NULL;
18765 + if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
18768 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18770 - /* don't mmap files > 128Mb
18773 + /* don't mmap files > 128Mb
18775 * we could use a sliding window, but currently there is no need for it
18779 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18782 buffer_reset(p->ofn);
18783 buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
18784 - BUFFER_APPEND_SLASH(p->ofn);
18786 + PATHNAME_APPEND_SLASH(p->ofn);
18788 if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
18789 size_t offset = p->ofn->used - 1;
18790 char *dir, *nextdir;
18793 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
18796 buffer_copy_string_buffer(p->b, p->ofn);
18800 for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
18804 if (-1 == mkdir(p->b->ptr, 0700)) {
18805 if (errno != EEXIST) {
18806 log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
18817 buffer_append_string_buffer(p->ofn, con->uri.path);
18822 case HTTP_ACCEPT_ENCODING_GZIP:
18823 buffer_append_string(p->ofn, "-gzip-");
18824 @@ -381,55 +415,64 @@
18825 log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type);
18830 buffer_append_string_buffer(p->ofn, sce->etag);
18834 + if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
18835 + /* file exists */
18837 + http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
18838 + con->file_finished = 1;
18843 if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
18844 if (errno == EEXIST) {
18845 /* cache-entry exists */
18847 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
18849 - buffer_copy_string_buffer(con->physical.path, p->ofn);
18855 - log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
18858 + log_error_write(srv, __FILE__, __LINE__, "sbss",
18859 + "creating cachefile", p->ofn,
18860 + "failed", strerror(errno));
18865 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
18868 if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
18869 - log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18871 + log_error_write(srv, __FILE__, __LINE__, "sbss",
18872 + "opening plain-file", fn,
18873 + "failed", strerror(errno));
18884 if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18885 - log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18887 + log_error_write(srv, __FILE__, __LINE__, "sbss",
18889 + "failed", strerror(errno));
18899 - case HTTP_ACCEPT_ENCODING_GZIP:
18900 + case HTTP_ACCEPT_ENCODING_GZIP:
18901 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
18903 - case HTTP_ACCEPT_ENCODING_DEFLATE:
18904 + case HTTP_ACCEPT_ENCODING_DEFLATE:
18905 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
18909 - case HTTP_ACCEPT_ENCODING_BZIP2:
18910 + case HTTP_ACCEPT_ENCODING_BZIP2:
18911 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
18914 @@ -437,26 +480,27 @@
18920 if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
18921 - munmap(start, sce->st.st_size);
18922 + munmap(start, sce->st.st_size);
18929 if ((size_t)r != p->b->used) {
18935 munmap(start, sce->st.st_size);
18940 if (ret != 0) return -1;
18942 - buffer_copy_string_buffer(con->physical.path, p->ofn);
18945 + http_chunk_append_file(srv, con, p->ofn, 0, r);
18946 + con->file_finished = 1;
18951 @@ -465,43 +509,44 @@
18958 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18961 /* don't mmap files > 128M
18964 * we could use a sliding window, but currently there is no need for it
18968 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18972 if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
18973 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18980 - if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18982 + start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
18986 + if (MAP_FAILED == start) {
18987 log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18997 - case HTTP_ACCEPT_ENCODING_GZIP:
18998 + case HTTP_ACCEPT_ENCODING_GZIP:
18999 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
19001 - case HTTP_ACCEPT_ENCODING_DEFLATE:
19002 + case HTTP_ACCEPT_ENCODING_DEFLATE:
19003 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
19007 - case HTTP_ACCEPT_ENCODING_BZIP2:
19008 + case HTTP_ACCEPT_ENCODING_BZIP2:
19009 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
19012 @@ -509,69 +554,64 @@
19018 munmap(start, sce->st.st_size);
19022 if (ret != 0) return -1;
19025 chunkqueue_reset(con->write_queue);
19026 b = chunkqueue_get_append_buffer(con->write_queue);
19027 buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
19030 buffer_reset(con->physical.path);
19033 con->file_finished = 1;
19034 con->file_started = 1;
19041 -#define PATCH(x) \
19042 - p->conf.x = s->x;
19043 static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
19045 plugin_config *s = p->config_storage[0];
19047 - PATCH(compress_cache_dir);
19049 - PATCH(compress_max_filesize);
19051 + PATCH_OPTION(compress_cache_dir);
19052 + PATCH_OPTION(compress);
19053 + PATCH_OPTION(compress_max_filesize);
19055 /* skip the first, the global context */
19056 for (i = 1; i < srv->config_context->used; i++) {
19057 data_config *dc = (data_config *)srv->config_context->data[i];
19058 s = p->config_storage[i];
19061 /* condition didn't match */
19062 if (!config_check_cond(srv, con, dc)) continue;
19066 for (j = 0; j < dc->value->used; j++) {
19067 data_unset *du = dc->value->data[j];
19070 if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
19071 - PATCH(compress_cache_dir);
19072 + PATCH_OPTION(compress_cache_dir);
19073 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
19075 + PATCH_OPTION(compress);
19076 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
19077 - PATCH(compress_max_filesize);
19078 + PATCH_OPTION(compress_max_filesize);
19088 PHYSICALPATH_FUNC(mod_compress_physical) {
19089 plugin_data *p = p_d;
19092 stat_cache_entry *sce = NULL;
19095 /* only GET and POST can get compressed */
19096 - if (con->request.http_method != HTTP_METHOD_GET &&
19097 + if (con->request.http_method != HTTP_METHOD_GET &&
19098 con->request.http_method != HTTP_METHOD_POST) {
19099 return HANDLER_GO_ON;
19101 @@ -579,46 +619,49 @@
19102 if (buffer_is_empty(con->physical.path)) {
19103 return HANDLER_GO_ON;
19107 mod_compress_patch_connection(srv, con, p);
19110 max_fsize = p->conf.compress_max_filesize;
19112 stat_cache_get_entry(srv, con, con->physical.path, &sce);
19114 /* don't compress files that are too large as we need to much time to handle them */
19115 if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
19118 + /* compressing the file might lead to larger files instead */
19119 + if (sce->st.st_size < 128) return HANDLER_GO_ON;
19121 /* check if mimetype is in compress-config */
19122 for (m = 0; m < p->conf.compress->used; m++) {
19123 data_string *compress_ds = (data_string *)p->conf.compress->data[m];
19126 if (!compress_ds) {
19127 log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
19130 return HANDLER_GO_ON;
19134 if (buffer_is_equal(compress_ds->value, sce->content_type)) {
19135 /* mimetype found */
19139 /* the response might change according to Accept-Encoding */
19140 response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
19143 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
19144 int accept_encoding = 0;
19145 char *value = ds->value->ptr;
19146 int srv_encodings = 0;
19147 int matched_encodings = 0;
19150 /* get client side support encodings */
19151 if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
19152 if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
19153 if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
19154 if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
19155 if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
19158 /* get server side supported ones */
19160 srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
19161 @@ -627,18 +670,31 @@
19162 srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
19163 srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
19167 /* find matching entries */
19168 matched_encodings = accept_encoding & srv_encodings;
19171 if (matched_encodings) {
19172 const char *dflt_gzip = "gzip";
19173 const char *dflt_deflate = "deflate";
19174 const char *dflt_bzip2 = "bzip2";
19177 const char *compression_name = NULL;
19178 int compression_type = 0;
19182 + mtime = strftime_cache_get(srv, sce->st.st_mtime);
19183 + etag_mutate(con->physical.etag, sce->etag);
19185 + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19186 + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19188 + /* perhaps we don't even have to compress the file as the browser still has the
19189 + * current version */
19190 + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
19191 + return HANDLER_FINISHED;
19194 /* select best matching encoding */
19195 if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
19196 compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
19197 @@ -650,31 +706,21 @@
19198 compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
19199 compression_name = dflt_deflate;
19203 - if (p->conf.compress_cache_dir->used) {
19204 - if (0 == deflate_file_to_file(srv, con, p,
19205 - con->physical.path, sce, compression_type)) {
19208 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
19210 - mtime = strftime_cache_get(srv, sce->st.st_mtime);
19211 - response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19213 - etag_mutate(con->physical.etag, sce->etag);
19214 - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19216 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
19218 - return HANDLER_GO_ON;
19220 - } else if (0 == deflate_file_to_buffer(srv, con, p,
19221 - con->physical.path, sce, compression_type)) {
19223 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
19224 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
19227 + /* deflate it to file (cached) or to memory */
19228 + if (0 == deflate_file_to_file(srv, con, p,
19229 + con->physical.path, sce, compression_type) ||
19230 + 0 == deflate_file_to_buffer(srv, con, p,
19231 + con->physical.path, sce, compression_type)) {
19233 + response_header_overwrite(srv, con,
19234 + CONST_STR_LEN("Content-Encoding"),
19235 + compression_name, strlen(compression_name));
19237 + response_header_overwrite(srv, con,
19238 + CONST_STR_LEN("Content-Type"),
19239 + CONST_BUF_LEN(sce->content_type));
19241 return HANDLER_FINISHED;
19244 @@ -682,20 +728,20 @@
19250 return HANDLER_GO_ON;
19253 int mod_compress_plugin_init(plugin *p) {
19254 p->version = LIGHTTPD_VERSION_ID;
19255 p->name = buffer_init_string("compress");
19258 p->init = mod_compress_init;
19259 p->set_defaults = mod_compress_setdefaults;
19260 p->handle_subrequest_start = mod_compress_physical;
19261 p->cleanup = mod_compress_free;
19269 --- lighttpd-1.4.11/src/mod_dirlisting.c 2006-01-13 00:00:45.000000000 +0200
19270 +++ lighttpd-1.4.12/src/mod_dirlisting.c 2006-07-11 22:07:53.000000000 +0300
19273 #include <stdlib.h>
19274 #include <string.h>
19275 -#include <dirent.h>
19276 #include <assert.h>
19279 -#include <unistd.h>
19284 #include <attr/attributes.h>
19287 +#include "sys-files.h"
19288 +#include "sys-strings.h"
19290 /* plugin config for all request/connections */
19294 unsigned short hide_readme_file;
19295 unsigned short show_header;
19296 unsigned short hide_header_file;
19299 excludes_buffer *excludes;
19301 buffer *external_css;
19302 @@ -63,13 +64,13 @@
19309 buffer *content_charset;
19312 plugin_config **config_storage;
19314 - plugin_config conf;
19316 + plugin_config conf;
19319 excludes_buffer *excludes_buffer_init(void) {
19320 @@ -146,44 +147,44 @@
19321 /* init the plugin data */
19322 INIT_FUNC(mod_dirlisting_init) {
19326 p = calloc(1, sizeof(*p));
19328 p->tmp_buf = buffer_init();
19329 p->content_charset = buffer_init();
19335 /* detroy the plugin data */
19336 FREE_FUNC(mod_dirlisting_free) {
19337 plugin_data *p = p_d;
19342 if (!p) return HANDLER_GO_ON;
19345 if (p->config_storage) {
19347 for (i = 0; i < srv->config_context->used; i++) {
19348 plugin_config *s = p->config_storage[i];
19354 excludes_buffer_free(s->excludes);
19355 buffer_free(s->external_css);
19356 buffer_free(s->encoding);
19361 free(p->config_storage);
19365 buffer_free(p->tmp_buf);
19366 buffer_free(p->content_charset);
19372 return HANDLER_GO_ON;
19375 @@ -215,10 +216,10 @@
19376 if (0 != excludes_buffer_append(s->excludes,
19377 ((data_string *)(da->value->data[j]))->value)) {
19379 - log_error_write(srv, __FILE__, __LINE__, "sb",
19380 + log_error_write(srv, __FILE__, __LINE__, "sb",
19381 "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
19383 - log_error_write(srv, __FILE__, __LINE__, "s",
19384 + log_error_write(srv, __FILE__, __LINE__, "s",
19385 "pcre support is missing, please install libpcre and the headers");
19388 @@ -233,8 +234,8 @@
19389 SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
19390 plugin_data *p = p_d;
19393 - config_values_t cv[] = {
19395 + config_values_t cv[] = {
19396 { "dir-listing.exclude", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
19397 { "dir-listing.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
19398 { "dir-listing.hide-dotfiles", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
19399 @@ -245,18 +246,18 @@
19400 { "dir-listing.show-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
19401 { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
19402 { "server.dir-listing", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
19405 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19409 if (!p) return HANDLER_ERROR;
19412 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19415 for (i = 0; i < srv->config_context->used; i++) {
19420 s = calloc(1, sizeof(plugin_config));
19421 s->excludes = excludes_buffer_init();
19422 s->dir_listing = 0;
19423 @@ -267,7 +268,7 @@
19424 s->show_header = 0;
19425 s->hide_header_file = 0;
19426 s->encoding = buffer_init();
19429 cv[0].destination = s->excludes;
19430 cv[1].destination = &(s->dir_listing);
19431 cv[2].destination = &(s->hide_dot_files);
19432 @@ -292,60 +293,57 @@
19433 return HANDLER_GO_ON;
19436 -#define PATCH(x) \
19437 - p->conf.x = s->x;
19438 static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
19440 plugin_config *s = p->config_storage[0];
19442 - PATCH(dir_listing);
19443 - PATCH(external_css);
19444 - PATCH(hide_dot_files);
19446 - PATCH(show_readme);
19447 - PATCH(hide_readme_file);
19448 - PATCH(show_header);
19449 - PATCH(hide_header_file);
19452 + PATCH_OPTION(dir_listing);
19453 + PATCH_OPTION(external_css);
19454 + PATCH_OPTION(hide_dot_files);
19455 + PATCH_OPTION(encoding);
19456 + PATCH_OPTION(show_readme);
19457 + PATCH_OPTION(hide_readme_file);
19458 + PATCH_OPTION(show_header);
19459 + PATCH_OPTION(hide_header_file);
19460 + PATCH_OPTION(excludes);
19462 /* skip the first, the global context */
19463 for (i = 1; i < srv->config_context->used; i++) {
19464 data_config *dc = (data_config *)srv->config_context->data[i];
19465 s = p->config_storage[i];
19468 /* condition didn't match */
19469 if (!config_check_cond(srv, con, dc)) continue;
19473 for (j = 0; j < dc->value->used; j++) {
19474 data_unset *du = dc->value->data[j];
19477 if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
19478 buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
19479 - PATCH(dir_listing);
19480 + PATCH_OPTION(dir_listing);
19481 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
19482 - PATCH(hide_dot_files);
19483 + PATCH_OPTION(hide_dot_files);
19484 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
19485 - PATCH(external_css);
19486 + PATCH_OPTION(external_css);
19487 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
19489 + PATCH_OPTION(encoding);
19490 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
19491 - PATCH(show_readme);
19492 + PATCH_OPTION(show_readme);
19493 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
19494 - PATCH(hide_readme_file);
19495 + PATCH_OPTION(hide_readme_file);
19496 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
19497 - PATCH(show_header);
19498 + PATCH_OPTION(show_header);
19499 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
19500 - PATCH(hide_header_file);
19501 + PATCH_OPTION(hide_header_file);
19502 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
19504 + PATCH_OPTION(excludes);
19516 @@ -432,7 +430,7 @@
19518 static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
19522 BUFFER_APPEND_STRING_CONST(out,
19523 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
19524 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
19525 @@ -492,11 +490,11 @@
19526 if (p->conf.show_header) {
19528 /* if we have a HEADER file, display it in <pre class="header"></pre> */
19531 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
19532 - BUFFER_APPEND_SLASH(p->tmp_buf);
19533 + PATHNAME_APPEND_SLASH(p->tmp_buf);
19534 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
19537 if (-1 != stream_open(&s, p->tmp_buf)) {
19538 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
19539 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19540 @@ -531,21 +529,21 @@
19542 static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
19546 BUFFER_APPEND_STRING_CONST(out,
19553 if (p->conf.show_readme) {
19555 /* if we have a README file, display it in <pre class="readme"></pre> */
19558 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
19559 - BUFFER_APPEND_SLASH(p->tmp_buf);
19560 + PATHNAME_APPEND_SLASH(p->tmp_buf);
19561 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
19564 if (-1 != stream_open(&s, p->tmp_buf)) {
19565 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
19566 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19567 @@ -553,7 +551,7 @@
19573 BUFFER_APPEND_STRING_CONST(out,
19574 "<div class=\"foot\">"
19576 @@ -595,7 +593,7 @@
19579 if (dir->used == 0) return -1;
19584 #ifdef HAVE_PATHCONF
19585 @@ -606,19 +604,24 @@
19586 name_max = 256; /* stupid default */
19589 -#elif defined __WIN32
19590 +#elif defined _WIN32
19591 name_max = FILENAME_MAX;
19593 name_max = NAME_MAX;
19597 path = malloc(dir->used + name_max);
19599 strcpy(path, dir->ptr);
19601 + /* append \*.* to the path and keep the \ as part of the pathname */
19602 + strcat(path, "\\*.*");
19605 path_file = path + i;
19607 if (NULL == (dp = opendir(path))) {
19608 - log_error_write(srv, __FILE__, __LINE__, "sbs",
19609 + log_error_write(srv, __FILE__, __LINE__, "sbs",
19610 "opendir failed:", dir, strerror(errno));
19613 @@ -633,7 +636,7 @@
19615 files.size = DIRLIST_BLOB_SIZE;
19619 while ((dent = readdir(dp)) != NULL) {
19620 unsigned short exclude_match = 0;
19622 @@ -686,15 +689,17 @@
19625 i = strlen(dent->d_name);
19628 /* NOTE: the manual says, d_name is never more than NAME_MAX
19629 * so this should actually not be a buffer-overflow-risk
19631 if (i > (size_t)name_max) continue;
19634 memcpy(path_file, dent->d_name, i + 1);
19635 - if (stat(path, &st) != 0)
19636 + if (stat(path, &st) != 0) {
19637 + fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, path, strerror(errno));
19642 if (S_ISDIR(st.st_mode))
19643 @@ -740,7 +745,7 @@
19645 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
19649 BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
19650 buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
19651 BUFFER_APPEND_STRING_CONST(out, "/\">");
19652 @@ -758,7 +763,7 @@
19654 content_type = NULL;
19658 if (con->conf.use_xattr) {
19659 memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
19660 attrlen = sizeof(attrval) - 1;
19661 @@ -768,7 +773,7 @@
19667 if (content_type == NULL) {
19668 content_type = "application/octet-stream";
19669 for (k = 0; k < con->conf.mimetypes->used; k++) {
19670 @@ -788,7 +793,7 @@
19676 #ifdef HAVE_LOCALTIME_R
19677 localtime_r(&(tmp->mtime), &tm);
19678 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
19679 @@ -837,36 +842,36 @@
19680 URIHANDLER_FUNC(mod_dirlisting_subrequest) {
19681 plugin_data *p = p_d;
19682 stat_cache_entry *sce = NULL;
19688 if (con->physical.path->used == 0) return HANDLER_GO_ON;
19689 if (con->uri.path->used == 0) return HANDLER_GO_ON;
19690 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
19693 mod_dirlisting_patch_connection(srv, con, p);
19695 if (!p->conf.dir_listing) return HANDLER_GO_ON;
19698 if (con->conf.log_request_handling) {
19699 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Dir-Listing");
19700 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
19704 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19705 fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
19710 if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
19713 if (http_list_directory(srv, con, p, con->physical.path)) {
19714 /* dirlisting failed */
19715 con->http_status = 403;
19719 buffer_reset(con->physical.path);
19723 return HANDLER_FINISHED;
19725 @@ -876,13 +881,13 @@
19726 int mod_dirlisting_plugin_init(plugin *p) {
19727 p->version = LIGHTTPD_VERSION_ID;
19728 p->name = buffer_init_string("dirlisting");
19731 p->init = mod_dirlisting_init;
19732 p->handle_subrequest_start = mod_dirlisting_subrequest;
19733 p->set_defaults = mod_dirlisting_set_defaults;
19734 p->cleanup = mod_dirlisting_free;
19742 --- lighttpd-1.4.11/src/mod_evasive.c 2006-01-04 15:24:51.000000000 +0200
19743 +++ lighttpd-1.4.12/src/mod_evasive.c 2006-07-11 22:07:53.000000000 +0300
19744 @@ -31,100 +31,97 @@
19750 plugin_config **config_storage;
19752 - plugin_config conf;
19754 + plugin_config conf;
19757 INIT_FUNC(mod_evasive_init) {
19761 p = calloc(1, sizeof(*p));
19767 FREE_FUNC(mod_evasive_free) {
19768 plugin_data *p = p_d;
19773 if (!p) return HANDLER_GO_ON;
19776 if (p->config_storage) {
19778 for (i = 0; i < srv->config_context->used; i++) {
19779 plugin_config *s = p->config_storage[i];
19784 free(p->config_storage);
19791 return HANDLER_GO_ON;
19794 SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
19795 plugin_data *p = p_d;
19798 - config_values_t cv[] = {
19800 + config_values_t cv[] = {
19801 { "evasive.max-conns-per-ip", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
19802 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19806 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19809 for (i = 0; i < srv->config_context->used; i++) {
19813 s = calloc(1, sizeof(plugin_config));
19817 cv[0].destination = &(s->max_conns);
19820 p->config_storage[i] = s;
19823 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19824 return HANDLER_ERROR;
19829 return HANDLER_GO_ON;
19832 -#define PATCH(x) \
19833 - p->conf.x = s->x;
19834 static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
19836 plugin_config *s = p->config_storage[0];
19838 - PATCH(max_conns);
19840 + PATCH_OPTION(max_conns);
19842 /* skip the first, the global context */
19843 for (i = 1; i < srv->config_context->used; i++) {
19844 data_config *dc = (data_config *)srv->config_context->data[i];
19845 s = p->config_storage[i];
19848 /* condition didn't match */
19849 if (!config_check_cond(srv, con, dc)) continue;
19853 for (j = 0; j < dc->value->used; j++) {
19854 data_unset *du = dc->value->data[j];
19857 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
19858 - PATCH(max_conns);
19859 + PATCH_OPTION(max_conns);
19869 URIHANDLER_FUNC(mod_evasive_uri_handler) {
19870 plugin_data *p = p_d;
19871 @@ -132,10 +129,10 @@
19874 if (con->uri.path->used == 0) return HANDLER_GO_ON;
19877 mod_evasive_patch_connection(srv, con, p);
19879 - /* no limit set, nothing to block */
19881 + /* no limit set, nothing to block */
19882 if (p->conf.max_conns == 0) return HANDLER_GO_ON;
19884 for (j = 0; j < srv->conns->used; j++) {
19885 @@ -147,7 +144,7 @@
19886 if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
19887 c->state > CON_STATE_REQUEST_END) {
19891 if (conns_by_ip > p->conf.max_conns) {
19892 log_error_write(srv, __FILE__, __LINE__, "ss",
19893 inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
19894 @@ -158,7 +155,7 @@
19900 return HANDLER_GO_ON;
19903 @@ -166,13 +163,13 @@
19904 int mod_evasive_plugin_init(plugin *p) {
19905 p->version = LIGHTTPD_VERSION_ID;
19906 p->name = buffer_init_string("evasive");
19909 p->init = mod_evasive_init;
19910 p->set_defaults = mod_evasive_set_defaults;
19911 p->handle_uri_clean = mod_evasive_uri_handler;
19912 p->cleanup = mod_evasive_free;
19920 --- lighttpd-1.4.11/src/mod_evhost.c 2005-08-17 10:42:03.000000000 +0300
19921 +++ lighttpd-1.4.12/src/mod_evhost.c 2006-07-11 22:07:51.000000000 +0300
19923 #include "response.h"
19924 #include "stat_cache.h"
19926 +#include "sys-files.h"
19929 /* unparsed pieces */
19930 buffer *path_pieces_raw;
19933 /* pieces for path creation */
19935 buffer **path_pieces;
19936 @@ -21,14 +23,14 @@
19939 plugin_config **config_storage;
19940 - plugin_config conf;
19941 + plugin_config conf;
19944 INIT_FUNC(mod_evhost_init) {
19948 p = calloc(1, sizeof(*p));
19951 p->tmp_buf = buffer_init();
19954 @@ -36,34 +38,34 @@
19956 FREE_FUNC(mod_evhost_free) {
19957 plugin_data *p = p_d;
19962 if (!p) return HANDLER_GO_ON;
19965 if (p->config_storage) {
19967 for (i = 0; i < srv->config_context->used; i++) {
19968 plugin_config *s = p->config_storage[i];
19973 if(s->path_pieces) {
19975 for (j = 0; j < s->len; j++) {
19976 buffer_free(s->path_pieces[j]);
19980 free(s->path_pieces);
19984 buffer_free(s->path_pieces_raw);
19989 free(p->config_storage);
19993 buffer_free(p->tmp_buf);
19996 @@ -73,30 +75,30 @@
19998 static void mod_evhost_parse_pattern(plugin_config *s) {
19999 char *ptr = s->path_pieces_raw->ptr,*pos;
20002 s->path_pieces = NULL;
20005 for(pos=ptr;*ptr;ptr++) {
20007 s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
20008 s->path_pieces[s->len] = buffer_init();
20009 s->path_pieces[s->len+1] = buffer_init();
20012 buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
20016 buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
20025 s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
20026 s->path_pieces[s->len] = buffer_init();
20029 buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
20035 @@ -104,9 +106,9 @@
20036 SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
20037 plugin_data *p = p_d;
20045 * # define a pattern for the host url finding
20047 @@ -117,39 +119,39 @@
20048 * # %4 => subdomain 2 name
20050 * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
20055 - config_values_t cv[] = {
20057 + config_values_t cv[] = {
20058 { "evhost.path-pattern", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
20059 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20063 if (!p) return HANDLER_ERROR;
20066 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20069 for (i = 0; i < srv->config_context->used; i++) {
20073 s = calloc(1, sizeof(plugin_config));
20074 s->path_pieces_raw = buffer_init();
20075 s->path_pieces = NULL;
20079 cv[0].destination = s->path_pieces_raw;
20082 p->config_storage[i] = s;
20085 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
20086 return HANDLER_ERROR;
20090 if (s->path_pieces_raw->used != 0) {
20091 mod_evhost_parse_pattern(s);
20096 return HANDLER_GO_ON;
20099 @@ -158,7 +160,7 @@
20100 * - %0 - full hostname (authority w/o port)
20102 * - %2 - domain.tld
20107 static int mod_evhost_parse_host(connection *con,array *host) {
20108 @@ -168,7 +170,7 @@
20114 /* first, find the domain + tld */
20115 for(;ptr > con->uri.authority->ptr;ptr--) {
20117 @@ -179,18 +181,18 @@
20123 ds = data_string_init();
20124 buffer_copy_string(ds->key,"%0");
20127 /* if we stopped at a dot, skip the dot */
20128 if (*ptr == '.') ptr++;
20129 buffer_copy_string_len(ds->value, ptr, colon-ptr);
20132 array_insert_unique(host,(data_unset *)ds);
20135 /* if the : is not the start of the authority, go on parsing the hostname */
20138 if (colon != con->uri.authority->ptr) {
20139 for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
20141 @@ -200,59 +202,55 @@
20142 buffer_copy_string(ds->key,"%");
20143 buffer_append_long(ds->key, i++);
20144 buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
20147 array_insert_unique(host,(data_unset *)ds);
20154 /* if the . is not the first charactor of the hostname */
20155 if (colon != ptr) {
20156 ds = data_string_init();
20157 buffer_copy_string(ds->key,"%");
20158 buffer_append_long(ds->key, i++);
20159 buffer_copy_string_len(ds->value,ptr,colon-ptr);
20162 array_insert_unique(host,(data_unset *)ds);
20170 -#define PATCH(x) \
20171 - p->conf.x = s->x;
20172 static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
20174 plugin_config *s = p->config_storage[0];
20176 - PATCH(path_pieces);
20180 + PATCH_OPTION(path_pieces);
20181 + PATCH_OPTION(len);
20183 /* skip the first, the global context */
20184 for (i = 1; i < srv->config_context->used; i++) {
20185 data_config *dc = (data_config *)srv->config_context->data[i];
20186 s = p->config_storage[i];
20189 /* condition didn't match */
20190 if (!config_check_cond(srv, con, dc)) continue;
20194 for (j = 0; j < dc->value->used; j++) {
20195 data_unset *du = dc->value->data[j];
20198 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
20199 - PATCH(path_pieces);
20201 + PATCH_OPTION(path_pieces);
20202 + PATCH_OPTION(len);
20213 static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
20214 plugin_data *p = p_d;
20215 @@ -261,29 +259,29 @@
20216 register char *ptr;
20218 stat_cache_entry *sce = NULL;
20221 /* not authority set */
20222 if (con->uri.authority->used == 0) return HANDLER_GO_ON;
20225 mod_evhost_patch_connection(srv, con, p);
20228 /* missing even default(global) conf */
20229 if (0 == p->conf.len) {
20230 return HANDLER_GO_ON;
20233 parsed_host = array_init();
20236 mod_evhost_parse_host(con, parsed_host);
20239 /* build document-root */
20240 buffer_reset(p->tmp_buf);
20243 for (i = 0; i < p->conf.len; i++) {
20244 ptr = p->conf.path_pieces[i]->ptr;
20249 if (*(ptr+1) == '%') {
20251 BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
20252 @@ -298,11 +296,11 @@
20253 buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
20257 - BUFFER_APPEND_SLASH(p->tmp_buf);
20260 + PATHNAME_APPEND_SLASH(p->tmp_buf);
20262 array_free(parsed_host);
20265 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
20266 log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
20268 @@ -310,11 +308,11 @@
20269 log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
20275 buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
20279 return HANDLER_GO_ON;
20282 @@ -325,9 +323,9 @@
20283 p->set_defaults = mod_evhost_set_defaults;
20284 p->handle_docroot = mod_evhost_uri_handler;
20285 p->cleanup = mod_evhost_free;
20294 --- lighttpd-1.4.11/src/mod_expire.c 2005-11-03 09:52:13.000000000 +0200
20295 +++ lighttpd-1.4.12/src/mod_expire.c 2006-07-11 22:07:52.000000000 +0300
20297 #include "stat_cache.h"
20300 - * this is a expire module for a lighttpd
20302 + * this is a expire module for a lighttpd
20304 * set 'Expires:' HTTP Headers on demand
20307 @@ -27,51 +27,51 @@
20313 buffer *expire_tstmp;
20316 plugin_config **config_storage;
20318 - plugin_config conf;
20320 + plugin_config conf;
20323 /* init the plugin data */
20324 INIT_FUNC(mod_expire_init) {
20328 p = calloc(1, sizeof(*p));
20331 p->expire_tstmp = buffer_init();
20334 buffer_prepare_copy(p->expire_tstmp, 255);
20340 /* detroy the plugin data */
20341 FREE_FUNC(mod_expire_free) {
20342 plugin_data *p = p_d;
20347 if (!p) return HANDLER_GO_ON;
20350 buffer_free(p->expire_tstmp);
20353 if (p->config_storage) {
20355 for (i = 0; i < srv->config_context->used; i++) {
20356 plugin_config *s = p->config_storage[i];
20359 array_free(s->expire_url);
20364 free(p->config_storage);
20371 return HANDLER_GO_ON;
20374 @@ -79,25 +79,25 @@
20387 * '(access|modification) [plus] {<num> <type>}*'
20390 * e.g. 'access 1 years'
20394 if (expire->used == 0) {
20395 - log_error_write(srv, __FILE__, __LINE__, "s",
20396 + log_error_write(srv, __FILE__, __LINE__, "s",
20405 if (0 == strncmp(ts, "access ", 7)) {
20408 @@ -110,39 +110,39 @@
20409 "invalid <base>:", ts);
20414 if (0 == strncmp(ts, "plus ", 5)) {
20415 /* skip the optional plus */
20420 /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
20426 if (NULL == (space = strchr(ts, ' '))) {
20427 - log_error_write(srv, __FILE__, __LINE__, "ss",
20428 + log_error_write(srv, __FILE__, __LINE__, "ss",
20429 "missing space after <num>:", ts);
20434 num = strtol(ts, &err, 10);
20436 - log_error_write(srv, __FILE__, __LINE__, "ss",
20437 + log_error_write(srv, __FILE__, __LINE__, "ss",
20438 "missing <type> after <num>:", ts);
20446 if (NULL != (space = strchr(ts, ' '))) {
20456 0 == strncmp(ts, "years", slen)) {
20457 num *= 60 * 60 * 24 * 30 * 12;
20458 } else if (slen == 6 &&
20459 @@ -161,13 +161,13 @@
20460 0 == strncmp(ts, "seconds", slen)) {
20463 - log_error_write(srv, __FILE__, __LINE__, "ss",
20464 + log_error_write(srv, __FILE__, __LINE__, "ss",
20465 "unknown type:", ts);
20475 if (0 == strcmp(ts, "years")) {
20476 @@ -183,19 +183,19 @@
20477 } else if (0 == strcmp(ts, "seconds")) {
20480 - log_error_write(srv, __FILE__, __LINE__, "ss",
20481 + log_error_write(srv, __FILE__, __LINE__, "ss",
20482 "unknown type:", ts);
20495 if (offset != NULL) *offset = retts;
20501 @@ -205,102 +205,99 @@
20502 SETDEFAULTS_FUNC(mod_expire_set_defaults) {
20503 plugin_data *p = p_d;
20506 - config_values_t cv[] = {
20508 + config_values_t cv[] = {
20509 { "expire.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
20510 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20514 if (!p) return HANDLER_ERROR;
20517 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20520 for (i = 0; i < srv->config_context->used; i++) {
20524 s = calloc(1, sizeof(plugin_config));
20525 s->expire_url = array_init();
20528 cv[0].destination = s->expire_url;
20531 p->config_storage[i] = s;
20534 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
20535 return HANDLER_ERROR;
20539 for (k = 0; k < s->expire_url->used; k++) {
20540 data_string *ds = (data_string *)s->expire_url->data[k];
20544 if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
20545 - log_error_write(srv, __FILE__, __LINE__, "sb",
20546 + log_error_write(srv, __FILE__, __LINE__, "sb",
20547 "parsing expire.url failed:", ds->value);
20548 return HANDLER_ERROR;
20556 return HANDLER_GO_ON;
20559 -#define PATCH(x) \
20560 - p->conf.x = s->x;
20561 static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
20563 plugin_config *s = p->config_storage[0];
20565 - PATCH(expire_url);
20568 + PATCH_OPTION(expire_url);
20570 /* skip the first, the global context */
20571 for (i = 1; i < srv->config_context->used; i++) {
20572 data_config *dc = (data_config *)srv->config_context->data[i];
20573 s = p->config_storage[i];
20576 /* condition didn't match */
20577 if (!config_check_cond(srv, con, dc)) continue;
20581 for (j = 0; j < dc->value->used; j++) {
20582 data_unset *du = dc->value->data[j];
20585 if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
20586 - PATCH(expire_url);
20587 + PATCH_OPTION(expire_url);
20597 URIHANDLER_FUNC(mod_expire_path_handler) {
20598 plugin_data *p = p_d;
20603 if (con->uri.path->used == 0) return HANDLER_GO_ON;
20606 mod_expire_patch_connection(srv, con, p);
20609 s_len = con->uri.path->used - 1;
20612 for (k = 0; k < p->conf.expire_url->used; k++) {
20613 data_string *ds = (data_string *)p->conf.expire_url->data[k];
20614 int ct_len = ds->key->used - 1;
20617 if (ct_len > s_len) continue;
20618 if (ds->key->used == 0) continue;
20621 if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
20625 stat_cache_entry *sce = NULL;
20628 stat_cache_get_entry(srv, con, con->physical.path, &sce);
20631 switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
20634 @@ -308,38 +305,38 @@
20640 t = (ts + sce->st.st_mtime);
20643 /* -1 is handled at parse-time */
20648 - if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
20651 + if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
20652 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
20653 /* could not set expire header, out of mem */
20656 return HANDLER_GO_ON;
20662 p->expire_tstmp->used = len + 1;
20667 response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
20671 buffer_copy_string(p->expire_tstmp, "max-age=");
20672 buffer_append_long(p->expire_tstmp, ts);
20675 response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
20678 return HANDLER_GO_ON;
20684 return HANDLER_GO_ON;
20686 @@ -349,13 +346,13 @@
20687 int mod_expire_plugin_init(plugin *p) {
20688 p->version = LIGHTTPD_VERSION_ID;
20689 p->name = buffer_init_string("expire");
20692 p->init = mod_expire_init;
20693 p->handle_subrequest_start = mod_expire_path_handler;
20694 p->set_defaults = mod_expire_set_defaults;
20695 p->cleanup = mod_expire_free;
20703 --- lighttpd-1.4.11/src/mod_fastcgi.c 2006-03-09 13:18:39.000000000 +0200
20704 +++ lighttpd-1.4.12/src/mod_fastcgi.c 2006-07-11 22:07:53.000000000 +0300
20706 #include <sys/types.h>
20707 -#include <unistd.h>
20710 #include <string.h>
20712 #include "inet_ntop_cache.h"
20713 #include "stat_cache.h"
20715 -#include <fastcgi.h>
20716 +#include "fastcgi.h"
20719 #ifdef HAVE_SYS_FILIO_H
20723 #include "sys-socket.h"
20724 +#include "sys-files.h"
20725 +#include "sys-strings.h"
20726 +#include "sys-process.h"
20728 +#include "http_resp.h"
20730 #ifndef UNIX_PATH_MAX
20731 # define UNIX_PATH_MAX 108
20732 @@ -45,14 +48,13 @@
20733 #include <sys/wait.h>
20743 * - add timeout for a connect to a non-fastcgi process
20744 * (use state_timestamp + state)
20749 typedef struct fcgi_proc {
20751 unsigned port; /* config.port + pno */
20753 buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
20756 pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
20759 @@ -70,20 +72,20 @@
20760 time_t last_used; /* see idle_timeout */
20761 size_t requests; /* see max_requests */
20762 struct fcgi_proc *prev, *next; /* see first */
20765 time_t disabled_until; /* this proc is disabled until, use something else until than */
20772 PROC_STATE_UNSET, /* init-phase */
20773 PROC_STATE_RUNNING, /* alive */
20774 - PROC_STATE_OVERLOADED, /* listen-queue is full,
20775 + PROC_STATE_OVERLOADED, /* listen-queue is full,
20776 don't send something to this proc for the next 2 seconds */
20777 PROC_STATE_DIED_WAIT_FOR_PID, /* */
20778 PROC_STATE_DIED, /* marked as dead, should be restarted */
20779 PROC_STATE_KILLED /* was killed as we don't have the load anymore */
20785 @@ -94,20 +96,20 @@
20786 * sorted by lowest load
20788 * whenever a job is done move it up in the list
20789 - * until it is sorted, move it down as soon as the
20790 + * until it is sorted, move it down as soon as the
20793 - fcgi_proc *first;
20794 - fcgi_proc *unused_procs;
20795 + fcgi_proc *first;
20796 + fcgi_proc *unused_procs;
20800 * spawn at least min_procs, at max_procs.
20802 - * as soon as the load of the first entry
20803 + * as soon as the load of the first entry
20804 * is max_load_per_proc we spawn a new one
20805 - * and add it to the first entry and give it
20806 + * and add it to the first entry and give it
20812 unsigned short min_procs;
20813 @@ -119,44 +121,44 @@
20816 * kick the process from the list if it was not
20817 - * used for idle_timeout until min_procs is
20818 + * used for idle_timeout until min_procs is
20819 * reached. this helps to get the processlist
20820 * small again we had a small peak load.
20825 unsigned short idle_timeout;
20829 * time after a disabled remote connection is tried to be re-enabled
20837 unsigned short disable_time;
20840 * same fastcgi processes get a little bit larger
20841 - * than wanted. max_requests_per_proc kills a
20842 + * than wanted. max_requests_per_proc kills a
20843 * process after a number of handled requests.
20846 size_t max_requests_per_proc;
20857 - * if host is one of the local IP adresses the
20858 + * if host is one of the local IP adresses the
20859 * whole connection is local
20861 * if tcp/ip should be used host AND port have
20862 - * to be specified
20866 + * to be specified
20870 unsigned short port;
20873 @@ -169,7 +171,7 @@
20875 buffer *unixsocket;
20877 - /* if socket is local we can start the fastcgi
20878 + /* if socket is local we can start the fastcgi
20881 * bin-path is the path to the binary
20882 @@ -177,19 +179,19 @@
20883 * check min_procs and max_procs for the number
20884 * of process to start-up
20886 - buffer *bin_path;
20888 - /* bin-path is set bin-environment is taken to
20889 + buffer *bin_path;
20891 + /* bin-path is set bin-environment is taken to
20892 * create the environement before starting the
20900 array *bin_env_copy;
20904 - * docroot-translation between URL->phys and the
20905 + * docroot-translation between URL->phys and the
20909 @@ -208,7 +210,7 @@
20910 unsigned short mode;
20913 - * check_local tell you if the phys file is stat()ed
20914 + * check_local tell you if the phys file is stat()ed
20915 * or not. FastCGI doesn't care if the service is
20916 * remote. If the web-server side doesn't contain
20917 * the fastcgi-files we should not stat() for them
20918 @@ -218,11 +220,11 @@
20921 * append PATH_INFO to SCRIPT_FILENAME
20924 * php needs this if cgi.fix_pathinfo is provied
20930 unsigned short break_scriptfilename_for_php;
20933 @@ -231,12 +233,12 @@
20936 unsigned short allow_xsendfile;
20939 ssize_t load; /* replace by host->load */
20941 size_t max_id; /* corresponds most of the time to
20945 only if a process is killed max_id waits for the process itself
20946 to die and decrements its afterwards */
20948 @@ -245,17 +247,17 @@
20951 * one extension can have multiple hosts assigned
20952 - * one host can spawn additional processes on the same
20953 + * one host can spawn additional processes on the same
20954 * socket (if we control it)
20956 * ext -> host -> procs
20959 - * if the fastcgi process is remote that whole goes down
20960 + * if the fastcgi process is remote that whole goes down
20963 * ext -> host -> procs
20967 * in case of PHP and FCGI_CHILDREN we have again a procs
20968 * but we don't control it directly.
20969 @@ -268,7 +270,7 @@
20972 fcgi_extension_host **hosts;
20978 @@ -282,10 +284,10 @@
20985 array *ext_mapping;
20991 @@ -297,7 +299,7 @@
21000 @@ -306,44 +308,44 @@
21003 buffer_uint fcgi_request_id;
21010 - buffer *parse_response;
21017 plugin_config **config_storage;
21020 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
21023 /* connection specific data */
21028 - FCGI_STATE_CONNECT_DELAYED,
21029 - FCGI_STATE_PREPARE_WRITE,
21030 - FCGI_STATE_WRITE,
21033 + FCGI_STATE_CONNECT_DELAYED,
21034 + FCGI_STATE_PREPARE_WRITE,
21035 + FCGI_STATE_WRITE,
21037 } fcgi_connection_state_t;
21041 fcgi_extension_host *host;
21042 fcgi_extension *ext;
21045 fcgi_connection_state_t state;
21046 time_t state_timestamp;
21049 int reconnects; /* number of reconnect attempts */
21051 - chunkqueue *rb; /* read queue */
21053 + chunkqueue *rb; /* the raw fcgi read-queue */
21054 + chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
21055 chunkqueue *wb; /* write queue */
21057 - buffer *response_header;
21061 int fd; /* fd to the fastcgi process */
21062 int fde_ndx; /* index into the fd-event buffer */
21063 @@ -352,9 +354,9 @@
21066 int send_content_body;
21069 plugin_config conf;
21072 connection *remote_conn; /* dumb pointer */
21073 plugin_data *plugin_data; /* dumb pointer */
21075 @@ -380,7 +382,7 @@
21079 -/* dummies of the statistic framework functions
21080 +/* dummies of the statistic framework functions
21081 * they will be moved to a statistics.c later */
21082 int status_counter_inc(server *srv, const char *s, size_t len) {
21083 data_integer *di = status_counter_get_counter(srv, s, len);
21084 @@ -429,7 +431,7 @@
21085 CLEAN(".connected");
21092 fastcgi_status_copy_procname(b, host, NULL); \
21093 @@ -438,33 +440,32 @@
21103 static handler_ctx * handler_ctx_init() {
21104 handler_ctx * hctx;
21107 hctx = calloc(1, sizeof(*hctx));
21111 hctx->fde_ndx = -1;
21113 - hctx->response_header = buffer_init();
21116 hctx->request_id = 0;
21117 hctx->state = FCGI_STATE_INIT;
21124 hctx->reconnects = 0;
21125 hctx->send_content_body = 1;
21127 hctx->rb = chunkqueue_init();
21128 + hctx->http_rb = chunkqueue_init();
21129 hctx->wb = chunkqueue_init();
21135 @@ -473,10 +474,9 @@
21136 hctx->host->load--;
21140 - buffer_free(hctx->response_header);
21142 chunkqueue_free(hctx->rb);
21143 + chunkqueue_free(hctx->http_rb);
21144 chunkqueue_free(hctx->wb);
21147 @@ -488,21 +488,21 @@
21148 f = calloc(1, sizeof(*f));
21149 f->unixsocket = buffer_init();
21150 f->connection_name = buffer_init();
21160 void fastcgi_process_free(fcgi_proc *f) {
21164 fastcgi_process_free(f->next);
21167 buffer_free(f->unixsocket);
21168 buffer_free(f->connection_name);
21174 @@ -519,13 +519,13 @@
21175 f->bin_env = array_init();
21176 f->bin_env_copy = array_init();
21177 f->strip_request_uri = buffer_init();
21183 void fastcgi_host_free(fcgi_extension_host *h) {
21187 buffer_free(h->id);
21188 buffer_free(h->host);
21189 buffer_free(h->unixsocket);
21190 @@ -534,49 +534,49 @@
21191 buffer_free(h->strip_request_uri);
21192 array_free(h->bin_env);
21193 array_free(h->bin_env_copy);
21196 fastcgi_process_free(h->first);
21197 fastcgi_process_free(h->unused_procs);
21205 fcgi_exts *fastcgi_extensions_init() {
21208 f = calloc(1, sizeof(*f));
21214 void fastcgi_extensions_free(fcgi_exts *f) {
21221 for (i = 0; i < f->used; i++) {
21222 fcgi_extension *fe;
21229 for (j = 0; j < fe->used; j++) {
21230 fcgi_extension_host *h;
21236 fastcgi_host_free(h);
21240 buffer_free(fe->key);
21254 @@ -625,24 +625,25 @@
21258 - fe->hosts[fe->used++] = fh;
21259 + fe->hosts[fe->used++] = fh;
21266 INIT_FUNC(mod_fastcgi_init) {
21270 p = calloc(1, sizeof(*p));
21273 p->fcgi_env = buffer_init();
21276 p->path = buffer_init();
21277 - p->parse_response = buffer_init();
21279 + p->resp = http_response_init();
21281 p->statuskey = buffer_init();
21287 @@ -650,81 +651,82 @@
21288 FREE_FUNC(mod_fastcgi_free) {
21289 plugin_data *p = p_d;
21290 buffer_uint *r = &(p->fcgi_request_id);
21295 if (r->ptr) free(r->ptr);
21298 buffer_free(p->fcgi_env);
21299 buffer_free(p->path);
21300 - buffer_free(p->parse_response);
21301 buffer_free(p->statuskey);
21304 + http_response_free(p->resp);
21306 if (p->config_storage) {
21308 for (i = 0; i < srv->config_context->used; i++) {
21309 plugin_config *s = p->config_storage[i];
21318 for (j = 0; j < exts->used; j++) {
21319 fcgi_extension *ex;
21322 ex = exts->exts[j];
21325 for (n = 0; n < ex->used; n++) {
21327 fcgi_extension_host *host;
21330 host = ex->hosts[n];
21333 for (proc = host->first; proc; proc = proc->next) {
21334 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21336 - if (proc->is_local &&
21338 + if (proc->is_local &&
21339 !buffer_is_empty(proc->unixsocket)) {
21340 unlink(proc->unixsocket->ptr);
21345 for (proc = host->unused_procs; proc; proc = proc->next) {
21346 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21348 - if (proc->is_local &&
21350 + if (proc->is_local &&
21351 !buffer_is_empty(proc->unixsocket)) {
21352 unlink(proc->unixsocket->ptr);
21359 fastcgi_extensions_free(s->exts);
21360 array_free(s->ext_mapping);
21365 free(p->config_storage);
21372 return HANDLER_GO_ON;
21375 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
21379 if (!key || !val) return -1;
21382 dst = malloc(key_len + val_len + 3);
21383 memcpy(dst, key, key_len);
21384 dst[key_len] = '=';
21385 /* add the \0 from the value */
21386 memcpy(dst + key_len + 1, val, val_len + 1);
21389 if (env->size == 0) {
21391 env->ptr = malloc(env->size * sizeof(*env->ptr));
21392 @@ -732,9 +734,9 @@
21394 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21398 env->ptr[env->used++] = dst;
21404 @@ -753,15 +755,15 @@
21405 if (env->size == 0) {
21407 env->ptr = malloc(env->size * sizeof(*env->ptr));
21408 - } else if (env->size == env->used) {
21409 + } else if (env->size == env->used) {
21411 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21417 env->ptr[env->used++] = start;
21420 start = b->ptr + i + 1;
21423 @@ -794,7 +796,7 @@
21427 -static int fcgi_spawn_connection(server *srv,
21428 +static int fcgi_spawn_connection(server *srv,
21430 fcgi_extension_host *host,
21432 @@ -806,31 +808,27 @@
21434 struct sockaddr_in fcgi_addr_in;
21435 struct sockaddr *fcgi_addr;
21446 if (p->conf.debug) {
21447 log_error_write(srv, __FILE__, __LINE__, "sdb",
21448 "new proc, socket:", proc->port, proc->unixsocket);
21452 if (!buffer_is_empty(proc->unixsocket)) {
21453 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
21456 #ifdef HAVE_SYS_UN_H
21457 fcgi_addr_un.sun_family = AF_UNIX;
21458 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
21462 servlen = SUN_LEN(&fcgi_addr_un);
21464 - /* stevens says: */
21465 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
21468 socket_type = AF_UNIX;
21469 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
21471 @@ -844,108 +842,108 @@
21474 fcgi_addr_in.sin_family = AF_INET;
21477 if (buffer_is_empty(host->host)) {
21478 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21480 struct hostent *he;
21483 /* set a usefull default */
21484 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21489 if (NULL == (he = gethostbyname(host->host->ptr))) {
21490 - log_error_write(srv, __FILE__, __LINE__,
21491 - "sdb", "gethostbyname failed: ",
21492 + log_error_write(srv, __FILE__, __LINE__,
21493 + "sdb", "gethostbyname failed: ",
21494 h_errno, host->host);
21499 if (he->h_addrtype != AF_INET) {
21500 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
21505 if (he->h_length != sizeof(struct in_addr)) {
21506 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
21511 memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
21515 fcgi_addr_in.sin_port = htons(proc->port);
21516 servlen = sizeof(fcgi_addr_in);
21519 socket_type = AF_INET;
21520 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
21523 buffer_copy_string(proc->connection_name, "tcp:");
21524 buffer_append_string_buffer(proc->connection_name, host->host);
21525 buffer_append_string(proc->connection_name, ":");
21526 buffer_append_long(proc->connection_name, proc->port);
21530 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21531 - log_error_write(srv, __FILE__, __LINE__, "ss",
21532 + log_error_write(srv, __FILE__, __LINE__, "ss",
21533 "failed:", strerror(errno));
21538 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
21539 /* server is not up, spawn in */
21543 - if (errno != ENOENT &&
21545 + if (errno != ENOENT &&
21546 !buffer_is_empty(proc->unixsocket)) {
21547 unlink(proc->unixsocket->ptr);
21554 /* reopen socket */
21555 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21556 - log_error_write(srv, __FILE__, __LINE__, "ss",
21557 + log_error_write(srv, __FILE__, __LINE__, "ss",
21558 "socket failed:", strerror(errno));
21564 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
21565 - log_error_write(srv, __FILE__, __LINE__, "ss",
21566 + log_error_write(srv, __FILE__, __LINE__, "ss",
21567 "socketsockopt failed:", strerror(errno));
21572 /* create socket */
21573 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
21574 - log_error_write(srv, __FILE__, __LINE__, "sbs",
21575 - "bind failed for:",
21576 + log_error_write(srv, __FILE__, __LINE__, "sbs",
21577 + "bind failed for:",
21578 proc->connection_name,
21584 if (-1 == listen(fcgi_fd, 1024)) {
21585 - log_error_write(srv, __FILE__, __LINE__, "ss",
21586 + log_error_write(srv, __FILE__, __LINE__, "ss",
21587 "listen failed:", strerror(errno));
21594 switch ((child = fork())) {
21602 /* create environment */
21611 @@ -955,18 +953,18 @@
21612 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
21617 /* we don't need the client socket */
21618 for (i = 3; i < 256; i++) {
21623 /* build clean environment */
21624 if (host->bin_env_copy->used) {
21625 for (i = 0; i < host->bin_env_copy->used; i++) {
21626 data_string *ds = (data_string *)host->bin_env_copy->data[i];
21630 if (NULL != (ge = getenv(ds->value->ptr))) {
21631 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
21633 @@ -974,39 +972,39 @@
21635 for (i = 0; environ[i]; i++) {
21639 if (NULL != (eq = strchr(environ[i], '='))) {
21640 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
21646 /* create environment */
21647 for (i = 0; i < host->bin_env->used; i++) {
21648 data_string *ds = (data_string *)host->bin_env->data[i];
21651 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
21655 for (i = 0; i < env.used; i++) {
21656 /* search for PHP_FCGI_CHILDREN */
21657 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
21661 /* not found, add a default */
21662 if (i == env.used) {
21663 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
21667 env.ptr[env.used] = NULL;
21669 parse_binpath(&arg, host->bin_path);
21672 /* chdir into the base of the bin-path,
21673 * search for the last / */
21674 if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
21678 /* change to the physical directory */
21679 if (-1 == chdir(arg.ptr[0])) {
21681 @@ -1018,12 +1016,12 @@
21684 execve(arg.ptr[0], arg.ptr, env.ptr);
21686 - log_error_write(srv, __FILE__, __LINE__, "sbs",
21688 + log_error_write(srv, __FILE__, __LINE__, "sbs",
21689 "execve failed for:", host->bin_path, strerror(errno));
21698 @@ -1031,17 +1029,17 @@
21705 select(0, NULL, NULL, NULL, &tv);
21708 switch (waitpid(child, &status, WNOHANG)) {
21710 /* child still running after timeout, good */
21713 /* no PID found ? should never happen */
21714 - log_error_write(srv, __FILE__, __LINE__, "ss",
21715 + log_error_write(srv, __FILE__, __LINE__, "ss",
21716 "pid not found:", strerror(errno));
21719 @@ -1049,10 +1047,10 @@
21720 "the fastcgi-backend", host->bin_path, "failed to start:");
21721 /* the child should not terminate at all */
21722 if (WIFEXITED(status)) {
21723 - log_error_write(srv, __FILE__, __LINE__, "sdb",
21724 - "child exited with status",
21725 + log_error_write(srv, __FILE__, __LINE__, "sdb",
21726 + "child exited with status",
21727 WEXITSTATUS(status), host->bin_path);
21728 - log_error_write(srv, __FILE__, __LINE__, "s",
21729 + log_error_write(srv, __FILE__, __LINE__, "s",
21730 "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n"
21731 "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' "
21732 "in the output, NOT (cgi) NOR (cli)\n"
21733 @@ -1060,8 +1058,8 @@
21734 log_error_write(srv, __FILE__, __LINE__, "s",
21735 "If this is PHP on Gentoo add fastcgi to the USE flags");
21736 } else if (WIFSIGNALED(status)) {
21737 - log_error_write(srv, __FILE__, __LINE__, "sd",
21738 - "terminated by signal:",
21739 + log_error_write(srv, __FILE__, __LINE__, "sd",
21740 + "terminated by signal:",
21743 if (WTERMSIG(status) == 11) {
21744 @@ -1071,8 +1069,8 @@
21745 "If this is PHP try to remove the byte-code caches for now and try again.");
21748 - log_error_write(srv, __FILE__, __LINE__, "sd",
21749 - "child died somehow:",
21750 + log_error_write(srv, __FILE__, __LINE__, "sd",
21751 + "child died somehow:",
21755 @@ -1082,26 +1080,26 @@
21757 proc->last_used = srv->cur_ts;
21758 proc->is_local = 1;
21765 proc->is_local = 0;
21769 if (p->conf.debug) {
21770 log_error_write(srv, __FILE__, __LINE__, "sb",
21771 "(debug) socket is already used, won't spawn:",
21772 proc->connection_name);
21777 proc->state = PROC_STATE_RUNNING;
21778 host->active_procs++;
21787 @@ -1111,93 +1109,93 @@
21790 buffer *fcgi_mode = buffer_init();
21792 - config_values_t cv[] = {
21794 + config_values_t cv[] = {
21795 { "fastcgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
21796 { "fastcgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
21797 { "fastcgi.map-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
21798 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21802 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21805 for (i = 0; i < srv->config_context->used; i++) {
21810 s = malloc(sizeof(plugin_config));
21811 s->exts = fastcgi_extensions_init();
21813 s->ext_mapping = array_init();
21816 cv[0].destination = s->exts;
21817 cv[1].destination = &(s->debug);
21818 cv[2].destination = s->ext_mapping;
21821 p->config_storage[i] = s;
21822 ca = ((data_config *)srv->config_context->data[i])->value;
21825 if (0 != config_insert_values_global(srv, ca, cv)) {
21826 return HANDLER_ERROR;
21836 if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
21838 data_array *da = (data_array *)du;
21841 if (du->type != TYPE_ARRAY) {
21842 - log_error_write(srv, __FILE__, __LINE__, "sss",
21843 + log_error_write(srv, __FILE__, __LINE__, "sss",
21844 "unexpected type for key: ", "fastcgi.server", "array of strings");
21847 return HANDLER_ERROR;
21852 - * fastcgi.server = ( "<ext>" => ( ... ),
21856 + * fastcgi.server = ( "<ext>" => ( ... ),
21857 * "<ext>" => ( ... ) )
21861 for (j = 0; j < da->value->used; j++) {
21863 data_array *da_ext = (data_array *)da->value->data[j];
21866 if (da->value->data[j]->type != TYPE_ARRAY) {
21867 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
21868 - "unexpected type for key: ", "fastcgi.server",
21869 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
21870 + "unexpected type for key: ", "fastcgi.server",
21871 "[", da->value->data[j]->key, "](string)");
21874 return HANDLER_ERROR;
21878 - * da_ext->key == name of the extension
21881 + * da_ext->key == name of the extension
21885 - * fastcgi.server = ( "<ext>" =>
21886 - * ( "<host>" => ( ... ),
21889 + * fastcgi.server = ( "<ext>" =>
21890 + * ( "<host>" => ( ... ),
21891 * "<host>" => ( ... )
21898 for (n = 0; n < da_ext->value->used; n++) {
21899 data_array *da_host = (data_array *)da_ext->value->data[n];
21902 fcgi_extension_host *host;
21904 - config_values_t fcv[] = {
21906 + config_values_t fcv[] = {
21907 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
21908 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
21909 { "mode", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
21910 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
21911 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
21914 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
21915 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
21916 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
21917 @@ -1205,28 +1203,28 @@
21918 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
21919 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
21920 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
21923 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
21924 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
21927 { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
21928 { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
21929 { "strip-request-uri", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
21932 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21936 if (da_host->type != TYPE_ARRAY) {
21937 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
21938 - "unexpected type for key:",
21939 - "fastcgi.server",
21940 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
21941 + "unexpected type for key:",
21942 + "fastcgi.server",
21943 "[", da_host->key, "](string)");
21946 return HANDLER_ERROR;
21950 host = fastcgi_host_init();
21953 buffer_copy_string_buffer(host->id, da_host->key);
21955 host->check_local = 1;
21956 @@ -1238,13 +1236,13 @@
21957 host->disable_time = 60;
21958 host->break_scriptfilename_for_php = 0;
21959 host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
21962 fcv[0].destination = host->host;
21963 fcv[1].destination = host->docroot;
21964 fcv[2].destination = fcgi_mode;
21965 fcv[3].destination = host->unixsocket;
21966 fcv[4].destination = host->bin_path;
21969 fcv[5].destination = &(host->check_local);
21970 fcv[6].destination = &(host->port);
21971 fcv[7].destination = &(host->min_procs);
21972 @@ -1252,35 +1250,35 @@
21973 fcv[9].destination = &(host->max_load_per_proc);
21974 fcv[10].destination = &(host->idle_timeout);
21975 fcv[11].destination = &(host->disable_time);
21978 fcv[12].destination = host->bin_env;
21979 fcv[13].destination = host->bin_env_copy;
21980 fcv[14].destination = &(host->break_scriptfilename_for_php);
21981 fcv[15].destination = &(host->allow_xsendfile);
21982 fcv[16].destination = host->strip_request_uri;
21985 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
21986 return HANDLER_ERROR;
21989 - if ((!buffer_is_empty(host->host) || host->port) &&
21991 + if ((!buffer_is_empty(host->host) || host->port) &&
21992 !buffer_is_empty(host->unixsocket)) {
21993 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21994 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21995 "either host/port or socket have to be set in:",
21998 da_ext->key, " => (",
21999 da_host->key, " ( ...");
22001 return HANDLER_ERROR;
22005 if (!buffer_is_empty(host->unixsocket)) {
22006 /* unix domain socket */
22009 if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
22010 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22011 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22012 "unixsocket is too long in:",
22015 da_ext->key, " => (",
22016 da_host->key, " ( ...");
22018 @@ -1288,37 +1286,37 @@
22023 - if (buffer_is_empty(host->host) &&
22025 + if (buffer_is_empty(host->host) &&
22026 buffer_is_empty(host->bin_path)) {
22027 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22028 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22029 "host or binpath have to be set in:",
22032 da_ext->key, " => (",
22033 da_host->key, " ( ...");
22036 return HANDLER_ERROR;
22037 } else if (host->port == 0) {
22038 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22039 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22040 "port has to be set in:",
22043 da_ext->key, " => (",
22044 da_host->key, " ( ...");
22046 return HANDLER_ERROR;
22050 - if (!buffer_is_empty(host->bin_path)) {
22052 + if (!buffer_is_empty(host->bin_path)) {
22053 /* a local socket + self spawning */
22056 /* HACK: just to make sure the adaptive spawing is disabled */
22057 host->min_procs = host->max_procs;
22060 if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
22061 if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
22065 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
22066 "--- fastcgi spawning local",
22067 @@ -1328,7 +1326,7 @@
22068 "\n\tmin-procs:", host->min_procs,
22069 "\n\tmax-procs:", host->max_procs);
22073 for (pno = 0; pno < host->min_procs; pno++) {
22076 @@ -1343,7 +1341,7 @@
22077 buffer_append_string(proc->unixsocket, "-");
22078 buffer_append_long(proc->unixsocket, pno);
22083 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
22084 "--- fastcgi spawning",
22085 @@ -1351,7 +1349,7 @@
22086 "\n\tsocket", host->unixsocket,
22087 "\n\tcurrent:", pno, "/", host->min_procs);
22091 if (fcgi_spawn_connection(srv, p, host, proc)) {
22092 log_error_write(srv, __FILE__, __LINE__, "s",
22093 "[ERROR]: spawning fcgi failed.");
22094 @@ -1359,35 +1357,35 @@
22097 fastcgi_status_init(srv, p->statuskey, host, proc);
22100 proc->next = host->first;
22101 if (host->first) host->first->prev = proc;
22104 host->first = proc;
22110 proc = fastcgi_process_init();
22111 proc->id = host->num_procs++;
22113 host->active_procs++;
22114 proc->state = PROC_STATE_RUNNING;
22117 if (buffer_is_empty(host->unixsocket)) {
22118 proc->port = host->port;
22120 buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
22124 fastcgi_status_init(srv, p->statuskey, host, proc);
22126 host->first = proc;
22129 host->min_procs = 1;
22130 host->max_procs = 1;
22134 if (!buffer_is_empty(fcgi_mode)) {
22135 if (strcmp(fcgi_mode->ptr, "responder") == 0) {
22136 host->mode = FCGI_RESPONDER;
22137 @@ -1411,16 +1409,16 @@
22143 buffer_free(fcgi_mode);
22146 return HANDLER_GO_ON;
22149 static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) {
22150 hctx->state = state;
22151 hctx->state_timestamp = srv->cur_ts;
22157 @@ -1429,13 +1427,13 @@
22160 buffer_uint *r = &(p->fcgi_request_id);
22165 for (i = 0; i < r->used; i++) {
22166 if (r->ptr[i] > m) m = r->ptr[i];
22170 if (r->size == 0) {
22172 r->ptr = malloc(sizeof(*r->ptr) * r->size);
22173 @@ -1443,54 +1441,54 @@
22175 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
22179 r->ptr[r->used++] = ++m;
22185 static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
22187 buffer_uint *r = &(p->fcgi_request_id);
22192 for (i = 0; i < r->used; i++) {
22193 if (r->ptr[i] == request_id) break;
22197 if (i != r->used) {
22201 if (i != r->used - 1) {
22202 r->ptr[i] = r->ptr[r->used - 1];
22210 void fcgi_connection_close(server *srv, handler_ctx *hctx) {
22215 if (NULL == hctx) return;
22218 p = hctx->plugin_data;
22219 con = hctx->remote_conn;
22222 if (con->mode != p->id) {
22228 if (hctx->fd != -1) {
22229 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
22230 fdevent_unregister(srv->ev, hctx->fd);
22236 if (hctx->request_id != 0) {
22237 fcgi_requestid_del(srv, p, hctx->request_id);
22239 @@ -1499,7 +1497,7 @@
22240 if (hctx->got_proc) {
22241 /* after the connect the process gets a load */
22242 hctx->proc->load--;
22245 status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
22247 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
22248 @@ -1509,39 +1507,39 @@
22250 if (p->conf.debug) {
22251 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
22252 - "released proc:",
22253 - "pid:", hctx->proc->pid,
22254 - "socket:", hctx->proc->connection_name,
22255 + "released proc:",
22256 + "pid:", hctx->proc->pid,
22257 + "socket:", hctx->proc->connection_name,
22258 "load:", hctx->proc->load);
22265 handler_ctx_free(hctx);
22266 - con->plugin_ctx[p->id] = NULL;
22267 + con->plugin_ctx[p->id] = NULL;
22270 static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
22271 plugin_data *p = hctx->plugin_data;
22282 * connect was ok, connection was accepted
22283 * but the php accept loop checks after the accept if it should die or not.
22285 - * if yes we can only detect it at a write()
22288 + * if yes we can only detect it at a write()
22290 * next step is resetting this attemp and setup a connection again
22293 * if we have more then 5 reconnects for the same request, die
22300 * we have a connection but the child died by some other reason
22305 if (hctx->fd != -1) {
22306 @@ -1551,59 +1549,59 @@
22312 fcgi_requestid_del(srv, p, hctx->request_id);
22315 fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
22318 hctx->request_id = 0;
22319 hctx->reconnects++;
22322 if (p->conf.debug > 2) {
22324 log_error_write(srv, __FILE__, __LINE__, "sdb",
22325 - "release proc for reconnect:",
22326 + "release proc for reconnect:",
22327 hctx->proc->pid, hctx->proc->connection_name);
22329 log_error_write(srv, __FILE__, __LINE__, "sb",
22330 - "release proc for reconnect:",
22331 + "release proc for reconnect:",
22332 hctx->host->unixsocket);
22336 - if (hctx->proc && hctx->got_proc) {
22337 + if (hctx->proc && hctx->got_proc) {
22338 hctx->proc->load--;
22341 /* perhaps another host gives us more luck */
22342 hctx->host->load--;
22350 static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
22351 plugin_data *p = p_d;
22354 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
22357 return HANDLER_GO_ON;
22361 static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
22365 if (!key || !val) return -1;
22368 len = key_len + val_len;
22371 len += key_len > 127 ? 4 : 1;
22372 len += val_len > 127 ? 4 : 1;
22375 buffer_prepare_append(env, len);
22378 if (key_len > 127) {
22379 env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
22380 env->ptr[env->used++] = (key_len >> 16) & 0xff;
22381 @@ -1612,7 +1610,7 @@
22383 env->ptr[env->used++] = (key_len >> 0) & 0xff;
22387 if (val_len > 127) {
22388 env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
22389 env->ptr[env->used++] = (val_len >> 16) & 0xff;
22390 @@ -1621,12 +1619,12 @@
22392 env->ptr[env->used++] = (val_len >> 0) & 0xff;
22396 memcpy(env->ptr + env->used, key, key_len);
22397 env->used += key_len;
22398 memcpy(env->ptr + env->used, val, val_len);
22399 env->used += val_len;
22405 @@ -1639,11 +1637,11 @@
22406 header->contentLengthB1 = (contentLength >> 8) & 0xff;
22407 header->paddingLength = paddingLength;
22408 header->reserved = 0;
22419 @@ -1665,26 +1663,23 @@
22420 struct sockaddr_un fcgi_addr_un;
22425 fcgi_extension_host *host = hctx->host;
22426 fcgi_proc *proc = hctx->proc;
22427 int fcgi_fd = hctx->fd;
22430 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
22433 if (!buffer_is_empty(proc->unixsocket)) {
22434 #ifdef HAVE_SYS_UN_H
22435 /* use the unix domain socket */
22436 fcgi_addr_un.sun_family = AF_UNIX;
22437 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
22440 servlen = SUN_LEN(&fcgi_addr_un);
22442 - /* stevens says: */
22443 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
22446 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
22449 if (buffer_is_empty(proc->connection_name)) {
22450 /* on remote spawing we have to set the connection-name now */
22451 buffer_copy_string(proc->connection_name, "unix:");
22452 @@ -1695,16 +1690,18 @@
22455 fcgi_addr_in.sin_family = AF_INET;
22457 if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
22458 - log_error_write(srv, __FILE__, __LINE__, "sbs",
22459 - "converting IP-adress failed for", host->host,
22460 + log_error_write(srv, __FILE__, __LINE__, "sbs",
22461 + "converting IP-adress failed for", host->host,
22462 "\nBe sure to specify an IP address here");
22468 fcgi_addr_in.sin_port = htons(proc->port);
22469 servlen = sizeof(fcgi_addr_in);
22472 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
22474 if (buffer_is_empty(proc->connection_name)) {
22475 @@ -1715,20 +1712,20 @@
22476 buffer_append_long(proc->connection_name, proc->port);
22481 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
22482 - if (errno == EINPROGRESS ||
22483 + if (errno == EINPROGRESS ||
22484 errno == EALREADY ||
22486 if (hctx->conf.debug > 2) {
22487 - log_error_write(srv, __FILE__, __LINE__, "sb",
22488 + log_error_write(srv, __FILE__, __LINE__, "sb",
22489 "connect delayed, will continue later:", proc->connection_name);
22493 return CONNECTION_DELAYED;
22494 } else if (errno == EAGAIN) {
22495 if (hctx->conf.debug) {
22496 - log_error_write(srv, __FILE__, __LINE__, "sbsd",
22497 + log_error_write(srv, __FILE__, __LINE__, "sbsd",
22498 "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
22499 "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
22500 "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
22501 @@ -1736,8 +1733,8 @@
22503 return CONNECTION_OVERLOADED;
22505 - log_error_write(srv, __FILE__, __LINE__, "sssb",
22506 - "connect failed:",
22507 + log_error_write(srv, __FILE__, __LINE__, "sssb",
22508 + "connect failed:",
22509 strerror(errno), "on",
22510 proc->connection_name);
22512 @@ -1747,7 +1744,7 @@
22514 hctx->reconnects = 0;
22515 if (hctx->conf.debug > 1) {
22516 - log_error_write(srv, __FILE__, __LINE__, "sd",
22517 + log_error_write(srv, __FILE__, __LINE__, "sd",
22518 "connect succeeded: ", fcgi_fd);
22521 @@ -1756,21 +1753,21 @@
22523 static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
22527 for (i = 0; i < con->request.headers->used; i++) {
22531 ds = (data_string *)con->request.headers->data[i];
22534 if (ds->value->used && ds->key->used) {
22536 buffer_reset(srv->tmp_buf);
22539 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
22540 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
22541 srv->tmp_buf->used--;
22545 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22546 for (j = 0; j < ds->key->used - 1; j++) {
22548 @@ -1784,20 +1781,20 @@
22549 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22551 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22554 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22559 for (i = 0; i < con->environment->used; i++) {
22563 ds = (data_string *)con->environment->data[i];
22566 if (ds->value->used && ds->key->used) {
22568 buffer_reset(srv->tmp_buf);
22571 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22572 for (j = 0; j < ds->key->used - 1; j++) {
22574 @@ -1811,11 +1808,11 @@
22575 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22577 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22580 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22588 @@ -1824,24 +1821,24 @@
22589 FCGI_BeginRequestRecord beginRecord;
22590 FCGI_Header header;
22597 char b2[INET6_ADDRSTRLEN + 1];
22601 plugin_data *p = hctx->plugin_data;
22602 fcgi_extension_host *host= hctx->host;
22604 connection *con = hctx->remote_conn;
22605 server_socket *srv_sock = con->srv_socket;
22608 sock_addr our_addr;
22609 socklen_t our_addr_len;
22612 /* send FCGI_BEGIN_REQUEST */
22615 fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0);
22616 beginRecord.body.roleB0 = host->mode;
22617 beginRecord.body.roleB1 = 0;
22618 @@ -1849,21 +1846,21 @@
22619 memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
22621 b = chunkqueue_get_append_buffer(hctx->wb);
22624 buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
22627 /* send FCGI_PARAMS */
22628 buffer_prepare_copy(p->fcgi_env, 1024);
22631 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
22634 if (con->server_name->used) {
22635 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
22638 - s = inet_ntop(srv_sock->addr.plain.sa_family,
22639 - srv_sock->addr.plain.sa_family == AF_INET6 ?
22640 + s = inet_ntop(srv_sock->addr.plain.sa_family,
22641 + srv_sock->addr.plain.sa_family == AF_INET6 ?
22642 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
22643 (const void *) &(srv_sock->addr.ipv4.sin_addr),
22645 @@ -1872,50 +1869,50 @@
22647 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
22651 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
22657 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
22659 ntohs(srv_sock->addr.ipv4.sin_port)
22664 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
22667 /* get the server-side of the connection to the client */
22668 our_addr_len = sizeof(our_addr);
22671 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
22672 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
22674 s = inet_ntop_cache_get_ip(srv, &(our_addr));
22676 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
22682 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
22684 ntohs(con->dst_addr.ipv4.sin_port)
22689 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
22692 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
22693 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
22696 if (!buffer_is_empty(con->authed_user)) {
22697 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
22698 CONST_BUF_LEN(con->authed_user));
22702 if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
22703 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
22706 /* request.content_length < SSIZE_MAX, see request.c */
22707 ltostr(buf, con->request.content_length);
22708 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
22709 @@ -1930,12 +1927,12 @@
22712 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
22715 if (!buffer_is_empty(con->request.pathinfo)) {
22716 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
22719 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
22722 if (!buffer_is_empty(host->docroot)) {
22723 buffer_copy_string_buffer(p->path, host->docroot);
22725 @@ -1957,27 +1954,27 @@
22728 if (!buffer_is_empty(host->docroot)) {
22730 - * rewrite SCRIPT_FILENAME
22733 + * rewrite SCRIPT_FILENAME
22738 buffer_copy_string_buffer(p->path, host->docroot);
22739 buffer_append_string_buffer(p->path, con->uri.path);
22742 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22743 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
22745 buffer_copy_string_buffer(p->path, con->physical.path);
22747 - /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22750 + /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22752 * see src/sapi/cgi_main.c, init_request_info()
22754 if (host->break_scriptfilename_for_php) {
22755 buffer_append_string_buffer(p->path, con->request.pathinfo);
22759 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22760 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
22762 @@ -1987,7 +1984,7 @@
22766 - * stripping /app1 or /app1/ should lead to
22767 + * stripping /app1 or /app1/ should lead to
22771 @@ -2001,7 +1998,7 @@
22772 0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
22773 /* the left is the same */
22775 - fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
22776 + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
22777 con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
22778 con->request.orig_uri->used - (host->strip_request_uri->used - 2));
22780 @@ -2018,26 +2015,26 @@
22782 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
22786 s = get_http_method_name(con->request.http_method);
22787 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
22788 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
22789 s = get_http_version_name(con->request.http_version);
22790 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
22794 if (srv_sock->is_ssl) {
22795 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
22802 fcgi_env_add_request_headers(srv, con, p);
22805 fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
22806 buffer_append_memory(b, (const char *)&header, sizeof(header));
22807 buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used);
22810 fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
22811 buffer_append_memory(b, (const char *)&header, sizeof(header));
22813 @@ -2057,7 +2054,7 @@
22815 /* we announce toWrite octects
22816 * now take all the request_content chunk that we need to fill this request
22820 b = chunkqueue_get_append_buffer(hctx->wb);
22821 fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0);
22822 @@ -2080,16 +2077,16 @@
22823 if (weHave > weWant - written) weHave = weWant - written;
22825 if (p->conf.debug > 10) {
22826 - fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22827 - __FILE__, __LINE__,
22830 - req_c->file.length,
22831 + fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22832 + __FILE__, __LINE__,
22835 + req_c->file.length,
22836 req_c->file.name->ptr);
22839 assert(weHave != 0);
22842 chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
22844 req_c->offset += weHave;
22845 @@ -2104,7 +2101,7 @@
22846 * - we reference the tempfile from the request-content-queue several times
22847 * if the req_c is larger than FCGI_MAX_LENGTH
22848 * - we can't simply cleanup the request-content-queue as soon as possible
22849 - * as it would remove the tempfiles
22850 + * as it would remove the tempfiles
22851 * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
22852 * referencing chunk of the fastcgi-write-queue
22854 @@ -2141,7 +2138,7 @@
22855 req_c->offset += weHave;
22856 req_cq->bytes_out += weHave;
22860 hctx->wb->bytes_in += weHave;
22862 if (req_c->offset == req_c->mem->used - 1) {
22863 @@ -2155,12 +2152,12 @@
22869 b->used++; /* add virtual \0 */
22875 b = chunkqueue_get_append_buffer(hctx->wb);
22876 /* terminate STDIN */
22877 fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0);
22878 @@ -2175,118 +2172,19 @@
22879 if ((i+1) % 16 == 0) {
22881 for (j = i-15; j <= i; j++) {
22882 - fprintf(stderr, "%c",
22883 + fprintf(stderr, "%c",
22884 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
22886 fprintf(stderr, "\n");
22894 -static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
22897 - handler_ctx *hctx = con->plugin_ctx[p->id];
22898 - fcgi_extension_host *host= hctx->host;
22902 - buffer_copy_string_buffer(p->parse_response, in);
22904 - /* search for \n */
22905 - for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
22906 - char *key, *value;
22910 - /* a good day. Someone has read the specs and is sending a \r\n to us */
22912 - if (ns > p->parse_response->ptr &&
22913 - *(ns-1) == '\r') {
22920 - if (NULL == (value = strchr(s, ':'))) {
22921 - /* we expect: "<key>: <value>\n" */
22925 - key_len = value - key;
22929 - while (*value == ' ' || *value == '\t') value++;
22931 - if (host->mode != FCGI_AUTHORIZER ||
22932 - !(con->http_status == 0 ||
22933 - con->http_status == 200)) {
22934 - /* authorizers shouldn't affect the response headers sent back to the client */
22936 - /* don't forward Status: */
22937 - if (0 != strncasecmp(key, "Status", key_len)) {
22938 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
22939 - ds = data_response_init();
22941 - buffer_copy_string_len(ds->key, key, key_len);
22942 - buffer_copy_string(ds->value, value);
22944 - array_insert_unique(con->response.headers, (data_unset *)ds);
22948 - switch(key_len) {
22950 - if (0 == strncasecmp(key, "Date", key_len)) {
22951 - con->parsed_response |= HTTP_DATE;
22955 - if (0 == strncasecmp(key, "Status", key_len)) {
22956 - con->http_status = strtol(value, NULL, 10);
22957 - con->parsed_response |= HTTP_STATUS;
22961 - if (0 == strncasecmp(key, "Location", key_len)) {
22962 - con->parsed_response |= HTTP_LOCATION;
22966 - if (0 == strncasecmp(key, "Connection", key_len)) {
22967 - con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
22968 - con->parsed_response |= HTTP_CONNECTION;
22972 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
22973 - con->response.content_length = strtol(value, NULL, 10);
22974 - con->parsed_response |= HTTP_CONTENT_LENGTH;
22976 - if (con->response.content_length < 0) con->response.content_length = 0;
22984 - /* CGI/1.1 rev 03 - 7.2.1.2 */
22985 - if ((con->parsed_response & HTTP_LOCATION) &&
22986 - !(con->parsed_response & HTTP_STATUS)) {
22987 - con->http_status = 302;
22999 @@ -2327,9 +2225,9 @@
23003 - /* we have at least a header, now check how much me have to fetch */
23004 + /* we have at least a header, now check how much me have to fetch */
23005 header = (FCGI_Header *)(packet->b->ptr);
23008 packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
23009 packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
23010 packet->type = header->type;
23011 @@ -2348,7 +2246,7 @@
23012 size_t weHave = c->mem->used - c->offset - offset - 1;
23014 if (weHave > weWant) weHave = weWant;
23017 buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
23019 /* we only skipped the first 8 bytes as they are the fcgi header */
23020 @@ -2380,65 +2278,37 @@
23023 chunkqueue_remove_finished_chunks(hctx->rb);
23029 static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
23035 plugin_data *p = hctx->plugin_data;
23036 connection *con = hctx->remote_conn;
23037 - int fcgi_fd = hctx->fd;
23038 fcgi_extension_host *host= hctx->host;
23039 fcgi_proc *proc = hctx->proc;
23042 - * check how much we have to read
23044 - if (ioctl(hctx->fd, FIONREAD, &toread)) {
23045 - log_error_write(srv, __FILE__, __LINE__, "sd",
23046 - "unexpected end-of-file (perhaps the fastcgi process died):",
23051 - /* init read-buffer */
23053 - if (toread > 0) {
23056 - b = chunkqueue_get_append_buffer(hctx->rb);
23057 - buffer_prepare_copy(b, toread + 1);
23059 - /* append to read-buffer */
23060 - if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
23061 - log_error_write(srv, __FILE__, __LINE__, "sds",
23062 - "unexpected end-of-file (perhaps the fastcgi process died):",
23063 - fcgi_fd, strerror(errno));
23067 - /* this should be catched by the b > 0 above */
23070 - b->used = r + 1; /* one extra for the fake \0 */
23071 - b->ptr[b->used - 1] = '\0';
23073 - log_error_write(srv, __FILE__, __LINE__, "ssdsb",
23074 + switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) {
23075 + case NETWORK_STATUS_WAIT_FOR_EVENT:
23076 + /* we are only triggered when there is a event */
23077 + log_error_write(srv, __FILE__, __LINE__, "ssdsb",
23078 "unexpected end-of-file (perhaps the fastcgi process died):",
23080 "socket:", proc->connection_name);
23083 + case NETWORK_STATUS_SUCCESS:
23086 + log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
23091 * parse the fastcgi packets and forward the content to the write-queue
23096 fastcgi_response_packet packet;
23098 @@ -2454,92 +2324,135 @@
23100 /* is the header already finished */
23101 if (0 == con->file_started) {
23106 - /* search for header terminator
23108 - * if we start with \r\n check if last packet terminated with \r\n
23109 - * if we start with \n check if last packet terminated with \n
23110 - * search for \r\n\r\n
23111 - * search for \n\n
23114 - if (hctx->response_header->used == 0) {
23115 - buffer_copy_string_buffer(hctx->response_header, packet.b);
23117 - buffer_append_string_buffer(hctx->response_header, packet.b);
23120 - if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
23121 - blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
23122 - hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
23123 - c += 4; /* point the the start of the response */
23124 - } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
23125 - blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
23126 - hctx->response_header->used = c - hctx->response_header->ptr + 2;
23127 - c += 2; /* point the the start of the response */
23129 - /* no luck, no header found */
23130 + int have_content_length = 0;
23131 + int need_more = 0;
23134 + /* append the current packet to the chunk queue */
23135 + chunkqueue_append_buffer(hctx->http_rb, packet.b);
23136 + http_response_reset(p->resp);
23138 + switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
23139 + case PARSE_ERROR:
23140 + /* parsing the response header failed */
23142 + con->http_status = 502; /* Bad Gateway */
23145 + case PARSE_NEED_MORE:
23147 + break; /* leave the loop */
23148 + case PARSE_SUCCESS:
23151 + /* should not happen */
23155 - /* parse the response header */
23156 - fcgi_response_parse(srv, con, p, hctx->response_header);
23157 + if (need_more) break;
23159 - con->file_started = 1;
23160 + chunkqueue_remove_finished_chunks(hctx->http_rb);
23162 - if (host->mode == FCGI_AUTHORIZER &&
23163 - (con->http_status == 0 ||
23164 - con->http_status == 200)) {
23165 - /* a authorizer with approved the static request, ignore the content here */
23166 - hctx->send_content_body = 0;
23169 - if (host->allow_xsendfile &&
23170 - NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
23171 - stat_cache_entry *sce;
23173 - if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
23176 - http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
23177 - hctx->send_content_body = 0; /* ignore the content */
23178 - joblist_append(srv, con);
23179 + con->http_status = p->resp->status;
23181 + /* handle the header fields */
23182 + if (host->mode == FCGI_AUTHORIZER) {
23183 + /* auth mode is a bit different */
23185 + if (con->http_status == 0 ||
23186 + con->http_status == 200) {
23187 + /* a authorizer with approved the static request, ignore the content here */
23188 + hctx->send_content_body = 0;
23192 + /* copy the http-headers */
23193 + for (i = 0; i < p->resp->headers->used; i++) {
23194 + const char *ign[] = { "Status", NULL };
23198 + data_string *header = (data_string *)p->resp->headers->data[i];
23200 + /* ignore all headers in AUTHORIZER mode */
23201 + if (host->mode == FCGI_AUTHORIZER) continue;
23203 + /* some headers are ignored by default */
23204 + for (j = 0; ign[j]; j++) {
23205 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
23207 + if (ign[j]) continue;
23209 + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
23210 + /* CGI/1.1 rev 03 - 7.2.1.2 */
23211 + con->http_status = 302;
23212 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
23213 + have_content_length = 1;
23214 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) ||
23215 + 0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
23217 + stat_cache_entry *sce;
23219 - if (hctx->send_content_body && blen > 1) {
23220 - /* enable chunked-transfer-encoding */
23221 + if (host->allow_xsendfile &&
23222 + HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
23223 + http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
23224 + hctx->send_content_body = 0; /* ignore the content */
23226 + joblist_append(srv, con);
23229 + continue; /* ignore header */
23232 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
23233 + ds = data_response_init();
23235 + buffer_copy_string_buffer(ds->key, header->key);
23236 + buffer_copy_string_buffer(ds->value, header->value);
23238 + array_insert_unique(con->response.headers, (data_unset *)ds);
23241 + /* header is complete ... go on with the body */
23243 + con->file_started = 1;
23245 + if (hctx->send_content_body) {
23246 + chunk *c = hctx->http_rb->first;
23248 + /* if we don't have a content-length enable chunked encoding
23251 + * TODO: move this to a later stage in the filter-queue
23253 if (con->request.http_version == HTTP_VERSION_1_1 &&
23254 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23255 + !have_content_length) {
23256 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23259 - http_chunk_append_mem(srv, con, c, blen);
23260 + /* copy the rest of the data */
23261 + for (c = hctx->http_rb->first; c; c = c->next) {
23262 + if (c->mem->used > 1) {
23263 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
23264 + c->offset = c->mem->used - 1;
23267 + chunkqueue_remove_finished_chunks(hctx->http_rb);
23268 joblist_append(srv, con);
23270 } else if (hctx->send_content_body && packet.b->used > 1) {
23271 - if (con->request.http_version == HTTP_VERSION_1_1 &&
23272 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23273 - /* enable chunked-transfer-encoding */
23274 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23277 http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
23278 joblist_append(srv, con);
23282 - log_error_write(srv, __FILE__, __LINE__, "sb",
23283 + log_error_write(srv, __FILE__, __LINE__, "sb",
23284 "FastCGI-stderr:", packet.b);
23288 case FCGI_END_REQUEST:
23289 con->file_finished = 1;
23292 if (host->mode != FCGI_AUTHORIZER ||
23293 !(con->http_status == 0 ||
23294 con->http_status == 200)) {
23295 @@ -2547,39 +2460,39 @@
23296 http_chunk_append_mem(srv, con, NULL, 0);
23297 joblist_append(srv, con);
23304 - log_error_write(srv, __FILE__, __LINE__, "sd",
23305 + log_error_write(srv, __FILE__, __LINE__, "sd",
23306 "FastCGI: header.type not handled: ", packet.type);
23309 buffer_free(packet.b);
23316 static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
23320 for (proc = host->first; proc; proc = proc->next) {
23323 if (p->conf.debug > 2) {
23324 - log_error_write(srv, __FILE__, __LINE__, "sbdddd",
23326 + log_error_write(srv, __FILE__, __LINE__, "sbdddd",
23328 proc->connection_name,
23338 * if the remote side is overloaded, we check back after <n> seconds
23342 switch (proc->state) {
23343 case PROC_STATE_KILLED:
23344 @@ -2592,13 +2505,13 @@
23346 case PROC_STATE_OVERLOADED:
23347 if (srv->cur_ts <= proc->disabled_until) break;
23350 proc->state = PROC_STATE_RUNNING;
23351 host->active_procs++;
23353 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
23354 - "fcgi-server re-enabled:",
23355 - host->host, host->port,
23357 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
23358 + "fcgi-server re-enabled:",
23359 + host->host, host->port,
23362 case PROC_STATE_DIED_WAIT_FOR_PID:
23363 @@ -2606,7 +2519,7 @@
23364 if (!proc->is_local) break;
23366 /* the child should not terminate at all */
23369 switch(waitpid(proc->pid, &status, WNOHANG)) {
23371 /* child is still alive */
23372 @@ -2616,45 +2529,45 @@
23374 if (WIFEXITED(status)) {
23376 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
23377 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
23378 "child exited, pid:", proc->pid,
23379 "status:", WEXITSTATUS(status));
23381 } else if (WIFSIGNALED(status)) {
23382 - log_error_write(srv, __FILE__, __LINE__, "sd",
23383 - "child signaled:",
23384 + log_error_write(srv, __FILE__, __LINE__, "sd",
23385 + "child signaled:",
23388 - log_error_write(srv, __FILE__, __LINE__, "sd",
23389 - "child died somehow:",
23390 + log_error_write(srv, __FILE__, __LINE__, "sd",
23391 + "child died somehow:",
23396 proc->state = PROC_STATE_DIED;
23401 /* fall through if we have a dead proc now */
23402 if (proc->state != PROC_STATE_DIED) break;
23404 case PROC_STATE_DIED:
23405 - /* local proc get restarted by us,
23406 + /* local proc get restarted by us,
23407 * remote ones hopefully by the admin */
23410 if (proc->is_local) {
23411 /* we still have connections bound to this proc,
23412 * let them terminate first */
23413 if (proc->load != 0) break;
23416 /* restart the child */
23419 if (p->conf.debug) {
23420 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23421 "--- fastcgi spawning",
23422 "\n\tsocket", proc->connection_name,
23423 "\n\tcurrent:", 1, "/", host->min_procs);
23427 if (fcgi_spawn_connection(srv, p, host, proc)) {
23428 log_error_write(srv, __FILE__, __LINE__, "s",
23429 "ERROR: spawning fcgi failed.");
23430 @@ -2662,18 +2575,18 @@
23433 if (srv->cur_ts <= proc->disabled_until) break;
23436 proc->state = PROC_STATE_RUNNING;
23437 host->active_procs++;
23439 - log_error_write(srv, __FILE__, __LINE__, "sb",
23440 - "fcgi-server re-enabled:",
23442 + log_error_write(srv, __FILE__, __LINE__, "sb",
23443 + "fcgi-server re-enabled:",
23444 proc->connection_name);
23454 @@ -2682,19 +2595,19 @@
23455 fcgi_extension_host *host= hctx->host;
23456 connection *con = hctx->remote_conn;
23462 - /* sanity check */
23463 + /* sanity check */
23465 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
23466 - log_error_write(srv, __FILE__, __LINE__, "sxddd",
23467 + log_error_write(srv, __FILE__, __LINE__, "sxddd",
23468 "write-req: error",
23472 host->unixsocket->used);
23475 hctx->proc->disabled_until = srv->cur_ts + 10;
23476 hctx->proc->state = PROC_STATE_DIED;
23478 @@ -2705,12 +2618,12 @@
23479 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23481 socklen_t socket_error_len = sizeof(socket_error);
23484 /* try to finish the connect() */
23485 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
23486 - log_error_write(srv, __FILE__, __LINE__, "ss",
23487 + log_error_write(srv, __FILE__, __LINE__, "ss",
23488 "getsockopt failed:", strerror(errno));
23491 hctx->proc->disabled_until = srv->cur_ts + 10;
23492 hctx->proc->state = PROC_STATE_DIED;
23494 @@ -2719,12 +2632,12 @@
23495 if (socket_error != 0) {
23496 if (!hctx->proc->is_local || p->conf.debug) {
23497 /* local procs get restarted */
23500 log_error_write(srv, __FILE__, __LINE__, "sssb",
23501 - "establishing connection failed:", strerror(socket_error),
23502 + "establishing connection failed:", strerror(socket_error),
23503 "socket:", hctx->proc->connection_name);
23507 hctx->proc->disabled_until = srv->cur_ts + 5;
23509 if (hctx->proc->is_local) {
23510 @@ -2732,17 +2645,17 @@
23512 hctx->proc->state = PROC_STATE_DIED;
23516 hctx->proc->state = PROC_STATE_DIED;
23519 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23520 buffer_append_string(p->statuskey, ".died");
23522 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23525 return HANDLER_ERROR;
23527 - /* go on with preparing the request */
23528 + /* go on with preparing the request */
23529 hctx->state = FCGI_STATE_PREPARE_WRITE;
23532 @@ -2755,14 +2668,14 @@
23533 /* do we have a running process for this host (max-procs) ? */
23536 - for (proc = hctx->host->first;
23537 - proc && proc->state != PROC_STATE_RUNNING;
23538 + for (proc = hctx->host->first;
23539 + proc && proc->state != PROC_STATE_RUNNING;
23540 proc = proc->next);
23543 /* all childs are dead */
23544 if (proc == NULL) {
23545 hctx->fde_ndx = -1;
23548 return HANDLER_ERROR;
23551 @@ -2775,50 +2688,50 @@
23554 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
23557 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
23558 if (errno == EMFILE ||
23560 - log_error_write(srv, __FILE__, __LINE__, "sd",
23561 + log_error_write(srv, __FILE__, __LINE__, "sd",
23562 "wait for fd at connection:", con->fd);
23565 return HANDLER_WAIT_FOR_FD;
23568 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
23570 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
23571 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
23572 return HANDLER_ERROR;
23574 hctx->fde_ndx = -1;
23580 fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
23583 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
23584 - log_error_write(srv, __FILE__, __LINE__, "ss",
23585 + log_error_write(srv, __FILE__, __LINE__, "ss",
23586 "fcntl failed:", strerror(errno));
23589 return HANDLER_ERROR;
23593 if (hctx->proc->is_local) {
23594 hctx->pid = hctx->proc->pid;
23598 switch (fcgi_establish_connection(srv, hctx)) {
23599 case CONNECTION_DELAYED:
23600 /* connection is in progress, wait for an event and call getsockopt() below */
23603 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23606 fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED);
23607 return HANDLER_WAIT_FOR_EVENT;
23608 case CONNECTION_OVERLOADED:
23609 /* cool down the backend, it is overloaded
23612 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23613 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23614 "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
23615 "reconnects:", hctx->reconnects,
23616 "load:", host->load);
23617 @@ -2831,7 +2744,7 @@
23618 buffer_append_string(p->statuskey, ".overloaded");
23620 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23623 return HANDLER_ERROR;
23624 case CONNECTION_DEAD:
23625 /* we got a hard error from the backend like
23626 @@ -2840,19 +2753,19 @@
23628 * for check if the host is back in 5 seconds
23632 hctx->proc->disabled_until = srv->cur_ts + 5;
23633 if (hctx->proc->is_local) {
23634 hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
23636 hctx->proc->state = PROC_STATE_DIED;
23639 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23641 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23642 "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
23643 "reconnects:", hctx->reconnects,
23644 "load:", host->load);
23647 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23648 buffer_append_string(p->statuskey, ".died");
23650 @@ -2863,19 +2776,19 @@
23651 /* everything is ok, go on */
23653 fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
23657 case CONNECTION_UNSET:
23662 case FCGI_STATE_PREPARE_WRITE:
23663 /* ok, we have the connection */
23666 hctx->proc->load++;
23667 hctx->proc->last_used = srv->cur_ts;
23668 hctx->got_proc = 1;
23671 status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
23672 status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
23674 @@ -2898,9 +2811,9 @@
23676 if (p->conf.debug) {
23677 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
23679 - "pid:", hctx->proc->pid,
23680 - "socket:", hctx->proc->connection_name,
23682 + "pid:", hctx->proc->pid,
23683 + "socket:", hctx->proc->connection_name,
23684 "load:", hctx->proc->load);
23687 @@ -2908,62 +2821,63 @@
23688 if (hctx->request_id == 0) {
23689 hctx->request_id = fcgi_requestid_new(srv, p);
23691 - log_error_write(srv, __FILE__, __LINE__, "sd",
23692 + log_error_write(srv, __FILE__, __LINE__, "sd",
23693 "fcgi-request is already in use:", hctx->request_id);
23698 fcgi_create_env(srv, hctx, hctx->request_id);
23701 fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
23705 case FCGI_STATE_WRITE:
23706 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
23707 + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
23709 chunkqueue_remove_finished_chunks(hctx->wb);
23715 - /* the connection got dropped after accept()
23717 - * this is most of the time a PHP which dies
23718 + /* the connection got dropped after accept()
23720 + * this is most of the time a PHP which dies
23721 * after PHP_FCGI_MAX_REQUESTS
23726 if (hctx->wb->bytes_out == 0 &&
23727 hctx->reconnects < 5) {
23728 - usleep(10000); /* take away the load of the webserver
23729 - * to let the php a chance to restart
23731 + usleep(10000); /* take away the load of the webserver
23732 + * to let the php a chance to restart
23736 fcgi_reconnect(srv, hctx);
23739 return HANDLER_WAIT_FOR_FD;
23743 /* not reconnected ... why
23746 * far@#lighttpd report this for FreeBSD
23751 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23753 + log_error_write(srv, __FILE__, __LINE__, "ssosd",
23754 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
23755 "write-offset:", hctx->wb->bytes_out,
23756 "reconnect attempts:", hctx->reconnects);
23759 return HANDLER_ERROR;
23762 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23765 return HANDLER_WAIT_FOR_EVENT;
23767 - log_error_write(srv, __FILE__, __LINE__, "ssd",
23768 + log_error_write(srv, __FILE__, __LINE__, "ssd",
23769 "write failed:", strerror(errno), errno);
23772 return HANDLER_ERROR;
23775 @@ -2975,7 +2889,7 @@
23776 fcgi_set_state(srv, hctx, FCGI_STATE_READ);
23778 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23781 return HANDLER_WAIT_FOR_EVENT;
23784 @@ -2987,7 +2901,7 @@
23785 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
23786 return HANDLER_ERROR;
23790 return HANDLER_WAIT_FOR_EVENT;
23793 @@ -2996,18 +2910,18 @@
23795 SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
23796 plugin_data *p = p_d;
23799 handler_ctx *hctx = con->plugin_ctx[p->id];
23801 fcgi_extension_host *host;
23804 if (NULL == hctx) return HANDLER_GO_ON;
23808 if (con->mode != p->id) return HANDLER_GO_ON;
23810 /* we don't have a host yet, choose one
23811 - * -> this happens in the first round
23812 + * -> this happens in the first round
23813 * and when the host died and we have to select a new one */
23814 if (hctx->host == NULL) {
23816 @@ -3016,23 +2930,23 @@
23817 /* get best server */
23818 for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
23819 host = hctx->ext->hosts[k];
23822 /* we should have at least one proc that can do something */
23823 if (host->active_procs == 0) continue;
23825 if (used == -1 || host->load < used) {
23834 /* found a server */
23836 /* all hosts are down */
23838 fcgi_connection_close(srv, hctx);
23841 con->http_status = 500;
23842 con->mode = DIRECT;
23844 @@ -3040,16 +2954,16 @@
23847 host = hctx->ext->hosts[ndx];
23850 - * if check-local is disabled, use the uri.path handler
23854 + * if check-local is disabled, use the uri.path handler
23859 /* init handler-context */
23862 - /* we put a connection on this host, move the other new connections to other hosts
23863 + /* we put a connection on this host, move the other new connections to other hosts
23865 * as soon as hctx->host is unassigned, decrease the load again */
23866 hctx->host->load++;
23867 @@ -3063,7 +2977,7 @@
23868 case HANDLER_ERROR:
23873 if (hctx->state == FCGI_STATE_INIT ||
23874 hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23875 if (proc) host->active_procs--;
23876 @@ -3078,7 +2992,7 @@
23877 return HANDLER_WAIT_FOR_FD;
23879 fcgi_connection_close(srv, hctx);
23882 buffer_reset(con->physical.path);
23883 con->mode = DIRECT;
23884 con->http_status = 500;
23885 @@ -3088,12 +3002,12 @@
23888 fcgi_connection_close(srv, hctx);
23891 buffer_reset(con->physical.path);
23892 con->mode = DIRECT;
23893 con->http_status = 503;
23894 joblist_append(srv, con); /* really ? */
23897 return HANDLER_FINISHED;
23899 case HANDLER_WAIT_FOR_EVENT:
23900 @@ -3115,7 +3029,7 @@
23901 handler_ctx *hctx = ctx;
23902 connection *con = hctx->remote_conn;
23903 plugin_data *p = hctx->plugin_data;
23906 fcgi_proc *proc = hctx->proc;
23907 fcgi_extension_host *host= hctx->host;
23909 @@ -3125,8 +3039,8 @@
23914 - if (host->mode == FCGI_AUTHORIZER &&
23916 + if (host->mode == FCGI_AUTHORIZER &&
23917 (con->http_status == 200 ||
23918 con->http_status == 0)) {
23920 @@ -3136,26 +3050,26 @@
23923 buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
23926 buffer_copy_string_buffer(con->physical.path, host->docroot);
23927 buffer_append_string_buffer(con->physical.path, con->uri.path);
23928 fcgi_connection_close(srv, hctx);
23931 con->mode = DIRECT;
23932 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
23935 fcgi_connection_close(srv, hctx);
23939 joblist_append(srv, con);
23940 return HANDLER_FINISHED;
23942 if (proc->pid && proc->state != PROC_STATE_DIED) {
23946 /* only fetch the zombie if it is not already done */
23949 switch(waitpid(proc->pid, &status, WNOHANG)) {
23951 /* child is still alive */
23952 @@ -3165,60 +3079,61 @@
23954 /* the child should not terminate at all */
23955 if (WIFEXITED(status)) {
23956 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
23957 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
23958 "child exited, pid:", proc->pid,
23959 "status:", WEXITSTATUS(status));
23960 } else if (WIFSIGNALED(status)) {
23961 - log_error_write(srv, __FILE__, __LINE__, "sd",
23962 - "child signaled:",
23963 + log_error_write(srv, __FILE__, __LINE__, "sd",
23964 + "child signaled:",
23967 - log_error_write(srv, __FILE__, __LINE__, "sd",
23968 - "child died somehow:",
23969 + log_error_write(srv, __FILE__, __LINE__, "sd",
23970 + "child died somehow:",
23975 if (p->conf.debug) {
23976 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23977 "--- fastcgi spawning",
23978 "\n\tsocket", proc->connection_name,
23979 "\n\tcurrent:", 1, "/", host->min_procs);
23983 if (fcgi_spawn_connection(srv, p, host, proc)) {
23984 /* respawning failed, retry later */
23985 proc->state = PROC_STATE_DIED;
23987 - log_error_write(srv, __FILE__, __LINE__, "s",
23988 + log_error_write(srv, __FILE__, __LINE__, "s",
23989 "respawning failed, will retry later");
23998 if (con->file_started == 0) {
23999 /* nothing has been send out yet, try to use another child */
24002 if (hctx->wb->bytes_out == 0 &&
24003 hctx->reconnects < 5) {
24004 fcgi_reconnect(srv, hctx);
24006 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
24008 + log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
24009 "response not received, request not sent",
24010 - "on socket:", proc->connection_name,
24011 + "on socket:", proc->connection_name,
24012 "for", con->uri.path, ", reconnecting");
24015 return HANDLER_WAIT_FOR_FD;
24018 - log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
24020 + log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
24021 "response not received, request sent:", hctx->wb->bytes_out,
24022 - "on socket:", proc->connection_name,
24023 + "on socket:", proc->connection_name,
24024 "for", con->uri.path, ", closing connection");
24027 fcgi_connection_close(srv, hctx);
24030 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
24031 buffer_reset(con->physical.path);
24032 con->http_status = 500;
24033 @@ -3226,76 +3141,76 @@
24035 /* response might have been already started, kill the connection */
24036 fcgi_connection_close(srv, hctx);
24038 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
24040 + log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
24041 "response already sent out, but backend returned error",
24042 - "on socket:", proc->connection_name,
24043 + "on socket:", proc->connection_name,
24044 "for", con->uri.path, ", terminating connection");
24047 connection_set_state(srv, con, CON_STATE_ERROR);
24055 joblist_append(srv, con);
24056 return HANDLER_FINISHED;
24061 if (revents & FDEVENT_OUT) {
24062 if (hctx->state == FCGI_STATE_CONNECT_DELAYED ||
24063 hctx->state == FCGI_STATE_WRITE) {
24064 /* we are allowed to send something out
24067 * 1. in a unfinished connect() call
24068 * 2. in a unfinished write() call (long POST request)
24070 return mod_fastcgi_handle_subrequest(srv, con, p);
24072 - log_error_write(srv, __FILE__, __LINE__, "sd",
24073 - "got a FDEVENT_OUT and didn't know why:",
24074 + log_error_write(srv, __FILE__, __LINE__, "sd",
24075 + "got a FDEVENT_OUT and didn't know why:",
24081 /* perhaps this issue is already handled */
24082 if (revents & FDEVENT_HUP) {
24083 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
24084 /* getoptsock will catch this one (right ?)
24086 - * if we are in connect we might get a EINPROGRESS
24087 - * in the first call and a FDEVENT_HUP in the
24089 + * if we are in connect we might get a EINPROGRESS
24090 + * in the first call and a FDEVENT_HUP in the
24094 * FIXME: as it is a bit ugly.
24098 return mod_fastcgi_handle_subrequest(srv, con, p);
24099 } else if (hctx->state == FCGI_STATE_READ &&
24100 hctx->proc->port == 0) {
24104 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
24105 * even if the FCGI_FIN packet is not received yet
24108 - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
24109 - "error: unexpected close of fastcgi connection for",
24110 + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
24111 + "error: unexpected close of fastcgi connection for",
24113 - "(no fastcgi process on host:",
24114 + "(no fastcgi process on host:",
24123 connection_set_state(srv, con, CON_STATE_ERROR);
24124 fcgi_connection_close(srv, hctx);
24125 joblist_append(srv, con);
24127 } else if (revents & FDEVENT_ERR) {
24128 - log_error_write(srv, __FILE__, __LINE__, "s",
24129 + log_error_write(srv, __FILE__, __LINE__, "s",
24130 "fcgi: got a FDEVENT_ERR. Don't know why.");
24131 /* kill all connections to the fastcgi process */
24133 @@ -3304,45 +3219,42 @@
24134 fcgi_connection_close(srv, hctx);
24135 joblist_append(srv, con);
24139 return HANDLER_FINISHED;
24141 -#define PATCH(x) \
24142 - p->conf.x = s->x;
24144 static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
24146 plugin_config *s = p->config_storage[0];
24150 - PATCH(ext_mapping);
24153 + PATCH_OPTION(exts);
24154 + PATCH_OPTION(debug);
24155 + PATCH_OPTION(ext_mapping);
24157 /* skip the first, the global context */
24158 for (i = 1; i < srv->config_context->used; i++) {
24159 data_config *dc = (data_config *)srv->config_context->data[i];
24160 s = p->config_storage[i];
24163 /* condition didn't match */
24164 if (!config_check_cond(srv, con, dc)) continue;
24168 for (j = 0; j < dc->value->used; j++) {
24169 data_unset *du = dc->value->data[j];
24172 if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
24174 + PATCH_OPTION(exts);
24175 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
24177 + PATCH_OPTION(debug);
24178 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
24179 - PATCH(ext_mapping);
24180 + PATCH_OPTION(ext_mapping);
24191 static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
24192 plugin_data *p = p_d;
24193 @@ -3351,16 +3263,16 @@
24195 fcgi_extension *extension = NULL;
24196 fcgi_extension_host *host = NULL;
24199 /* Possibly, we processed already this request */
24200 if (con->file_started == 1) return HANDLER_GO_ON;
24202 fn = uri_path_handler ? con->uri.path : con->physical.path;
24204 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
24207 s_len = fn->used - 1;
24210 fcgi_patch_connection(srv, con, p);
24212 /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
24213 @@ -3368,24 +3280,24 @@
24214 * fastcgi.map-extensions = ( ".php3" => ".php" )
24216 * fastcgi.server = ( ".php" => ... )
24221 /* check if extension-mapping matches */
24222 for (k = 0; k < p->conf.ext_mapping->used; k++) {
24223 data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
24224 size_t ct_len; /* length of the config entry */
24227 if (ds->key->used == 0) continue;
24230 ct_len = ds->key->used - 1;
24233 if (s_len < ct_len) continue;
24236 /* found a mapping */
24237 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
24238 /* check if we know the extension */
24241 /* we can reuse k here */
24242 for (k = 0; k < p->conf.exts->used; k++) {
24243 extension = p->conf.exts->exts[k];
24244 @@ -3407,15 +3319,15 @@
24245 /* check if extension matches */
24246 for (k = 0; k < p->conf.exts->used; k++) {
24247 size_t ct_len; /* length of the config entry */
24250 extension = p->conf.exts->exts[k];
24253 if (extension->key->used == 0) continue;
24256 ct_len = extension->key->used - 1;
24259 if (s_len < ct_len) continue;
24262 /* check extension in the form "/fcgi_pattern" */
24263 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
24265 @@ -3441,10 +3353,10 @@
24269 - /* we found one host that is alive */
24270 + /* we found one host that is alive */
24276 /* sorry, we don't have a server alive for this ext */
24277 buffer_reset(con->physical.path);
24278 @@ -3459,72 +3371,72 @@
24279 "on", extension->key,
24284 return HANDLER_FINISHED;
24287 /* a note about no handler is not sent yey */
24288 extension->note_is_sent = 0;
24291 - * if check-local is disabled, use the uri.path handler
24294 + * if check-local is disabled, use the uri.path handler
24299 /* init handler-context */
24300 if (uri_path_handler) {
24301 if (host->check_local == 0) {
24306 hctx = handler_ctx_init();
24309 hctx->remote_conn = con;
24310 hctx->plugin_data = p;
24312 hctx->ext = extension;
24316 hctx->conf.exts = p->conf.exts;
24317 hctx->conf.debug = p->conf.debug;
24320 con->plugin_ctx[p->id] = hctx;
24326 if (con->conf.log_request_handling) {
24327 - log_error_write(srv, __FILE__, __LINE__, "s",
24328 + log_error_write(srv, __FILE__, __LINE__, "s",
24329 "handling it in mod_fastcgi");
24332 - /* the prefix is the SCRIPT_NAME,
24334 + /* the prefix is the SCRIPT_NAME,
24335 * everthing from start to the next slash
24336 * this is important for check-local = "disable"
24339 * if prefix = /admin.fcgi
24342 * /admin.fcgi/foo/bar
24345 * SCRIPT_NAME = /admin.fcgi
24346 * PATH_INFO = /foo/bar
24349 * if prefix = /fcgi-bin/
24352 * /fcgi-bin/foo/bar
24355 * SCRIPT_NAME = /fcgi-bin/foo
24362 /* the rewrite is only done for /prefix/? matches */
24363 if (extension->key->ptr[0] == '/' &&
24364 con->uri.path->used > extension->key->used &&
24365 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
24366 - /* rewrite uri.path and pathinfo */
24368 + /* rewrite uri.path and pathinfo */
24370 buffer_copy_string(con->request.pathinfo, pathinfo);
24373 con->uri.path->used -= con->request.pathinfo->used - 1;
24374 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
24376 @@ -3532,19 +3444,19 @@
24379 hctx = handler_ctx_init();
24382 hctx->remote_conn = con;
24383 hctx->plugin_data = p;
24385 hctx->ext = extension;
24388 hctx->conf.exts = p->conf.exts;
24389 hctx->conf.debug = p->conf.debug;
24392 con->plugin_ctx[p->id] = hctx;
24398 if (con->conf.log_request_handling) {
24399 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
24401 @@ -3566,19 +3478,19 @@
24402 JOBLIST_FUNC(mod_fastcgi_handle_joblist) {
24403 plugin_data *p = p_d;
24404 handler_ctx *hctx = con->plugin_ctx[p->id];
24407 if (hctx == NULL) return HANDLER_GO_ON;
24409 if (hctx->fd != -1) {
24410 switch (hctx->state) {
24411 case FCGI_STATE_READ:
24412 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
24416 case FCGI_STATE_CONNECT_DELAYED:
24417 case FCGI_STATE_WRITE:
24418 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24422 case FCGI_STATE_INIT:
24424 @@ -3595,7 +3507,7 @@
24426 static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
24427 plugin_data *p = p_d;
24430 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
24432 return HANDLER_GO_ON;
24433 @@ -3604,16 +3516,39 @@
24434 TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
24435 plugin_data *p = p_d;
24441 /* perhaps we should kill a connect attempt after 10-15 seconds
24444 * currently we wait for the TCP timeout which is on Linux 180 seconds
24451 + for (i = 0; i < srv->conns->used; i++) {
24452 + connection *con = srv->conns->ptr[i];
24453 + handler_ctx *hctx = con->plugin_ctx[p->id];
24455 + /* if a connection is ours and is in handle-req for more than max-request-time
24456 + * kill the connection */
24458 + if (con->mode != p->id) continue;
24459 + if (con->state != CON_STATE_HANDLE_REQUEST) continue;
24460 + if (srv->cur_ts < con->request_start + 60) continue;
24462 + /* the request is waiting for a FCGI_STDOUT since 60 seconds */
24464 + /* kill the connection */
24466 + log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
24468 + fcgi_connection_close(srv, hctx);
24470 + con->mode = DIRECT;
24471 + con->http_status = 500;
24473 + joblist_append(srv, con);
24476 /* check all childs if they are still up */
24478 for (i = 0; i < srv->config_context->used; i++) {
24479 @@ -3628,45 +3563,45 @@
24480 fcgi_extension *ex;
24482 ex = exts->exts[j];
24485 for (n = 0; n < ex->used; n++) {
24489 unsigned long sum_load = 0;
24490 fcgi_extension_host *host;
24493 host = ex->hosts[n];
24496 fcgi_restart_dead_procs(srv, p, host);
24499 for (proc = host->first; proc; proc = proc->next) {
24500 sum_load += proc->load;
24504 if (host->num_procs &&
24505 host->num_procs < host->max_procs &&
24506 (sum_load / host->num_procs) > host->max_load_per_proc) {
24507 /* overload, spawn new child */
24508 if (p->conf.debug) {
24509 - log_error_write(srv, __FILE__, __LINE__, "s",
24510 + log_error_write(srv, __FILE__, __LINE__, "s",
24511 "overload detected, spawning a new child");
24515 for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
24519 if (proc == host->unused_procs) host->unused_procs = proc->next;
24522 if (proc->next) proc->next->prev = NULL;
24527 proc = fastcgi_process_init();
24528 proc->id = host->max_id++;
24535 if (buffer_is_empty(host->unixsocket)) {
24536 proc->port = host->port + proc->id;
24538 @@ -3674,13 +3609,13 @@
24539 buffer_append_string(proc->unixsocket, "-");
24540 buffer_append_long(proc->unixsocket, proc->id);
24544 if (fcgi_spawn_connection(srv, p, host, proc)) {
24545 log_error_write(srv, __FILE__, __LINE__, "s",
24546 "ERROR: spawning fcgi failed.");
24547 return HANDLER_ERROR;
24552 proc->next = host->first;
24554 @@ -3688,56 +3623,56 @@
24556 host->first = proc;
24560 for (proc = host->first; proc; proc = proc->next) {
24561 if (proc->load != 0) break;
24562 if (host->num_procs <= host->min_procs) break;
24563 if (proc->pid == 0) continue;
24566 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
24567 /* a proc is idling for a long time now,
24571 if (p->conf.debug) {
24572 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24573 - "idle-timeout reached, terminating child:",
24574 - "socket:", proc->connection_name,
24575 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24576 + "idle-timeout reached, terminating child:",
24577 + "socket:", proc->connection_name,
24584 if (proc->next) proc->next->prev = proc->prev;
24585 if (proc->prev) proc->prev->next = proc->next;
24588 if (proc->prev == NULL) host->first = proc->next;
24592 proc->next = host->unused_procs;
24595 if (host->unused_procs) host->unused_procs->prev = proc;
24596 host->unused_procs = proc;
24599 kill(proc->pid, SIGTERM);
24602 proc->state = PROC_STATE_KILLED;
24604 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24606 - "socket:", proc->connection_name,
24608 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24610 + "socket:", proc->connection_name,
24617 /* proc is now in unused, let the next second handle the next process */
24624 for (proc = host->unused_procs; proc; proc = proc->next) {
24628 if (proc->pid == 0) continue;
24631 switch (waitpid(proc->pid, &status, WNOHANG)) {
24633 /* child still running after timeout, good */
24634 @@ -3745,10 +3680,10 @@
24636 if (errno != EINTR) {
24637 /* no PID found ? should never happen */
24638 - log_error_write(srv, __FILE__, __LINE__, "sddss",
24639 + log_error_write(srv, __FILE__, __LINE__, "sddss",
24640 "pid ", proc->pid, proc->state,
24641 "not found:", strerror(errno));
24645 if (errno == ECHILD) {
24646 /* someone else has cleaned up for us */
24647 @@ -3762,25 +3697,26 @@
24648 /* the child should not terminate at all */
24649 if (WIFEXITED(status)) {
24650 if (proc->state != PROC_STATE_KILLED) {
24651 - log_error_write(srv, __FILE__, __LINE__, "sdb",
24653 + log_error_write(srv, __FILE__, __LINE__, "sdb",
24655 WEXITSTATUS(status), proc->connection_name);
24657 } else if (WIFSIGNALED(status)) {
24658 if (WTERMSIG(status) != SIGTERM) {
24659 - log_error_write(srv, __FILE__, __LINE__, "sd",
24660 - "child signaled:",
24661 + log_error_write(srv, __FILE__, __LINE__, "sd",
24662 + "child signaled:",
24666 - log_error_write(srv, __FILE__, __LINE__, "sd",
24667 - "child died somehow:",
24668 + log_error_write(srv, __FILE__, __LINE__, "sd",
24669 + "child died somehow:",
24673 proc->state = PROC_STATE_UNSET;
24680 @@ -3804,8 +3740,8 @@
24681 p->handle_subrequest = mod_fastcgi_handle_subrequest;
24682 p->handle_joblist = mod_fastcgi_handle_joblist;
24683 p->handle_trigger = mod_fastcgi_handle_trigger;
24691 --- lighttpd-1.4.11/src/mod_flv_streaming.c 2006-03-07 14:06:26.000000000 +0200
24692 +++ lighttpd-1.4.12/src/mod_flv_streaming.c 2006-07-11 22:07:52.000000000 +0300
24693 @@ -23,35 +23,35 @@
24703 plugin_config **config_storage;
24705 - plugin_config conf;
24707 + plugin_config conf;
24710 /* init the plugin data */
24711 INIT_FUNC(mod_flv_streaming_init) {
24715 p = calloc(1, sizeof(*p));
24718 p->query_str = buffer_init();
24719 p->get_params = array_init();
24725 /* detroy the plugin data */
24726 FREE_FUNC(mod_flv_streaming_free) {
24727 plugin_data *p = p_d;
24732 if (!p) return HANDLER_GO_ON;
24735 if (p->config_storage) {
24738 @@ -59,19 +59,19 @@
24739 plugin_config *s = p->config_storage[i];
24744 array_free(s->extensions);
24749 free(p->config_storage);
24753 buffer_free(p->query_str);
24754 array_free(p->get_params);
24760 return HANDLER_GO_ON;
24763 @@ -80,83 +80,80 @@
24764 SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
24765 plugin_data *p = p_d;
24768 - config_values_t cv[] = {
24770 + config_values_t cv[] = {
24771 { "flv-streaming.extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
24772 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
24776 if (!p) return HANDLER_ERROR;
24779 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24782 for (i = 0; i < srv->config_context->used; i++) {
24786 s = calloc(1, sizeof(plugin_config));
24787 s->extensions = array_init();
24790 cv[0].destination = s->extensions;
24793 p->config_storage[i] = s;
24796 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24797 return HANDLER_ERROR;
24802 return HANDLER_GO_ON;
24805 -#define PATCH(x) \
24806 - p->conf.x = s->x;
24807 static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
24809 plugin_config *s = p->config_storage[0];
24811 - PATCH(extensions);
24814 + PATCH_OPTION(extensions);
24816 /* skip the first, the global context */
24817 for (i = 1; i < srv->config_context->used; i++) {
24818 data_config *dc = (data_config *)srv->config_context->data[i];
24819 s = p->config_storage[i];
24822 /* condition didn't match */
24823 if (!config_check_cond(srv, con, dc)) continue;
24827 for (j = 0; j < dc->value->used; j++) {
24828 data_unset *du = dc->value->data[j];
24831 if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
24832 - PATCH(extensions);
24833 + PATCH_OPTION(extensions);
24843 -static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
24844 +static int split_get_params(array *get_params, buffer *qrystr) {
24847 char *key = NULL, *val = NULL;
24853 /* we need the \0 */
24854 for (i = 0; i < qrystr->used; i++) {
24855 switch(qrystr->ptr[i]) {
24858 val = qrystr->ptr + i + 1;
24861 qrystr->ptr[i] = '\0';
24870 case '\0': /* fin symbol */
24871 @@ -167,7 +164,7 @@
24872 /* terminate the value */
24873 qrystr->ptr[i] = '\0';
24875 - if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
24876 + if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
24877 ds = data_string_init();
24879 buffer_copy_string_len(ds->key, key, strlen(key));
24880 @@ -175,14 +172,14 @@
24882 array_insert_unique(get_params, (data_unset *)ds);
24886 key = qrystr->ptr + i + 1;
24897 @@ -190,34 +187,34 @@
24898 plugin_data *p = p_d;
24905 if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
24908 mod_flv_streaming_patch_connection(srv, con, p);
24910 s_len = con->physical.path->used - 1;
24913 for (k = 0; k < p->conf.extensions->used; k++) {
24914 data_string *ds = (data_string *)p->conf.extensions->data[k];
24915 int ct_len = ds->value->used - 1;
24918 if (ct_len > s_len) continue;
24919 if (ds->value->used == 0) continue;
24922 if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
24923 data_string *get_param;
24924 stat_cache_entry *sce = NULL;
24928 - /* if there is a start=[0-9]+ in the header use it as start,
24929 + /* if there is a start=[0-9]+ in the header use it as start,
24930 * otherwise send the full file */
24932 array_reset(p->get_params);
24933 buffer_copy_string_buffer(p->query_str, con->uri.query);
24934 - split_get_params(srv, con, p->get_params, p->query_str);
24935 + split_get_params(p->get_params, p->query_str);
24937 if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
24938 return HANDLER_GO_ON;
24939 @@ -256,7 +253,7 @@
24940 return HANDLER_FINISHED;
24946 return HANDLER_GO_ON;
24948 @@ -266,13 +263,13 @@
24949 int mod_flv_streaming_plugin_init(plugin *p) {
24950 p->version = LIGHTTPD_VERSION_ID;
24951 p->name = buffer_init_string("flv_streaming");
24954 p->init = mod_flv_streaming_init;
24955 p->handle_physical = mod_flv_streaming_path_handler;
24956 p->set_defaults = mod_flv_streaming_set_defaults;
24957 p->cleanup = mod_flv_streaming_free;
24965 --- lighttpd-1.4.11/src/mod_indexfile.c 2005-09-30 01:08:53.000000000 +0300
24966 +++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-11 22:07:53.000000000 +0300
24967 @@ -20,51 +20,51 @@
24976 plugin_config **config_storage;
24978 - plugin_config conf;
24980 + plugin_config conf;
24983 /* init the plugin data */
24984 INIT_FUNC(mod_indexfile_init) {
24988 p = calloc(1, sizeof(*p));
24991 p->tmp_buf = buffer_init();
24997 /* detroy the plugin data */
24998 FREE_FUNC(mod_indexfile_free) {
24999 plugin_data *p = p_d;
25004 if (!p) return HANDLER_GO_ON;
25007 if (p->config_storage) {
25009 for (i = 0; i < srv->config_context->used; i++) {
25010 plugin_config *s = p->config_storage[i];
25015 array_free(s->indexfiles);
25020 free(p->config_storage);
25024 buffer_free(p->tmp_buf);
25030 return HANDLER_GO_ON;
25033 @@ -73,131 +73,128 @@
25034 SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
25035 plugin_data *p = p_d;
25038 - config_values_t cv[] = {
25040 + config_values_t cv[] = {
25041 { "index-file.names", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
25042 { "server.indexfiles", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
25043 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25047 if (!p) return HANDLER_ERROR;
25050 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25053 for (i = 0; i < srv->config_context->used; i++) {
25057 s = calloc(1, sizeof(plugin_config));
25058 s->indexfiles = array_init();
25061 cv[0].destination = s->indexfiles;
25062 cv[1].destination = s->indexfiles; /* old name for [0] */
25065 p->config_storage[i] = s;
25068 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
25069 return HANDLER_ERROR;
25074 return HANDLER_GO_ON;
25077 -#define PATCH(x) \
25078 - p->conf.x = s->x;
25079 static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
25081 plugin_config *s = p->config_storage[0];
25083 - PATCH(indexfiles);
25086 + PATCH_OPTION(indexfiles);
25088 /* skip the first, the global context */
25089 for (i = 1; i < srv->config_context->used; i++) {
25090 data_config *dc = (data_config *)srv->config_context->data[i];
25091 s = p->config_storage[i];
25094 /* condition didn't match */
25095 if (!config_check_cond(srv, con, dc)) continue;
25099 for (j = 0; j < dc->value->used; j++) {
25100 data_unset *du = dc->value->data[j];
25103 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
25104 - PATCH(indexfiles);
25105 + PATCH_OPTION(indexfiles);
25106 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
25107 - PATCH(indexfiles);
25108 + PATCH_OPTION(indexfiles);
25118 URIHANDLER_FUNC(mod_indexfile_subrequest) {
25119 plugin_data *p = p_d;
25121 stat_cache_entry *sce = NULL;
25124 if (con->uri.path->used == 0) return HANDLER_GO_ON;
25125 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
25128 mod_indexfile_patch_connection(srv, con, p);
25131 if (con->conf.log_request_handling) {
25132 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Indexfile");
25133 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
25138 for (k = 0; k < p->conf.indexfiles->used; k++) {
25139 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
25142 if (ds->value && ds->value->ptr[0] == '/') {
25143 - /* if the index-file starts with a prefix as use this file as
25144 + /* if the index-file starts with a prefix as use this file as
25145 * index-generator */
25146 buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
25148 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
25150 buffer_append_string_buffer(p->tmp_buf, ds->value);
25153 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25154 if (errno == EACCES) {
25155 con->http_status = 403;
25156 buffer_reset(con->physical.path);
25159 return HANDLER_FINISHED;
25163 if (errno != ENOENT &&
25164 errno != ENOTDIR) {
25165 /* we have no idea what happend. let's tell the user so. */
25168 con->http_status = 500;
25171 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
25172 "file not found ... or so: ", strerror(errno),
25174 "->", con->physical.path);
25177 buffer_reset(con->physical.path);
25180 return HANDLER_FINISHED;
25186 /* rewrite uri.path to the real path (/ -> /index.php) */
25187 buffer_append_string_buffer(con->uri.path, ds->value);
25188 buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
25191 /* fce is already set up a few lines above */
25194 return HANDLER_GO_ON;
25199 return HANDLER_GO_ON;
25201 @@ -207,13 +204,13 @@
25202 int mod_indexfile_plugin_init(plugin *p) {
25203 p->version = LIGHTTPD_VERSION_ID;
25204 p->name = buffer_init_string("indexfile");
25207 p->init = mod_indexfile_init;
25208 p->handle_subrequest_start = mod_indexfile_subrequest;
25209 p->set_defaults = mod_indexfile_set_defaults;
25210 p->cleanup = mod_indexfile_free;
25218 --- lighttpd-1.4.11/src/mod_mysql_vhost.c 2006-01-14 20:35:10.000000000 +0200
25219 +++ lighttpd-1.4.12/src/mod_mysql_vhost.c 2006-07-11 22:07:52.000000000 +0300
25221 -#include <unistd.h>
25225 -#include <strings.h>
25226 +#include <string.h>
25228 #ifdef HAVE_CONFIG_H
25229 #include "config.h"
25232 +#ifdef HAVE_MYSQL_H
25233 +# ifdef HAVE_LIBMYSQL
25234 +# define HAVE_MYSQL
25241 @@ -16,61 +21,40 @@
25244 #include "stat_cache.h"
25245 -#ifdef DEBUG_MOD_MYSQL_VHOST
25248 +#include "sys-files.h"
25251 - * Plugin for lighttpd to use MySQL
25252 - * for domain to directory lookups,
25253 - * i.e virtual hosts (vhosts).
25255 - * Optionally sets fcgi_offset and fcgi_arg
25256 - * in preparation for fcgi.c to handle
25257 - * per-user fcgi chroot jails.
25259 - * /ada@riksnet.se 2004-12-06
25261 +#include "mod_sql_vhost_core.h"
25265 +#define CORE_PLUGIN "mod_sql_vhost_core"
25275 - buffer *hostname;
25276 - unsigned short port;
25280 buffer *mysql_post;
25282 + mod_sql_vhost_core_plugin_config *core;
25285 /* global plugin data */
25293 plugin_config **config_storage;
25295 - plugin_config conf;
25297 + plugin_config conf;
25300 -/* per connection plugin data */
25302 - buffer *server_name;
25303 - buffer *document_root;
25304 - buffer *fcgi_arg;
25305 - unsigned fcgi_offset;
25306 -} plugin_connection_data;
25307 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost);
25309 /* init the plugin data */
25310 INIT_FUNC(mod_mysql_vhost_init) {
25314 p = calloc(1, sizeof(*p));
25316 p->tmp_buf = buffer_init();
25317 @@ -83,144 +67,77 @@
25318 plugin_data *p = p_d;
25323 - log_error_write(srv, __FILE__, __LINE__, "ss",
25324 - "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
25327 if (!p) return HANDLER_GO_ON;
25330 if (p->config_storage) {
25332 for (i = 0; i < srv->config_context->used; i++) {
25333 plugin_config *s = p->config_storage[i];
25338 mysql_close(s->mysql);
25340 - buffer_free(s->mydb);
25341 - buffer_free(s->myuser);
25342 - buffer_free(s->mypass);
25343 - buffer_free(s->mysock);
25345 buffer_free(s->mysql_pre);
25346 buffer_free(s->mysql_post);
25351 free(p->config_storage);
25353 buffer_free(p->tmp_buf);
25357 - return HANDLER_GO_ON;
25360 -/* handle the plugin per connection data */
25361 -static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
25363 - plugin_data *p = p_d;
25364 - plugin_connection_data *c = con->plugin_ctx[p->id];
25369 - log_error_write(srv, __FILE__, __LINE__, "ss",
25370 - "mod_mysql_connection_data", c ? "old" : "NEW");
25374 - c = calloc(1, sizeof(*c));
25376 - c->server_name = buffer_init();
25377 - c->document_root = buffer_init();
25378 - c->fcgi_arg = buffer_init();
25379 - c->fcgi_offset = 0;
25381 - return con->plugin_ctx[p->id] = c;
25384 -/* destroy the plugin per connection data */
25385 -CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
25386 - plugin_data *p = p_d;
25387 - plugin_connection_data *c = con->plugin_ctx[p->id];
25392 - log_error_write(srv, __FILE__, __LINE__, "ss",
25393 - "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
25396 - if (!c) return HANDLER_GO_ON;
25398 - buffer_free(c->server_name);
25399 - buffer_free(c->document_root);
25400 - buffer_free(c->fcgi_arg);
25401 - c->fcgi_offset = 0;
25406 - con->plugin_ctx[p->id] = NULL;
25407 return HANDLER_GO_ON;
25410 /* set configuration values */
25411 SERVER_FUNC(mod_mysql_vhost_set_defaults) {
25412 plugin_data *p = p_d;
25413 + mod_sql_vhost_core_plugin_data *core_config;
25418 - config_values_t cv[] = {
25419 - { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25420 - { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25421 - { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25422 - { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25423 - { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25424 - { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
25425 - { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER },
25426 - { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25429 + /* our very own plugin storage, one entry for each conditional
25431 + * srv->config_context->used is the number of conditionals
25433 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25436 + /* get the config of the core-plugin */
25437 + core_config = plugin_get_config(srv, CORE_PLUGIN);
25440 + /* walk through all conditionals and check for assignments */
25441 for (i = 0; i < srv->config_context->used; i++) {
25448 + /* get the config from the core plugin for this conditional-context */
25449 s = calloc(1, sizeof(plugin_config));
25450 - s->mydb = buffer_init();
25451 - s->myuser = buffer_init();
25452 - s->mypass = buffer_init();
25453 - s->mysock = buffer_init();
25454 - s->hostname = buffer_init();
25455 - s->port = 0; /* default port for mysql */
25456 - sel = buffer_init();
25459 + s->core = core_config->config_storage[i];
25463 s->mysql_pre = buffer_init();
25464 s->mysql_post = buffer_init();
25466 - cv[0].destination = s->mydb;
25467 - cv[1].destination = s->myuser;
25468 - cv[2].destination = s->mypass;
25469 - cv[3].destination = s->mysock;
25470 - cv[4].destination = sel;
25471 - cv[5].destination = s->hostname;
25472 - cv[6].destination = &(s->port);
25475 p->config_storage[i] = s;
25477 - if (config_insert_values_global(srv,
25478 - ((data_config *)srv->config_context->data[i])->value,
25479 - cv)) return HANDLER_ERROR;
25481 - s->mysql_pre = buffer_init();
25482 - s->mysql_post = buffer_init();
25485 + /* check if we are the plugin for this backend */
25486 + if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
25488 + /* attach us to the core-plugin */
25489 + s->core->backend_data = p;
25490 + s->core->get_vhost = mod_mysql_vhost_get_vhost;
25492 + sel = buffer_init();
25493 + buffer_copy_string_buffer(sel, s->core->select_vhost);
25495 if (sel->used && (qmark = index(sel->ptr, '?'))) {
25497 buffer_copy_string(s->mysql_pre, sel->ptr);
25498 @@ -228,35 +145,35 @@
25500 buffer_copy_string_buffer(s->mysql_pre, sel);
25511 * - password, default: empty
25512 * - socket, default: mysql default
25513 * - hostname, if set overrides socket
25514 * - port, default: 3306
25518 /* all have to be set */
25519 - if (!(buffer_is_empty(s->myuser) ||
25520 - buffer_is_empty(s->mydb))) {
25521 + if (!(buffer_is_empty(s->core->user) ||
25522 + buffer_is_empty(s->core->db))) {
25527 if (NULL == (s->mysql = mysql_init(NULL))) {
25528 log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
25531 return HANDLER_ERROR;
25533 -#define FOO(x) (s->x->used ? s->x->ptr : NULL)
25535 - if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass),
25536 - FOO(mydb), s->port, FOO(mysock), 0)) {
25537 +#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
25539 + if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
25540 + FOO(db), s->core->port, FOO(sock), 0)) {
25541 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
25544 return HANDLER_ERROR;
25547 @@ -265,61 +182,47 @@
25548 /* otherwise we cannot be sure that mysql is fd i-1 */
25549 if (-1 == (fd = open("/dev/null", 0))) {
25551 - fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25552 + fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25561 return HANDLER_GO_ON;
25564 -#define PATCH(x) \
25565 - p->conf.x = s->x;
25566 static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
25569 plugin_config *s = p->config_storage[0];
25571 - PATCH(mysql_pre);
25572 - PATCH(mysql_post);
25578 + PATCH_OPTION(mysql_pre);
25579 + PATCH_OPTION(mysql_post);
25580 + PATCH_OPTION(mysql);
25582 /* skip the first, the global context */
25583 for (i = 1; i < srv->config_context->used; i++) {
25584 data_config *dc = (data_config *)srv->config_context->data[i];
25585 s = p->config_storage[i];
25588 /* condition didn't match */
25589 if (!config_check_cond(srv, con, dc)) continue;
25591 - /* merge config */
25592 - for (j = 0; j < dc->value->used; j++) {
25593 - data_unset *du = dc->value->data[j];
25595 - if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
25596 - PATCH(mysql_pre);
25597 - PATCH(mysql_post);
25604 + PATCH_OPTION(mysql);
25605 + PATCH_OPTION(mysql_pre);
25606 + PATCH_OPTION(mysql_post);
25616 -/* handle document root request */
25617 -CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
25619 + * get the vhost info from the database
25621 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
25622 plugin_data *p = p_d;
25623 - plugin_connection_data *c;
25624 - stat_cache_entry *sce;
25628 @@ -332,13 +235,6 @@
25630 if (!p->conf.mysql) return HANDLER_GO_ON;
25632 - /* sets up connection data if not done yet */
25633 - c = mod_mysql_vhost_connection_data(srv, con, p_d);
25635 - /* check if cached this connection */
25636 - if (c->server_name->used && /* con->uri.authority->used && */
25637 - buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
25639 /* build and run SQL query */
25640 buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
25641 if (p->conf.mysql_post->used) {
25642 @@ -347,77 +243,43 @@
25644 if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
25645 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
25648 + mysql_free_result(result);
25649 + return HANDLER_GO_ON;
25651 result = mysql_store_result(p->conf.mysql);
25652 cols = mysql_num_fields(result);
25653 row = mysql_fetch_row(result);
25655 if (!row || cols < 1) {
25656 /* no such virtual host */
25657 mysql_free_result(result);
25658 return HANDLER_GO_ON;
25661 - /* sanity check that really is a directory */
25662 - buffer_copy_string(p->tmp_buf, row[0]);
25663 - BUFFER_APPEND_SLASH(p->tmp_buf);
25665 - if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25666 - log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
25669 - if (!S_ISDIR(sce->st.st_mode)) {
25670 - log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
25673 + buffer_copy_string(docroot, row[0]);
25675 - /* cache the data */
25676 - buffer_copy_string_buffer(c->server_name, con->uri.authority);
25677 - buffer_copy_string_buffer(c->document_root, p->tmp_buf);
25679 - /* fcgi_offset and fcgi_arg are optional */
25680 - if (cols > 1 && row[1]) {
25681 - c->fcgi_offset = atoi(row[1]);
25683 - if (cols > 2 && row[2]) {
25684 - buffer_copy_string(c->fcgi_arg, row[2]);
25686 - c->fcgi_arg->used = 0;
25689 - c->fcgi_offset = c->fcgi_arg->used = 0;
25691 mysql_free_result(result);
25693 - /* fix virtual server and docroot */
25694 -GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
25695 - buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
25698 - log_error_write(srv, __FILE__, __LINE__, "sbbdb",
25699 - result ? "NOT CACHED" : "cached",
25700 - con->server_name, con->physical.doc_root,
25701 - c->fcgi_offset, c->fcgi_arg);
25703 - return HANDLER_GO_ON;
25705 -ERR500: if (result) mysql_free_result(result);
25706 - con->http_status = 500; /* Internal Error */
25707 - return HANDLER_FINISHED;
25708 + return HANDLER_GO_ON;
25711 /* this function is called at dlopen() time and inits the callbacks */
25712 int mod_mysql_vhost_plugin_init(plugin *p) {
25715 p->version = LIGHTTPD_VERSION_ID;
25716 p->name = buffer_init_string("mysql_vhost");
25718 p->init = mod_mysql_vhost_init;
25719 p->cleanup = mod_mysql_vhost_cleanup;
25720 - p->handle_request_done = mod_mysql_vhost_handle_connection_close;
25722 p->set_defaults = mod_mysql_vhost_set_defaults;
25723 - p->handle_docroot = mod_mysql_vhost_handle_docroot;
25725 + ds = data_string_init();
25726 + buffer_copy_string(ds->value, CORE_PLUGIN);
25727 + array_insert_unique(p->required_plugins, (data_unset *)ds);
25732 --- lighttpd-1.4.11/src/mod_proxy.c 2006-01-31 13:01:22.000000000 +0200
25733 +++ lighttpd-1.4.12/src/mod_proxy.c 2006-07-11 22:07:52.000000000 +0300
25735 #include <sys/types.h>
25737 -#include <unistd.h>
25740 #include <string.h>
25743 #include "inet_ntop_cache.h"
25745 +#include "network.h"
25747 +#include "http_resp.h"
25754 #include "sys-socket.h"
25755 +#include "sys-files.h"
25756 +#include "sys-strings.h"
25758 #define data_proxy data_fastcgi
25759 #define data_proxy_init data_fastcgi_init
25760 @@ -38,16 +42,16 @@
25761 #define PROXY_RETRY_TIMEOUT 60
25765 - * the proxy module is based on the fastcgi module
25768 + * the proxy module is based on the fastcgi module
25770 * 28.06.2004 Jan Kneschke The first release
25771 * 01.07.2004 Evgeny Rodichev Several bugfixes and cleanups
25772 * - co-ordinate up- and downstream flows correctly (proxy_demux_response
25773 * and proxy_handle_fdevent)
25774 * - correctly transfer upstream http_response_status;
25775 * - some unused structures removed.
25778 * TODO: - delay upstream read if write_queue is too large
25779 * (to prevent memory eating, like in apache). Shoud be
25781 @@ -66,26 +70,31 @@
25784 proxy_balance_t balance;
25786 + array *last_used_backends; /* "extension" : last_used_backend */
25793 buffer *parse_response;
25794 buffer *balance_buf;
25797 + array *ignore_headers;
25799 plugin_config **config_storage;
25802 plugin_config conf;
25806 - PROXY_STATE_INIT,
25807 - PROXY_STATE_CONNECT,
25808 - PROXY_STATE_PREPARE_WRITE,
25809 - PROXY_STATE_WRITE,
25810 - PROXY_STATE_READ,
25811 - PROXY_STATE_ERROR
25813 + PROXY_STATE_INIT,
25814 + PROXY_STATE_CONNECT,
25815 + PROXY_STATE_PREPARE_WRITE,
25816 + PROXY_STATE_WRITE,
25817 + PROXY_STATE_RESPONSE_HEADER,
25818 + PROXY_STATE_RESPONSE_CONTENT,
25819 + PROXY_STATE_ERROR
25820 } proxy_connection_state_t;
25822 enum { PROXY_STDOUT, PROXY_END_REQUEST };
25823 @@ -93,19 +102,20 @@
25825 proxy_connection_state_t state;
25826 time_t state_timestamp;
25833 buffer *response_header;
25839 int fd; /* fd to the proxy process */
25840 int fde_ndx; /* index into the fd-event buffer */
25842 size_t path_info_offset; /* start of path_info in uri.path */
25845 connection *remote_conn; /* dump pointer */
25846 plugin_data *plugin_data; /* dump pointer */
25848 @@ -116,21 +126,22 @@
25850 static handler_ctx * handler_ctx_init() {
25851 handler_ctx * hctx;
25855 hctx = calloc(1, sizeof(*hctx));
25858 hctx->state = PROXY_STATE_INIT;
25862 hctx->response = buffer_init();
25863 hctx->response_header = buffer_init();
25865 hctx->wb = chunkqueue_init();
25866 + hctx->rb = chunkqueue_init();
25869 hctx->fde_ndx = -1;
25875 @@ -138,47 +149,70 @@
25876 buffer_free(hctx->response);
25877 buffer_free(hctx->response_header);
25878 chunkqueue_free(hctx->wb);
25880 + chunkqueue_free(hctx->rb);
25885 INIT_FUNC(mod_proxy_init) {
25890 + char *hop2hop_headers[] = {
25897 p = calloc(1, sizeof(*p));
25900 p->parse_response = buffer_init();
25901 p->balance_buf = buffer_init();
25903 + p->ignore_headers = array_init();
25905 + for (i = 0; hop2hop_headers[i]; i++) {
25908 + if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
25909 + ds = data_string_init();
25912 + buffer_copy_string(ds->value, hop2hop_headers[i]);
25913 + array_insert_unique(p->ignore_headers, (data_unset *)ds);
25920 FREE_FUNC(mod_proxy_free) {
25921 plugin_data *p = p_d;
25926 buffer_free(p->parse_response);
25927 buffer_free(p->balance_buf);
25930 if (p->config_storage) {
25932 for (i = 0; i < srv->config_context->used; i++) {
25933 plugin_config *s = p->config_storage[i];
25938 array_free(s->extensions);
25940 + array_free(s->last_used_backends);
25945 free(p->config_storage);
25949 + free(p->ignore_headers);
25954 return HANDLER_GO_ON;
25957 @@ -186,37 +220,38 @@
25958 plugin_data *p = p_d;
25962 - config_values_t cv[] = {
25964 + config_values_t cv[] = {
25965 { "proxy.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
25966 { "proxy.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
25967 { "proxy.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
25968 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25972 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25975 for (i = 0; i < srv->config_context->used; i++) {
25980 s = malloc(sizeof(plugin_config));
25981 - s->extensions = array_init();
25982 + s->extensions = array_init();
25983 + s->last_used_backends = array_init();
25987 cv[0].destination = s->extensions;
25988 cv[1].destination = &(s->debug);
25989 cv[2].destination = p->balance_buf;
25991 buffer_reset(p->balance_buf);
25994 p->config_storage[i] = s;
25995 ca = ((data_config *)srv->config_context->data[i])->value;
25998 if (0 != config_insert_values_global(srv, ca, cv)) {
25999 return HANDLER_ERROR;
26003 if (buffer_is_empty(p->balance_buf)) {
26004 s->balance = PROXY_BALANCE_FAIR;
26005 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
26006 @@ -226,7 +261,7 @@
26007 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
26008 s->balance = PROXY_BALANCE_HASH;
26010 - log_error_write(srv, __FILE__, __LINE__, "sb",
26011 + log_error_write(srv, __FILE__, __LINE__, "sb",
26012 "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
26013 return HANDLER_ERROR;
26015 @@ -234,91 +269,91 @@
26016 if (NULL != (du = array_get_element(ca, "proxy.server"))) {
26018 data_array *da = (data_array *)du;
26021 if (du->type != TYPE_ARRAY) {
26022 - log_error_write(srv, __FILE__, __LINE__, "sss",
26023 + log_error_write(srv, __FILE__, __LINE__, "sss",
26024 "unexpected type for key: ", "proxy.server", "array of strings");
26027 return HANDLER_ERROR;
26033 * proxy.server = ( "<ext>" => ...,
26038 for (j = 0; j < da->value->used; j++) {
26039 data_array *da_ext = (data_array *)da->value->data[j];
26043 if (da_ext->type != TYPE_ARRAY) {
26044 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
26045 - "unexpected type for key: ", "proxy.server",
26046 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
26047 + "unexpected type for key: ", "proxy.server",
26048 "[", da->value->data[j]->key, "](string)");
26051 return HANDLER_ERROR;
26055 - * proxy.server = ( "<ext>" =>
26056 - * ( "<host>" => ( ... ),
26059 + * proxy.server = ( "<ext>" =>
26060 + * ( "<host>" => ( ... ),
26061 * "<host>" => ( ... )
26068 for (n = 0; n < da_ext->value->used; n++) {
26069 data_array *da_host = (data_array *)da_ext->value->data[n];
26075 - config_values_t pcv[] = {
26077 + config_values_t pcv[] = {
26078 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
26079 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
26080 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
26084 if (da_host->type != TYPE_ARRAY) {
26085 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
26086 - "unexpected type for key:",
26088 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
26089 + "unexpected type for key:",
26091 "[", da_ext->value->data[n]->key, "](string)");
26094 return HANDLER_ERROR;
26098 df = data_proxy_init();
26104 buffer_copy_string_buffer(df->key, da_host->key);
26107 pcv[0].destination = df->host;
26108 pcv[1].destination = &(df->port);
26111 if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
26112 return HANDLER_ERROR;
26116 if (buffer_is_empty(df->host)) {
26117 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
26118 - "missing key (string):",
26119 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
26120 + "missing key (string):",
26127 return HANDLER_ERROR;
26131 /* if extension already exists, take it */
26134 if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
26135 dfa = data_array_init();
26138 buffer_copy_string_buffer(dfa->key, da_ext->key);
26141 array_insert_unique(dfa->value, (data_unset *)df);
26142 array_insert_unique(s->extensions, (data_unset *)dfa);
26144 @@ -328,19 +363,19 @@
26150 return HANDLER_GO_ON;
26153 void proxy_connection_close(server *srv, handler_ctx *hctx) {
26158 if (NULL == hctx) return;
26161 p = hctx->plugin_data;
26162 con = hctx->remote_conn;
26165 if (hctx->fd != -1) {
26166 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26167 fdevent_unregister(srv->ev, hctx->fd);
26168 @@ -348,47 +383,56 @@
26174 handler_ctx_free(hctx);
26175 - con->plugin_ctx[p->id] = NULL;
26176 + con->plugin_ctx[p->id] = NULL;
26179 static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
26180 struct sockaddr *proxy_addr;
26181 struct sockaddr_in proxy_addr_in;
26185 plugin_data *p = hctx->plugin_data;
26186 data_proxy *host= hctx->host;
26187 int proxy_fd = hctx->fd;
26190 memset(&proxy_addr, 0, sizeof(proxy_addr));
26193 proxy_addr_in.sin_family = AF_INET;
26194 proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr);
26195 proxy_addr_in.sin_port = htons(host->port);
26196 servlen = sizeof(proxy_addr_in);
26199 proxy_addr = (struct sockaddr *) &proxy_addr_in;
26202 if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
26203 - if (errno == EINPROGRESS || errno == EALREADY) {
26205 + errno = WSAGetLastError();
26209 + case WSAEWOULDBLOCK:
26211 + case EINPROGRESS:
26213 if (p->conf.debug) {
26214 - log_error_write(srv, __FILE__, __LINE__, "sd",
26215 + log_error_write(srv, __FILE__, __LINE__, "sd",
26216 "connect delayed:", proxy_fd);
26223 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
26226 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
26227 "connect failed:", proxy_fd, strerror(errno), errno);
26233 + fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
26234 if (p->conf.debug) {
26235 - log_error_write(srv, __FILE__, __LINE__, "sd",
26236 + log_error_write(srv, __FILE__, __LINE__, "sd",
26237 "connect succeeded: ", proxy_fd);
26240 @@ -422,25 +466,26 @@
26242 static int proxy_create_env(server *srv, handler_ctx *hctx) {
26246 connection *con = hctx->remote_conn;
26247 + plugin_data *p = hctx->plugin_data;
26253 b = chunkqueue_get_append_buffer(hctx->wb);
26257 buffer_copy_string(b, get_http_method_name(con->request.http_method));
26258 BUFFER_APPEND_STRING_CONST(b, " ");
26261 buffer_append_string_buffer(b, con->request.uri);
26262 BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
26264 proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
26265 - /* http_host is NOT is just a pointer to a buffer
26266 + /* http_host is NOT is just a pointer to a buffer
26267 * which is NULL if it is not set */
26268 - if (con->request.http_host &&
26269 + if (con->request.http_host &&
26270 !buffer_is_empty(con->request.http_host)) {
26271 proxy_set_header(con, "X-Host", con->request.http_host->ptr);
26273 @@ -449,24 +494,26 @@
26274 /* request header */
26275 for (i = 0; i < con->request.headers->used; i++) {
26279 ds = (data_string *)con->request.headers->data[i];
26282 if (ds->value->used && ds->key->used) {
26283 - if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
26286 + /* don't copy hop-to-hop headers */
26287 + if (array_get_element(p->ignore_headers, ds->key->ptr)) continue;
26289 buffer_append_string_buffer(b, ds->key);
26290 BUFFER_APPEND_STRING_CONST(b, ": ");
26291 buffer_append_string_buffer(b, ds->value);
26292 BUFFER_APPEND_STRING_CONST(b, "\r\n");
26297 BUFFER_APPEND_STRING_CONST(b, "\r\n");
26300 hctx->wb->bytes_in += b->used - 1;
26304 if (con->request.content_length) {
26305 chunkqueue *req_cq = con->request_content_queue;
26307 @@ -479,7 +526,7 @@
26309 /* we announce toWrite octects
26310 * now take all the request_content chunk that we need to fill this request
26314 switch (req_c->type) {
26316 @@ -507,223 +554,125 @@
26318 req_c->offset += weHave;
26319 req_cq->bytes_out += weHave;
26322 hctx->wb->bytes_in += weHave;
26339 static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) {
26340 hctx->state = state;
26341 hctx->state_timestamp = srv->cur_ts;
26348 -static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
26350 - int http_response_status = -1;
26353 +static void chunkqueue_print(chunkqueue *cq) {
26356 - /* \r\n -> \0\0 */
26358 - buffer_copy_string_buffer(p->parse_response, in);
26360 - for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
26361 - char *key, *value;
26369 - if (-1 == http_response_status) {
26370 - /* The first line of a Response message is the Status-Line */
26372 - for (key=s; *key && *key != ' '; key++);
26375 - http_response_status = (int) strtol(key, NULL, 10);
26376 - if (http_response_status <= 0) http_response_status = 502;
26378 - http_response_status = 502;
26381 - con->http_status = http_response_status;
26382 - con->parsed_response |= HTTP_STATUS;
26386 - if (NULL == (value = strchr(s, ':'))) {
26387 - /* now we expect: "<key>: <value>\n" */
26393 - key_len = value - key;
26397 - while (*value == ' ' || *value == '\t') value++;
26401 - switch(key_len) {
26403 - if (0 == strncasecmp(key, "Date", key_len)) {
26404 - con->parsed_response |= HTTP_DATE;
26408 - if (0 == strncasecmp(key, "Location", key_len)) {
26409 - con->parsed_response |= HTTP_LOCATION;
26413 - if (0 == strncasecmp(key, "Connection", key_len)) {
26418 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
26419 - con->response.content_length = strtol(value, NULL, 10);
26420 - con->parsed_response |= HTTP_CONTENT_LENGTH;
26427 - if (copy_header) {
26428 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26429 - ds = data_response_init();
26431 - buffer_copy_string_len(ds->key, key, key_len);
26432 - buffer_copy_string(ds->value, value);
26434 - array_insert_unique(con->response.headers, (data_unset *)ds);
26439 + for (c = cq->first; c; c = c->next) {
26440 + fprintf(stderr, "%s", c->mem->ptr + c->offset);
26442 + fprintf(stderr, "\r\n");
26446 static int proxy_demux_response(server *srv, handler_ctx *hctx) {
26451 plugin_data *p = hctx->plugin_data;
26452 connection *con = hctx->remote_conn;
26453 int proxy_fd = hctx->fd;
26455 - /* check how much we have to read */
26456 - if (ioctl(hctx->fd, FIONREAD, &b)) {
26457 - log_error_write(srv, __FILE__, __LINE__, "sd",
26458 - "ioctl failed: ",
26463 + chunkqueue *next_queue = NULL;
26466 - if (p->conf.debug) {
26467 - log_error_write(srv, __FILE__, __LINE__, "sd",
26468 - "proxy - have to read:", b);
26472 - if (hctx->response->used == 0) {
26473 - /* avoid too small buffer */
26474 - buffer_prepare_append(hctx->response, b + 1);
26475 - hctx->response->used = 1;
26477 - buffer_prepare_append(hctx->response, hctx->response->used + b);
26480 - if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
26481 - log_error_write(srv, __FILE__, __LINE__, "sds",
26482 - "unexpected end-of-file (perhaps the proxy process died):",
26483 - proxy_fd, strerror(errno));
26487 - /* this should be catched by the b > 0 above */
26490 - hctx->response->used += r;
26491 - hctx->response->ptr[hctx->response->used - 1] = '\0';
26494 - log_error_write(srv, __FILE__, __LINE__, "sdsbs",
26495 - "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
26498 - if (0 == con->got_response) {
26499 - con->got_response = 1;
26500 - buffer_prepare_copy(hctx->response_header, 128);
26503 - if (0 == con->file_started) {
26506 - /* search for the \r\n\r\n in the string */
26507 - if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
26508 - size_t hlen = c - hctx->response->ptr + 4;
26509 - size_t blen = hctx->response->used - hlen - 1;
26512 - buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
26514 - log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
26516 - /* parse the response header */
26517 - proxy_response_parse(srv, con, p, hctx->response_header);
26519 - /* enable chunked-transfer-encoding */
26520 - if (con->request.http_version == HTTP_VERSION_1_1 &&
26521 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
26522 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26525 - con->file_started = 1;
26527 - http_chunk_append_mem(srv, con, c + 4, blen + 1);
26528 - joblist_append(srv, con);
26530 - hctx->response->used = 0;
26533 - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
26534 - joblist_append(srv, con);
26535 - hctx->response->used = 0;
26539 - /* reading from upstream done */
26540 + switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
26541 + case NETWORK_STATUS_SUCCESS:
26542 + /* we got content */
26544 + case NETWORK_STATUS_CONNECTION_CLOSE:
26545 + /* we are done, get out of here */
26546 con->file_finished = 1;
26549 + /* close the chunk-queue with a empty chunk */
26550 http_chunk_append_mem(srv, con, NULL, 0);
26551 joblist_append(srv, con);
26561 + /* looks like we got some content
26563 + * split off the header from the incoming stream
26566 + if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
26567 + http_resp *resp = http_response_init();
26569 + /* the response header is not fully received yet,
26571 + * extract the http-response header from the rb-cq
26573 + fprintf(stderr, "%s.%d: network-read\r\n", __FILE__, __LINE__);
26574 + chunkqueue_print(hctx->rb);
26576 + switch (http_response_parse_cq(hctx->rb, resp)) {
26577 + case PARSE_ERROR:
26578 + /* parsing failed */
26580 + con->http_status = 502; /* Bad Gateway */
26582 + case PARSE_NEED_MORE:
26584 + case PARSE_SUCCESS:
26585 + con->http_status = resp->status;
26587 + fprintf(stderr, "%s.%d: parsing done\r\n", __FILE__, __LINE__);
26588 + chunkqueue_print(hctx->rb);
26590 + con->file_started = 1;
26592 + hctx->state = PROXY_STATE_RESPONSE_CONTENT;
26597 + /* FIXME: pass the response-header to the other plugins to
26598 + * setup the filter-queue
26600 + * - use next-queue instead of con->write_queue
26603 + next_queue = con->write_queue;
26605 + assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
26607 + /* FIXME: if we have a content-length or chunked-encoding
26610 + * for now we wait for EOF on the socket */
26612 + /* copy the content to the next cq */
26613 + for (c = hctx->rb->first; c; c = c->next) {
26614 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
26616 + c->offset = c->mem->used - 1;
26621 + chunkqueue_remove_finished_chunks(hctx->rb);
26627 @@ -731,12 +680,12 @@
26628 data_proxy *host= hctx->host;
26629 plugin_data *p = hctx->plugin_data;
26630 connection *con = hctx->remote_conn;
26638 (!host->host->used || !host->port)) return -1;
26641 switch(hctx->state) {
26642 case PROXY_STATE_INIT:
26643 if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
26644 @@ -744,19 +693,19 @@
26645 return HANDLER_ERROR;
26647 hctx->fde_ndx = -1;
26653 fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
26656 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
26657 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
26660 return HANDLER_ERROR;
26667 case PROXY_STATE_CONNECT:
26668 /* try to finish the connect() */
26669 if (hctx->state == PROXY_STATE_INIT) {
26670 @@ -764,16 +713,16 @@
26671 switch (proxy_establish_connection(srv, hctx)) {
26673 proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
26676 /* connection is in progress, wait for an event and call getsockopt() below */
26679 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26682 return HANDLER_WAIT_FOR_EVENT;
26684 /* if ECONNREFUSED choose another connection -> FIXME */
26685 hctx->fde_ndx = -1;
26688 return HANDLER_ERROR;
26690 /* everything is ok, go on */
26691 @@ -782,152 +731,152 @@
26694 socklen_t socket_error_len = sizeof(socket_error);
26696 - /* we don't need it anymore */
26698 + /* we don't need it anymore */
26699 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26701 /* try to finish the connect() */
26702 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
26703 - log_error_write(srv, __FILE__, __LINE__, "ss",
26704 + log_error_write(srv, __FILE__, __LINE__, "ss",
26705 "getsockopt failed:", strerror(errno));
26708 return HANDLER_ERROR;
26710 if (socket_error != 0) {
26711 log_error_write(srv, __FILE__, __LINE__, "ss",
26712 - "establishing connection failed:", strerror(socket_error),
26713 + "establishing connection failed:", strerror(socket_error),
26714 "port:", hctx->host->port);
26717 return HANDLER_ERROR;
26719 if (p->conf.debug) {
26720 - log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
26721 + log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
26723 + fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, hctx->fd);
26727 proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
26729 case PROXY_STATE_PREPARE_WRITE:
26730 proxy_create_env(srv, hctx);
26733 proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
26737 case PROXY_STATE_WRITE:;
26738 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
26739 + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
26741 chunkqueue_remove_finished_chunks(hctx->wb);
26744 - if (errno != EAGAIN &&
26745 - errno != EINTR) {
26746 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26748 - return HANDLER_ERROR;
26750 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26752 + case NETWORK_STATUS_FATAL_ERROR:
26753 + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26755 - return HANDLER_WAIT_FOR_EVENT;
26757 + return HANDLER_ERROR;
26758 + case NETWORK_STATUS_WAIT_FOR_EVENT:
26760 + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26762 + return HANDLER_WAIT_FOR_EVENT;
26765 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
26766 - proxy_set_state(srv, hctx, PROXY_STATE_READ);
26767 + proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
26769 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26770 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
26772 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26775 return HANDLER_WAIT_FOR_EVENT;
26779 return HANDLER_WAIT_FOR_EVENT;
26780 - case PROXY_STATE_READ:
26781 + case PROXY_STATE_RESPONSE_HEADER:
26782 /* waiting for a response */
26784 return HANDLER_WAIT_FOR_EVENT;
26786 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
26787 return HANDLER_ERROR;
26791 return HANDLER_GO_ON;
26794 -#define PATCH(x) \
26795 - p->conf.x = s->x;
26796 static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
26798 plugin_config *s = p->config_storage[0];
26800 - PATCH(extensions);
26805 + PATCH_OPTION(extensions);
26806 + PATCH_OPTION(debug);
26807 + PATCH_OPTION(balance);
26808 + PATCH_OPTION(last_used_backends);
26810 /* skip the first, the global context */
26811 for (i = 1; i < srv->config_context->used; i++) {
26812 data_config *dc = (data_config *)srv->config_context->data[i];
26813 s = p->config_storage[i];
26816 /* condition didn't match */
26817 if (!config_check_cond(srv, con, dc)) continue;
26821 for (j = 0; j < dc->value->used; j++) {
26822 data_unset *du = dc->value->data[j];
26825 if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
26826 - PATCH(extensions);
26827 + PATCH_OPTION(extensions);
26828 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
26830 + PATCH_OPTION(debug);
26831 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
26833 + PATCH_OPTION(balance);
26834 + PATCH_OPTION(last_used_backends);
26844 SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
26845 plugin_data *p = p_d;
26848 handler_ctx *hctx = con->plugin_ctx[p->id];
26852 if (NULL == hctx) return HANDLER_GO_ON;
26854 mod_proxy_patch_connection(srv, con, p);
26861 if (con->mode != p->id) return HANDLER_GO_ON;
26864 /* ok, create the request */
26865 switch(proxy_write_request(srv, hctx)) {
26866 case HANDLER_ERROR:
26867 - log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
26868 + log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
26874 /* disable this server */
26875 host->is_disabled = 1;
26876 host->disable_ts = srv->cur_ts;
26879 proxy_connection_close(srv, hctx);
26881 - /* reset the enviroment and restart the sub-request */
26883 + /* reset the enviroment and restart the sub-request */
26884 buffer_reset(con->physical.path);
26885 con->mode = DIRECT;
26887 joblist_append(srv, con);
26889 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26890 - * and hope that the childs will be restarted
26892 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26893 + * and hope that the childs will be restarted
26897 return HANDLER_WAIT_FOR_FD;
26898 @@ -938,7 +887,7 @@
26904 if (con->file_started == 1) {
26905 return HANDLER_FINISHED;
26907 @@ -951,13 +900,14 @@
26908 handler_ctx *hctx = ctx;
26909 connection *con = hctx->remote_conn;
26910 plugin_data *p = hctx->plugin_data;
26915 if ((revents & FDEVENT_IN) &&
26916 - hctx->state == PROXY_STATE_READ) {
26917 + (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
26918 + hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
26920 if (p->conf.debug) {
26921 - log_error_write(srv, __FILE__, __LINE__, "sd",
26922 + log_error_write(srv, __FILE__, __LINE__, "sd",
26923 "proxy: fdevent-in", hctx->state);
26926 @@ -966,10 +916,10 @@
26929 hctx->host->usage--;
26933 proxy_connection_close(srv, hctx);
26936 joblist_append(srv, con);
26937 return HANDLER_FINISHED;
26939 @@ -982,53 +932,53 @@
26940 /* response might have been already started, kill the connection */
26941 connection_set_state(srv, con, CON_STATE_ERROR);
26945 joblist_append(srv, con);
26946 return HANDLER_FINISHED;
26951 if (revents & FDEVENT_OUT) {
26952 if (p->conf.debug) {
26953 - log_error_write(srv, __FILE__, __LINE__, "sd",
26954 + log_error_write(srv, __FILE__, __LINE__, "sd",
26955 "proxy: fdevent-out", hctx->state);
26958 if (hctx->state == PROXY_STATE_CONNECT ||
26959 hctx->state == PROXY_STATE_WRITE) {
26960 /* we are allowed to send something out
26963 * 1. in a unfinished connect() call
26964 * 2. in a unfinished write() call (long POST request)
26966 return mod_proxy_handle_subrequest(srv, con, p);
26968 - log_error_write(srv, __FILE__, __LINE__, "sd",
26969 + log_error_write(srv, __FILE__, __LINE__, "sd",
26970 "proxy: out", hctx->state);
26975 /* perhaps this issue is already handled */
26976 if (revents & FDEVENT_HUP) {
26977 if (p->conf.debug) {
26978 - log_error_write(srv, __FILE__, __LINE__, "sd",
26979 + log_error_write(srv, __FILE__, __LINE__, "sd",
26980 "proxy: fdevent-hup", hctx->state);
26984 if (hctx->state == PROXY_STATE_CONNECT) {
26985 /* connect() -> EINPROGRESS -> HUP */
26989 - * what is proxy is doing if it can't reach the next hop ?
26991 + * what is proxy is doing if it can't reach the next hop ?
26996 proxy_connection_close(srv, hctx);
26997 joblist_append(srv, con);
27000 con->http_status = 503;
27001 con->mode = DIRECT;
27004 return HANDLER_FINISHED;
27007 @@ -1038,13 +988,13 @@
27008 joblist_append(srv, con);
27009 } else if (revents & FDEVENT_ERR) {
27010 /* kill all connections to the proxy process */
27013 log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
27015 joblist_append(srv, con);
27016 proxy_connection_close(srv, hctx);
27020 return HANDLER_FINISHED;
27023 @@ -1058,44 +1008,49 @@
27025 data_array *extension = NULL;
27026 size_t path_info_offset;
27028 + data_integer *last_used_backend;
27029 + data_proxy *host = NULL;
27030 + handler_ctx *hctx = NULL;
27032 + array *backends = NULL;
27034 /* Possibly, we processed already this request */
27035 if (con->file_started == 1) return HANDLER_GO_ON;
27038 mod_proxy_patch_connection(srv, con, p);
27041 fn = con->uri.path;
27043 if (fn->used == 0) {
27044 return HANDLER_ERROR;
27048 s_len = fn->used - 1;
27053 path_info_offset = 0;
27055 - if (p->conf.debug) {
27056 + if (p->conf.debug) {
27057 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - start");
27060 /* check if extension matches */
27061 for (k = 0; k < p->conf.extensions->used; k++) {
27065 extension = (data_array *)p->conf.extensions->data[k];
27068 if (extension->key->used == 0) continue;
27071 ct_len = extension->key->used - 1;
27074 if (s_len < ct_len) continue;
27077 /* check extension in the form "/proxy_pattern" */
27078 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
27079 if (s_len > ct_len + 1) {
27083 if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
27084 path_info_offset = pi_offset - fn->ptr;
27086 @@ -1106,12 +1061,14 @@
27092 if (k == p->conf.extensions->used) {
27093 return HANDLER_GO_ON;
27096 - if (p->conf.debug) {
27097 + backends = extension->value;
27099 + if (p->conf.debug) {
27100 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found");
27103 @@ -1120,34 +1077,34 @@
27104 /* hash balancing */
27106 if (p->conf.debug) {
27107 - log_error_write(srv, __FILE__, __LINE__, "sd",
27108 - "proxy - used hash balancing, hosts:", extension->value->used);
27109 + log_error_write(srv, __FILE__, __LINE__, "sd",
27110 + "proxy - used hash balancing, hosts:", backends->used);
27113 - for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
27114 - data_proxy *host = (data_proxy *)extension->value->data[k];
27115 + for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
27116 unsigned long cur_max;
27118 - if (host->is_disabled) continue;
27120 + data_proxy *cur = (data_proxy *)backends->data[k];
27122 + if (cur->is_disabled) continue;
27124 cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
27125 - generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
27126 + generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
27127 generate_crc32c(CONST_BUF_LEN(con->uri.authority));
27130 if (p->conf.debug) {
27131 - log_error_write(srv, __FILE__, __LINE__, "sbbbd",
27132 + log_error_write(srv, __FILE__, __LINE__, "sbbbd",
27133 "proxy - election:",
27137 con->uri.authority,
27141 - if ((last_max == ULONG_MAX) || /* first round */
27142 - (cur_max > last_max)) {
27143 + if (host == NULL || (cur_max > last_max)) {
27144 last_max = cur_max;
27151 @@ -1155,19 +1112,20 @@
27152 case PROXY_BALANCE_FAIR:
27153 /* fair balancing */
27154 if (p->conf.debug) {
27155 - log_error_write(srv, __FILE__, __LINE__, "s",
27156 + log_error_write(srv, __FILE__, __LINE__, "s",
27157 "proxy - used fair balancing");
27160 - for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27161 - data_proxy *host = (data_proxy *)extension->value->data[k];
27163 - if (host->is_disabled) continue;
27165 - if (host->usage < max_usage) {
27166 - max_usage = host->usage;
27169 + /* try to find the host with the lowest load */
27170 + for (k = 0, max_usage = 0; k < backends->used; k++) {
27171 + data_proxy *cur = (data_proxy *)backends->data[k];
27173 + if (cur->is_disabled) continue;
27175 + if (NULL == host || cur->usage < max_usage) {
27176 + max_usage = cur->usage;
27182 @@ -1175,89 +1133,100 @@
27183 case PROXY_BALANCE_RR:
27185 if (p->conf.debug) {
27186 - log_error_write(srv, __FILE__, __LINE__, "s",
27187 + log_error_write(srv, __FILE__, __LINE__, "s",
27188 "proxy - used round-robin balancing");
27191 /* just to be sure */
27192 - assert(extension->value->used < INT_MAX);
27194 - for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27195 - data_proxy *host = (data_proxy *)extension->value->data[k];
27197 - if (host->is_disabled) continue;
27199 - /* first usable ndx */
27200 - if (max_usage == INT_MAX) {
27203 + assert(backends->used < INT_MAX);
27205 - /* get next ndx */
27206 - if ((int)k > host->last_used_ndx) {
27208 - host->last_used_ndx = k;
27209 + /* send each request to another host:
27213 + * if we have three hosts it is
27215 + * 1 .. 2 .. 3 .. 1 .. 2 .. 3
27221 + /* walk through the list */
27222 + last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
27224 + if (NULL == last_used_backend) {
27225 + last_used_backend = data_integer_init();
27227 + buffer_copy_string_buffer(last_used_backend->key, extension->key);
27228 + last_used_backend->value = 0;
27230 + array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
27233 + /* scan all but the last host to see if they are up
27234 + * take the first running host */
27235 + for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
27236 + data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
27238 + if (cur->is_disabled) continue;
27242 + last_used_backend->value = k;
27247 - /* didn't found a higher id, wrap to the start */
27248 - if (ndx != -1 && max_usage != INT_MAX) {
27251 + if (NULL == host) {
27252 + /* we found nothing better, fallback to the last used backend
27253 + * and check if it is still up */
27254 + host = (data_proxy *)backends->data[last_used_backend->value];
27256 + if (host->is_disabled) host = NULL;
27264 - /* found a server */
27266 - data_proxy *host = (data_proxy *)extension->value->data[ndx];
27269 - * if check-local is disabled, use the uri.path handler
27273 - /* init handler-context */
27274 - handler_ctx *hctx;
27275 - hctx = handler_ctx_init();
27277 - hctx->path_info_offset = path_info_offset;
27278 - hctx->remote_conn = con;
27279 - hctx->plugin_data = p;
27280 - hctx->host = host;
27282 - con->plugin_ctx[p->id] = hctx;
27286 - con->mode = p->id;
27288 - if (p->conf.debug) {
27289 - log_error_write(srv, __FILE__, __LINE__, "sbd",
27290 - "proxy - found a host",
27291 - host->host, host->port);
27294 - return HANDLER_GO_ON;
27296 - /* no handler found */
27297 + /* we havn't found a host */
27298 + if (NULL == host) {
27299 con->http_status = 500;
27301 - log_error_write(srv, __FILE__, __LINE__, "sb",
27302 - "no proxy-handler found for:",
27304 + log_error_write(srv, __FILE__, __LINE__, "sb",
27305 + "no proxy-handler found for:",
27309 return HANDLER_FINISHED;
27312 + /* init handler-context */
27313 + hctx = handler_ctx_init();
27315 + hctx->path_info_offset = path_info_offset;
27316 + hctx->remote_conn = con;
27317 + hctx->plugin_data = p;
27318 + hctx->host = host;
27320 + con->plugin_ctx[p->id] = hctx;
27324 + /* we handle this request */
27325 + con->mode = p->id;
27327 + if (p->conf.debug) {
27328 + log_error_write(srv, __FILE__, __LINE__, "sbd",
27329 + "proxy - found a host",
27330 + host->host, host->port);
27333 return HANDLER_GO_ON;
27336 static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
27337 plugin_data *p = p_d;
27340 proxy_connection_close(srv, con->plugin_ctx[p->id]);
27342 return HANDLER_GO_ON;
27343 @@ -1276,11 +1245,11 @@
27345 for (i = 0; i < srv->config_context->used; i++) {
27346 plugin_config *s = p->config_storage[i];
27348 - if (!s) continue;
27350 + if (!s) continue;
27352 /* get the extensions for all configs */
27355 for (k = 0; k < s->extensions->used; k++) {
27356 data_array *extension = (data_array *)s->extensions->data[k];
27358 @@ -1290,8 +1259,8 @@
27360 if (!host->is_disabled ||
27361 srv->cur_ts - host->disable_ts < 5) continue;
27363 - log_error_write(srv, __FILE__, __LINE__, "sbd",
27365 + log_error_write(srv, __FILE__, __LINE__, "sbd",
27366 "proxy - re-enabled:",
27367 host->host, host->port);
27369 @@ -1317,8 +1286,8 @@
27370 p->handle_uri_clean = mod_proxy_check_extension;
27371 p->handle_subrequest = mod_proxy_handle_subrequest;
27372 p->handle_trigger = mod_proxy_trigger;
27380 --- lighttpd-1.4.11/src/mod_redirect.c 2006-02-08 15:38:06.000000000 +0200
27381 +++ lighttpd-1.4.12/src/mod_redirect.c 2006-07-11 22:07:52.000000000 +0300
27382 @@ -22,35 +22,35 @@
27388 plugin_config **config_storage;
27390 - plugin_config conf;
27392 + plugin_config conf;
27395 INIT_FUNC(mod_redirect_init) {
27399 p = calloc(1, sizeof(*p));
27402 p->match_buf = buffer_init();
27403 p->location = buffer_init();
27409 FREE_FUNC(mod_redirect_free) {
27410 plugin_data *p = p_d;
27413 if (!p) return HANDLER_GO_ON;
27415 if (p->config_storage) {
27417 for (i = 0; i < srv->config_context->used; i++) {
27418 plugin_config *s = p->config_storage[i];
27421 pcre_keyvalue_buffer_free(s->redirect);
27426 free(p->config_storage);
27429 buffer_free(p->match_buf);
27430 buffer_free(p->location);
27436 return HANDLER_GO_ON;
27439 @@ -69,195 +69,137 @@
27440 plugin_data *p = p_d;
27444 - config_values_t cv[] = {
27446 + config_values_t cv[] = {
27447 { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27448 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27452 if (!p) return HANDLER_ERROR;
27456 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27459 for (i = 0; i < srv->config_context->used; i++) {
27463 data_array *da = (data_array *)du;
27466 s = calloc(1, sizeof(plugin_config));
27467 s->redirect = pcre_keyvalue_buffer_init();
27470 cv[0].destination = s->redirect;
27473 p->config_storage[i] = s;
27474 ca = ((data_config *)srv->config_context->data[i])->value;
27477 if (0 != config_insert_values_global(srv, ca, cv)) {
27478 return HANDLER_ERROR;
27482 if (NULL == (du = array_get_element(ca, "url.redirect"))) {
27483 /* no url.redirect defined */
27488 if (du->type != TYPE_ARRAY) {
27489 - log_error_write(srv, __FILE__, __LINE__, "sss",
27490 + log_error_write(srv, __FILE__, __LINE__, "sss",
27491 "unexpected type for key: ", "url.redirect", "array of strings");
27494 return HANDLER_ERROR;
27498 da = (data_array *)du;
27501 for (j = 0; j < da->value->used; j++) {
27502 if (da->value->data[j]->type != TYPE_STRING) {
27503 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
27504 - "unexpected type for key: ",
27506 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
27507 + "unexpected type for key: ",
27509 "[", da->value->data[j]->key, "](string)");
27512 return HANDLER_ERROR;
27515 - if (0 != pcre_keyvalue_buffer_append(s->redirect,
27517 + if (0 != pcre_keyvalue_buffer_append(s->redirect,
27518 ((data_string *)(da->value->data[j]))->key->ptr,
27519 ((data_string *)(da->value->data[j]))->value->ptr)) {
27521 - log_error_write(srv, __FILE__, __LINE__, "sb",
27523 + log_error_write(srv, __FILE__, __LINE__, "sb",
27524 "pcre-compile failed for", da->value->data[j]->key);
27530 return HANDLER_GO_ON;
27533 static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
27535 plugin_config *s = p->config_storage[0];
27538 p->conf.redirect = s->redirect;
27541 /* skip the first, the global context */
27542 for (i = 1; i < srv->config_context->used; i++) {
27543 data_config *dc = (data_config *)srv->config_context->data[i];
27544 s = p->config_storage[i];
27547 /* condition didn't match */
27548 if (!config_check_cond(srv, con, dc)) continue;
27552 for (j = 0; j < dc->value->used; j++) {
27553 data_unset *du = dc->value->data[j];
27556 if (0 == strcmp(du->key->ptr, "url.redirect")) {
27557 p->conf.redirect = s->redirect;
27558 p->conf.context = dc;
27567 static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
27569 plugin_data *p = p_data;
27578 * e.g. redirect /base/ to /index.php?section=base
27584 mod_redirect_patch_connection(srv, con, p);
27587 buffer_copy_string_buffer(p->match_buf, con->request.uri);
27589 - for (i = 0; i < p->conf.redirect->used; i++) {
27591 - pcre_extra *extra;
27592 - const char *pattern;
27593 - size_t pattern_len;
27595 - pcre_keyvalue *kv = p->conf.redirect->kv[i];
27600 - extra = kv->key_extra;
27601 - pattern = kv->value->ptr;
27602 - pattern_len = kv->value->used - 1;
27604 - if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
27605 - if (n != PCRE_ERROR_NOMATCH) {
27606 - log_error_write(srv, __FILE__, __LINE__, "sd",
27607 - "execution error while matching: ", n);
27608 - return HANDLER_ERROR;
27611 - const char **list;
27612 - size_t start, end;
27616 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
27618 - /* search for $[0-9] */
27620 - buffer_reset(p->location);
27622 - start = 0; end = pattern_len;
27623 - for (k = 0; k < pattern_len; k++) {
27624 - if ((pattern[k] == '$' || pattern[k] == '%') &&
27625 - isdigit((unsigned char)pattern[k + 1])) {
27628 - size_t num = pattern[k + 1] - '0';
27632 - buffer_append_string_len(p->location, pattern + start, end - start);
27634 - if (pattern[k] == '$') {
27635 - /* n is always > 0 */
27636 - if (num < (size_t)n) {
27637 - buffer_append_string(p->location, list[num]);
27640 - config_append_cond_match_buffer(con, p->conf.context, p->location, num);
27648 - buffer_append_string_len(p->location, pattern + start, pattern_len - start);
27652 - response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27654 - con->http_status = 301;
27655 - con->file_finished = 1;
27657 - return HANDLER_FINISHED;
27659 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
27662 + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27664 + con->http_status = 301;
27665 + con->file_finished = 1;
27667 + return HANDLER_FINISHED;
27669 + else if (i != PCRE_ERROR_NOMATCH) {
27670 + log_error_write(srv, __FILE__, __LINE__, "s",
27671 + "execution error while matching", i);
27683 return HANDLER_GO_ON;
27686 @@ -265,13 +207,13 @@
27687 int mod_redirect_plugin_init(plugin *p) {
27688 p->version = LIGHTTPD_VERSION_ID;
27689 p->name = buffer_init_string("redirect");
27692 p->init = mod_redirect_init;
27693 p->handle_uri_clean = mod_redirect_uri_handler;
27694 p->set_defaults = mod_redirect_set_defaults;
27695 p->cleanup = mod_redirect_free;
27703 --- lighttpd-1.4.11/src/mod_rewrite.c 2005-09-29 20:59:10.000000000 +0300
27704 +++ lighttpd-1.4.12/src/mod_rewrite.c 2006-07-11 22:07:51.000000000 +0300
27709 -#ifdef HAVE_PCRE_H
27719 - rewrite_rule **ptr;
27723 -} rewrite_rule_buffer;
27726 - rewrite_rule_buffer *rewrite;
27727 + pcre_keyvalue_buffer *rewrite;
27729 data_config *context; /* to which apply me */
27732 @@ -42,20 +26,20 @@
27738 plugin_config **config_storage;
27740 - plugin_config conf;
27742 + plugin_config conf;
27745 static handler_ctx * handler_ctx_init() {
27746 handler_ctx * hctx;
27749 hctx = calloc(1, sizeof(*hctx));
27752 hctx->state = REWRITE_STATE_UNSET;
27759 @@ -63,207 +47,136 @@
27763 -rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
27764 - rewrite_rule_buffer *kvb;
27766 - kvb = calloc(1, sizeof(*kvb));
27771 -int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
27772 -#ifdef HAVE_PCRE_H
27774 - const char *errptr;
27777 - if (!key) return -1;
27779 - if (kvb->size == 0) {
27783 - kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
27785 - for(i = 0; i < kvb->size; i++) {
27786 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27788 - } else if (kvb->used == kvb->size) {
27791 - kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
27793 - for(i = kvb->used; i < kvb->size; i++) {
27794 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27798 - if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
27799 - 0, &errptr, &erroff, NULL))) {
27804 - kvb->ptr[kvb->used]->value = buffer_init();
27805 - buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
27806 - kvb->ptr[kvb->used]->once = once;
27821 -void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
27822 -#ifdef HAVE_PCRE_H
27825 - for (i = 0; i < kvb->size; i++) {
27826 - if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
27827 - if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
27828 - free(kvb->ptr[i]);
27831 - if (kvb->ptr) free(kvb->ptr);
27838 INIT_FUNC(mod_rewrite_init) {
27842 p = calloc(1, sizeof(*p));
27845 p->match_buf = buffer_init();
27851 FREE_FUNC(mod_rewrite_free) {
27852 plugin_data *p = p_d;
27857 if (!p) return HANDLER_GO_ON;
27860 buffer_free(p->match_buf);
27861 if (p->config_storage) {
27863 for (i = 0; i < srv->config_context->used; i++) {
27864 plugin_config *s = p->config_storage[i];
27865 - rewrite_rule_buffer_free(s->rewrite);
27867 + pcre_keyvalue_buffer_free(s->rewrite);
27868 + buffer_free(s->once);
27872 free(p->config_storage);
27879 return HANDLER_GO_ON;
27882 static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
27886 if (NULL != (du = array_get_element(ca, option))) {
27887 data_array *da = (data_array *)du;
27891 if (du->type != TYPE_ARRAY) {
27892 - log_error_write(srv, __FILE__, __LINE__, "sss",
27893 + log_error_write(srv, __FILE__, __LINE__, "sss",
27894 "unexpected type for key: ", option, "array of strings");
27897 return HANDLER_ERROR;
27901 da = (data_array *)du;
27904 for (j = 0; j < da->value->used; j++) {
27905 if (da->value->data[j]->type != TYPE_STRING) {
27906 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
27907 - "unexpected type for key: ",
27909 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
27910 + "unexpected type for key: ",
27912 "[", da->value->data[j]->key, "](string)");
27915 return HANDLER_ERROR;
27918 - if (0 != rewrite_rule_buffer_append(s->rewrite,
27919 - ((data_string *)(da->value->data[j]))->key,
27920 - ((data_string *)(da->value->data[j]))->value,
27923 + if (0 != pcre_keyvalue_buffer_append(s->rewrite,
27924 + ((data_string *)(da->value->data[j]))->key->ptr,
27925 + ((data_string *)(da->value->data[j]))->value->ptr)) {
27927 - log_error_write(srv, __FILE__, __LINE__, "sb",
27928 + log_error_write(srv, __FILE__, __LINE__, "sb",
27929 "pcre-compile failed for", da->value->data[j]->key);
27931 - log_error_write(srv, __FILE__, __LINE__, "s",
27932 + log_error_write(srv, __FILE__, __LINE__, "s",
27933 "pcre support is missing, please install libpcre and the headers");
27938 + buffer_append_string_len(s->once, CONST_STR_LEN("1"));
27940 + buffer_append_string_len(s->once, CONST_STR_LEN("0"));
27949 SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
27950 plugin_data *p = p_d;
27953 - config_values_t cv[] = {
27955 + config_values_t cv[] = {
27956 { "url.rewrite-repeat", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27957 { "url.rewrite-once", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
27959 - /* old names, still supported
27962 + /* old names, still supported
27964 * url.rewrite remapped to url.rewrite-once
27965 * url.rewrite-final is url.rewrite-once
27969 { "url.rewrite", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
27970 { "url.rewrite-final", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
27971 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27975 if (!p) return HANDLER_ERROR;
27979 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27982 for (i = 0; i < srv->config_context->used; i++) {
27987 s = calloc(1, sizeof(plugin_config));
27988 - s->rewrite = rewrite_rule_buffer_init();
27990 - cv[0].destination = s->rewrite;
27991 - cv[1].destination = s->rewrite;
27992 - cv[2].destination = s->rewrite;
27994 + s->rewrite = pcre_keyvalue_buffer_init();
27995 + s->once = buffer_init();
27997 p->config_storage[i] = s;
27998 ca = ((data_config *)srv->config_context->data[i])->value;
28001 if (0 != config_insert_values_global(srv, ca, cv)) {
28002 return HANDLER_ERROR;
28006 parse_config_entry(srv, s, ca, "url.rewrite-once", 1);
28007 parse_config_entry(srv, s, ca, "url.rewrite-final", 1);
28008 parse_config_entry(srv, s, ca, "url.rewrite", 1);
28009 parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
28013 return HANDLER_GO_ON;
28016 @@ -271,157 +184,107 @@
28018 plugin_config *s = p->config_storage[0];
28019 p->conf.rewrite = s->rewrite;
28021 + p->conf.once = s->once;
28023 /* skip the first, the global context */
28024 for (i = 1; i < srv->config_context->used; i++) {
28025 data_config *dc = (data_config *)srv->config_context->data[i];
28026 s = p->config_storage[i];
28029 if (COMP_HTTP_URL == dc->comp) continue;
28032 /* condition didn't match */
28033 if (!config_check_cond(srv, con, dc)) continue;
28037 for (j = 0; j < dc->value->used; j++) {
28038 data_unset *du = dc->value->data[j];
28041 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
28042 p->conf.rewrite = s->rewrite;
28043 + p->conf.once = s->once;
28044 p->conf.context = dc;
28045 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
28046 p->conf.rewrite = s->rewrite;
28047 + p->conf.once = s->once;
28048 p->conf.context = dc;
28049 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
28050 p->conf.rewrite = s->rewrite;
28051 + p->conf.once = s->once;
28052 p->conf.context = dc;
28053 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
28054 p->conf.rewrite = s->rewrite;
28055 + p->conf.once = s->once;
28056 p->conf.context = dc;
28065 URIHANDLER_FUNC(mod_rewrite_con_reset) {
28066 plugin_data *p = p_d;
28072 if (con->plugin_ctx[p->id]) {
28073 handler_ctx_free(con->plugin_ctx[p->id]);
28074 con->plugin_ctx[p->id] = NULL;
28078 return HANDLER_GO_ON;
28081 URIHANDLER_FUNC(mod_rewrite_uri_handler) {
28083 plugin_data *p = p_d;
28093 * e.g. rewrite /base/ to /index.php?section=base
28099 if (con->plugin_ctx[p->id]) {
28100 hctx = con->plugin_ctx[p->id];
28103 if (hctx->loops++ > 100) {
28104 - log_error_write(srv, __FILE__, __LINE__, "s",
28105 + log_error_write(srv, __FILE__, __LINE__, "s",
28106 "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
28109 return HANDLER_ERROR;
28113 if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
28117 mod_rewrite_patch_connection(srv, con, p);
28119 if (!p->conf.rewrite) return HANDLER_GO_ON;
28122 buffer_copy_string_buffer(p->match_buf, con->request.uri);
28124 - for (i = 0; i < p->conf.rewrite->used; i++) {
28126 - const char *pattern;
28127 - size_t pattern_len;
28129 - rewrite_rule *rule = p->conf.rewrite->ptr[i];
28133 - match = rule->key;
28134 - pattern = rule->value->ptr;
28135 - pattern_len = rule->value->used - 1;
28137 - if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
28138 - if (n != PCRE_ERROR_NOMATCH) {
28139 - log_error_write(srv, __FILE__, __LINE__, "sd",
28140 - "execution error while matching: ", n);
28141 - return HANDLER_ERROR;
28144 - const char **list;
28145 - size_t start, end;
28149 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
28151 - /* search for $[0-9] */
28153 - buffer_reset(con->request.uri);
28155 - start = 0; end = pattern_len;
28156 - for (k = 0; k < pattern_len; k++) {
28157 - if ((pattern[k] == '$' || pattern[k] == '%') &&
28158 - isdigit((unsigned char)pattern[k + 1])) {
28161 - size_t num = pattern[k + 1] - '0';
28165 - buffer_append_string_len(con->request.uri, pattern + start, end - start);
28167 - if (pattern[k] == '$') {
28168 - /* n is always > 0 */
28169 - if (num < (size_t)n) {
28170 - buffer_append_string(con->request.uri, list[num]);
28173 - config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
28181 - buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
28185 - hctx = handler_ctx_init();
28187 - con->plugin_ctx[p->id] = hctx;
28189 - if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
28191 - return HANDLER_COMEBACK;
28193 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
28196 + hctx = handler_ctx_init();
28198 + con->plugin_ctx[p->id] = hctx;
28200 + if (p->conf.once->ptr[i] == '1')
28201 + hctx->state = REWRITE_STATE_FINISHED;
28203 + return HANDLER_COMEBACK;
28205 + else if (i != PCRE_ERROR_NOMATCH) {
28206 + log_error_write(srv, __FILE__, __LINE__, "s",
28207 + "execution error while matching", i);
28215 @@ -434,17 +297,17 @@
28216 int mod_rewrite_plugin_init(plugin *p) {
28217 p->version = LIGHTTPD_VERSION_ID;
28218 p->name = buffer_init_string("rewrite");
28221 p->init = mod_rewrite_init;
28222 /* it has to stay _raw as we are matching on uri + querystring
28226 p->handle_uri_raw = mod_rewrite_uri_handler;
28227 p->set_defaults = mod_rewrite_set_defaults;
28228 p->cleanup = mod_rewrite_free;
28229 p->connection_reset = mod_rewrite_con_reset;
28237 --- lighttpd-1.4.11/src/mod_rrdtool.c 2005-08-22 01:52:24.000000000 +0300
28238 +++ lighttpd-1.4.12/src/mod_rrdtool.c 2006-07-11 22:07:52.000000000 +0300
28240 #include <stdlib.h>
28242 #include <string.h>
28243 -#include <unistd.h>
28247 @@ -20,10 +19,14 @@
28248 /* no need for waitpid if we don't have fork */
28249 #include <sys/wait.h>
28252 +#include "sys-files.h"
28253 +#include "sys-process.h"
28256 buffer *path_rrdtool_bin;
28260 double requests, *requests_ptr;
28261 double bytes_written, *bytes_written_ptr;
28262 double bytes_read, *bytes_read_ptr;
28263 @@ -31,84 +34,84 @@
28273 int read_fd, write_fd;
28277 int rrdtool_running;
28280 plugin_config **config_storage;
28281 plugin_config conf;
28284 INIT_FUNC(mod_rrd_init) {
28288 p = calloc(1, sizeof(*p));
28291 p->resp = buffer_init();
28292 p->cmd = buffer_init();
28298 FREE_FUNC(mod_rrd_free) {
28299 plugin_data *p = p_d;
28303 if (!p) return HANDLER_GO_ON;
28306 if (p->config_storage) {
28307 for (i = 0; i < srv->config_context->used; i++) {
28308 plugin_config *s = p->config_storage[i];
28311 buffer_free(s->path_rrdtool_bin);
28312 buffer_free(s->path_rrd);
28318 buffer_free(p->cmd);
28319 buffer_free(p->resp);
28322 free(p->config_storage);
28325 if (p->rrdtool_pid) {
28328 close(p->write_fd);
28331 /* collect status */
28332 waitpid(p->rrdtool_pid, &status, 0);
28340 return HANDLER_GO_ON;
28343 int mod_rrd_create_pipe(server *srv, plugin_data *p) {
28347 int to_rrdtool_fds[2];
28348 int from_rrdtool_fds[2];
28351 if (pipe(to_rrdtool_fds)) {
28352 - log_error_write(srv, __FILE__, __LINE__, "ss",
28353 + log_error_write(srv, __FILE__, __LINE__, "ss",
28354 "pipe failed: ", strerror(errno));
28359 if (pipe(from_rrdtool_fds)) {
28360 - log_error_write(srv, __FILE__, __LINE__, "ss",
28361 + log_error_write(srv, __FILE__, __LINE__, "ss",
28362 "pipe failed: ", strerror(errno));
28368 switch (pid = fork()) {
28370 @@ -117,33 +120,33 @@
28376 /* move stdout to from_rrdtool_fd[1] */
28377 close(STDOUT_FILENO);
28378 dup2(from_rrdtool_fds[1], STDOUT_FILENO);
28379 close(from_rrdtool_fds[1]);
28381 close(from_rrdtool_fds[0]);
28384 /* move the stdin to to_rrdtool_fd[0] */
28385 close(STDIN_FILENO);
28386 dup2(to_rrdtool_fds[0], STDIN_FILENO);
28387 close(to_rrdtool_fds[0]);
28389 close(to_rrdtool_fds[1]);
28392 close(STDERR_FILENO);
28395 if (srv->errorlog_mode == ERRORLOG_FILE) {
28396 dup2(srv->errorlog_fd, STDERR_FILENO);
28397 close(srv->errorlog_fd);
28403 args = malloc(sizeof(*args) * argc);
28407 args[i++] = p->conf.path_rrdtool_bin->ptr;
28410 @@ -152,12 +155,12 @@
28411 for (i = 3; i < 256; i++) {
28417 execv(args[0], args);
28420 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
28426 @@ -168,19 +171,19 @@
28432 close(from_rrdtool_fds[1]);
28433 close(to_rrdtool_fds[0]);
28436 /* register PID and wait for them asyncronously */
28437 p->write_fd = to_rrdtool_fds[1];
28438 p->read_fd = from_rrdtool_fds[0];
28439 p->rrdtool_pid = pid;
28450 @@ -189,19 +192,19 @@
28452 static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
28456 /* check if DB already exists */
28457 if (0 == stat(s->path_rrd->ptr, &st)) {
28458 /* check if it is plain file */
28459 if (!S_ISREG(st.st_mode)) {
28460 - log_error_write(srv, __FILE__, __LINE__, "sb",
28461 + log_error_write(srv, __FILE__, __LINE__, "sb",
28462 "not a regular file:", s->path_rrd);
28463 return HANDLER_ERROR;
28467 /* create a new one */
28470 BUFFER_COPY_STRING_CONST(p->cmd, "create ");
28471 buffer_append_string_buffer(p->cmd, s->path_rrd);
28472 buffer_append_string(p->cmd, " --step 60 ");
28473 @@ -220,158 +223,155 @@
28474 buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
28475 buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
28476 buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
28479 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28480 - log_error_write(srv, __FILE__, __LINE__, "ss",
28481 + log_error_write(srv, __FILE__, __LINE__, "ss",
28482 "rrdtool-write: failed", strerror(errno));
28485 return HANDLER_ERROR;
28489 buffer_prepare_copy(p->resp, 4096);
28490 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28491 - log_error_write(srv, __FILE__, __LINE__, "ss",
28492 + log_error_write(srv, __FILE__, __LINE__, "ss",
28493 "rrdtool-read: failed", strerror(errno));
28496 return HANDLER_ERROR;
28503 if (p->resp->ptr[0] != 'O' ||
28504 p->resp->ptr[1] != 'K') {
28505 - log_error_write(srv, __FILE__, __LINE__, "sbb",
28506 + log_error_write(srv, __FILE__, __LINE__, "sbb",
28507 "rrdtool-response:", p->cmd, p->resp);
28510 return HANDLER_ERROR;
28515 return HANDLER_GO_ON;
28518 -#define PATCH(x) \
28519 - p->conf.x = s->x;
28520 static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
28522 plugin_config *s = p->config_storage[0];
28524 - PATCH(path_rrdtool_bin);
28528 + PATCH_OPTION(path_rrdtool_bin);
28529 + PATCH_OPTION(path_rrd);
28531 p->conf.bytes_written_ptr = &(s->bytes_written);
28532 p->conf.bytes_read_ptr = &(s->bytes_read);
28533 p->conf.requests_ptr = &(s->requests);
28536 /* skip the first, the global context */
28537 for (i = 1; i < srv->config_context->used; i++) {
28538 data_config *dc = (data_config *)srv->config_context->data[i];
28539 s = p->config_storage[i];
28542 /* condition didn't match */
28543 if (!config_check_cond(srv, con, dc)) continue;
28547 for (j = 0; j < dc->value->used; j++) {
28548 data_unset *du = dc->value->data[j];
28551 if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
28553 + PATCH_OPTION(path_rrd);
28554 /* get pointers to double values */
28557 p->conf.bytes_written_ptr = &(s->bytes_written);
28558 p->conf.bytes_read_ptr = &(s->bytes_read);
28559 p->conf.requests_ptr = &(s->requests);
28569 SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
28570 plugin_data *p = p_d;
28573 - config_values_t cv[] = {
28575 + config_values_t cv[] = {
28576 { "rrdtool.binary", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
28577 { "rrdtool.db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
28578 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
28582 if (!p) return HANDLER_ERROR;
28585 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28588 for (i = 0; i < srv->config_context->used; i++) {
28592 s = calloc(1, sizeof(plugin_config));
28593 s->path_rrdtool_bin = buffer_init();
28594 s->path_rrd = buffer_init();
28596 s->bytes_written = 0;
28600 cv[0].destination = s->path_rrdtool_bin;
28601 cv[1].destination = s->path_rrd;
28604 p->config_storage[i] = s;
28607 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
28608 return HANDLER_ERROR;
28612 if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
28613 /* path_rrdtool_bin is a global option */
28615 - log_error_write(srv, __FILE__, __LINE__, "s",
28617 + log_error_write(srv, __FILE__, __LINE__, "s",
28618 "rrdtool.binary can only be set as a global option.");
28621 return HANDLER_ERROR;
28628 p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
28629 p->rrdtool_running = 0;
28632 /* check for dir */
28635 if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
28636 - log_error_write(srv, __FILE__, __LINE__, "s",
28637 + log_error_write(srv, __FILE__, __LINE__, "s",
28638 "rrdtool.binary has to be set");
28639 return HANDLER_ERROR;
28643 /* open the pipe to rrdtool */
28644 if (mod_rrd_create_pipe(srv, p)) {
28645 return HANDLER_ERROR;
28649 p->rrdtool_running = 1;
28652 return HANDLER_GO_ON;
28655 TRIGGER_FUNC(mod_rrd_trigger) {
28656 plugin_data *p = p_d;
28660 if (!p->rrdtool_running) return HANDLER_GO_ON;
28661 if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
28664 for (i = 0; i < srv->config_context->used; i++) {
28665 plugin_config *s = p->config_storage[i];
28669 if (buffer_is_empty(s->path_rrd)) continue;
28672 /* write the data down every minute */
28675 if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
28678 BUFFER_COPY_STRING_CONST(p->cmd, "update ");
28679 buffer_append_string_buffer(p->cmd, s->path_rrd);
28680 BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
28681 @@ -381,69 +381,69 @@
28682 BUFFER_APPEND_STRING_CONST(p->cmd, ":");
28683 buffer_append_long(p->cmd, s->requests);
28684 BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
28687 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28688 p->rrdtool_running = 0;
28690 - log_error_write(srv, __FILE__, __LINE__, "ss",
28692 + log_error_write(srv, __FILE__, __LINE__, "ss",
28693 "rrdtool-write: failed", strerror(errno));
28696 return HANDLER_ERROR;
28700 buffer_prepare_copy(p->resp, 4096);
28701 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28702 p->rrdtool_running = 0;
28704 - log_error_write(srv, __FILE__, __LINE__, "ss",
28706 + log_error_write(srv, __FILE__, __LINE__, "ss",
28707 "rrdtool-read: failed", strerror(errno));
28710 return HANDLER_ERROR;
28717 if (p->resp->ptr[0] != 'O' ||
28718 p->resp->ptr[1] != 'K') {
28719 p->rrdtool_running = 0;
28721 - log_error_write(srv, __FILE__, __LINE__, "sbb",
28723 + log_error_write(srv, __FILE__, __LINE__, "sbb",
28724 "rrdtool-response:", p->cmd, p->resp);
28727 return HANDLER_ERROR;
28730 s->bytes_written = 0;
28735 return HANDLER_GO_ON;
28738 REQUESTDONE_FUNC(mod_rrd_account) {
28739 plugin_data *p = p_d;
28742 mod_rrd_patch_connection(srv, con, p);
28745 *(p->conf.requests_ptr) += 1;
28746 *(p->conf.bytes_written_ptr) += con->bytes_written;
28747 *(p->conf.bytes_read_ptr) += con->bytes_read;
28750 return HANDLER_GO_ON;
28753 int mod_rrdtool_plugin_init(plugin *p) {
28754 p->version = LIGHTTPD_VERSION_ID;
28755 p->name = buffer_init_string("rrd");
28758 p->init = mod_rrd_init;
28759 p->cleanup = mod_rrd_free;
28760 p->set_defaults= mod_rrd_set_defaults;
28763 p->handle_trigger = mod_rrd_trigger;
28764 p->handle_request_done = mod_rrd_account;
28772 --- lighttpd-1.4.11/src/mod_scgi.c 2006-03-04 17:15:26.000000000 +0200
28773 +++ lighttpd-1.4.12/src/mod_scgi.c 2006-07-11 22:07:51.000000000 +0300
28775 #include <sys/types.h>
28776 -#include <unistd.h>
28779 #include <string.h>
28783 #include "sys-socket.h"
28785 +#include "sys-files.h"
28786 +#include "sys-strings.h"
28787 +#include "sys-process.h"
28789 #ifndef UNIX_PATH_MAX
28790 # define UNIX_PATH_MAX 108
28791 @@ -46,30 +47,29 @@
28792 enum {EOL_UNSET, EOL_N, EOL_RN};
28800 * - add timeout for a connect to a non-scgi process
28801 * (use state_timestamp + state)
28806 typedef struct scgi_proc {
28807 size_t id; /* id will be between 1 and max_procs */
28808 buffer *socket; /* config.socket + "-" + id */
28809 unsigned port; /* config.port + pno */
28811 - pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
28813 + pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
28815 size_t load; /* number of requests waiting on this process */
28817 time_t last_used; /* see idle_timeout */
28818 size_t requests; /* see max_requests */
28819 struct scgi_proc *prev, *next; /* see first */
28822 time_t disable_ts; /* replace by host->something */
28827 enum { PROC_STATE_UNSET, /* init-phase */
28829 PROC_STATE_KILLED, /* was killed as we don't have the load anymore */
28830 PROC_STATE_DIED, /* marked as dead, should be restarted */
28831 PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
28837 @@ -86,20 +86,20 @@
28838 * sorted by lowest load
28840 * whenever a job is done move it up in the list
28841 - * until it is sorted, move it down as soon as the
28842 + * until it is sorted, move it down as soon as the
28845 - scgi_proc *first;
28846 - scgi_proc *unused_procs;
28847 + scgi_proc *first;
28848 + scgi_proc *unused_procs;
28852 * spawn at least min_procs, at max_procs.
28854 - * as soon as the load of the first entry
28855 + * as soon as the load of the first entry
28856 * is max_load_per_proc we spawn a new one
28857 - * and add it to the first entry and give it
28858 + * and add it to the first entry and give it
28864 unsigned short min_procs;
28865 @@ -111,44 +111,44 @@
28868 * kick the process from the list if it was not
28869 - * used for idle_timeout until min_procs is
28870 + * used for idle_timeout until min_procs is
28871 * reached. this helps to get the processlist
28872 * small again we had a small peak load.
28877 unsigned short idle_timeout;
28881 * time after a disabled remote connection is tried to be re-enabled
28889 unsigned short disable_time;
28892 * same scgi processes get a little bit larger
28893 - * than wanted. max_requests_per_proc kills a
28894 + * than wanted. max_requests_per_proc kills a
28895 * process after a number of handled requests.
28898 size_t max_requests_per_proc;
28909 - * if host is one of the local IP adresses the
28910 + * if host is one of the local IP adresses the
28911 * whole connection is local
28913 * if tcp/ip should be used host AND port have
28914 - * to be specified
28918 + * to be specified
28922 unsigned short port;
28925 @@ -161,7 +161,7 @@
28927 buffer *unixsocket;
28929 - /* if socket is local we can start the scgi
28930 + /* if socket is local we can start the scgi
28933 * bin-path is the path to the binary
28934 @@ -169,19 +169,19 @@
28935 * check min_procs and max_procs for the number
28936 * of process to start-up
28938 - buffer *bin_path;
28940 - /* bin-path is set bin-environment is taken to
28941 + buffer *bin_path;
28943 + /* bin-path is set bin-environment is taken to
28944 * create the environement before starting the
28952 array *bin_env_copy;
28956 - * docroot-translation between URL->phys and the
28957 + * docroot-translation between URL->phys and the
28961 @@ -192,7 +192,7 @@
28965 - * check_local tell you if the phys file is stat()ed
28966 + * check_local tell you if the phys file is stat()ed
28967 * or not. FastCGI doesn't care if the service is
28968 * remote. If the web-server side doesn't contain
28969 * the scgi-files we should not stat() for them
28970 @@ -202,33 +202,33 @@
28973 * append PATH_INFO to SCRIPT_FILENAME
28976 * php needs this if cgi.fix_pathinfo is provied
28982 ssize_t load; /* replace by host->load */
28984 size_t max_id; /* corresponds most of the time to
28988 only if a process is killed max_id waits for the process itself
28989 to die and decrements its afterwards */
28990 } scgi_extension_host;
28993 * one extension can have multiple hosts assigned
28994 - * one host can spawn additional processes on the same
28995 + * one host can spawn additional processes on the same
28996 * socket (if we control it)
28998 * ext -> host -> procs
29001 - * if the scgi process is remote that whole goes down
29002 + * if the scgi process is remote that whole goes down
29005 * ext -> host -> procs
29009 * in case of PHP and FCGI_CHILDREN we have again a procs
29010 * but we don't control it directly.
29011 @@ -239,7 +239,7 @@
29012 buffer *key; /* like .php */
29014 scgi_extension_host **hosts;
29020 @@ -253,14 +253,14 @@
29038 @@ -268,52 +268,51 @@
29039 /* generic plugin data, shared between all connections */
29048 buffer *parse_response;
29051 plugin_config **config_storage;
29054 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
29057 /* connection specific data */
29058 -typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
29059 - FCGI_STATE_WRITE, FCGI_STATE_READ
29060 +typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
29061 + FCGI_STATE_WRITE, FCGI_STATE_READ
29062 } scgi_connection_state_t;
29065 - buffer *response;
29066 + buffer *response;
29067 size_t response_len;
29069 int response_padding;
29073 scgi_extension_host *host;
29076 scgi_connection_state_t state;
29077 time_t state_timestamp;
29080 int reconnects; /* number of reconnect attempts */
29087 buffer *response_header;
29090 int delayed; /* flag to mark that the connect() is delayed */
29094 int fd; /* fd to the scgi process */
29095 int fde_ndx; /* index into the fd-event buffer */
29101 plugin_config conf;
29104 connection *remote_conn; /* dumb pointer */
29105 plugin_data *plugin_data; /* dumb pointer */
29107 @@ -328,28 +327,28 @@
29109 static handler_ctx * handler_ctx_init() {
29110 handler_ctx * hctx;
29113 hctx = calloc(1, sizeof(*hctx));
29117 hctx->fde_ndx = -1;
29120 hctx->response = buffer_init();
29121 hctx->response_header = buffer_init();
29124 hctx->request_id = 0;
29125 hctx->state = FCGI_STATE_INIT;
29129 hctx->response_len = 0;
29130 hctx->response_type = 0;
29131 hctx->response_padding = 0;
29135 hctx->reconnects = 0;
29137 hctx->wb = chunkqueue_init();
29143 @@ -358,12 +357,12 @@
29144 buffer_free(hctx->response_header);
29146 chunkqueue_free(hctx->wb);
29150 if (hctx->rb->ptr) free(hctx->rb->ptr);
29158 @@ -372,20 +371,20 @@
29160 f = calloc(1, sizeof(*f));
29161 f->socket = buffer_init();
29171 void scgi_process_free(scgi_proc *f) {
29175 scgi_process_free(f->next);
29178 buffer_free(f->socket);
29184 @@ -400,62 +399,62 @@
29185 f->bin_path = buffer_init();
29186 f->bin_env = array_init();
29187 f->bin_env_copy = array_init();
29193 void scgi_host_free(scgi_extension_host *h) {
29197 buffer_free(h->host);
29198 buffer_free(h->unixsocket);
29199 buffer_free(h->docroot);
29200 buffer_free(h->bin_path);
29201 array_free(h->bin_env);
29202 array_free(h->bin_env_copy);
29205 scgi_process_free(h->first);
29206 scgi_process_free(h->unused_procs);
29214 scgi_exts *scgi_extensions_init() {
29217 f = calloc(1, sizeof(*f));
29223 void scgi_extensions_free(scgi_exts *f) {
29230 for (i = 0; i < f->used; i++) {
29231 scgi_extension *fe;
29238 for (j = 0; j < fe->used; j++) {
29239 scgi_extension_host *h;
29249 buffer_free(fe->key);
29263 @@ -504,99 +503,103 @@
29267 - fe->hosts[fe->used++] = fh;
29268 + fe->hosts[fe->used++] = fh;
29275 INIT_FUNC(mod_scgi_init) {
29279 p = calloc(1, sizeof(*p));
29282 p->scgi_env = buffer_init();
29285 p->path = buffer_init();
29286 p->parse_response = buffer_init();
29293 FREE_FUNC(mod_scgi_free) {
29294 plugin_data *p = p_d;
29299 buffer_free(p->scgi_env);
29300 buffer_free(p->path);
29301 buffer_free(p->parse_response);
29304 if (p->config_storage) {
29306 for (i = 0; i < srv->config_context->used; i++) {
29307 plugin_config *s = p->config_storage[i];
29316 for (j = 0; j < exts->used; j++) {
29317 scgi_extension *ex;
29320 ex = exts->exts[j];
29323 for (n = 0; n < ex->used; n++) {
29325 scgi_extension_host *host;
29328 host = ex->hosts[n];
29331 for (proc = host->first; proc; proc = proc->next) {
29333 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29335 - if (proc->is_local &&
29338 + if (proc->is_local &&
29339 !buffer_is_empty(proc->socket)) {
29340 unlink(proc->socket->ptr);
29345 for (proc = host->unused_procs; proc; proc = proc->next) {
29347 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29349 - if (proc->is_local &&
29352 + if (proc->is_local &&
29353 !buffer_is_empty(proc->socket)) {
29354 unlink(proc->socket->ptr);
29361 scgi_extensions_free(s->exts);
29366 free(p->config_storage);
29373 return HANDLER_GO_ON;
29376 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
29380 if (!key || !val) return -1;
29383 dst = malloc(key_len + val_len + 3);
29384 memcpy(dst, key, key_len);
29385 dst[key_len] = '=';
29386 /* add the \0 from the value */
29387 memcpy(dst + key_len + 1, val, val_len + 1);
29390 if (env->size == 0) {
29392 env->ptr = malloc(env->size * sizeof(*env->ptr));
29393 @@ -604,13 +607,13 @@
29395 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
29399 env->ptr[env->used++] = dst;
29405 -static int scgi_spawn_connection(server *srv,
29406 +static int scgi_spawn_connection(server *srv,
29408 scgi_extension_host *host,
29410 @@ -622,31 +625,27 @@
29412 struct sockaddr_in scgi_addr_in;
29413 struct sockaddr *scgi_addr;
29424 if (p->conf.debug) {
29425 log_error_write(srv, __FILE__, __LINE__, "sdb",
29426 "new proc, socket:", proc->port, proc->socket);
29430 if (!buffer_is_empty(proc->socket)) {
29431 memset(&scgi_addr, 0, sizeof(scgi_addr));
29434 #ifdef HAVE_SYS_UN_H
29435 scgi_addr_un.sun_family = AF_UNIX;
29436 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
29440 servlen = SUN_LEN(&scgi_addr_un);
29442 - /* stevens says: */
29443 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
29446 socket_type = AF_UNIX;
29447 scgi_addr = (struct sockaddr *) &scgi_addr_un;
29449 @@ -656,115 +655,115 @@
29452 scgi_addr_in.sin_family = AF_INET;
29455 if (buffer_is_empty(host->host)) {
29456 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29458 struct hostent *he;
29461 /* set a usefull default */
29462 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29467 if (NULL == (he = gethostbyname(host->host->ptr))) {
29468 - log_error_write(srv, __FILE__, __LINE__,
29469 - "sdb", "gethostbyname failed: ",
29470 + log_error_write(srv, __FILE__, __LINE__,
29471 + "sdb", "gethostbyname failed: ",
29472 h_errno, host->host);
29477 if (he->h_addrtype != AF_INET) {
29478 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
29483 if (he->h_length != sizeof(struct in_addr)) {
29484 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
29489 memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
29493 scgi_addr_in.sin_port = htons(proc->port);
29494 servlen = sizeof(scgi_addr_in);
29497 socket_type = AF_INET;
29498 scgi_addr = (struct sockaddr *) &scgi_addr_in;
29502 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29503 - log_error_write(srv, __FILE__, __LINE__, "ss",
29504 + log_error_write(srv, __FILE__, __LINE__, "ss",
29505 "failed:", strerror(errno));
29510 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
29511 /* server is not up, spawn in */
29516 if (!buffer_is_empty(proc->socket)) {
29517 unlink(proc->socket->ptr);
29524 /* reopen socket */
29525 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29526 - log_error_write(srv, __FILE__, __LINE__, "ss",
29527 + log_error_write(srv, __FILE__, __LINE__, "ss",
29528 "socket failed:", strerror(errno));
29534 if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
29535 - log_error_write(srv, __FILE__, __LINE__, "ss",
29536 + log_error_write(srv, __FILE__, __LINE__, "ss",
29537 "socketsockopt failed:", strerror(errno));
29542 /* create socket */
29543 if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
29544 - log_error_write(srv, __FILE__, __LINE__, "sbds",
29545 - "bind failed for:",
29548 + log_error_write(srv, __FILE__, __LINE__, "sbds",
29549 + "bind failed for:",
29557 if (-1 == listen(scgi_fd, 1024)) {
29558 - log_error_write(srv, __FILE__, __LINE__, "ss",
29559 + log_error_write(srv, __FILE__, __LINE__, "ss",
29560 "listen failed:", strerror(errno));
29567 switch ((child = fork())) {
29577 /* create environment */
29583 /* we don't need the client socket */
29584 for (fd = 3; fd < 256; fd++) {
29585 if (fd != 2 && fd != scgi_fd) close(fd);
29589 /* build clean environment */
29590 if (host->bin_env_copy->used) {
29591 for (i = 0; i < host->bin_env_copy->used; i++) {
29592 data_string *ds = (data_string *)host->bin_env_copy->data[i];
29596 if (NULL != (ge = getenv(ds->value->ptr))) {
29597 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
29599 @@ -772,44 +771,44 @@
29601 for (i = 0; environ[i]; i++) {
29605 if (NULL != (eq = strchr(environ[i], '='))) {
29606 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
29612 /* create environment */
29613 for (i = 0; i < host->bin_env->used; i++) {
29614 data_string *ds = (data_string *)host->bin_env->data[i];
29617 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
29621 for (i = 0; i < env.used; i++) {
29622 /* search for PHP_FCGI_CHILDREN */
29623 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
29627 /* not found, add a default */
29628 if (i == env.used) {
29629 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
29633 env.ptr[env.used] = NULL;
29637 buffer_copy_string(b, "exec ");
29638 buffer_append_string_buffer(b, host->bin_path);
29642 execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
29644 - log_error_write(srv, __FILE__, __LINE__, "sbs",
29646 + log_error_write(srv, __FILE__, __LINE__, "sbs",
29647 "execl failed for:", host->bin_path, strerror(errno));
29656 @@ -817,32 +816,32 @@
29663 select(0, NULL, NULL, NULL, &tv);
29666 switch (waitpid(child, &status, WNOHANG)) {
29668 /* child still running after timeout, good */
29671 /* no PID found ? should never happen */
29672 - log_error_write(srv, __FILE__, __LINE__, "ss",
29673 + log_error_write(srv, __FILE__, __LINE__, "ss",
29674 "pid not found:", strerror(errno));
29677 /* the child should not terminate at all */
29678 if (WIFEXITED(status)) {
29679 - log_error_write(srv, __FILE__, __LINE__, "sd",
29680 - "child exited (is this a SCGI binary ?):",
29681 + log_error_write(srv, __FILE__, __LINE__, "sd",
29682 + "child exited (is this a SCGI binary ?):",
29683 WEXITSTATUS(status));
29684 } else if (WIFSIGNALED(status)) {
29685 - log_error_write(srv, __FILE__, __LINE__, "sd",
29686 - "child signaled:",
29687 + log_error_write(srv, __FILE__, __LINE__, "sd",
29688 + "child signaled:",
29691 - log_error_write(srv, __FILE__, __LINE__, "sd",
29692 - "child died somehow:",
29693 + log_error_write(srv, __FILE__, __LINE__, "sd",
29694 + "child died somehow:",
29698 @@ -852,26 +851,26 @@
29700 proc->last_used = srv->cur_ts;
29701 proc->is_local = 1;
29708 proc->is_local = 0;
29712 if (p->conf.debug) {
29713 log_error_write(srv, __FILE__, __LINE__, "sb",
29714 "(debug) socket is already used, won't spawn:",
29720 proc->state = PROC_STATE_RUNNING;
29721 host->active_procs++;
29730 @@ -880,89 +879,89 @@
29731 plugin_data *p = p_d;
29735 - config_values_t cv[] = {
29737 + config_values_t cv[] = {
29738 { "scgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
29739 { "scgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
29740 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29744 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
29747 for (i = 0; i < srv->config_context->used; i++) {
29752 s = malloc(sizeof(plugin_config));
29753 s->exts = scgi_extensions_init();
29757 cv[0].destination = s->exts;
29758 cv[1].destination = &(s->debug);
29761 p->config_storage[i] = s;
29762 ca = ((data_config *)srv->config_context->data[i])->value;
29765 if (0 != config_insert_values_global(srv, ca, cv)) {
29766 return HANDLER_ERROR;
29776 if (NULL != (du = array_get_element(ca, "scgi.server"))) {
29778 data_array *da = (data_array *)du;
29781 if (du->type != TYPE_ARRAY) {
29782 - log_error_write(srv, __FILE__, __LINE__, "sss",
29783 + log_error_write(srv, __FILE__, __LINE__, "sss",
29784 "unexpected type for key: ", "scgi.server", "array of strings");
29787 return HANDLER_ERROR;
29792 - * scgi.server = ( "<ext>" => ( ... ),
29796 + * scgi.server = ( "<ext>" => ( ... ),
29797 * "<ext>" => ( ... ) )
29801 for (j = 0; j < da->value->used; j++) {
29803 data_array *da_ext = (data_array *)da->value->data[j];
29806 if (da->value->data[j]->type != TYPE_ARRAY) {
29807 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
29808 - "unexpected type for key: ", "scgi.server",
29809 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
29810 + "unexpected type for key: ", "scgi.server",
29811 "[", da->value->data[j]->key, "](string)");
29814 return HANDLER_ERROR;
29818 - * da_ext->key == name of the extension
29821 + * da_ext->key == name of the extension
29825 - * scgi.server = ( "<ext>" =>
29826 - * ( "<host>" => ( ... ),
29829 + * scgi.server = ( "<ext>" =>
29830 + * ( "<host>" => ( ... ),
29831 * "<host>" => ( ... )
29838 for (n = 0; n < da_ext->value->used; n++) {
29839 data_array *da_host = (data_array *)da_ext->value->data[n];
29842 scgi_extension_host *df;
29844 - config_values_t fcv[] = {
29846 + config_values_t fcv[] = {
29847 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
29848 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
29849 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
29850 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
29853 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
29854 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
29855 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
29856 @@ -970,37 +969,37 @@
29857 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
29858 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
29859 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
29862 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
29863 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
29868 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29872 if (da_host->type != TYPE_ARRAY) {
29873 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29874 - "unexpected type for key:",
29876 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29877 + "unexpected type for key:",
29879 "[", da_host->key, "](string)");
29882 return HANDLER_ERROR;
29886 df = scgi_host_init();
29889 df->check_local = 1;
29892 df->max_load_per_proc = 1;
29893 df->idle_timeout = 60;
29894 df->disable_time = 60;
29897 fcv[0].destination = df->host;
29898 fcv[1].destination = df->docroot;
29899 fcv[2].destination = df->unixsocket;
29900 fcv[3].destination = df->bin_path;
29903 fcv[4].destination = &(df->check_local);
29904 fcv[5].destination = &(df->port);
29905 fcv[6].destination = &(df->min_procs);
29906 @@ -1008,47 +1007,47 @@
29907 fcv[8].destination = &(df->max_load_per_proc);
29908 fcv[9].destination = &(df->idle_timeout);
29909 fcv[10].destination = &(df->disable_time);
29912 fcv[11].destination = df->bin_env;
29913 fcv[12].destination = df->bin_env_copy;
29918 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
29919 return HANDLER_ERROR;
29922 - if ((!buffer_is_empty(df->host) || df->port) &&
29924 + if ((!buffer_is_empty(df->host) || df->port) &&
29925 !buffer_is_empty(df->unixsocket)) {
29926 - log_error_write(srv, __FILE__, __LINE__, "s",
29927 + log_error_write(srv, __FILE__, __LINE__, "s",
29928 "either host+port or socket");
29931 return HANDLER_ERROR;
29935 if (!buffer_is_empty(df->unixsocket)) {
29936 /* unix domain socket */
29939 if (df->unixsocket->used > UNIX_PATH_MAX - 2) {
29940 - log_error_write(srv, __FILE__, __LINE__, "s",
29941 + log_error_write(srv, __FILE__, __LINE__, "s",
29942 "path of the unixdomain socket is too large");
29943 return HANDLER_ERROR;
29948 - if (buffer_is_empty(df->host) &&
29950 + if (buffer_is_empty(df->host) &&
29951 buffer_is_empty(df->bin_path)) {
29952 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29953 - "missing key (string):",
29954 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29955 + "missing key (string):",
29962 return HANDLER_ERROR;
29963 } else if (df->port == 0) {
29964 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29965 - "missing key (short):",
29966 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29967 + "missing key (short):",
29971 @@ -1056,14 +1055,14 @@
29972 return HANDLER_ERROR;
29976 - if (!buffer_is_empty(df->bin_path)) {
29978 + if (!buffer_is_empty(df->bin_path)) {
29979 /* a local socket + self spawning */
29983 if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
29984 if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
29988 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
29989 "--- scgi spawning local",
29990 @@ -1073,7 +1072,7 @@
29991 "\n\tmin-procs:", df->min_procs,
29992 "\n\tmax-procs:", df->max_procs);
29996 for (pno = 0; pno < df->min_procs; pno++) {
29999 @@ -1088,7 +1087,7 @@
30000 buffer_append_string(proc->socket, "-");
30001 buffer_append_long(proc->socket, pno);
30006 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
30007 "--- scgi spawning",
30008 @@ -1096,53 +1095,53 @@
30009 "\n\tsocket", df->unixsocket,
30010 "\n\tcurrent:", pno, "/", df->min_procs);
30014 if (scgi_spawn_connection(srv, p, df, proc)) {
30015 log_error_write(srv, __FILE__, __LINE__, "s",
30016 "[ERROR]: spawning fcgi failed.");
30017 return HANDLER_ERROR;
30021 proc->next = df->first;
30022 if (df->first) df->first->prev = proc;
30031 fp = scgi_process_init();
30032 fp->id = df->num_procs++;
30034 df->active_procs++;
30035 fp->state = PROC_STATE_RUNNING;
30038 if (buffer_is_empty(df->unixsocket)) {
30039 fp->port = df->port;
30041 buffer_copy_string_buffer(fp->socket, df->unixsocket);
30053 /* if extension already exists, take it */
30054 scgi_extension_insert(s->exts, da_ext->key, df);
30061 return HANDLER_GO_ON;
30064 static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) {
30065 hctx->state = state;
30066 hctx->state_timestamp = srv->cur_ts;
30072 @@ -1150,34 +1149,34 @@
30073 void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
30078 if (NULL == hctx) return;
30081 p = hctx->plugin_data;
30082 con = hctx->remote_conn;
30085 if (con->mode != p->id) {
30091 if (hctx->fd != -1) {
30092 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30093 fdevent_unregister(srv->ev, hctx->fd);
30099 if (hctx->host && hctx->proc) {
30100 hctx->host->load--;
30103 if (hctx->got_proc) {
30104 /* after the connect the process gets a load */
30105 hctx->proc->load--;
30108 if (p->conf.debug) {
30109 log_error_write(srv, __FILE__, __LINE__, "sddb",
30113 hctx->proc->pid, hctx->proc->socket);
30115 @@ -1186,87 +1185,87 @@
30116 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30121 handler_ctx_free(hctx);
30122 - con->plugin_ctx[p->id] = NULL;
30123 + con->plugin_ctx[p->id] = NULL;
30126 static int scgi_reconnect(server *srv, handler_ctx *hctx) {
30127 plugin_data *p = hctx->plugin_data;
30138 * connect was ok, connection was accepted
30139 * but the php accept loop checks after the accept if it should die or not.
30141 - * if yes we can only detect it at a write()
30144 + * if yes we can only detect it at a write()
30146 * next step is resetting this attemp and setup a connection again
30149 * if we have more then 5 reconnects for the same request, die
30156 * we have a connection but the child died by some other reason
30162 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30163 fdevent_unregister(srv->ev, hctx->fd);
30168 scgi_set_state(srv, hctx, FCGI_STATE_INIT);
30171 hctx->request_id = 0;
30172 hctx->reconnects++;
30175 if (p->conf.debug) {
30176 log_error_write(srv, __FILE__, __LINE__, "sddb",
30180 hctx->proc->pid, hctx->proc->socket);
30184 hctx->proc->load--;
30185 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30192 static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
30193 plugin_data *p = p_d;
30196 scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
30199 return HANDLER_GO_ON;
30203 static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
30207 if (!key || !val) return -1;
30210 len = key_len + val_len + 2;
30213 buffer_prepare_append(env, len);
30215 - /* include the NUL */
30216 + /* include the NUL */
30217 memcpy(env->ptr + env->used, key, key_len + 1);
30218 env->used += key_len + 1;
30219 memcpy(env->ptr + env->used, val, val_len + 1);
30220 env->used += val_len + 1;
30233 @@ -1280,24 +1279,21 @@
30234 struct sockaddr_un scgi_addr_un;
30239 scgi_extension_host *host = hctx->host;
30240 scgi_proc *proc = hctx->proc;
30241 int scgi_fd = hctx->fd;
30244 memset(&scgi_addr, 0, sizeof(scgi_addr));
30247 if (!buffer_is_empty(proc->socket)) {
30248 #ifdef HAVE_SYS_UN_H
30249 /* use the unix domain socket */
30250 scgi_addr_un.sun_family = AF_UNIX;
30251 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
30254 servlen = SUN_LEN(&scgi_addr_un);
30256 - /* stevens says: */
30257 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
30260 scgi_addr = (struct sockaddr *) &scgi_addr_un;
30263 @@ -1305,105 +1301,105 @@
30265 scgi_addr_in.sin_family = AF_INET;
30266 if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) {
30267 - log_error_write(srv, __FILE__, __LINE__, "sbs",
30268 - "converting IP-adress failed for", host->host,
30269 + log_error_write(srv, __FILE__, __LINE__, "sbs",
30270 + "converting IP-adress failed for", host->host,
30271 "\nBe sure to specify an IP address here");
30276 scgi_addr_in.sin_port = htons(proc->port);
30277 servlen = sizeof(scgi_addr_in);
30280 scgi_addr = (struct sockaddr *) &scgi_addr_in;
30284 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
30285 - if (errno == EINPROGRESS ||
30286 + if (errno == EINPROGRESS ||
30287 errno == EALREADY ||
30289 if (hctx->conf.debug) {
30290 - log_error_write(srv, __FILE__, __LINE__, "sd",
30291 + log_error_write(srv, __FILE__, __LINE__, "sd",
30292 "connect delayed, will continue later:", scgi_fd);
30298 - log_error_write(srv, __FILE__, __LINE__, "sdsddb",
30299 - "connect failed:", scgi_fd,
30300 + log_error_write(srv, __FILE__, __LINE__, "sdsddb",
30301 + "connect failed:", scgi_fd,
30302 strerror(errno), errno,
30303 proc->port, proc->socket);
30305 if (errno == EAGAIN) {
30306 /* this is Linux only */
30308 - log_error_write(srv, __FILE__, __LINE__, "s",
30310 + log_error_write(srv, __FILE__, __LINE__, "s",
30311 "If this happend on Linux: You have been run out of local ports. "
30312 "Check the manual, section Performance how to handle this.");
30320 if (hctx->conf.debug > 1) {
30321 - log_error_write(srv, __FILE__, __LINE__, "sd",
30322 + log_error_write(srv, __FILE__, __LINE__, "sd",
30323 "connect succeeded: ", scgi_fd);
30332 static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
30336 for (i = 0; i < con->request.headers->used; i++) {
30340 ds = (data_string *)con->request.headers->data[i];
30343 if (ds->value->used && ds->key->used) {
30345 buffer_reset(srv->tmp_buf);
30348 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
30349 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
30350 srv->tmp_buf->used--;
30354 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30355 for (j = 0; j < ds->key->used - 1; j++) {
30356 - srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30357 - light_isalpha(ds->key->ptr[j]) ?
30358 + srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30359 + light_isalpha(ds->key->ptr[j]) ?
30360 ds->key->ptr[j] & ~32 : '_';
30362 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30365 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30370 for (i = 0; i < con->environment->used; i++) {
30374 ds = (data_string *)con->environment->data[i];
30377 if (ds->value->used && ds->key->used) {
30379 buffer_reset(srv->tmp_buf);
30382 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30383 for (j = 0; j < ds->key->used - 1; j++) {
30384 - srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30385 - isalpha((unsigned char)ds->key->ptr[j]) ?
30386 + srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30387 + isalpha((unsigned char)ds->key->ptr[j]) ?
30388 toupper((unsigned char)ds->key->ptr[j]) : '_';
30390 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30393 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30401 @@ -1415,20 +1411,20 @@
30402 char b2[INET6_ADDRSTRLEN + 1];
30407 plugin_data *p = hctx->plugin_data;
30408 scgi_extension_host *host= hctx->host;
30410 connection *con = hctx->remote_conn;
30411 server_socket *srv_sock = con->srv_socket;
30414 sock_addr our_addr;
30415 socklen_t our_addr_len;
30418 buffer_prepare_copy(p->scgi_env, 1024);
30420 /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
30423 /* request.content_length < SSIZE_MAX, see request.c */
30424 ltostr(buf, con->request.content_length);
30425 scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
30426 @@ -1436,13 +1432,13 @@
30429 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
30432 if (con->server_name->used) {
30433 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
30436 - s = inet_ntop(srv_sock->addr.plain.sa_family,
30437 - srv_sock->addr.plain.sa_family == AF_INET6 ?
30438 + s = inet_ntop(srv_sock->addr.plain.sa_family,
30439 + srv_sock->addr.plain.sa_family == AF_INET6 ?
30440 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
30441 (const void *) &(srv_sock->addr.ipv4.sin_addr),
30443 @@ -1451,47 +1447,47 @@
30445 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
30449 scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
30455 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
30457 ntohs(srv_sock->addr.ipv4.sin_port)
30462 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
30465 /* get the server-side of the connection to the client */
30466 our_addr_len = sizeof(our_addr);
30469 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
30470 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
30472 s = inet_ntop_cache_get_ip(srv, &(our_addr));
30474 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
30480 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
30482 ntohs(con->dst_addr.ipv4.sin_port)
30487 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
30490 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
30491 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
30494 if (!buffer_is_empty(con->authed_user)) {
30495 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
30496 CONST_BUF_LEN(con->authed_user));
30502 * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
30503 @@ -1500,12 +1496,12 @@
30506 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
30509 if (!buffer_is_empty(con->request.pathinfo)) {
30510 scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
30513 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
30516 if (!buffer_is_empty(host->docroot)) {
30517 buffer_copy_string_buffer(p->path, host->docroot);
30519 @@ -1526,19 +1522,19 @@
30522 if (!buffer_is_empty(host->docroot)) {
30524 - * rewrite SCRIPT_FILENAME
30527 + * rewrite SCRIPT_FILENAME
30532 buffer_copy_string_buffer(p->path, host->docroot);
30533 buffer_append_string_buffer(p->path, con->uri.path);
30536 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30537 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
30539 buffer_copy_string_buffer(p->path, con->physical.path);
30542 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30543 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
30545 @@ -1551,30 +1547,30 @@
30547 scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
30551 s = get_http_method_name(con->request.http_method);
30552 scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
30553 scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
30554 s = get_http_version_name(con->request.http_version);
30555 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
30559 if (srv_sock->is_ssl) {
30560 scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
30565 scgi_env_add_request_headers(srv, con, p);
30567 b = chunkqueue_get_append_buffer(hctx->wb);
30570 buffer_append_long(b, p->scgi_env->used);
30571 buffer_append_string_len(b, CONST_STR_LEN(":"));
30572 buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used);
30573 buffer_append_string_len(b, CONST_STR_LEN(","));
30575 hctx->wb->bytes_in += b->used - 1;
30578 if (con->request.content_length) {
30579 chunkqueue *req_cq = con->request_content_queue;
30581 @@ -1587,7 +1583,7 @@
30583 /* we announce toWrite octects
30584 * now take all the request_content chunk that we need to fill this request
30588 switch (req_c->type) {
30590 @@ -1615,32 +1611,32 @@
30592 req_c->offset += weHave;
30593 req_cq->bytes_out += weHave;
30596 hctx->wb->bytes_in += weHave;
30610 for (i = 0; i < hctx->write_buffer->used; i++) {
30611 fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]);
30612 if ((i+1) % 16 == 0) {
30614 for (j = i-15; j <= i; j++) {
30615 - fprintf(stderr, "%c",
30616 + fprintf(stderr, "%c",
30617 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
30619 fprintf(stderr, "\n");
30628 @@ -1648,32 +1644,32 @@
30637 buffer_copy_string_buffer(p->parse_response, in);
30639 - for (s = p->parse_response->ptr;
30640 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
30642 + for (s = p->parse_response->ptr;
30643 + NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
30644 s = ns + (eol == EOL_RN ? 2 : 1), line++) {
30645 const char *key, *value;
30655 0 == strncmp(s, "HTTP/1.", 7)) {
30656 /* non-parsed header ... we parse them anyway */
30659 if ((s[7] == '1' ||
30663 /* after the space should be a status code for us */
30666 status = strtol(s+9, NULL, 10);
30669 if (con->http_status >= 100 &&
30670 con->http_status < 1000) {
30671 /* we expected 3 digits and didn't got them */
30672 @@ -1682,27 +1678,27 @@
30679 if (NULL == (value = strchr(s, ':'))) {
30680 /* we expect: "<key>: <value>\r\n" */
30685 key_len = value - key;
30690 while (*value == ' ' || *value == '\t') value++;
30693 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
30694 ds = data_response_init();
30696 buffer_copy_string_len(ds->key, key, key_len);
30697 buffer_copy_string(ds->value, value);
30700 array_insert_unique(con->response.headers, (data_unset *)ds);
30705 if (0 == strncasecmp(key, "Date", key_len)) {
30706 @@ -1737,13 +1733,13 @@
30712 /* CGI/1.1 rev 03 - 7.2.1.2 */
30713 if ((con->parsed_response & HTTP_LOCATION) &&
30714 !(con->parsed_response & HTTP_STATUS)) {
30715 con->http_status = 302;
30722 @@ -1751,10 +1747,10 @@
30723 static int scgi_demux_response(server *srv, handler_ctx *hctx) {
30724 plugin_data *p = hctx->plugin_data;
30725 connection *con = hctx->remote_conn;
30732 buffer_prepare_copy(hctx->response, 1024);
30733 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
30734 if (errno == EAGAIN || errno == EINTR) {
30735 @@ -1765,143 +1761,143 @@
30736 log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
30742 /* read finished */
30745 con->file_finished = 1;
30748 /* send final chunk */
30749 http_chunk_append_mem(srv, con, NULL, 0);
30750 joblist_append(srv, con);
30757 hctx->response->ptr[n] = '\0';
30758 hctx->response->used = n+1;
30761 /* split header from body */
30764 if (con->file_started == 0) {
30767 int header_end = 0;
30768 int cp, eol = EOL_UNSET;
30772 buffer_append_string_buffer(hctx->response_header, hctx->response);
30775 /* nph (non-parsed headers) */
30776 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
30779 /* search for the \r\n\r\n or \n\n in the string */
30780 for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
30781 if (*c == ':') in_header = 1;
30782 else if (*c == '\n') {
30783 if (in_header == 0) {
30784 /* got a response without a response header */
30793 if (eol == EOL_UNSET) eol = EOL_N;
30796 if (*(c+1) == '\n') {
30802 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
30803 if (in_header == 0) {
30804 /* got a response without a response header */
30813 if (eol == EOL_UNSET) eol = EOL_RN;
30817 - *(c+2) == '\r' &&
30818 + *(c+2) == '\r' &&
30835 /* no header, but a body */
30838 if (con->request.http_version == HTTP_VERSION_1_1) {
30839 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30843 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
30844 joblist_append(srv, con);
30846 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
30847 size_t blen = hctx->response_header->used - hlen - 1;
30850 /* a small hack: terminate after at the second \r */
30851 hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
30852 hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
30855 /* parse the response header */
30856 scgi_response_parse(srv, con, p, hctx->response_header, eol);
30859 /* enable chunked-transfer-encoding */
30860 if (con->request.http_version == HTTP_VERSION_1_1 &&
30861 !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
30862 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30866 if ((hctx->response->used != hlen) && blen > 0) {
30867 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
30868 joblist_append(srv, con);
30873 con->file_started = 1;
30876 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
30877 joblist_append(srv, con);
30883 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
30892 int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30898 - /* we have been the smallest of the current list
30899 - * and we want to insert the node sorted as soon
30901 + /* we have been the smallest of the current list
30902 + * and we want to insert the node sorted as soon
30915 /* nothing to sort, only one element */
30916 @@ -1909,9 +1905,9 @@
30918 for (p = proc; p->next && p->next->load < proc->load; p = p->next);
30920 - /* no need to move something
30921 + /* no need to move something
30928 @@ -1930,16 +1926,16 @@
30930 if (proc->prev) proc->prev->next = proc->next;
30931 if (proc->next) proc->next->prev = proc->prev;
30934 /* proc should be right of p */
30937 proc->next = p->next;
30939 if (p->next) p->next->prev = proc;
30942 for(p = host->first; p; p = p->next) {
30943 - log_error_write(srv, __FILE__, __LINE__, "dd",
30944 + log_error_write(srv, __FILE__, __LINE__, "dd",
30948 @@ -1951,21 +1947,21 @@
30950 int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30956 - /* we have been the smallest of the current list
30957 - * and we want to insert the node sorted as soon
30959 + /* we have been the smallest of the current list
30960 + * and we want to insert the node sorted as soon
30970 * the basic is idea is:
30971 - * - the last active scgi process should be still
30972 + * - the last active scgi process should be still
30973 * in ram and is not swapped out yet
30974 * - processes that are not reused will be killed
30975 * after some time by the trigger-handler
30976 @@ -1975,7 +1971,7 @@
30977 * ice-cold processes are propably unused since more
30978 * than 'unused-timeout', are swaped out and won't be
30979 * reused in the next seconds anyway.
30984 /* nothing to sort, only one element */
30985 @@ -1984,16 +1980,16 @@
30986 for (p = host->first; p != proc && p->load < proc->load; p = p->next);
30989 - /* no need to move something
30990 + /* no need to move something
30999 if (p == proc) return 0;
31002 /* we have to move left. If we are already the first element
31004 if (host->first == proc) return 0;
31005 @@ -2009,9 +2005,9 @@
31008 if (proc->prev == NULL) host->first = proc;
31011 for(p = host->first; p; p = p->next) {
31012 - log_error_write(srv, __FILE__, __LINE__, "dd",
31013 + log_error_write(srv, __FILE__, __LINE__, "dd",
31017 @@ -2023,41 +2019,42 @@
31019 static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
31023 for (proc = host->first; proc; proc = proc->next) {
31024 if (p->conf.debug) {
31025 - log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
31027 - host->host, proc->port,
31028 + log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
31030 + host->host, proc->port,
31039 if (0 == proc->is_local) {
31041 - * external servers might get disabled
31043 - * enable the server again, perhaps it is back again
31045 + * external servers might get disabled
31047 + * enable the server again, perhaps it is back again
31051 if ((proc->state == PROC_STATE_DISABLED) &&
31052 (srv->cur_ts - proc->disable_ts > host->disable_time)) {
31053 proc->state = PROC_STATE_RUNNING;
31054 host->active_procs++;
31056 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
31057 - "fcgi-server re-enabled:",
31058 - host->host, host->port,
31060 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
31061 + "fcgi-server re-enabled:",
31062 + host->host, host->port,
31066 /* the child should not terminate at all */
31070 if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
31072 switch(waitpid(proc->pid, &status, WNOHANG)) {
31074 /* child is still alive */
31075 @@ -2067,33 +2064,34 @@
31077 if (WIFEXITED(status)) {
31079 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
31080 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
31081 "child exited, pid:", proc->pid,
31082 "status:", WEXITSTATUS(status));
31084 } else if (WIFSIGNALED(status)) {
31085 - log_error_write(srv, __FILE__, __LINE__, "sd",
31086 - "child signaled:",
31087 + log_error_write(srv, __FILE__, __LINE__, "sd",
31088 + "child signaled:",
31091 - log_error_write(srv, __FILE__, __LINE__, "sd",
31092 - "child died somehow:",
31093 + log_error_write(srv, __FILE__, __LINE__, "sd",
31094 + "child died somehow:",
31099 proc->state = PROC_STATE_DIED;
31108 * local servers might died, but we restart them
31112 if (proc->state == PROC_STATE_DIED &&
31114 /* restart the child */
31117 if (p->conf.debug) {
31118 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31119 "--- scgi spawning",
31120 @@ -2101,18 +2099,18 @@
31121 "\n\tsocket", host->unixsocket,
31122 "\n\tcurrent:", 1, "/", host->min_procs);
31126 if (scgi_spawn_connection(srv, p, host, proc)) {
31127 log_error_write(srv, __FILE__, __LINE__, "s",
31128 "ERROR: spawning fcgi failed.");
31129 return HANDLER_ERROR;
31133 scgi_proclist_sort_down(srv, host, proc);
31142 @@ -2121,13 +2119,13 @@
31143 plugin_data *p = hctx->plugin_data;
31144 scgi_extension_host *host= hctx->host;
31145 connection *con = hctx->remote_conn;
31150 - /* sanity check */
31151 + /* sanity check */
31153 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
31154 - log_error_write(srv, __FILE__, __LINE__, "sxddd",
31155 + log_error_write(srv, __FILE__, __LINE__, "sxddd",
31156 "write-req: error",
31159 @@ -2135,179 +2133,180 @@
31160 host->unixsocket->used);
31161 return HANDLER_ERROR;
31166 switch(hctx->state) {
31167 case FCGI_STATE_INIT:
31168 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
31171 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
31172 if (errno == EMFILE ||
31174 - log_error_write(srv, __FILE__, __LINE__, "sd",
31175 + log_error_write(srv, __FILE__, __LINE__, "sd",
31176 "wait for fd at connection:", con->fd);
31179 return HANDLER_WAIT_FOR_FD;
31182 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
31184 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
31185 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
31186 return HANDLER_ERROR;
31188 hctx->fde_ndx = -1;
31194 fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
31197 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
31198 - log_error_write(srv, __FILE__, __LINE__, "ss",
31199 + log_error_write(srv, __FILE__, __LINE__, "ss",
31200 "fcntl failed: ", strerror(errno));
31203 return HANDLER_ERROR;
31208 case FCGI_STATE_CONNECT:
31209 if (hctx->state == FCGI_STATE_INIT) {
31210 - for (hctx->proc = hctx->host->first;
31211 - hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
31212 + for (hctx->proc = hctx->host->first;
31213 + hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
31214 hctx->proc = hctx->proc->next);
31217 /* all childs are dead */
31218 if (hctx->proc == NULL) {
31219 hctx->fde_ndx = -1;
31222 return HANDLER_ERROR;
31226 if (hctx->proc->is_local) {
31227 hctx->pid = hctx->proc->pid;
31231 switch (scgi_establish_connection(srv, hctx)) {
31233 scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
31236 /* connection is in progress, wait for an event and call getsockopt() below */
31239 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31242 return HANDLER_WAIT_FOR_EVENT;
31244 /* if ECONNREFUSED choose another connection -> FIXME */
31245 hctx->fde_ndx = -1;
31248 return HANDLER_ERROR;
31250 /* everything is ok, go on */
31258 socklen_t socket_error_len = sizeof(socket_error);
31261 /* try to finish the connect() */
31262 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
31263 - log_error_write(srv, __FILE__, __LINE__, "ss",
31264 + log_error_write(srv, __FILE__, __LINE__, "ss",
31265 "getsockopt failed:", strerror(errno));
31268 return HANDLER_ERROR;
31270 if (socket_error != 0) {
31271 if (!hctx->proc->is_local || p->conf.debug) {
31272 /* local procs get restarted */
31275 log_error_write(srv, __FILE__, __LINE__, "ss",
31276 - "establishing connection failed:", strerror(socket_error),
31277 + "establishing connection failed:", strerror(socket_error),
31278 "port:", hctx->proc->port);
31282 return HANDLER_ERROR;
31287 /* ok, we have the connection */
31290 hctx->proc->load++;
31291 hctx->proc->last_used = srv->cur_ts;
31292 hctx->got_proc = 1;
31295 if (p->conf.debug) {
31296 log_error_write(srv, __FILE__, __LINE__, "sddbdd",
31301 - hctx->proc->socket,
31303 + hctx->proc->socket,
31308 /* move the proc-list entry down the list */
31309 scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
31312 scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
31314 case FCGI_STATE_PREPARE_WRITE:
31315 scgi_create_env(srv, hctx);
31318 scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
31322 case FCGI_STATE_WRITE:
31323 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
31324 + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
31326 chunkqueue_remove_finished_chunks(hctx->wb);
31330 if (errno == ENOTCONN) {
31331 - /* the connection got dropped after accept()
31333 - * this is most of the time a PHP which dies
31334 + /* the connection got dropped after accept()
31336 + * this is most of the time a PHP which dies
31337 * after PHP_FCGI_MAX_REQUESTS
31342 if (hctx->wb->bytes_out == 0 &&
31343 hctx->reconnects < 5) {
31344 - usleep(10000); /* take away the load of the webserver
31345 - * to let the php a chance to restart
31347 + usleep(10000); /* take away the load of the webserver
31348 + * to let the php a chance to restart
31352 scgi_reconnect(srv, hctx);
31355 return HANDLER_WAIT_FOR_FD;
31359 /* not reconnected ... why
31362 * far@#lighttpd report this for FreeBSD
31367 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31369 + log_error_write(srv, __FILE__, __LINE__, "ssosd",
31370 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
31371 "write-offset:", hctx->wb->bytes_out,
31372 "reconnect attempts:", hctx->reconnects);
31375 return HANDLER_ERROR;
31379 if ((errno != EAGAIN) &&
31380 (errno != EINTR)) {
31382 - log_error_write(srv, __FILE__, __LINE__, "ssd",
31384 + log_error_write(srv, __FILE__, __LINE__, "ssd",
31385 "write failed:", strerror(errno), errno);
31388 return HANDLER_ERROR;
31390 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31393 return HANDLER_WAIT_FOR_EVENT;
31398 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
31399 /* we don't need the out event anymore */
31400 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
31401 @@ -2315,10 +2314,10 @@
31402 scgi_set_state(srv, hctx, FCGI_STATE_READ);
31404 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31407 return HANDLER_WAIT_FOR_EVENT;
31412 case FCGI_STATE_READ:
31413 /* waiting for a response */
31414 @@ -2327,67 +2326,67 @@
31415 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
31416 return HANDLER_ERROR;
31420 return HANDLER_WAIT_FOR_EVENT;
31423 SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
31424 plugin_data *p = p_d;
31427 handler_ctx *hctx = con->plugin_ctx[p->id];
31429 scgi_extension_host *host;
31432 if (NULL == hctx) return HANDLER_GO_ON;
31436 if (con->mode != p->id) return HANDLER_GO_ON;
31439 /* ok, create the request */
31440 switch(scgi_write_request(srv, hctx)) {
31441 case HANDLER_ERROR:
31448 0 == proc->is_local &&
31449 proc->state != PROC_STATE_DISABLED) {
31450 /* only disable remote servers as we don't manage them*/
31452 - log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
31454 + log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
31460 /* disable this server */
31461 proc->disable_ts = srv->cur_ts;
31462 proc->state = PROC_STATE_DISABLED;
31463 host->active_procs--;
31467 if (hctx->state == FCGI_STATE_INIT ||
31468 hctx->state == FCGI_STATE_CONNECT) {
31469 - /* connect() or getsockopt() failed,
31470 - * restart the request-handling
31471 + /* connect() or getsockopt() failed,
31472 + * restart the request-handling
31474 if (proc && proc->is_local) {
31476 if (p->conf.debug) {
31477 - log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
31478 + log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
31486 * several hctx might reference the same proc
31489 * Only one of them should mark the proc as dead all the other
31490 * ones should just take a new one.
31493 * If a new proc was started with the old struct this might lead
31494 * the mark a perfect proc as dead otherwise
31498 if (proc->state == PROC_STATE_RUNNING &&
31499 hctx->pid == proc->pid) {
31500 @@ -2395,25 +2394,25 @@
31503 scgi_restart_dead_procs(srv, p, host);
31506 scgi_connection_cleanup(srv, hctx);
31509 buffer_reset(con->physical.path);
31510 con->mode = DIRECT;
31511 joblist_append(srv, con);
31513 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31514 - * and hope that the childs will be restarted
31517 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31518 + * and hope that the childs will be restarted
31521 return HANDLER_WAIT_FOR_FD;
31523 scgi_connection_cleanup(srv, hctx);
31526 buffer_reset(con->physical.path);
31527 con->mode = DIRECT;
31528 con->http_status = 503;
31531 return HANDLER_FINISHED;
31533 case HANDLER_WAIT_FOR_EVENT:
31534 @@ -2433,23 +2432,23 @@
31535 static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
31540 if (NULL == hctx) return HANDLER_GO_ON;
31543 p = hctx->plugin_data;
31544 con = hctx->remote_conn;
31547 if (con->mode != p->id) return HANDLER_GO_ON;
31549 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31550 - "emergency exit: scgi:",
31552 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31553 + "emergency exit: scgi:",
31554 "connection-fd:", con->fd,
31555 "fcgi-fd:", hctx->fd);
31562 scgi_connection_cleanup(srv, hctx);
31565 return HANDLER_FINISHED;
31568 @@ -2459,7 +2458,7 @@
31569 handler_ctx *hctx = ctx;
31570 connection *con = hctx->remote_conn;
31571 plugin_data *p = hctx->plugin_data;
31574 scgi_proc *proc = hctx->proc;
31575 scgi_extension_host *host= hctx->host;
31577 @@ -2471,15 +2470,15 @@
31580 scgi_connection_cleanup(srv, hctx);
31583 joblist_append(srv, con);
31584 return HANDLER_FINISHED;
31586 if (proc->pid && proc->state != PROC_STATE_DIED) {
31590 /* only fetch the zombie if it is not already done */
31593 switch(waitpid(proc->pid, &status, WNOHANG)) {
31595 /* child is still alive */
31596 @@ -2489,19 +2488,19 @@
31598 /* the child should not terminate at all */
31599 if (WIFEXITED(status)) {
31600 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
31601 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
31602 "child exited, pid:", proc->pid,
31603 "status:", WEXITSTATUS(status));
31604 } else if (WIFSIGNALED(status)) {
31605 - log_error_write(srv, __FILE__, __LINE__, "sd",
31606 - "child signaled:",
31607 + log_error_write(srv, __FILE__, __LINE__, "sd",
31608 + "child signaled:",
31611 - log_error_write(srv, __FILE__, __LINE__, "sd",
31612 - "child died somehow:",
31613 + log_error_write(srv, __FILE__, __LINE__, "sd",
31614 + "child died somehow:",
31619 if (p->conf.debug) {
31620 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31621 "--- scgi spawning",
31622 @@ -2509,40 +2508,41 @@
31623 "\n\tsocket", host->unixsocket,
31624 "\n\tcurrent:", 1, "/", host->min_procs);
31628 if (scgi_spawn_connection(srv, p, host, proc)) {
31630 proc->state = PROC_STATE_DIED;
31632 scgi_proclist_sort_down(srv, host, proc);
31641 if (con->file_started == 0) {
31642 /* nothing has been send out yet, try to use another child */
31645 if (hctx->wb->bytes_out == 0 &&
31646 hctx->reconnects < 5) {
31647 scgi_reconnect(srv, hctx);
31649 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31651 + log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31652 "response not sent, request not sent, reconnection.",
31653 "connection-fd:", con->fd,
31654 "fcgi-fd:", hctx->fd);
31657 return HANDLER_WAIT_FOR_FD;
31660 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31662 + log_error_write(srv, __FILE__, __LINE__, "sosdsd",
31663 "response not sent, request sent:", hctx->wb->bytes_out,
31664 "connection-fd:", con->fd,
31665 "fcgi-fd:", hctx->fd);
31668 scgi_connection_cleanup(srv, hctx);
31671 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
31672 buffer_reset(con->physical.path);
31673 con->http_status = 500;
31674 @@ -2550,76 +2550,76 @@
31676 /* response might have been already started, kill the connection */
31677 scgi_connection_cleanup(srv, hctx);
31679 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31681 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31682 "response already sent out, termination connection",
31683 "connection-fd:", con->fd,
31684 "fcgi-fd:", hctx->fd);
31687 connection_set_state(srv, con, CON_STATE_ERROR);
31695 joblist_append(srv, con);
31696 return HANDLER_FINISHED;
31701 if (revents & FDEVENT_OUT) {
31702 if (hctx->state == FCGI_STATE_CONNECT ||
31703 hctx->state == FCGI_STATE_WRITE) {
31704 /* we are allowed to send something out
31707 * 1. in a unfinished connect() call
31708 * 2. in a unfinished write() call (long POST request)
31710 return mod_scgi_handle_subrequest(srv, con, p);
31712 - log_error_write(srv, __FILE__, __LINE__, "sd",
31713 - "got a FDEVENT_OUT and didn't know why:",
31714 + log_error_write(srv, __FILE__, __LINE__, "sd",
31715 + "got a FDEVENT_OUT and didn't know why:",
31721 /* perhaps this issue is already handled */
31722 if (revents & FDEVENT_HUP) {
31723 if (hctx->state == FCGI_STATE_CONNECT) {
31724 /* getoptsock will catch this one (right ?)
31726 - * if we are in connect we might get a EINPROGRESS
31727 - * in the first call and a FDEVENT_HUP in the
31729 + * if we are in connect we might get a EINPROGRESS
31730 + * in the first call and a FDEVENT_HUP in the
31734 * FIXME: as it is a bit ugly.
31738 return mod_scgi_handle_subrequest(srv, con, p);
31739 } else if (hctx->state == FCGI_STATE_READ &&
31740 hctx->proc->port == 0) {
31744 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
31745 * even if the FCGI_FIN packet is not received yet
31748 - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
31749 - "error: unexpected close of scgi connection for",
31750 + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
31751 + "error: unexpected close of scgi connection for",
31753 - "(no scgi process on host: ",
31754 + "(no scgi process on host: ",
31763 connection_set_state(srv, con, CON_STATE_ERROR);
31764 scgi_connection_close(srv, hctx);
31765 joblist_append(srv, con);
31767 } else if (revents & FDEVENT_ERR) {
31768 - log_error_write(srv, __FILE__, __LINE__, "s",
31769 + log_error_write(srv, __FILE__, __LINE__, "s",
31770 "fcgi: got a FDEVENT_ERR. Don't know why.");
31771 /* kill all connections to the scgi process */
31773 @@ -2628,42 +2628,39 @@
31774 scgi_connection_close(srv, hctx);
31775 joblist_append(srv, con);
31779 return HANDLER_FINISHED;
31781 -#define PATCH(x) \
31782 - p->conf.x = s->x;
31784 static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
31786 plugin_config *s = p->config_storage[0];
31792 + PATCH_OPTION(exts);
31793 + PATCH_OPTION(debug);
31795 /* skip the first, the global context */
31796 for (i = 1; i < srv->config_context->used; i++) {
31797 data_config *dc = (data_config *)srv->config_context->data[i];
31798 s = p->config_storage[i];
31801 /* condition didn't match */
31802 if (!config_check_cond(srv, con, dc)) continue;
31806 for (j = 0; j < dc->value->used; j++) {
31807 data_unset *du = dc->value->data[j];
31810 if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
31812 + PATCH_OPTION(exts);
31813 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
31815 + PATCH_OPTION(debug);
31826 static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
31827 plugin_data *p = p_d;
31828 @@ -2673,30 +2670,30 @@
31831 scgi_extension *extension = NULL;
31834 /* Possibly, we processed already this request */
31835 if (con->file_started == 1) return HANDLER_GO_ON;
31838 fn = uri_path_handler ? con->uri.path : con->physical.path;
31840 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
31842 s_len = fn->used - 1;
31845 scgi_patch_connection(srv, con, p);
31847 /* check if extension matches */
31848 for (k = 0; k < p->conf.exts->used; k++) {
31852 extension = p->conf.exts->exts[k];
31855 if (extension->key->used == 0) continue;
31858 ct_len = extension->key->used - 1;
31861 if (s_len < ct_len) continue;
31864 /* check extension in the form "/scgi_pattern" */
31865 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
31867 @@ -2710,17 +2707,17 @@
31868 if (k == p->conf.exts->used) {
31869 return HANDLER_GO_ON;
31873 /* get best server */
31874 for (k = 0, ndx = -1; k < extension->used; k++) {
31875 scgi_extension_host *host = extension->hosts[k];
31878 /* we should have at least one proc that can do somthing */
31879 if (host->active_procs == 0) continue;
31881 if (used == -1 || host->load < used) {
31888 @@ -2728,12 +2725,12 @@
31889 /* found a server */
31891 scgi_extension_host *host = extension->hosts[ndx];
31894 - * if check-local is disabled, use the uri.path handler
31898 + * if check-local is disabled, use the uri.path handler
31903 /* init handler-context */
31904 if (uri_path_handler) {
31905 if (host->check_local == 0) {
31906 @@ -2741,7 +2738,7 @@
31909 hctx = handler_ctx_init();
31912 hctx->remote_conn = con;
31913 hctx->plugin_data = p;
31915 @@ -2749,45 +2746,45 @@
31917 hctx->conf.exts = p->conf.exts;
31918 hctx->conf.debug = p->conf.debug;
31921 con->plugin_ctx[p->id] = hctx;
31929 if (con->conf.log_request_handling) {
31930 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
31933 - /* the prefix is the SCRIPT_NAME,
31934 + /* the prefix is the SCRIPT_NAME,
31935 * everthing from start to the next slash
31936 * this is important for check-local = "disable"
31939 * if prefix = /admin.fcgi
31942 * /admin.fcgi/foo/bar
31945 * SCRIPT_NAME = /admin.fcgi
31946 * PATH_INFO = /foo/bar
31949 * if prefix = /fcgi-bin/
31952 * /fcgi-bin/foo/bar
31955 * SCRIPT_NAME = /fcgi-bin/foo
31962 /* the rewrite is only done for /prefix/? matches */
31963 if (extension->key->ptr[0] == '/' &&
31964 con->uri.path->used > extension->key->used &&
31965 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
31966 - /* rewrite uri.path and pathinfo */
31968 + /* rewrite uri.path and pathinfo */
31970 buffer_copy_string(con->request.pathinfo, pathinfo);
31973 con->uri.path->used -= con->request.pathinfo->used - 1;
31974 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
31976 @@ -2796,21 +2793,21 @@
31979 hctx = handler_ctx_init();
31982 hctx->remote_conn = con;
31983 hctx->plugin_data = p;
31988 hctx->conf.exts = p->conf.exts;
31989 hctx->conf.debug = p->conf.debug;
31992 con->plugin_ctx[p->id] = hctx;
32001 if (con->conf.log_request_handling) {
32002 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
32004 @@ -2821,11 +2818,11 @@
32005 /* no handler found */
32006 buffer_reset(con->physical.path);
32007 con->http_status = 500;
32009 - log_error_write(srv, __FILE__, __LINE__, "sb",
32010 - "no fcgi-handler found for:",
32012 + log_error_write(srv, __FILE__, __LINE__, "sb",
32013 + "no fcgi-handler found for:",
32017 return HANDLER_FINISHED;
32019 return HANDLER_GO_ON;
32020 @@ -2844,19 +2841,19 @@
32021 JOBLIST_FUNC(mod_scgi_handle_joblist) {
32022 plugin_data *p = p_d;
32023 handler_ctx *hctx = con->plugin_ctx[p->id];
32026 if (hctx == NULL) return HANDLER_GO_ON;
32028 if (hctx->fd != -1) {
32029 switch (hctx->state) {
32030 case FCGI_STATE_READ:
32031 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
32035 case FCGI_STATE_CONNECT:
32036 case FCGI_STATE_WRITE:
32037 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
32041 case FCGI_STATE_INIT:
32043 @@ -2873,21 +2870,21 @@
32045 static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
32046 plugin_data *p = p_d;
32049 return scgi_connection_close(srv, con->plugin_ctx[p->id]);
32052 TRIGGER_FUNC(mod_scgi_handle_trigger) {
32053 plugin_data *p = p_d;
32059 /* perhaps we should kill a connect attempt after 10-15 seconds
32062 * currently we wait for the TCP timeout which is on Linux 180 seconds
32071 /* check all childs if they are still up */
32072 @@ -2904,47 +2901,47 @@
32073 scgi_extension *ex;
32075 ex = exts->exts[j];
32078 for (n = 0; n < ex->used; n++) {
32082 unsigned long sum_load = 0;
32083 scgi_extension_host *host;
32086 host = ex->hosts[n];
32089 scgi_restart_dead_procs(srv, p, host);
32092 for (proc = host->first; proc; proc = proc->next) {
32093 sum_load += proc->load;
32097 if (host->num_procs &&
32098 host->num_procs < host->max_procs &&
32099 (sum_load / host->num_procs) > host->max_load_per_proc) {
32100 /* overload, spawn new child */
32101 scgi_proc *fp = NULL;
32104 if (p->conf.debug) {
32105 - log_error_write(srv, __FILE__, __LINE__, "s",
32106 + log_error_write(srv, __FILE__, __LINE__, "s",
32107 "overload detected, spawning a new child");
32111 for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
32115 if (fp == host->unused_procs) host->unused_procs = fp->next;
32118 if (fp->next) fp->next->prev = NULL;
32123 fp = scgi_process_init();
32124 fp->id = host->max_id++;
32131 if (buffer_is_empty(host->unixsocket)) {
32132 fp->port = host->port + fp->id;
32134 @@ -2952,13 +2949,13 @@
32135 buffer_append_string(fp->socket, "-");
32136 buffer_append_long(fp->socket, fp->id);
32140 if (scgi_spawn_connection(srv, p, host, fp)) {
32141 log_error_write(srv, __FILE__, __LINE__, "s",
32142 "ERROR: spawning fcgi failed.");
32143 return HANDLER_ERROR;
32148 fp->next = host->first;
32150 @@ -2966,56 +2963,57 @@
32156 for (proc = host->first; proc; proc = proc->next) {
32157 if (proc->load != 0) break;
32158 if (host->num_procs <= host->min_procs) break;
32159 if (proc->pid == 0) continue;
32162 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
32163 /* a proc is idling for a long time now,
32167 if (p->conf.debug) {
32168 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32169 - "idle-timeout reached, terminating child:",
32170 - "socket:", proc->socket,
32171 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32172 + "idle-timeout reached, terminating child:",
32173 + "socket:", proc->socket,
32180 if (proc->next) proc->next->prev = proc->prev;
32181 if (proc->prev) proc->prev->next = proc->next;
32184 if (proc->prev == NULL) host->first = proc->next;
32188 proc->next = host->unused_procs;
32191 if (host->unused_procs) host->unused_procs->prev = proc;
32192 host->unused_procs = proc;
32195 kill(proc->pid, SIGTERM);
32198 proc->state = PROC_STATE_KILLED;
32200 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32202 - "socket:", proc->socket,
32204 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32206 + "socket:", proc->socket,
32213 /* proc is now in unused, let the next second handle the next process */
32221 for (proc = host->unused_procs; proc; proc = proc->next) {
32225 if (proc->pid == 0) continue;
32228 switch (waitpid(proc->pid, &status, WNOHANG)) {
32230 /* child still running after timeout, good */
32231 @@ -3023,10 +3021,10 @@
32233 if (errno != EINTR) {
32234 /* no PID found ? should never happen */
32235 - log_error_write(srv, __FILE__, __LINE__, "sddss",
32236 + log_error_write(srv, __FILE__, __LINE__, "sddss",
32237 "pid ", proc->pid, proc->state,
32238 "not found:", strerror(errno));
32242 if (errno == ECHILD) {
32243 /* someone else has cleaned up for us */
32244 @@ -3040,25 +3038,26 @@
32245 /* the child should not terminate at all */
32246 if (WIFEXITED(status)) {
32247 if (proc->state != PROC_STATE_KILLED) {
32248 - log_error_write(srv, __FILE__, __LINE__, "sdb",
32250 + log_error_write(srv, __FILE__, __LINE__, "sdb",
32252 WEXITSTATUS(status), proc->socket);
32254 } else if (WIFSIGNALED(status)) {
32255 if (WTERMSIG(status) != SIGTERM) {
32256 - log_error_write(srv, __FILE__, __LINE__, "sd",
32257 - "child signaled:",
32258 + log_error_write(srv, __FILE__, __LINE__, "sd",
32259 + "child signaled:",
32263 - log_error_write(srv, __FILE__, __LINE__, "sd",
32264 - "child died somehow:",
32265 + log_error_write(srv, __FILE__, __LINE__, "sd",
32266 + "child died somehow:",
32270 proc->state = PROC_STATE_UNSET;
32277 @@ -3082,8 +3081,8 @@
32278 p->handle_subrequest = mod_scgi_handle_subrequest;
32279 p->handle_joblist = mod_scgi_handle_joblist;
32280 p->handle_trigger = mod_scgi_handle_trigger;
32288 --- lighttpd-1.4.11/src/mod_secure_download.c 2005-12-14 14:37:29.000000000 +0200
32289 +++ lighttpd-1.4.12/src/mod_secure_download.c 2006-07-11 22:07:51.000000000 +0300
32299 @@ -36,28 +36,28 @@
32302 buffer *uri_prefix;
32305 unsigned short timeout;
32315 plugin_config **config_storage;
32317 - plugin_config conf;
32319 + plugin_config conf;
32322 /* init the plugin data */
32323 INIT_FUNC(mod_secdownload_init) {
32327 p = calloc(1, sizeof(*p));
32330 p->md5 = buffer_init();
32336 @@ -65,27 +65,27 @@
32337 FREE_FUNC(mod_secdownload_free) {
32338 plugin_data *p = p_d;
32342 if (!p) return HANDLER_GO_ON;
32345 if (p->config_storage) {
32347 for (i = 0; i < srv->config_context->used; i++) {
32348 plugin_config *s = p->config_storage[i];
32351 buffer_free(s->secret);
32352 buffer_free(s->doc_root);
32353 buffer_free(s->uri_prefix);
32358 free(p->config_storage);
32362 buffer_free(p->md5);
32368 return HANDLER_GO_ON;
32371 @@ -94,107 +94,103 @@
32372 SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
32373 plugin_data *p = p_d;
32376 - config_values_t cv[] = {
32378 + config_values_t cv[] = {
32379 { "secdownload.secret", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
32380 { "secdownload.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
32381 { "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
32382 { "secdownload.timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
32383 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32387 if (!p) return HANDLER_ERROR;
32390 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32393 for (i = 0; i < srv->config_context->used; i++) {
32397 s = calloc(1, sizeof(plugin_config));
32398 s->secret = buffer_init();
32399 s->doc_root = buffer_init();
32400 s->uri_prefix = buffer_init();
32404 cv[0].destination = s->secret;
32405 cv[1].destination = s->doc_root;
32406 cv[2].destination = s->uri_prefix;
32407 cv[3].destination = &(s->timeout);
32410 p->config_storage[i] = s;
32413 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32414 return HANDLER_ERROR;
32419 return HANDLER_GO_ON;
32423 * checks if the supplied string is a MD5 string
32426 * @param str a possible MD5 string
32427 * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
32430 int is_hex_len(const char *str, size_t len) {
32434 if (NULL == str) return 0;
32437 for (i = 0; i < len && *str; i++, str++) {
32438 /* illegal characters */
32439 if (!((*str >= '0' && *str <= '9') ||
32440 (*str >= 'a' && *str <= 'f') ||
32441 - (*str >= 'A' && *str <= 'F'))
32442 + (*str >= 'A' && *str <= 'F'))
32452 -#define PATCH(x) \
32453 - p->conf.x = s->x;
32454 static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
32456 plugin_config *s = p->config_storage[0];
32460 - PATCH(uri_prefix);
32464 + PATCH_OPTION(secret);
32465 + PATCH_OPTION(doc_root);
32466 + PATCH_OPTION(uri_prefix);
32467 + PATCH_OPTION(timeout);
32469 /* skip the first, the global context */
32470 for (i = 1; i < srv->config_context->used; i++) {
32471 data_config *dc = (data_config *)srv->config_context->data[i];
32472 s = p->config_storage[i];
32475 /* condition didn't match */
32476 if (!config_check_cond(srv, con, dc)) continue;
32480 for (j = 0; j < dc->value->used; j++) {
32481 data_unset *du = dc->value->data[j];
32484 if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
32486 + PATCH_OPTION(secret);
32487 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
32489 + PATCH_OPTION(doc_root);
32490 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
32491 - PATCH(uri_prefix);
32492 + PATCH_OPTION(uri_prefix);
32493 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
32495 + PATCH_OPTION(timeout);
32506 URIHANDLER_FUNC(mod_secdownload_uri_handler) {
32507 plugin_data *p = p_d;
32508 @@ -203,88 +199,88 @@
32509 const char *rel_uri, *ts_str, *md5_str;
32514 if (con->uri.path->used == 0) return HANDLER_GO_ON;
32517 mod_secdownload_patch_connection(srv, con, p);
32519 if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
32522 if (buffer_is_empty(p->conf.secret)) {
32523 log_error_write(srv, __FILE__, __LINE__, "s",
32524 "secdownload.secret has to be set");
32525 return HANDLER_ERROR;
32529 if (buffer_is_empty(p->conf.doc_root)) {
32530 log_error_write(srv, __FILE__, __LINE__, "s",
32531 "secdownload.document-root has to be set");
32532 return HANDLER_ERROR;
32538 * /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
32542 if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
32545 md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
32548 if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
32549 if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
32552 ts_str = md5_str + 32 + 1;
32555 if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
32556 if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
32559 for (i = 0; i < 8; i++) {
32560 ts = (ts << 4) + hex2int(*(ts_str + i));
32565 - if (srv->cur_ts - ts > p->conf.timeout ||
32566 + if (srv->cur_ts - ts > p->conf.timeout ||
32567 srv->cur_ts - ts < -p->conf.timeout) {
32568 con->http_status = 408;
32571 return HANDLER_FINISHED;
32575 rel_uri = ts_str + 8;
32582 * <secret><rel-path><timestamp-hex>
32586 buffer_copy_string_buffer(p->md5, p->conf.secret);
32587 buffer_append_string(p->md5, rel_uri);
32588 buffer_append_string_len(p->md5, ts_str, 8);
32592 MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
32593 MD5_Final(HA1, &Md5Ctx);
32596 buffer_copy_string_hex(p->md5, (char *)HA1, 16);
32599 if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
32600 con->http_status = 403;
32602 - log_error_write(srv, __FILE__, __LINE__, "sss",
32604 + log_error_write(srv, __FILE__, __LINE__, "sss",
32606 md5_str, p->md5->ptr);
32609 return HANDLER_FINISHED;
32613 /* starting with the last / we should have relative-path to the docroot
32617 buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
32618 buffer_copy_string(con->physical.rel_path, rel_uri);
32619 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
32620 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
32623 return HANDLER_GO_ON;
32626 @@ -293,13 +289,13 @@
32627 int mod_secdownload_plugin_init(plugin *p) {
32628 p->version = LIGHTTPD_VERSION_ID;
32629 p->name = buffer_init_string("secdownload");
32632 p->init = mod_secdownload_init;
32633 p->handle_physical = mod_secdownload_uri_handler;
32634 p->set_defaults = mod_secdownload_set_defaults;
32635 p->cleanup = mod_secdownload_free;
32643 --- lighttpd-1.4.11/src/mod_setenv.c 2006-01-14 20:33:12.000000000 +0200
32644 +++ lighttpd-1.4.12/src/mod_setenv.c 2006-07-11 22:07:53.000000000 +0300
32645 @@ -18,25 +18,25 @@
32647 array *request_header;
32648 array *response_header;
32651 array *environment;
32658 plugin_config **config_storage;
32660 - plugin_config conf;
32662 + plugin_config conf;
32665 static handler_ctx * handler_ctx_init() {
32666 handler_ctx * hctx;
32669 hctx = calloc(1, sizeof(*hctx));
32678 @@ -48,36 +48,36 @@
32679 /* init the plugin data */
32680 INIT_FUNC(mod_setenv_init) {
32684 p = calloc(1, sizeof(*p));
32690 /* detroy the plugin data */
32691 FREE_FUNC(mod_setenv_free) {
32692 plugin_data *p = p_d;
32697 if (!p) return HANDLER_GO_ON;
32700 if (p->config_storage) {
32702 for (i = 0; i < srv->config_context->used; i++) {
32703 plugin_config *s = p->config_storage[i];
32706 array_free(s->request_header);
32707 array_free(s->response_header);
32708 array_free(s->environment);
32713 free(p->config_storage);
32720 return HANDLER_GO_ON;
32723 @@ -86,86 +86,83 @@
32724 SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
32725 plugin_data *p = p_d;
32728 - config_values_t cv[] = {
32730 + config_values_t cv[] = {
32731 { "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
32732 { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
32733 { "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
32734 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32738 if (!p) return HANDLER_ERROR;
32741 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32744 for (i = 0; i < srv->config_context->used; i++) {
32748 s = calloc(1, sizeof(plugin_config));
32749 s->request_header = array_init();
32750 s->response_header = array_init();
32751 s->environment = array_init();
32754 cv[0].destination = s->request_header;
32755 cv[1].destination = s->response_header;
32756 cv[2].destination = s->environment;
32759 p->config_storage[i] = s;
32762 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32763 return HANDLER_ERROR;
32768 return HANDLER_GO_ON;
32771 -#define PATCH(x) \
32772 - p->conf.x = s->x;
32773 static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
32775 plugin_config *s = p->config_storage[0];
32777 - PATCH(request_header);
32778 - PATCH(response_header);
32779 - PATCH(environment);
32782 + PATCH_OPTION(request_header);
32783 + PATCH_OPTION(response_header);
32784 + PATCH_OPTION(environment);
32786 /* skip the first, the global context */
32787 for (i = 1; i < srv->config_context->used; i++) {
32788 data_config *dc = (data_config *)srv->config_context->data[i];
32789 s = p->config_storage[i];
32792 /* condition didn't match */
32793 if (!config_check_cond(srv, con, dc)) continue;
32797 for (j = 0; j < dc->value->used; j++) {
32798 data_unset *du = dc->value->data[j];
32801 if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
32802 - PATCH(request_header);
32803 + PATCH_OPTION(request_header);
32804 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
32805 - PATCH(response_header);
32806 + PATCH_OPTION(response_header);
32807 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
32808 - PATCH(environment);
32809 + PATCH_OPTION(environment);
32819 URIHANDLER_FUNC(mod_setenv_uri_handler) {
32820 plugin_data *p = p_d;
32825 if (con->plugin_ctx[p->id]) {
32826 hctx = con->plugin_ctx[p->id];
32828 hctx = handler_ctx_init();
32831 con->plugin_ctx[p->id] = hctx;
32834 @@ -180,52 +177,52 @@
32835 for (k = 0; k < p->conf.request_header->used; k++) {
32836 data_string *ds = (data_string *)p->conf.request_header->data[k];
32837 data_string *ds_dst;
32840 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
32841 ds_dst = data_string_init();
32845 buffer_copy_string_buffer(ds_dst->key, ds->key);
32846 buffer_copy_string_buffer(ds_dst->value, ds->value);
32849 array_insert_unique(con->request.headers, (data_unset *)ds_dst);
32853 for (k = 0; k < p->conf.environment->used; k++) {
32854 data_string *ds = (data_string *)p->conf.environment->data[k];
32855 data_string *ds_dst;
32858 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
32859 ds_dst = data_string_init();
32863 buffer_copy_string_buffer(ds_dst->key, ds->key);
32864 buffer_copy_string_buffer(ds_dst->value, ds->value);
32867 array_insert_unique(con->environment, (data_unset *)ds_dst);
32871 for (k = 0; k < p->conf.response_header->used; k++) {
32872 data_string *ds = (data_string *)p->conf.response_header->data[k];
32875 response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
32880 return HANDLER_GO_ON;
32883 REQUESTDONE_FUNC(mod_setenv_reset) {
32884 plugin_data *p = p_d;
32890 if (con->plugin_ctx[p->id]) {
32891 handler_ctx_free(con->plugin_ctx[p->id]);
32892 con->plugin_ctx[p->id] = NULL;
32895 - return HANDLER_GO_ON;
32896 + return HANDLER_GO_ON;
32899 /* this function is called at dlopen() time and inits the callbacks */
32900 @@ -233,15 +230,15 @@
32901 int mod_setenv_plugin_init(plugin *p) {
32902 p->version = LIGHTTPD_VERSION_ID;
32903 p->name = buffer_init_string("setenv");
32906 p->init = mod_setenv_init;
32907 p->handle_uri_clean = mod_setenv_uri_handler;
32908 p->set_defaults = mod_setenv_set_defaults;
32909 p->cleanup = mod_setenv_free;
32912 p->handle_request_done = mod_setenv_reset;
32919 --- lighttpd-1.4.11/src/mod_simple_vhost.c 2005-11-18 15:16:13.000000000 +0200
32920 +++ lighttpd-1.4.12/src/mod_simple_vhost.c 2006-07-11 22:07:52.000000000 +0300
32923 #include "plugin.h"
32925 +#include "sys-files.h"
32927 #ifdef HAVE_CONFIG_H
32928 #include "config.h"
32931 buffer *server_root;
32932 buffer *default_host;
32933 buffer *document_root;
32936 buffer *docroot_cache_key;
32937 buffer *docroot_cache_value;
32938 buffer *docroot_cache_servername;
32939 @@ -28,138 +30,138 @@
32948 plugin_config **config_storage;
32949 - plugin_config conf;
32950 + plugin_config conf;
32953 INIT_FUNC(mod_simple_vhost_init) {
32957 p = calloc(1, sizeof(*p));
32960 p->doc_root = buffer_init();
32966 FREE_FUNC(mod_simple_vhost_free) {
32967 plugin_data *p = p_d;
32972 if (!p) return HANDLER_GO_ON;
32975 if (p->config_storage) {
32977 for (i = 0; i < srv->config_context->used; i++) {
32978 plugin_config *s = p->config_storage[i];
32981 buffer_free(s->document_root);
32982 buffer_free(s->default_host);
32983 buffer_free(s->server_root);
32986 buffer_free(s->docroot_cache_key);
32987 buffer_free(s->docroot_cache_value);
32988 buffer_free(s->docroot_cache_servername);
32995 free(p->config_storage);
32999 buffer_free(p->doc_root);
33005 return HANDLER_GO_ON;
33008 SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
33009 plugin_data *p = p_d;
33012 - config_values_t cv[] = {
33014 + config_values_t cv[] = {
33015 { "simple-vhost.server-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33016 { "simple-vhost.default-host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33017 { "simple-vhost.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33018 { "simple-vhost.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
33019 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33023 if (!p) return HANDLER_ERROR;
33026 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33029 for (i = 0; i < srv->config_context->used; i++) {
33033 s = calloc(1, sizeof(plugin_config));
33036 s->server_root = buffer_init();
33037 s->default_host = buffer_init();
33038 s->document_root = buffer_init();
33041 s->docroot_cache_key = buffer_init();
33042 s->docroot_cache_value = buffer_init();
33043 s->docroot_cache_servername = buffer_init();
33048 cv[0].destination = s->server_root;
33049 cv[1].destination = s->default_host;
33050 cv[2].destination = s->document_root;
33051 cv[3].destination = &(s->debug);
33056 p->config_storage[i] = s;
33059 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33060 return HANDLER_ERROR;
33065 return HANDLER_GO_ON;
33068 static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
33069 stat_cache_entry *sce = NULL;
33072 buffer_prepare_copy(out, 128);
33074 if (p->conf.server_root->used) {
33075 buffer_copy_string_buffer(out, p->conf.server_root);
33079 /* a hostname has to start with a alpha-numerical character
33080 * and must not contain a slash "/"
33084 - BUFFER_APPEND_SLASH(out);
33087 + PATHNAME_APPEND_SLASH(out);
33089 if (NULL == (dp = strchr(host->ptr, ':'))) {
33090 buffer_append_string_buffer(out, host);
33092 buffer_append_string_len(out, host->ptr, dp - host->ptr);
33095 - BUFFER_APPEND_SLASH(out);
33097 + PATHNAME_APPEND_SLASH(out);
33099 if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
33100 buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
33102 buffer_append_string_buffer(out, p->conf.document_root);
33103 - BUFFER_APPEND_SLASH(out);
33104 + PATHNAME_APPEND_SLASH(out);
33107 buffer_copy_string_buffer(out, con->conf.document_root);
33108 - BUFFER_APPEND_SLASH(out);
33109 + PATHNAME_APPEND_SLASH(out);
33113 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
33114 if (p->conf.debug) {
33115 log_error_write(srv, __FILE__, __LINE__, "sb",
33116 @@ -169,57 +171,53 @@
33117 } else if (!S_ISDIR(sce->st.st_mode)) {
33126 -#define PATCH(x) \
33127 - p->conf.x = s->x;
33128 static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
33130 plugin_config *s = p->config_storage[0];
33132 - PATCH(server_root);
33133 - PATCH(default_host);
33134 - PATCH(document_root);
33136 - PATCH(docroot_cache_key);
33137 - PATCH(docroot_cache_value);
33138 - PATCH(docroot_cache_servername);
33142 + PATCH_OPTION(server_root);
33143 + PATCH_OPTION(default_host);
33144 + PATCH_OPTION(document_root);
33146 + PATCH_OPTION(docroot_cache_key);
33147 + PATCH_OPTION(docroot_cache_value);
33148 + PATCH_OPTION(docroot_cache_servername);
33150 + PATCH_OPTION(debug);
33152 /* skip the first, the global context */
33153 for (i = 1; i < srv->config_context->used; i++) {
33154 data_config *dc = (data_config *)srv->config_context->data[i];
33155 s = p->config_storage[i];
33158 /* condition didn't match */
33159 if (!config_check_cond(srv, con, dc)) continue;
33163 for (j = 0; j < dc->value->used; j++) {
33164 data_unset *du = dc->value->data[j];
33167 if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
33168 - PATCH(server_root);
33169 - PATCH(docroot_cache_key);
33170 - PATCH(docroot_cache_value);
33171 - PATCH(docroot_cache_servername);
33172 + PATCH_OPTION(server_root);
33173 + PATCH_OPTION(docroot_cache_key);
33174 + PATCH_OPTION(docroot_cache_value);
33175 + PATCH_OPTION(docroot_cache_servername);
33176 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
33177 - PATCH(default_host);
33178 + PATCH_OPTION(default_host);
33179 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
33180 - PATCH(document_root);
33181 + PATCH_OPTION(document_root);
33182 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
33184 + PATCH_OPTION(debug);
33194 static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
33195 plugin_data *p = p_data;
33196 @@ -227,12 +225,12 @@
33198 * cache the last successfull translation from hostname (authority) to docroot
33199 * - this saves us a stat() call
33205 mod_simple_vhost_patch_connection(srv, con, p);
33207 - if (p->conf.docroot_cache_key->used &&
33209 + if (p->conf.docroot_cache_key->used &&
33210 con->uri.authority->used &&
33211 buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
33213 @@ -243,8 +241,8 @@
33214 if ((con->uri.authority->used == 0) ||
33215 build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
33216 /* not found, fallback the default-host */
33217 - if (build_doc_root(srv, con, p,
33219 + if (build_doc_root(srv, con, p,
33221 p->conf.default_host)) {
33222 return HANDLER_GO_ON;
33224 @@ -253,15 +251,15 @@
33226 buffer_copy_string_buffer(con->server_name, con->uri.authority);
33230 /* copy to cache */
33231 buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority);
33232 buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root);
33233 buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
33236 buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
33240 return HANDLER_GO_ON;
33243 @@ -269,13 +267,13 @@
33244 int mod_simple_vhost_plugin_init(plugin *p) {
33245 p->version = LIGHTTPD_VERSION_ID;
33246 p->name = buffer_init_string("simple_vhost");
33249 p->init = mod_simple_vhost_init;
33250 p->set_defaults = mod_simple_vhost_set_defaults;
33251 p->handle_docroot = mod_simple_vhost_docroot;
33252 p->cleanup = mod_simple_vhost_free;
33260 --- lighttpd-1.4.11/src/mod_skeleton.c 2005-10-02 18:30:51.000000000 +0300
33261 +++ lighttpd-1.4.12/src/mod_skeleton.c 2006-07-11 22:07:51.000000000 +0300
33262 @@ -14,13 +14,13 @@
33265 * this is a skeleton for a lighttpd plugin
33268 * just replaces every occurance of 'skeleton' by your plugin name
33274 * :%s/skeleton/myhandler/
33280 @@ -33,12 +33,12 @@
33289 plugin_config **config_storage;
33291 - plugin_config conf;
33293 + plugin_config conf;
33297 @@ -47,36 +47,36 @@
33299 static handler_ctx * handler_ctx_init() {
33300 handler_ctx * hctx;
33303 hctx = calloc(1, sizeof(*hctx));
33309 static void handler_ctx_free(handler_ctx *hctx) {
33315 /* init the plugin data */
33316 INIT_FUNC(mod_skeleton_init) {
33320 p = calloc(1, sizeof(*p));
33323 p->match_buf = buffer_init();
33329 /* detroy the plugin data */
33330 FREE_FUNC(mod_skeleton_free) {
33331 plugin_data *p = p_d;
33336 if (!p) return HANDLER_GO_ON;
33339 if (p->config_storage) {
33342 @@ -84,18 +84,18 @@
33343 plugin_config *s = p->config_storage[i];
33348 array_free(s->match);
33353 free(p->config_storage);
33357 buffer_free(p->match_buf);
33363 return HANDLER_GO_ON;
33366 @@ -104,91 +104,88 @@
33367 SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
33368 plugin_data *p = p_d;
33371 - config_values_t cv[] = {
33373 + config_values_t cv[] = {
33374 { "skeleton.array", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
33375 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33379 if (!p) return HANDLER_ERROR;
33382 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33385 for (i = 0; i < srv->config_context->used; i++) {
33389 s = calloc(1, sizeof(plugin_config));
33390 s->match = array_init();
33393 cv[0].destination = s->match;
33396 p->config_storage[i] = s;
33399 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33400 return HANDLER_ERROR;
33405 return HANDLER_GO_ON;
33408 -#define PATCH(x) \
33409 - p->conf.x = s->x;
33410 static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
33412 plugin_config *s = p->config_storage[0];
33417 + PATCH_OPTION(match);
33419 /* skip the first, the global context */
33420 for (i = 1; i < srv->config_context->used; i++) {
33421 data_config *dc = (data_config *)srv->config_context->data[i];
33422 s = p->config_storage[i];
33425 /* condition didn't match */
33426 if (!config_check_cond(srv, con, dc)) continue;
33430 for (j = 0; j < dc->value->used; j++) {
33431 data_unset *du = dc->value->data[j];
33434 if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
33436 + PATCH_OPTION(match);
33446 URIHANDLER_FUNC(mod_skeleton_uri_handler) {
33447 plugin_data *p = p_d;
33454 if (con->uri.path->used == 0) return HANDLER_GO_ON;
33457 mod_skeleton_patch_connection(srv, con, p);
33459 s_len = con->uri.path->used - 1;
33462 for (k = 0; k < p->conf.match->used; k++) {
33463 data_string *ds = (data_string *)p->conf.match->data[k];
33464 int ct_len = ds->value->used - 1;
33467 if (ct_len > s_len) continue;
33468 if (ds->value->used == 0) continue;
33471 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
33472 con->http_status = 403;
33475 return HANDLER_FINISHED;
33481 return HANDLER_GO_ON;
33483 @@ -198,13 +195,13 @@
33484 int mod_skeleton_plugin_init(plugin *p) {
33485 p->version = LIGHTTPD_VERSION_ID;
33486 p->name = buffer_init_string("skeleton");
33489 p->init = mod_skeleton_init;
33490 p->handle_uri_clean = mod_skeleton_uri_handler;
33491 p->set_defaults = mod_skeleton_set_defaults;
33492 p->cleanup = mod_skeleton_free;
33500 --- lighttpd-1.4.11/src/mod_sql_vhost_core.c 1970-01-01 03:00:00.000000000 +0300
33501 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.c 2006-07-11 22:07:53.000000000 +0300
33503 +#include <stdio.h>
33504 +#include <errno.h>
33505 +#include <fcntl.h>
33506 +#include <string.h>
33508 +#ifdef HAVE_CONFIG_H
33509 +#include "config.h"
33512 +#include "plugin.h"
33515 +#include "stat_cache.h"
33517 +#include "mod_sql_vhost_core.h"
33519 +#define plugin_data mod_sql_vhost_core_plugin_data
33520 +#define plugin_config mod_sql_vhost_core_plugin_config
33522 +/* init the plugin data */
33523 +INIT_FUNC(mod_sql_vhost_core_init) {
33526 + p = calloc(1, sizeof(*p));
33528 + p->docroot = buffer_init();
33529 + p->host = buffer_init();
33534 +/* cleanup the plugin data */
33535 +SERVER_FUNC(mod_sql_vhost_core_cleanup) {
33536 + plugin_data *p = p_d;
33540 + if (!p) return HANDLER_GO_ON;
33542 + if (p->config_storage) {
33544 + for (i = 0; i < srv->config_context->used; i++) {
33545 + plugin_config *s = p->config_storage[i];
33547 + if (!s) continue;
33549 + buffer_free(s->db);
33550 + buffer_free(s->user);
33551 + buffer_free(s->pass);
33552 + buffer_free(s->sock);
33553 + buffer_free(s->backend);
33557 + free(p->config_storage);
33559 + buffer_free(p->docroot);
33560 + buffer_free(p->host);
33564 + return HANDLER_GO_ON;
33567 +/* set configuration values */
33568 +SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
33569 + plugin_data *p = p_d;
33573 + config_values_t cv[] = {
33574 + { "sql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
33575 + { "sql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
33576 + { "sql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
33577 + { "sql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
33578 + { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
33579 + { "sql-vhost.hostname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
33580 + { "sql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
33581 + { "sql-vhost.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
33583 + /* backward compat */
33584 + { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
33585 + { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
33586 + { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
33587 + { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
33588 + { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
33589 + { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
33590 + { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
33592 + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33595 + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33597 + for (i = 0; i < srv->config_context->used; i++) {
33598 + plugin_config *s;
33600 + s = calloc(1, sizeof(plugin_config));
33601 + s->db = buffer_init();
33602 + s->user = buffer_init();
33603 + s->pass = buffer_init();
33604 + s->sock = buffer_init();
33605 + s->hostname = buffer_init();
33606 + s->backend = buffer_init();
33607 + s->port = 0; /* default port for mysql */
33608 + s->select_vhost = buffer_init();
33609 + s->backend_data = NULL;
33611 + cv[0].destination = s->db;
33612 + cv[1].destination = s->user;
33613 + cv[2].destination = s->pass;
33614 + cv[3].destination = s->sock;
33615 + cv[4].destination = s->select_vhost;
33616 + cv[5].destination = s->hostname;
33617 + cv[6].destination = &(s->port);
33618 + cv[7].destination = s->backend;
33620 + /* backend compat */
33621 + cv[8].destination = cv[0].destination;
33622 + cv[9].destination = cv[1].destination;
33623 + cv[10].destination = cv[2].destination;
33624 + cv[11].destination = cv[3].destination;
33625 + cv[12].destination = cv[4].destination;
33626 + cv[13].destination = cv[5].destination;
33627 + cv[14].destination = cv[6].destination;
33629 + p->config_storage[i] = s;
33631 + if (config_insert_values_global(srv,
33632 + ((data_config *)srv->config_context->data[i])->value,
33633 + cv)) return HANDLER_ERROR;
33635 + /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
33638 + return HANDLER_GO_ON;
33641 +static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
33643 + plugin_config *s = p->config_storage[0];
33645 + PATCH_OPTION(backend_data);
33646 + PATCH_OPTION(get_vhost);
33648 + /* skip the first, the global context */
33649 + for (i = 1; i < srv->config_context->used; i++) {
33650 + data_config *dc = (data_config *)srv->config_context->data[i];
33651 + s = p->config_storage[i];
33653 + /* condition didn't match */
33654 + if (!config_check_cond(srv, con, dc)) continue;
33656 + if (s->backend_data) {
33657 + PATCH_OPTION(backend_data);
33658 + PATCH_OPTION(get_vhost);
33665 +/* handle document root request */
33666 +CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
33667 + plugin_data *p = p_d;
33668 + stat_cache_entry *sce;
33670 + /* no host specified? */
33671 + if (!con->uri.authority->used) return HANDLER_GO_ON;
33673 + mod_sql_vhost_core_patch_connection(srv, con, p);
33675 + /* do we have backend ? */
33676 + if (!p->conf.get_vhost) return HANDLER_GO_ON;
33678 + /* ask the backend for the data */
33679 + if (0 != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
33680 + return HANDLER_GO_ON;
33683 + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
33684 + log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->docroot);
33685 + return HANDLER_GO_ON;
33687 + if (!S_ISDIR(sce->st.st_mode)) {
33688 + log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->docroot);
33689 + return HANDLER_GO_ON;
33692 + buffer_copy_string_buffer(con->server_name, p->host);
33693 + buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
33695 + return HANDLER_GO_ON;
33698 +/* this function is called at dlopen() time and inits the callbacks */
33699 +int mod_sql_vhost_core_plugin_init(plugin *p) {
33700 + p->version = LIGHTTPD_VERSION_ID;
33701 + p->name = buffer_init_string("mod_sql_vhost_core");
33703 + p->init = mod_sql_vhost_core_init;
33704 + p->cleanup = mod_sql_vhost_core_cleanup;
33706 + p->set_defaults = mod_sql_vhost_core_set_defaults;
33707 + p->handle_docroot = mod_sql_vhost_core_handle_docroot;
33712 --- lighttpd-1.4.11/src/mod_sql_vhost_core.h 1970-01-01 03:00:00.000000000 +0300
33713 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.h 2006-07-11 22:07:53.000000000 +0300
33715 +#ifndef _MOD_SQL_VHOST_CORE_H_
33716 +#define _MOD_SQL_VHOST_CORE_H_
33718 +#include "buffer.h"
33719 +#include "plugin.h"
33721 +#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
33722 + (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
33724 +#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
33726 +#define SQLVHOST_BACKEND_GETVHOST(name) \
33727 + SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
33729 +#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
33730 + SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
33738 + buffer *hostname;
33739 + unsigned short port;
33742 + void *backend_data;
33744 + buffer *select_vhost;
33746 + SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
33747 +} mod_sql_vhost_core_plugin_config;
33749 +/* global plugin data */
33756 + mod_sql_vhost_core_plugin_config **config_storage;
33758 + mod_sql_vhost_core_plugin_config conf;
33759 +} mod_sql_vhost_core_plugin_data;
33764 --- lighttpd-1.4.11/src/mod_ssi.c 2006-03-04 17:09:48.000000000 +0200
33765 +++ lighttpd-1.4.12/src/mod_ssi.c 2006-07-11 22:07:53.000000000 +0300
33767 #include <string.h>
33770 -#include <unistd.h>
33775 #include "inet_ntop_cache.h"
33777 #include "sys-socket.h"
33778 +#include "sys-strings.h"
33779 +#include "sys-files.h"
33783 @@ -39,15 +40,15 @@
33784 /* init the plugin data */
33785 INIT_FUNC(mod_ssi_init) {
33789 p = calloc(1, sizeof(*p));
33792 p->timefmt = buffer_init();
33793 p->stat_fn = buffer_init();
33796 p->ssi_vars = array_init();
33797 p->ssi_cgi_env = array_init();
33803 @@ -55,21 +56,21 @@
33804 FREE_FUNC(mod_ssi_free) {
33805 plugin_data *p = p_d;
33809 if (!p) return HANDLER_GO_ON;
33812 if (p->config_storage) {
33814 for (i = 0; i < srv->config_context->used; i++) {
33815 plugin_config *s = p->config_storage[i];
33818 array_free(s->ssi_extension);
33823 free(p->config_storage);
33827 array_free(p->ssi_vars);
33828 array_free(p->ssi_cgi_env);
33832 buffer_free(p->timefmt);
33833 buffer_free(p->stat_fn);
33839 return HANDLER_GO_ON;
33842 @@ -92,36 +93,36 @@
33843 const char *errptr;
33847 - config_values_t cv[] = {
33849 + config_values_t cv[] = {
33850 { "ssi.extension", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
33851 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33855 if (!p) return HANDLER_ERROR;
33858 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33861 for (i = 0; i < srv->config_context->used; i++) {
33865 s = calloc(1, sizeof(plugin_config));
33866 s->ssi_extension = array_init();
33869 cv[0].destination = s->ssi_extension;
33872 p->config_storage[i] = s;
33875 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33876 return HANDLER_ERROR;
33882 /* allow 2 params */
33883 if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
33884 log_error_write(srv, __FILE__, __LINE__, "sds",
33888 return HANDLER_ERROR;
33890 @@ -130,52 +131,52 @@
33891 "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
33892 return HANDLER_ERROR;
33896 return HANDLER_GO_ON;
33899 int ssi_env_add(array *env, const char *key, const char *val) {
33903 if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
33904 ds = data_string_init();
33906 buffer_copy_string(ds->key, key);
33907 buffer_copy_string(ds->value, val);
33910 array_insert_unique(env, (data_unset *)ds);
33918 * the next two functions are take from fcgi.c
33923 static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
33927 for (i = 0; i < con->request.headers->used; i++) {
33931 ds = (data_string *)con->request.headers->data[i];
33934 if (ds->value->used && ds->key->used) {
33936 buffer_reset(srv->tmp_buf);
33939 /* don't forward the Authorization: Header */
33940 if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
33945 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
33946 buffer_copy_string(srv->tmp_buf, "HTTP_");
33947 srv->tmp_buf->used--;
33951 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
33952 for (j = 0; j < ds->key->used - 1; j++) {
33954 @@ -189,33 +190,33 @@
33955 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
33957 srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
33960 ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
33968 static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
33972 server_socket *srv_sock = con->srv_socket;
33976 char b2[INET6_ADDRSTRLEN + 1];
33979 #define CONST_STRING(x) \
33983 array_reset(p->ssi_cgi_env);
33986 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
33987 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
33989 - inet_ntop(srv_sock->addr.plain.sa_family,
33990 - srv_sock->addr.plain.sa_family == AF_INET6 ?
33991 + inet_ntop(srv_sock->addr.plain.sa_family,
33992 + srv_sock->addr.plain.sa_family == AF_INET6 ?
33993 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
33994 (const void *) &(srv_sock->addr.ipv4.sin_addr),
33996 @@ -224,28 +225,28 @@
33999 ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
34005 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
34007 ntohs(srv_sock->addr.ipv4.sin_port)
34012 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
34015 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
34016 inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
34019 if (con->authed_user->used) {
34020 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
34021 con->authed_user->ptr);
34025 if (con->request.content_length > 0) {
34026 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
34029 /* request.content_length < SSIZE_MAX, see request.c */
34030 ltostr(buf, con->request.content_length);
34031 ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
34032 @@ -271,30 +272,30 @@
34033 if (con->request.pathinfo->used) {
34034 ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
34038 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
34039 ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
34042 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
34043 ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
34044 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
34045 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
34046 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
34049 ssi_env_add_request_headers(srv, con, p);
34055 -static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
34056 +static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
34057 const char **l, size_t n) {
34058 size_t i, ssicmd = 0;
34066 - enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
34067 + enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
34068 SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
34069 SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
34071 @@ -310,27 +311,27 @@
34072 { "endif", SSI_ENDIF },
34073 { "else", SSI_ELSE },
34074 { "exec", SSI_EXEC },
34077 { NULL, SSI_UNSET }
34081 for (i = 0; ssicmds[i].var; i++) {
34082 if (0 == strcmp(l[1], ssicmds[i].var)) {
34083 ssicmd = ssicmds[i].type;
34092 int var = 0, enc = 0;
34093 const char *var_val = NULL;
34094 stat_cache_entry *sce = NULL;
34100 - enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
34101 + enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
34102 SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
34104 { "DATE_GMT", SSI_ECHO_DATE_GMT },
34105 @@ -339,27 +340,27 @@
34106 { "DOCUMENT_URI", SSI_ECHO_DOCUMENT_URI },
34107 { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
34108 { "USER_NAME", SSI_ECHO_USER_NAME },
34111 { NULL, SSI_ECHO_UNSET }
34118 enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
34120 { "url", SSI_ENC_URL },
34121 { "none", SSI_ENC_NONE },
34122 { "entity", SSI_ENC_ENTITY },
34125 { NULL, SSI_ENC_UNSET }
34129 for (i = 2; i < n; i += 2) {
34130 if (0 == strcmp(l[i], "var")) {
34137 for (j = 0; echovars[j].var; j++) {
34138 if (0 == strcmp(l[i+1], echovars[j].var)) {
34139 var = echovars[j].type;
34140 @@ -368,7 +369,7 @@
34142 } else if (0 == strcmp(l[i], "encoding")) {
34146 for (j = 0; encvars[j].var; j++) {
34147 if (0 == strcmp(l[i+1], encvars[j].var)) {
34148 enc = encvars[j].type;
34149 @@ -377,26 +378,26 @@
34152 log_error_write(srv, __FILE__, __LINE__, "sss",
34153 - "ssi: unknow attribute for ",
34154 + "ssi: unknow attribute for ",
34160 if (p->if_is_false) break;
34164 log_error_write(srv, __FILE__, __LINE__, "sss",
34167 l[1], "var is missing");
34171 stat_cache_get_entry(srv, con, con->physical.path, &sce);
34175 case SSI_ECHO_USER_NAME: {
34179 b = chunkqueue_get_append_buffer(con->write_queue);
34181 if (NULL == (pw = getpwuid(sce->st.st_uid))) {
34182 @@ -411,7 +412,7 @@
34184 case SSI_ECHO_LAST_MODIFIED: {
34185 time_t t = sce->st.st_mtime;
34188 b = chunkqueue_get_append_buffer(con->write_queue);
34189 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34190 buffer_copy_string(b, "(none)");
34191 @@ -422,7 +423,7 @@
34193 case SSI_ECHO_DATE_LOCAL: {
34194 time_t t = time(NULL);
34197 b = chunkqueue_get_append_buffer(con->write_queue);
34198 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34199 buffer_copy_string(b, "(none)");
34200 @@ -433,7 +434,7 @@
34202 case SSI_ECHO_DATE_GMT: {
34203 time_t t = time(NULL);
34206 b = chunkqueue_get_append_buffer(con->write_queue);
34207 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
34208 buffer_copy_string(b, "(none)");
34209 @@ -444,7 +445,7 @@
34211 case SSI_ECHO_DOCUMENT_NAME: {
34215 b = chunkqueue_get_append_buffer(con->write_queue);
34216 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34217 buffer_copy_string_buffer(b, con->physical.path);
34218 @@ -461,15 +462,15 @@
34221 /* check if it is a cgi-var */
34224 b = chunkqueue_get_append_buffer(con->write_queue);
34227 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
34228 buffer_copy_string_buffer(b, ds->value);
34230 buffer_copy_string(b, "(none)");
34237 @@ -481,7 +482,7 @@
34238 const char * file_path = NULL, *virt_path = NULL;
34243 for (i = 2; i < n; i += 2) {
34244 if (0 == strcmp(l[i], "file")) {
34245 file_path = l[i+1];
34246 @@ -489,28 +490,28 @@
34247 virt_path = l[i+1];
34249 log_error_write(srv, __FILE__, __LINE__, "sss",
34250 - "ssi: unknow attribute for ",
34251 + "ssi: unknow attribute for ",
34257 if (!file_path && !virt_path) {
34258 log_error_write(srv, __FILE__, __LINE__, "sss",
34261 l[1], "file or virtual are missing");
34266 if (file_path && virt_path) {
34267 log_error_write(srv, __FILE__, __LINE__, "sss",
34270 l[1], "only one of file and virtual is allowed here");
34277 if (p->if_is_false) break;
34281 /* current doc-root */
34282 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34283 @@ -519,46 +520,46 @@
34284 buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
34287 - buffer_copy_string(srv->tmp_buf, file_path);
34288 + buffer_copy_string(srv->tmp_buf, file_path);
34289 buffer_urldecode_path(srv->tmp_buf);
34290 - buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
34291 - buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34292 + buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
34293 + buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34298 if (virt_path[0] == '/') {
34299 buffer_copy_string(p->stat_fn, virt_path);
34301 /* there is always a / */
34302 sl = strrchr(con->uri.path->ptr, '/');
34305 buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
34306 buffer_append_string(p->stat_fn, virt_path);
34310 buffer_urldecode_path(p->stat_fn);
34311 buffer_path_simplify(srv->tmp_buf, p->stat_fn);
34314 /* we have an uri */
34317 buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
34318 buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34322 if (0 == stat(p->stat_fn->ptr, &st)) {
34323 time_t t = st.st_mtime;
34328 b = chunkqueue_get_append_buffer(con->write_queue);
34331 const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
34334 off_t s = st.st_size;
34337 for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
34340 buffer_copy_off_t(b, s);
34341 buffer_append_string(b, abr[j]);
34343 @@ -579,7 +580,7 @@
34346 log_error_write(srv, __FILE__, __LINE__, "sbs",
34347 - "ssi: stating failed ",
34348 + "ssi: stating failed ",
34349 p->stat_fn, strerror(errno));
34352 @@ -593,33 +594,33 @@
34355 log_error_write(srv, __FILE__, __LINE__, "sss",
34356 - "ssi: unknow attribute for ",
34357 + "ssi: unknow attribute for ",
34363 if (p->if_is_false) break;
34370 if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
34371 ds = data_string_init();
34373 buffer_copy_string(ds->key, key);
34374 buffer_copy_string(ds->value, val);
34377 array_insert_unique(p->ssi_vars, (data_unset *)ds);
34379 log_error_write(srv, __FILE__, __LINE__, "sss",
34380 - "ssi: var and value have to be set in",
34381 + "ssi: var and value have to be set in",
34388 if (p->if_is_false) break;
34391 for (i = 2; i < n; i += 2) {
34392 if (0 == strcmp(l[i], "timefmt")) {
34393 buffer_copy_string(p->timefmt, l[i+1]);
34394 @@ -632,63 +633,65 @@
34395 log_error_write(srv, __FILE__, __LINE__, "sssss",
34396 "ssi: unknow value for attribute '",
34403 log_error_write(srv, __FILE__, __LINE__, "sss",
34404 - "ssi: unknow attribute for ",
34405 + "ssi: unknow attribute for ",
34411 if (p->if_is_false) break;
34414 b = chunkqueue_get_append_buffer(con->write_queue);
34415 buffer_copy_string(b, "<pre>");
34416 for (i = 0; i < p->ssi_vars->used; i++) {
34417 data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
34420 buffer_append_string_buffer(b, ds->key);
34421 buffer_append_string(b, ": ");
34422 buffer_append_string_buffer(b, ds->value);
34423 buffer_append_string(b, "<br />");
34427 buffer_append_string(b, "</pre>");
34434 const char *cmd = NULL;
34436 int from_exec_fds[2];
34439 for (i = 2; i < n; i += 2) {
34440 if (0 == strcmp(l[i], "cmd")) {
34443 log_error_write(srv, __FILE__, __LINE__, "sss",
34444 - "ssi: unknow attribute for ",
34445 + "ssi: unknow attribute for ",
34451 if (p->if_is_false) break;
34454 /* create a return pipe and send output to the html-page
34456 - * as exec is assumed evil it is implemented synchronously
34458 + * as exec is assumed evil it is implemented synchronously
34465 if (pipe(from_exec_fds)) {
34466 - log_error_write(srv, __FILE__, __LINE__, "ss",
34467 + log_error_write(srv, __FILE__, __LINE__, "ss",
34468 "pipe failed: ", strerror(errno));
34474 switch (pid = fork()) {
34476 @@ -698,14 +701,14 @@
34477 close(from_exec_fds[1]);
34479 close(from_exec_fds[0]);
34483 close(STDIN_FILENO);
34486 execl("/bin/sh", "sh", "-c", cmd, NULL);
34489 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
34495 @@ -718,9 +721,9 @@
34501 close(from_exec_fds[1]);
34504 /* wait for the client to end */
34505 if (-1 == waitpid(pid, &status, 0)) {
34506 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
34507 @@ -730,7 +733,7 @@
34510 if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
34511 - log_error_write(srv, __FILE__, __LINE__, "s",
34512 + log_error_write(srv, __FILE__, __LINE__, "s",
34513 "unexpected end-of-file (perhaps the ssi-exec process died)");
34516 @@ -738,10 +741,10 @@
34518 b = chunkqueue_get_append_buffer(con->write_queue);
34520 - buffer_prepare_copy(b, toread + 1);
34521 + buffer_prepare_copy(b, toread + 1);
34523 if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
34524 - /* read failed */
34525 + /* read failed */
34529 @@ -755,59 +758,58 @@
34530 log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
34532 close(from_exec_fds[0]);
34547 const char *expr = NULL;
34550 for (i = 2; i < n; i += 2) {
34551 if (0 == strcmp(l[i], "expr")) {
34554 log_error_write(srv, __FILE__, __LINE__, "sss",
34555 - "ssi: unknow attribute for ",
34556 + "ssi: unknow attribute for ",
34563 log_error_write(srv, __FILE__, __LINE__, "sss",
34566 l[1], "expr missing");
34571 if ((!p->if_is_false) &&
34572 - ((p->if_is_false_level == 0) ||
34573 + ((p->if_is_false_level == 0) ||
34574 (p->if_level < p->if_is_false_level))) {
34575 switch (ssi_eval_expr(srv, con, p, expr)) {
34578 - p->if_is_false = 1;
34580 + p->if_is_false = 1;
34581 p->if_is_false_level = p->if_level;
34584 - p->if_is_false = 0;
34586 + p->if_is_false = 0;
34601 if (p->if_is_false) {
34602 if ((p->if_level == p->if_is_false_level) &&
34603 (p->if_is_false_endif == 0)) {
34604 @@ -815,11 +817,11 @@
34607 p->if_is_false = 1;
34610 p->if_is_false_level = p->if_level;
34617 const char *expr = NULL;
34618 @@ -828,52 +830,52 @@
34621 log_error_write(srv, __FILE__, __LINE__, "sss",
34622 - "ssi: unknow attribute for ",
34623 + "ssi: unknow attribute for ",
34630 log_error_write(srv, __FILE__, __LINE__, "sss",
34633 l[1], "expr missing");
34641 if (p->if_level == p->if_is_false_level) {
34642 if ((p->if_is_false) &&
34643 (p->if_is_false_endif == 0)) {
34644 switch (ssi_eval_expr(srv, con, p, expr)) {
34647 - p->if_is_false = 1;
34649 + p->if_is_false = 1;
34650 p->if_is_false_level = p->if_level;
34653 - p->if_is_false = 0;
34655 + p->if_is_false = 0;
34659 - p->if_is_false = 1;
34660 + p->if_is_false = 1;
34661 p->if_is_false_level = p->if_level;
34662 p->if_is_false_endif = 1;
34676 if (p->if_level == p->if_is_false_level) {
34677 p->if_is_false = 0;
34678 p->if_is_false_endif = 0;
34684 log_error_write(srv, __FILE__, __LINE__, "ss",
34685 @@ -881,41 +883,41 @@
34696 static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
34707 /* get a stream to the file */
34710 array_reset(p->ssi_vars);
34711 array_reset(p->ssi_cgi_env);
34712 buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z");
34714 build_ssi_cgi_vars(srv, con, p);
34715 p->if_is_false = 0;
34718 if (-1 == stream_open(&s, con->physical.path)) {
34719 log_error_write(srv, __FILE__, __LINE__, "sb",
34720 "stream-open: ", con->physical.path);
34728 - * <!--#element attribute=value attribute=value ... -->
34730 + * <!--#element attribute=value attribute=value ... -->
34733 - * errmsg -- missing
34734 + * errmsg -- missing
34738 @@ -937,13 +939,13 @@
34755 @@ -951,118 +953,115 @@
34767 - * The current date in Greenwich Mean Time.
34769 - * The current date in the local time zone.
34771 - * The filename (excluding directories) of the document requested by the user.
34773 - * The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document.
34775 - * The last modification date of the document requested by the user.
34778 + * The current date in Greenwich Mean Time.
34780 + * The current date in the local time zone.
34782 + * The filename (excluding directories) of the document requested by the user.
34784 + * The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document.
34786 + * The last modification date of the document requested by the user.
34788 * Contains the owner of the file which included it.
34792 -#ifdef HAVE_PCRE_H
34793 +#ifdef HAVE_PCRE_H
34794 for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
34796 /* take everything from last offset to current match pos */
34799 if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
34802 pcre_get_substring_list(s.start, ovec, n, &l);
34803 process_ssi_stmt(srv, con, p, l, n);
34804 pcre_free_substring_list(l);
34809 case PCRE_ERROR_NOMATCH:
34810 /* copy everything/the rest */
34811 chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
34816 log_error_write(srv, __FILE__, __LINE__, "sd",
34817 "execution error while matching: ", n);
34829 con->file_started = 1;
34830 con->file_finished = 1;
34833 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
34836 /* reset physical.path */
34837 buffer_reset(con->physical.path);
34843 -#define PATCH(x) \
34844 - p->conf.x = s->x;
34845 static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
34847 plugin_config *s = p->config_storage[0];
34849 - PATCH(ssi_extension);
34852 + PATCH_OPTION(ssi_extension);
34854 /* skip the first, the global context */
34855 for (i = 1; i < srv->config_context->used; i++) {
34856 data_config *dc = (data_config *)srv->config_context->data[i];
34857 s = p->config_storage[i];
34860 /* condition didn't match */
34861 if (!config_check_cond(srv, con, dc)) continue;
34865 for (j = 0; j < dc->value->used; j++) {
34866 data_unset *du = dc->value->data[j];
34869 if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
34870 - PATCH(ssi_extension);
34871 + PATCH_OPTION(ssi_extension);
34881 URIHANDLER_FUNC(mod_ssi_physical_path) {
34882 plugin_data *p = p_d;
34886 if (con->physical.path->used == 0) return HANDLER_GO_ON;
34889 mod_ssi_patch_connection(srv, con, p);
34892 for (k = 0; k < p->conf.ssi_extension->used; k++) {
34893 data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
34896 if (ds->value->used == 0) continue;
34899 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
34900 /* handle ssi-request */
34903 if (mod_ssi_handle_request(srv, con, p)) {
34905 con->http_status = 500;
34909 return HANDLER_FINISHED;
34915 return HANDLER_GO_ON;
34917 @@ -1072,13 +1071,13 @@
34918 int mod_ssi_plugin_init(plugin *p) {
34919 p->version = LIGHTTPD_VERSION_ID;
34920 p->name = buffer_init_string("ssi");
34923 p->init = mod_ssi_init;
34924 p->handle_subrequest_start = mod_ssi_physical_path;
34925 p->set_defaults = mod_ssi_set_defaults;
34926 p->cleanup = mod_ssi_free;
34934 --- lighttpd-1.4.11/src/mod_ssi.h 2005-08-11 01:26:39.000000000 +0300
34935 +++ lighttpd-1.4.12/src/mod_ssi.h 2006-07-11 22:07:53.000000000 +0300
34936 @@ -19,23 +19,23 @@
34941 -#ifdef HAVE_PCRE_H
34943 +#ifdef HAVE_PCRE_H
34955 array *ssi_cgi_env;
34958 int if_level, if_is_false_level, if_is_false, if_is_false_endif;
34961 plugin_config **config_storage;
34963 - plugin_config conf;
34965 + plugin_config conf;
34968 int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
34969 --- lighttpd-1.4.11/src/mod_ssi_expr.c 2005-08-11 01:26:48.000000000 +0300
34970 +++ lighttpd-1.4.12/src/mod_ssi_expr.c 2006-07-11 22:07:52.000000000 +0300
34983 @@ -21,15 +21,15 @@
34985 ssi_val_t *ssi_val_init() {
34989 s = calloc(1, sizeof(*s));
34995 void ssi_val_free(ssi_val_t *s) {
34996 if (s->str) buffer_free(s->str);
35002 @@ -45,175 +45,175 @@
35003 ssi_tokenizer_t *t, int *token_id, buffer *token) {
35010 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
35011 char c = t->input[t->offset];
35025 buffer_copy_string(token, "(=)");
35030 if (t->input[t->offset + 1] == '=') {
35038 buffer_copy_string(token, "(>=)");
35047 buffer_copy_string(token, "(>)");
35053 if (t->input[t->offset + 1] == '=') {
35061 buffer_copy_string(token, "(<=)");
35070 buffer_copy_string(token, "(<)");
35078 if (t->input[t->offset + 1] == '=') {
35086 buffer_copy_string(token, "(!=)");
35095 buffer_copy_string(token, "(!)");
35101 if (t->input[t->offset + 1] == '&') {
35109 buffer_copy_string(token, "(&&)");
35111 - log_error_write(srv, __FILE__, __LINE__, "sds",
35112 - "pos:", t->line_pos,
35113 + log_error_write(srv, __FILE__, __LINE__, "sds",
35114 + "pos:", t->line_pos,
35115 "missing second &");
35122 if (t->input[t->offset + 1] == '|') {
35130 buffer_copy_string(token, "(||)");
35132 - log_error_write(srv, __FILE__, __LINE__, "sds",
35133 - "pos:", t->line_pos,
35134 + log_error_write(srv, __FILE__, __LINE__, "sds",
35135 + "pos:", t->line_pos,
35136 "missing second |");
35150 /* search for the terminating " */
35151 for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
35154 if (t->input[t->offset + i]) {
35158 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35161 t->offset += i + 1;
35162 t->line_pos += i + 1;
35166 - log_error_write(srv, __FILE__, __LINE__, "sds",
35167 - "pos:", t->line_pos,
35169 + log_error_write(srv, __FILE__, __LINE__, "sds",
35170 + "pos:", t->line_pos,
35171 "missing closing quote");
35187 buffer_copy_string(token, "(");
35197 buffer_copy_string(token, ")");
35200 if (t->input[t->offset + 1] == '{') {
35201 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
35204 if (t->input[t->offset + i] != '}') {
35205 - log_error_write(srv, __FILE__, __LINE__, "sds",
35206 - "pos:", t->line_pos,
35207 + log_error_write(srv, __FILE__, __LINE__, "sds",
35208 + "pos:", t->line_pos,
35209 "missing closing quote");
35216 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
35218 for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_'; i++);
35221 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35228 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
35229 buffer_copy_string_buffer(token, ds->value);
35230 } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
35231 @@ -221,16 +221,16 @@
35233 buffer_copy_string(token, "");
35243 for (i = 0; isgraph(t->input[t->offset + i]); i++) {
35244 char d = t->input[t->offset + i];
35251 @@ -244,25 +244,25 @@
35260 buffer_copy_string_len(token, t->input + t->offset, i);
35277 } else if (t->offset < t->size) {
35278 - log_error_write(srv, __FILE__, __LINE__, "sds",
35279 - "pos:", t->line_pos,
35280 + log_error_write(srv, __FILE__, __LINE__, "sds",
35281 + "pos:", t->line_pos,
35285 @@ -275,50 +275,50 @@
35293 t.size = strlen(expr);
35306 /* default context */
35309 pParser = ssiexprparserAlloc( malloc );
35310 token = buffer_init();
35311 while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
35312 ssiexprparser(pParser, token_id, token, &context);
35315 token = buffer_init();
35317 ssiexprparser(pParser, 0, token, &context);
35318 ssiexprparserFree(pParser, free );
35321 buffer_free(token);
35325 - log_error_write(srv, __FILE__, __LINE__, "s",
35326 + log_error_write(srv, __FILE__, __LINE__, "s",
35327 "expr parser failed");
35332 if (context.ok == 0) {
35333 - log_error_write(srv, __FILE__, __LINE__, "sds",
35334 - "pos:", t.line_pos,
35335 + log_error_write(srv, __FILE__, __LINE__, "sds",
35336 + "pos:", t.line_pos,
35337 "parser failed somehow near here");
35341 - log_error_write(srv, __FILE__, __LINE__, "ssd",
35342 + log_error_write(srv, __FILE__, __LINE__, "ssd",
35348 return context.val.bo;
35350 --- lighttpd-1.4.11/src/mod_ssi_expr.h 2005-08-11 01:26:48.000000000 +0300
35351 +++ lighttpd-1.4.12/src/mod_ssi_expr.h 2006-07-11 22:07:52.000000000 +0300
35355 enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
35372 --- lighttpd-1.4.11/src/mod_ssi_exprparser.c 2005-10-03 00:40:25.000000000 +0300
35373 +++ lighttpd-1.4.12/src/mod_ssi_exprparser.c 2006-07-11 22:08:02.000000000 +0300
35374 @@ -18,10 +18,10 @@
35375 /* Next is all token values, in a form suitable for use by makeheaders.
35376 ** This section will be null unless lemon is run with the -m switch.
35380 ** These constants (all generated automatically by the parser generator)
35381 ** specify the various kinds of tokens (terminals) that the parser
35385 ** Each symbol here is a terminal symbol in the grammar.
35388 ** and nonterminals. "int" is used otherwise.
35389 ** YYNOCODE is a number of type YYCODETYPE which corresponds
35390 ** to no legal terminal or nonterminal number. This
35391 -** number is used to fill in empty slots of the hash
35392 +** number is used to fill in empty slots of the hash
35394 ** YYFALLBACK If defined, this indicates that one or more tokens
35395 ** have fall-back values which should be used if the
35397 ** and nonterminal numbers. "unsigned char" is
35398 ** used if there are fewer than 250 rules and
35399 ** states combined. "int" is used otherwise.
35400 -** ssiexprparserTOKENTYPE is the data type used for minor tokens given
35401 +** ssiexprparserTOKENTYPE is the data type used for minor tokens given
35402 ** directly to the parser from the tokenizer.
35403 ** YYMINORTYPE is the data type used for all minor tokens.
35404 ** This is typically a union of many types, one of
35406 /* Next are that tables used to determine what action to take based on the
35407 ** current state and lookahead token. These tables are used to implement
35408 ** functions that take a state number and lookahead value and return an
35409 -** action integer.
35410 +** action integer.
35412 ** Suppose the action integer is N. Then the action is determined as
35414 @@ -116,7 +116,7 @@
35415 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
35416 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
35417 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
35418 -** and that yy_default[S] should be used instead.
35419 +** and that yy_default[S] should be used instead.
35421 ** The formula above is for computing the action when the lookahead is
35422 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
35423 @@ -168,7 +168,7 @@
35425 /* The next table maps tokens into fallback tokens. If a construct
35426 ** like the following:
35429 ** %fallback ID X Y Z.
35431 ** appears in the grammer, then ID becomes a fallback token for X, Y,
35432 @@ -219,10 +219,10 @@
35433 #endif /* NDEBUG */
35438 ** Turn parser tracing on by giving a stream to which to write the trace
35439 ** and a prompt to preface each trace message. Tracing is turned off
35440 -** by making either argument NULL
35441 +** by making either argument NULL
35445 @@ -247,7 +247,7 @@
35447 /* For tracing shifts, the names of all terminals and nonterminals
35448 ** are required. The following table supplies these names */
35449 -static const char *yyTokenName[] = {
35450 +static const char *yyTokenName[] = {
35451 "$", "AND", "OR", "EQ",
35452 "NE", "GT", "GE", "LT",
35453 "LE", "NOT", "LPARAN", "RPARAN",
35454 @@ -295,7 +295,7 @@
35460 ** This function allocates a new parser.
35461 ** The only argument is a pointer to a function which works like
35463 @@ -326,7 +326,7 @@
35464 /* Here is inserted the actions which take place when a
35465 ** terminal or non-terminal is destroyed. This can happen
35466 ** when the symbol is popped from the stack during a
35467 - ** reduce or during error processing or when a parser is
35468 + ** reduce or during error processing or when a parser is
35469 ** being destroyed before it is finished parsing.
35471 ** Note: during a reduce, the only symbols destroyed are those
35472 @@ -379,7 +379,7 @@
35478 ** Deallocate and destroy a parser. Destructors are all called for
35479 ** all stack elements before shutting the parser down.
35481 @@ -415,7 +415,7 @@
35484 int stateno = pParser->yystack[pParser->yyidx].stateno;
35487 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
35488 i = yy_shift_ofst[stateno];
35489 if( i==YY_SHIFT_USE_DFLT ){
35490 @@ -459,7 +459,7 @@
35493 int stateno = pParser->yystack[pParser->yyidx].stateno;
35496 i = yy_reduce_ofst[stateno];
35497 if( i==YY_REDUCE_USE_DFLT ){
35498 return yy_default[stateno];
35499 @@ -559,7 +559,7 @@
35500 ssiexprparserARG_FETCH;
35501 yymsp = &yypParser->yystack[yypParser->yyidx];
35503 - if( yyTraceFILE && yyruleno>=0
35504 + if( yyTraceFILE && yyruleno>=0
35505 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
35506 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
35507 yyRuleName[yyruleno]);
35508 @@ -872,7 +872,7 @@
35509 #ifdef YYERRORSYMBOL
35510 /* A syntax error has occurred.
35511 ** The response to an error depends upon whether or not the
35512 - ** grammar defines an error token "ERROR".
35513 + ** grammar defines an error token "ERROR".
35515 ** This is what we do if the grammar does define ERROR:
35517 --- lighttpd-1.4.11/src/mod_staticfile.c 2006-02-15 14:31:14.000000000 +0200
35518 +++ lighttpd-1.4.12/src/mod_staticfile.c 2006-07-11 22:07:51.000000000 +0300
35520 #include "http_chunk.h"
35521 #include "response.h"
35523 +#include "sys-files.h"
35524 +#include "sys-strings.h"
35526 * this is a staticfile for a lighttpd plugin
35532 @@ -29,48 +31,48 @@
35541 plugin_config **config_storage;
35543 - plugin_config conf;
35545 + plugin_config conf;
35548 /* init the plugin data */
35549 INIT_FUNC(mod_staticfile_init) {
35553 p = calloc(1, sizeof(*p));
35556 p->range_buf = buffer_init();
35562 -/* detroy the plugin data */
35563 +/* destroy the plugin data */
35564 FREE_FUNC(mod_staticfile_free) {
35565 plugin_data *p = p_d;
35570 if (!p) return HANDLER_GO_ON;
35573 if (p->config_storage) {
35575 for (i = 0; i < srv->config_context->used; i++) {
35576 plugin_config *s = p->config_storage[i];
35579 array_free(s->exclude_ext);
35584 free(p->config_storage);
35586 buffer_free(p->range_buf);
35592 return HANDLER_GO_ON;
35595 @@ -79,63 +81,60 @@
35596 SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
35597 plugin_data *p = p_d;
35600 - config_values_t cv[] = {
35602 + config_values_t cv[] = {
35603 { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
35604 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
35608 if (!p) return HANDLER_ERROR;
35611 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
35614 for (i = 0; i < srv->config_context->used; i++) {
35618 s = calloc(1, sizeof(plugin_config));
35619 s->exclude_ext = array_init();
35622 cv[0].destination = s->exclude_ext;
35625 p->config_storage[i] = s;
35628 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
35629 return HANDLER_ERROR;
35634 return HANDLER_GO_ON;
35637 -#define PATCH(x) \
35638 - p->conf.x = s->x;
35639 static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
35641 plugin_config *s = p->config_storage[0];
35643 - PATCH(exclude_ext);
35646 + PATCH_OPTION(exclude_ext);
35648 /* skip the first, the global context */
35649 for (i = 1; i < srv->config_context->used; i++) {
35650 data_config *dc = (data_config *)srv->config_context->data[i];
35651 s = p->config_storage[i];
35654 /* condition didn't match */
35655 if (!config_check_cond(srv, con, dc)) continue;
35659 for (j = 0; j < dc->value->used; j++) {
35660 data_unset *du = dc->value->data[j];
35663 if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
35664 - PATCH(exclude_ext);
35665 + PATCH_OPTION(exclude_ext);
35675 static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
35677 @@ -146,69 +145,69 @@
35679 stat_cache_entry *sce = NULL;
35680 buffer *content_type = NULL;
35683 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35689 end = sce->st.st_size - 1;
35692 con->response.content_length = 0;
35695 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
35696 content_type = ds->value;
35700 for (s = con->request.http_range, error = 0;
35701 !error && *s && NULL != (minus = strchr(s, '-')); ) {
35710 le = strtoll(s, &err, 10);
35714 /* RFC 2616 - 14.35.1 */
35717 con->http_status = 416;
35719 } else if (*err == '\0') {
35724 end = sce->st.st_size - 1;
35725 start = sce->st.st_size + le;
35726 } else if (*err == ',') {
35731 end = sce->st.st_size - 1;
35732 start = sce->st.st_size + le;
35738 } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
35742 la = strtoll(s, &err, 10);
35745 if (err == minus) {
35749 if (*(err + 1) == '\0') {
35753 end = sce->st.st_size - 1;
35757 } else if (*(err + 1) == ',') {
35762 end = sce->st.st_size - 1;
35765 @@ -220,64 +219,64 @@
35768 /* <start>-<stop> */
35771 la = strtoll(s, &err, 10);
35774 if (err == minus) {
35775 le = strtoll(minus+1, &err, 10);
35778 /* RFC 2616 - 14.35.1 */
35784 if (*err == '\0') {
35791 } else if (*err == ',') {
35814 if (start < 0) start = 0;
35817 /* RFC 2616 - 14.35.1 */
35818 if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
35821 if (start > sce->st.st_size - 1) {
35825 con->http_status = 416;
35832 /* write boundary-header */
35836 b = chunkqueue_get_append_buffer(con->write_queue);
35839 buffer_copy_string(b, "\r\n--");
35840 buffer_append_string(b, boundary);
35843 /* write Content-Range */
35844 buffer_append_string(b, "\r\nContent-Range: bytes ");
35845 buffer_append_off_t(b, start);
35846 @@ -285,54 +284,54 @@
35847 buffer_append_off_t(b, end);
35848 buffer_append_string(b, "/");
35849 buffer_append_off_t(b, sce->st.st_size);
35852 buffer_append_string(b, "\r\nContent-Type: ");
35853 buffer_append_string_buffer(b, content_type);
35856 /* write END-OF-HEADER */
35857 buffer_append_string(b, "\r\n\r\n");
35860 con->response.content_length += b->used - 1;
35866 chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
35867 con->response.content_length += end - start + 1;
35872 /* something went wrong */
35873 if (error) return -1;
35877 /* add boundary end */
35881 b = chunkqueue_get_append_buffer(con->write_queue);
35884 buffer_copy_string_len(b, "\r\n--", 4);
35885 buffer_append_string(b, boundary);
35886 buffer_append_string_len(b, "--\r\n", 4);
35889 con->response.content_length += b->used - 1;
35892 /* set header-fields */
35895 buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
35896 buffer_append_string(p->range_buf, boundary);
35899 /* overwrite content-type */
35900 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
35902 /* add Content-Range-header */
35905 buffer_copy_string(p->range_buf, "bytes ");
35906 buffer_append_off_t(p->range_buf, start);
35907 buffer_append_string(p->range_buf, "-");
35908 buffer_append_off_t(p->range_buf, end);
35909 buffer_append_string(p->range_buf, "/");
35910 buffer_append_off_t(p->range_buf, sce->st.st_size);
35913 response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
35916 @@ -347,12 +346,12 @@
35917 stat_cache_entry *sce = NULL;
35922 /* someone else has done a decision for us */
35923 if (con->http_status != 0) return HANDLER_GO_ON;
35924 if (con->uri.path->used == 0) return HANDLER_GO_ON;
35925 if (con->physical.path->used == 0) return HANDLER_GO_ON;
35928 /* someone else has handled this request */
35929 if (con->mode != DIRECT) return HANDLER_GO_ON;
35931 @@ -365,52 +364,52 @@
35933 return HANDLER_GO_ON;
35937 mod_staticfile_patch_connection(srv, con, p);
35940 s_len = con->uri.path->used - 1;
35943 /* ignore certain extensions */
35944 for (k = 0; k < p->conf.exclude_ext->used; k++) {
35945 - ds = (data_string *)p->conf.exclude_ext->data[k];
35947 + ds = (data_string *)p->conf.exclude_ext->data[k];
35949 if (ds->value->used == 0) continue;
35951 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
35952 return HANDLER_GO_ON;
35958 if (con->conf.log_request_handling) {
35959 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling file as static file");
35963 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35964 con->http_status = 403;
35967 log_error_write(srv, __FILE__, __LINE__, "sbsb",
35968 "not a regular file:", con->uri.path,
35969 "->", con->physical.path);
35972 return HANDLER_FINISHED;
35975 - /* we only handline regular files */
35977 + /* we only handle regular files */
35978 if (!S_ISREG(sce->st.st_mode)) {
35979 con->http_status = 404;
35982 if (con->conf.log_file_not_found) {
35983 log_error_write(srv, __FILE__, __LINE__, "sbsb",
35984 "not a regular file:", con->uri.path,
35989 return HANDLER_FINISHED;
35992 - /* mod_compress might set several data directly, don't overwrite them */
35994 + /* mod_compress might set several parameters directly; don't overwrite them */
35996 /* set response content-type, if not set already */
35998 if (NULL == array_get_element(con->response.headers, "Content-Type")) {
35999 @@ -420,15 +419,15 @@
36000 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
36005 if (NULL == array_get_element(con->response.headers, "ETag")) {
36006 /* generate e-tag */
36007 etag_mutate(con->physical.etag, sce->etag);
36010 response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
36012 response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
36015 /* prepare header */
36016 if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
36017 mtime = strftime_cache_get(srv, sce->st.st_mtime);
36018 @@ -444,34 +443,34 @@
36019 /* check if we have a conditional GET */
36021 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) {
36022 - /* if the value is the same as our ETag, we do a Range-request,
36023 + /* if the value is the same as our ETag, we do a Range-request,
36024 * otherwise a full 200 */
36026 if (!buffer_is_equal(ds->value, con->physical.etag)) {
36027 do_range_request = 0;
36032 if (do_range_request) {
36033 /* content prepared, I'm done */
36034 con->file_finished = 1;
36037 if (0 == http_response_parse_range(srv, con, p)) {
36038 con->http_status = 206;
36040 return HANDLER_FINISHED;
36045 /* if we are still here, prepare body */
36047 - /* we add it here for all requests
36048 - * the HEAD request will drop it afterwards again
36050 + /* we add it here for all requests
36051 + * the HEAD request will drop it afterwards again
36053 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
36056 con->file_finished = 1;
36059 return HANDLER_FINISHED;
36062 @@ -480,13 +479,13 @@
36063 int mod_staticfile_plugin_init(plugin *p) {
36064 p->version = LIGHTTPD_VERSION_ID;
36065 p->name = buffer_init_string("staticfile");
36068 p->init = mod_staticfile_init;
36069 p->handle_subrequest_start = mod_staticfile_subrequest;
36070 p->set_defaults = mod_staticfile_set_defaults;
36071 p->cleanup = mod_staticfile_free;
36079 --- lighttpd-1.4.11/src/mod_status.c 2006-01-10 21:45:32.000000000 +0200
36080 +++ lighttpd-1.4.12/src/mod_status.c 2006-07-11 22:07:53.000000000 +0300
36083 #include <stdlib.h>
36084 #include <string.h>
36085 -#include <unistd.h>
36089 @@ -29,114 +28,114 @@
36095 double traffic_out;
36099 double mod_5s_traffic_out[5];
36100 double mod_5s_requests[5];
36104 double rel_traffic_out;
36105 double rel_requests;
36108 double abs_traffic_out;
36109 double abs_requests;
36112 double bytes_written;
36115 buffer *module_list;
36118 plugin_config **config_storage;
36120 - plugin_config conf;
36122 + plugin_config conf;
36125 INIT_FUNC(mod_status_init) {
36130 p = calloc(1, sizeof(*p));
36133 p->traffic_out = p->requests = 0;
36134 p->rel_traffic_out = p->rel_requests = 0;
36135 p->abs_traffic_out = p->abs_requests = 0;
36136 p->bytes_written = 0;
36137 p->module_list = buffer_init();
36140 for (i = 0; i < 5; i++) {
36141 p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
36148 FREE_FUNC(mod_status_free) {
36149 plugin_data *p = p_d;
36154 if (!p) return HANDLER_GO_ON;
36157 buffer_free(p->module_list);
36160 if (p->config_storage) {
36162 for (i = 0; i < srv->config_context->used; i++) {
36163 plugin_config *s = p->config_storage[i];
36166 buffer_free(s->status_url);
36167 buffer_free(s->statistics_url);
36168 buffer_free(s->config_url);
36173 free(p->config_storage);
36182 return HANDLER_GO_ON;
36185 SETDEFAULTS_FUNC(mod_status_set_defaults) {
36186 plugin_data *p = p_d;
36189 - config_values_t cv[] = {
36191 + config_values_t cv[] = {
36192 { "status.status-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36193 { "status.config-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36194 { "status.enable-sort", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
36195 { "status.statistics-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36196 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36200 if (!p) return HANDLER_ERROR;
36203 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36206 for (i = 0; i < srv->config_context->used; i++) {
36210 s = calloc(1, sizeof(plugin_config));
36211 s->config_url = buffer_init();
36212 s->status_url = buffer_init();
36214 s->statistics_url = buffer_init();
36217 cv[0].destination = s->status_url;
36218 cv[1].destination = s->config_url;
36219 cv[2].destination = &(s->sort);
36220 cv[3].destination = s->statistics_url;
36223 p->config_storage[i] = s;
36226 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36227 return HANDLER_ERROR;
36232 return HANDLER_GO_ON;
36235 @@ -151,7 +150,7 @@
36236 buffer_append_string(b, value);
36237 BUFFER_APPEND_STRING_CONST(b, "</td>\n");
36238 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
36244 @@ -161,13 +160,13 @@
36245 buffer_append_string(b, key);
36246 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36247 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
36253 static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
36254 plugin_data *p = p_d;
36257 if (p->conf.sort) {
36258 BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">");
36259 buffer_append_string(b, key);
36260 @@ -177,13 +176,13 @@
36261 buffer_append_string(b, key);
36262 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36269 static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
36273 if (*avg > size) { *avg /= size; *multiplier = 'k'; }
36274 if (*avg > size) { *avg /= size; *multiplier = 'M'; }
36275 if (*avg > size) { *avg /= size; *multiplier = 'G'; }
36276 @@ -202,21 +201,21 @@
36279 char multiplier = '\0';
36285 int days, hours, mins, seconds;
36288 b = chunkqueue_get_append_buffer(con->write_queue);
36290 - BUFFER_COPY_STRING_CONST(b,
36291 + BUFFER_COPY_STRING_CONST(b,
36292 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36293 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36294 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36295 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
36297 " <title>Status</title>\n");
36300 BUFFER_APPEND_STRING_CONST(b,
36301 " <style type=\"text/css\">\n"
36302 " table.status { border: black solid thin; }\n"
36303 @@ -226,14 +225,14 @@
36304 " a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
36305 " span.sortarrow { color: white; text-decoration: none; }\n"
36309 if (p->conf.sort) {
36310 BUFFER_APPEND_STRING_CONST(b,
36311 "<script type=\"text/javascript\">\n"
36313 "var sort_column;\n"
36314 "var prev_span = null;\n");
36317 BUFFER_APPEND_STRING_CONST(b,
36318 "function get_inner_text(el) {\n"
36319 " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
36320 @@ -251,7 +250,7 @@
36326 BUFFER_APPEND_STRING_CONST(b,
36327 "function sortfn(a,b) {\n"
36328 " var at = get_inner_text(a.cells[sort_column]);\n"
36329 @@ -266,7 +265,7 @@
36330 " else return 1;\n"
36335 BUFFER_APPEND_STRING_CONST(b,
36336 "function resort(lnk) {\n"
36337 " var span = lnk.childNodes[1];\n"
36338 @@ -276,7 +275,7 @@
36339 " rows[j-1] = table.rows[j];\n"
36340 " sort_column = lnk.parentNode.cellIndex;\n"
36341 " rows.sort(sortfn);\n");
36344 BUFFER_APPEND_STRING_CONST(b,
36345 " if (prev_span != null) prev_span.innerHTML = '';\n"
36346 " if (span.getAttribute('sortdir')=='down') {\n"
36347 @@ -294,175 +293,175 @@
36352 - BUFFER_APPEND_STRING_CONST(b,
36354 + BUFFER_APPEND_STRING_CONST(b,
36363 /* connection listing */
36364 BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
36366 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
36367 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
36369 + BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
36370 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
36371 buffer_append_string_buffer(b, con->uri.authority);
36372 - BUFFER_APPEND_STRING_CONST(b, " (");
36373 + BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
36374 buffer_append_string_buffer(b, con->server_name);
36375 - BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
36376 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
36378 + BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
36379 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
36381 ts = srv->cur_ts - srv->startup_ts;
36384 days = ts / (60 * 60 * 24);
36385 ts %= (60 * 60 * 24);
36388 hours = ts / (60 * 60);
36400 buffer_append_long(b, days);
36401 BUFFER_APPEND_STRING_CONST(b, " days ");
36406 buffer_append_long(b, hours);
36407 BUFFER_APPEND_STRING_CONST(b, " hours ");
36412 buffer_append_long(b, mins);
36413 BUFFER_APPEND_STRING_CONST(b, " min ");
36417 buffer_append_long(b, seconds);
36418 BUFFER_APPEND_STRING_CONST(b, " s");
36421 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36422 BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
36425 ts = srv->startup_ts;
36427 - strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
36429 + strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
36430 buffer_append_string(b, buf);
36431 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36436 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
36438 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36440 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
36441 avg = p->abs_requests;
36443 mod_status_get_multiplier(&avg, &multiplier, 1000);
36446 buffer_append_long(b, avg);
36447 - BUFFER_APPEND_STRING_CONST(b, " ");
36448 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
36449 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36450 - BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
36452 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36453 + BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
36455 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
36456 avg = p->abs_traffic_out;
36458 mod_status_get_multiplier(&avg, &multiplier, 1024);
36460 sprintf(buf, "%.2f", avg);
36461 buffer_append_string(b, buf);
36462 - BUFFER_APPEND_STRING_CONST(b, " ");
36463 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_mult\">");
36464 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36465 - BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
36466 + BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
36470 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
36472 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36474 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
36475 avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
36477 mod_status_get_multiplier(&avg, &multiplier, 1000);
36479 buffer_append_long(b, avg);
36480 - BUFFER_APPEND_STRING_CONST(b, " ");
36481 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
36482 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36483 - BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36485 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36486 + BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36488 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
36489 avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
36491 mod_status_get_multiplier(&avg, &multiplier, 1024);
36493 sprintf(buf, "%.2f", avg);
36494 buffer_append_string(b, buf);
36495 - BUFFER_APPEND_STRING_CONST(b, " ");
36496 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
36497 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36498 - BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36499 + BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36505 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n");
36506 for (j = 0, avg = 0; j < 5; j++) {
36507 avg += p->mod_5s_requests[j];
36513 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36515 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
36517 mod_status_get_multiplier(&avg, &multiplier, 1000);
36519 buffer_append_long(b, avg);
36520 - BUFFER_APPEND_STRING_CONST(b, " ");
36521 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
36522 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36524 - BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36527 + BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36529 for (j = 0, avg = 0; j < 5; j++) {
36530 avg += p->mod_5s_traffic_out[j];
36536 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36538 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
36540 mod_status_get_multiplier(&avg, &multiplier, 1024);
36542 sprintf(buf, "%.2f", avg);
36543 buffer_append_string(b, buf);
36544 - BUFFER_APPEND_STRING_CONST(b, " ");
36545 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
36546 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36547 - BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36549 + BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36551 BUFFER_APPEND_STRING_CONST(b, "</table>\n");
36556 BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n");
36557 BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n");
36558 BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n");
36559 BUFFER_APPEND_STRING_CONST(b, "q = request-start, Q = request-end\n");
36560 BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
36562 - BUFFER_APPEND_STRING_CONST(b, "<b>");
36564 + BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
36565 buffer_append_long(b, srv->conns->used);
36566 - BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
36568 + BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
36570 for (j = 0; j < srv->conns->used; j++) {
36571 connection *c = srv->conns->ptr[j];
36572 const char *state = connection_get_short_state(c->state);
36575 buffer_append_string_len(b, state, 1);
36578 if (((j + 1) % 50) == 0) {
36579 BUFFER_APPEND_STRING_CONST(b, "\n");
36584 BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
36586 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
36588 + BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
36589 BUFFER_APPEND_STRING_CONST(b, "<tr>");
36590 mod_status_header_append_sort(b, p_d, "Client IP");
36591 mod_status_header_append_sort(b, p_d, "Read");
36592 @@ -473,16 +472,16 @@
36593 mod_status_header_append_sort(b, p_d, "URI");
36594 mod_status_header_append_sort(b, p_d, "File");
36595 BUFFER_APPEND_STRING_CONST(b, "</tr>\n");
36598 for (j = 0; j < srv->conns->used; j++) {
36599 connection *c = srv->conns->ptr[j];
36601 - BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
36604 + BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
36606 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
36608 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36611 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
36613 if (con->request.content_length) {
36614 buffer_append_long(b, c->request_content_queue->bytes_in);
36615 BUFFER_APPEND_STRING_CONST(b, "/");
36616 @@ -490,55 +489,55 @@
36618 BUFFER_APPEND_STRING_CONST(b, "0/0");
36621 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36624 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
36626 buffer_append_off_t(b, chunkqueue_written(c->write_queue));
36627 BUFFER_APPEND_STRING_CONST(b, "/");
36628 buffer_append_off_t(b, chunkqueue_length(c->write_queue));
36630 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36633 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
36635 buffer_append_string(b, connection_get_state(c->state));
36637 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36640 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
36642 buffer_append_long(b, srv->cur_ts - c->request_start);
36644 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36647 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
36649 if (buffer_is_empty(c->server_name)) {
36650 buffer_append_string_buffer(b, c->uri.authority);
36653 buffer_append_string_buffer(b, c->server_name);
36656 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36659 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
36661 if (!buffer_is_empty(c->uri.path)) {
36662 buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
36665 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36668 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
36670 buffer_append_string_buffer(b, c->physical.path);
36673 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36677 - BUFFER_APPEND_STRING_CONST(b,
36680 + BUFFER_APPEND_STRING_CONST(b,
36684 - BUFFER_APPEND_STRING_CONST(b,
36687 + BUFFER_APPEND_STRING_CONST(b,
36693 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36699 @@ -548,7 +547,7 @@
36705 b = chunkqueue_get_append_buffer(con->write_queue);
36707 /* output total number of requests */
36708 @@ -556,19 +555,19 @@
36709 avg = p->abs_requests;
36710 buffer_append_long(b, avg);
36711 BUFFER_APPEND_STRING_CONST(b, "\n");
36714 /* output total traffic out in kbytes */
36715 BUFFER_APPEND_STRING_CONST(b, "Total kBytes: ");
36716 avg = p->abs_traffic_out / 1024;
36717 buffer_append_long(b, avg);
36718 BUFFER_APPEND_STRING_CONST(b, "\n");
36721 /* output uptime */
36722 BUFFER_APPEND_STRING_CONST(b, "Uptime: ");
36723 ts = srv->cur_ts - srv->startup_ts;
36724 buffer_append_long(b, ts);
36725 BUFFER_APPEND_STRING_CONST(b, "\n");
36728 /* output busy servers */
36729 BUFFER_APPEND_STRING_CONST(b, "BusyServers: ");
36730 buffer_append_long(b, srv->conns->used);
36731 @@ -577,7 +576,7 @@
36732 /* set text/plain output */
36734 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36740 @@ -591,10 +590,10 @@
36741 /* we have nothing to send */
36742 con->http_status = 204;
36743 con->file_finished = 1;
36746 return HANDLER_FINISHED;
36750 b = chunkqueue_get_append_buffer(con->write_queue);
36752 for (i = 0; i < st->used; i++) {
36753 @@ -605,27 +604,27 @@
36754 buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
36755 buffer_append_string(b, "\n");
36759 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36762 con->http_status = 200;
36763 con->file_finished = 1;
36766 return HANDLER_FINISHED;
36770 static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
36773 if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
36774 mod_status_handle_server_status_text(srv, con, p_d);
36776 mod_status_handle_server_status_html(srv, con, p_d);
36780 con->http_status = 200;
36781 con->file_finished = 1;
36784 return HANDLER_FINISHED;
36787 @@ -634,9 +633,9 @@
36788 plugin_data *p = p_d;
36789 buffer *b, *m = p->module_list;
36792 - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36795 + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36797 /* - poll is most reliable
36798 * - select works everywhere
36799 * - linux-* are experimental
36800 @@ -661,10 +660,10 @@
36802 { FDEVENT_HANDLER_UNSET, NULL }
36806 b = chunkqueue_get_append_buffer(con->write_queue);
36808 - BUFFER_COPY_STRING_CONST(b,
36810 + BUFFER_COPY_STRING_CONST(b,
36811 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36812 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36813 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36814 @@ -675,7 +674,7 @@
36816 " <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
36817 " <table border=\"1\">\n");
36820 mod_status_header_append(b, "Server-Features");
36822 mod_status_row_append(b, "RegEx Conditionals", "enabled");
36823 @@ -683,21 +682,21 @@
36824 mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
36826 mod_status_header_append(b, "Network Engine");
36829 for (i = 0; event_handlers[i].name; i++) {
36830 if (event_handlers[i].et == srv->event_handler) {
36831 mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
36837 mod_status_header_append(b, "Config-File-Settings");
36840 for (i = 0; i < srv->plugins.used; i++) {
36841 plugin **ps = srv->plugins.ptr;
36844 plugin *pl = ps[i];
36848 buffer_copy_string_buffer(m, pl->name);
36850 @@ -705,137 +704,135 @@
36851 buffer_append_string_buffer(m, pl->name);
36856 mod_status_row_append(b, "Loaded Modules", m->ptr);
36859 BUFFER_APPEND_STRING_CONST(b, " </table>\n");
36861 - BUFFER_APPEND_STRING_CONST(b,
36863 + BUFFER_APPEND_STRING_CONST(b,
36869 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36872 con->http_status = 200;
36873 con->file_finished = 1;
36876 return HANDLER_FINISHED;
36879 -#define PATCH(x) \
36880 - p->conf.x = s->x;
36881 static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
36883 plugin_config *s = p->config_storage[0];
36885 - PATCH(status_url);
36886 - PATCH(config_url);
36888 - PATCH(statistics_url);
36891 + PATCH_OPTION(status_url);
36892 + PATCH_OPTION(config_url);
36893 + PATCH_OPTION(sort);
36894 + PATCH_OPTION(statistics_url);
36896 /* skip the first, the global context */
36897 for (i = 1; i < srv->config_context->used; i++) {
36898 data_config *dc = (data_config *)srv->config_context->data[i];
36899 s = p->config_storage[i];
36902 /* condition didn't match */
36903 if (!config_check_cond(srv, con, dc)) continue;
36907 for (j = 0; j < dc->value->used; j++) {
36908 data_unset *du = dc->value->data[j];
36911 if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
36912 - PATCH(status_url);
36913 + PATCH_OPTION(status_url);
36914 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
36915 - PATCH(config_url);
36916 + PATCH_OPTION(config_url);
36917 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
36919 + PATCH_OPTION(sort);
36920 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
36921 - PATCH(statistics_url);
36923 + PATCH_OPTION(statistics_url);
36932 static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
36933 plugin_data *p = p_d;
36936 mod_status_patch_connection(srv, con, p);
36938 - if (!buffer_is_empty(p->conf.status_url) &&
36940 + if (!buffer_is_empty(p->conf.status_url) &&
36941 buffer_is_equal(p->conf.status_url, con->uri.path)) {
36942 return mod_status_handle_server_status(srv, con, p_d);
36943 - } else if (!buffer_is_empty(p->conf.config_url) &&
36944 + } else if (!buffer_is_empty(p->conf.config_url) &&
36945 buffer_is_equal(p->conf.config_url, con->uri.path)) {
36946 return mod_status_handle_server_config(srv, con, p_d);
36947 - } else if (!buffer_is_empty(p->conf.statistics_url) &&
36948 + } else if (!buffer_is_empty(p->conf.statistics_url) &&
36949 buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
36950 return mod_status_handle_server_statistics(srv, con, p_d);
36954 return HANDLER_GO_ON;
36957 TRIGGER_FUNC(mod_status_trigger) {
36958 plugin_data *p = p_d;
36962 /* check all connections */
36963 for (i = 0; i < srv->conns->used; i++) {
36964 connection *c = srv->conns->ptr[i];
36967 p->bytes_written += c->bytes_written_cur_second;
36971 /* a sliding average */
36972 p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
36973 p->mod_5s_requests [p->mod_5s_ndx] = p->requests;
36976 p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
36979 p->abs_traffic_out += p->bytes_written;
36980 p->rel_traffic_out += p->bytes_written;
36983 p->bytes_written = 0;
36986 /* reset storage - second */
36987 p->traffic_out = 0;
36991 return HANDLER_GO_ON;
36994 REQUESTDONE_FUNC(mod_status_account) {
36995 plugin_data *p = p_d;
37005 p->bytes_written += con->bytes_written_cur_second;
37008 return HANDLER_GO_ON;
37011 int mod_status_plugin_init(plugin *p) {
37012 p->version = LIGHTTPD_VERSION_ID;
37013 p->name = buffer_init_string("status");
37016 p->init = mod_status_init;
37017 p->cleanup = mod_status_free;
37018 p->set_defaults= mod_status_set_defaults;
37021 p->handle_uri_clean = mod_status_handler;
37022 p->handle_trigger = mod_status_trigger;
37023 p->handle_request_done = mod_status_account;
37031 --- lighttpd-1.4.11/src/mod_trigger_b4_dl.c 2005-09-23 22:53:55.000000000 +0300
37032 +++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c 2006-07-11 22:07:51.000000000 +0300
37033 @@ -24,18 +24,18 @@
37036 * this is a trigger_b4_dl for a lighttpd plugin
37041 /* plugin config for all request/connections */
37044 buffer *db_filename;
37047 buffer *trigger_url;
37048 buffer *download_url;
37053 buffer *mc_namespace;
37054 #if defined(HAVE_PCRE_H)
37055 @@ -46,58 +46,58 @@
37059 -#if defined(HAVE_MEMCACHE_H)
37060 +#if defined(HAVE_MEMCACHE_H)
37061 struct memcache *mc;
37065 unsigned short trigger_timeout;
37066 unsigned short debug;
37076 plugin_config **config_storage;
37078 - plugin_config conf;
37080 + plugin_config conf;
37083 /* init the plugin data */
37084 INIT_FUNC(mod_trigger_b4_dl_init) {
37088 p = calloc(1, sizeof(*p));
37091 p->tmp_buf = buffer_init();
37097 /* detroy the plugin data */
37098 FREE_FUNC(mod_trigger_b4_dl_free) {
37099 plugin_data *p = p_d;
37104 if (!p) return HANDLER_GO_ON;
37107 if (p->config_storage) {
37109 for (i = 0; i < srv->config_context->used; i++) {
37110 plugin_config *s = p->config_storage[i];
37115 buffer_free(s->db_filename);
37116 buffer_free(s->download_url);
37117 buffer_free(s->trigger_url);
37118 buffer_free(s->deny_url);
37121 buffer_free(s->mc_namespace);
37122 array_free(s->mc_hosts);
37125 #if defined(HAVE_PCRE_H)
37126 if (s->trigger_regex) pcre_free(s->trigger_regex);
37127 if (s->download_regex) pcre_free(s->download_regex);
37128 @@ -108,16 +108,16 @@
37129 #if defined(HAVE_MEMCACHE_H)
37130 if (s->mc) mc_free(s->mc);
37136 free(p->config_storage);
37140 buffer_free(p->tmp_buf);
37146 return HANDLER_GO_ON;
37149 @@ -126,9 +126,9 @@
37150 SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
37151 plugin_data *p = p_d;
37155 - config_values_t cv[] = {
37158 + config_values_t cv[] = {
37159 { "trigger-before-download.gdbm-filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
37160 { "trigger-before-download.trigger-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
37161 { "trigger-before-download.download-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
37162 @@ -139,18 +139,18 @@
37163 { "trigger-before-download.debug", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
37164 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37168 if (!p) return HANDLER_ERROR;
37171 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37174 for (i = 0; i < srv->config_context->used; i++) {
37176 #if defined(HAVE_PCRE_H)
37177 const char *errptr;
37182 s = calloc(1, sizeof(plugin_config));
37183 s->db_filename = buffer_init();
37184 s->download_url = buffer_init();
37185 @@ -158,7 +158,7 @@
37186 s->deny_url = buffer_init();
37187 s->mc_hosts = array_init();
37188 s->mc_namespace = buffer_init();
37191 cv[0].destination = s->db_filename;
37192 cv[1].destination = s->trigger_url;
37193 cv[2].destination = s->download_url;
37194 @@ -167,41 +167,41 @@
37195 cv[5].destination = s->mc_hosts;
37196 cv[6].destination = s->mc_namespace;
37197 cv[7].destination = &(s->debug);
37200 p->config_storage[i] = s;
37203 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37204 return HANDLER_ERROR;
37206 #if defined(HAVE_GDBM_H)
37207 if (!buffer_is_empty(s->db_filename)) {
37208 if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
37209 - log_error_write(srv, __FILE__, __LINE__, "s",
37210 + log_error_write(srv, __FILE__, __LINE__, "s",
37211 "gdbm-open failed");
37212 return HANDLER_ERROR;
37216 -#if defined(HAVE_PCRE_H)
37217 +#if defined(HAVE_PCRE_H)
37218 if (!buffer_is_empty(s->download_url)) {
37219 if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
37220 0, &errptr, &erroff, NULL))) {
37222 - log_error_write(srv, __FILE__, __LINE__, "sbss",
37223 - "compiling regex for download-url failed:",
37225 + log_error_write(srv, __FILE__, __LINE__, "sbss",
37226 + "compiling regex for download-url failed:",
37227 s->download_url, "pos:", erroff);
37228 return HANDLER_ERROR;
37233 if (!buffer_is_empty(s->trigger_url)) {
37234 if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
37235 0, &errptr, &erroff, NULL))) {
37237 - log_error_write(srv, __FILE__, __LINE__, "sbss",
37238 - "compiling regex for trigger-url failed:",
37240 + log_error_write(srv, __FILE__, __LINE__, "sbss",
37241 + "compiling regex for trigger-url failed:",
37242 s->trigger_url, "pos:", erroff);
37245 return HANDLER_ERROR;
37248 @@ -211,100 +211,97 @@
37249 #if defined(HAVE_MEMCACHE_H)
37254 for (k = 0; k < s->mc_hosts->used; k++) {
37255 data_string *ds = (data_string *)s->mc_hosts->data[k];
37258 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
37259 - log_error_write(srv, __FILE__, __LINE__, "sb",
37260 - "connection to host failed:",
37261 + log_error_write(srv, __FILE__, __LINE__, "sb",
37262 + "connection to host failed:",
37266 return HANDLER_ERROR;
37270 - log_error_write(srv, __FILE__, __LINE__, "s",
37271 + log_error_write(srv, __FILE__, __LINE__, "s",
37272 "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
37273 return HANDLER_ERROR;
37279 #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
37280 - log_error_write(srv, __FILE__, __LINE__, "s",
37281 + log_error_write(srv, __FILE__, __LINE__, "s",
37282 "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
37283 return HANDLER_ERROR;
37288 return HANDLER_GO_ON;
37291 -#define PATCH(x) \
37292 - p->conf.x = s->x;
37293 static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
37295 plugin_config *s = p->config_storage[0];
37298 #if defined(HAVE_GDBM)
37301 + PATCH_OPTION(db);
37303 #if defined(HAVE_PCRE_H)
37304 - PATCH(download_regex);
37305 - PATCH(trigger_regex);
37307 - PATCH(trigger_timeout);
37309 - PATCH(mc_namespace);
37311 + PATCH_OPTION(download_regex);
37312 + PATCH_OPTION(trigger_regex);
37314 + PATCH_OPTION(trigger_timeout);
37315 + PATCH_OPTION(deny_url);
37316 + PATCH_OPTION(mc_namespace);
37317 + PATCH_OPTION(debug);
37318 #if defined(HAVE_MEMCACHE_H)
37320 + PATCH_OPTION(mc);
37324 /* skip the first, the global context */
37325 for (i = 1; i < srv->config_context->used; i++) {
37326 data_config *dc = (data_config *)srv->config_context->data[i];
37327 s = p->config_storage[i];
37330 /* condition didn't match */
37331 if (!config_check_cond(srv, con, dc)) continue;
37335 for (j = 0; j < dc->value->used; j++) {
37336 data_unset *du = dc->value->data[j];
37338 if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
37339 #if defined(HAVE_PCRE_H)
37340 - PATCH(download_regex);
37341 + PATCH_OPTION(download_regex);
37343 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
37344 # if defined(HAVE_PCRE_H)
37345 - PATCH(trigger_regex);
37346 + PATCH_OPTION(trigger_regex);
37348 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
37349 #if defined(HAVE_GDBM_H)
37351 + PATCH_OPTION(db);
37353 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
37354 - PATCH(trigger_timeout);
37355 + PATCH_OPTION(trigger_timeout);
37356 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
37358 + PATCH_OPTION(debug);
37359 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
37361 + PATCH_OPTION(deny_url);
37362 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
37363 - PATCH(mc_namespace);
37364 + PATCH_OPTION(mc_namespace);
37365 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
37366 #if defined(HAVE_MEMCACHE_H)
37368 + PATCH_OPTION(mc);
37379 URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
37380 plugin_data *p = p_d;
37381 @@ -315,20 +312,20 @@
37387 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37390 mod_trigger_b4_dl_patch_connection(srv, con, p);
37393 if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
37396 # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
37397 return HANDLER_GO_ON;
37398 # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
37399 if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
37400 if (p->conf.db && p->conf.mc) {
37401 /* can't decide which one */
37404 return HANDLER_GO_ON;
37406 # elif defined(HAVE_GDBM_H)
37407 @@ -336,12 +333,12 @@
37409 if (!p->conf.mc) return HANDLER_GO_ON;
37413 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) {
37414 /* X-Forwarded-For contains the ip behind the proxy */
37417 remote_ip = ds->value->ptr;
37420 /* memcache can't handle spaces */
37422 remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
37423 @@ -350,13 +347,13 @@
37424 if (p->conf.debug) {
37425 log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
37429 /* check if URL is a trigger -> insert IP into DB */
37430 if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37431 if (n != PCRE_ERROR_NOMATCH) {
37432 log_error_write(srv, __FILE__, __LINE__, "sd",
37433 "execution error while matching:", n);
37436 return HANDLER_ERROR;
37439 @@ -364,34 +361,34 @@
37441 /* the trigger matched */
37445 key.dptr = (char *)remote_ip;
37446 key.dsize = strlen(remote_ip);
37449 val.dptr = (char *)&(srv->cur_ts);
37450 val.dsize = sizeof(srv->cur_ts);
37453 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37454 log_error_write(srv, __FILE__, __LINE__, "s",
37459 -# if defined(HAVE_MEMCACHE_H)
37460 +# if defined(HAVE_MEMCACHE_H)
37463 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37464 buffer_append_string(p->tmp_buf, remote_ip);
37467 for (i = 0; i < p->tmp_buf->used - 1; i++) {
37468 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37472 if (p->conf.debug) {
37473 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
37476 - if (0 != mc_set(p->conf.mc,
37477 + if (0 != mc_set(p->conf.mc,
37478 CONST_BUF_LEN(p->tmp_buf),
37479 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37480 p->conf.trigger_timeout, 0)) {
37481 @@ -401,7 +398,7 @@
37487 /* check if URL is a download -> check IP in DB, update timestamp */
37488 if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37489 if (n != PCRE_ERROR_NOMATCH) {
37490 @@ -411,93 +408,93 @@
37493 /* the download uri matched */
37494 -# if defined(HAVE_GDBM_H)
37495 +# if defined(HAVE_GDBM_H)
37501 key.dptr = (char *)remote_ip;
37502 key.dsize = strlen(remote_ip);
37505 val = gdbm_fetch(p->conf.db, key);
37508 if (val.dptr == NULL) {
37509 /* not found, redirect */
37512 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37515 con->http_status = 307;
37518 return HANDLER_FINISHED;
37522 last_hit = *(time_t *)(val.dptr);
37528 if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
37529 /* found, but timeout, redirect */
37532 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37533 con->http_status = 307;
37537 if (0 != gdbm_delete(p->conf.db, key)) {
37538 log_error_write(srv, __FILE__, __LINE__, "s",
37544 return HANDLER_FINISHED;
37548 val.dptr = (char *)&(srv->cur_ts);
37549 val.dsize = sizeof(srv->cur_ts);
37552 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37553 log_error_write(srv, __FILE__, __LINE__, "s",
37559 -# if defined(HAVE_MEMCACHE_H)
37561 +# if defined(HAVE_MEMCACHE_H)
37567 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37568 buffer_append_string(p->tmp_buf, remote_ip);
37571 for (i = 0; i < p->tmp_buf->used - 1; i++) {
37572 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37576 if (p->conf.debug) {
37577 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
37583 * memcached is do expiration for us, as long as we can fetch it every thing is ok
37584 - * and the timestamp is updated
37586 + * and the timestamp is updated
37589 - if (NULL == (r = mc_aget(p->conf.mc,
37590 + if (NULL == (r = mc_aget(p->conf.mc,
37591 CONST_BUF_LEN(p->tmp_buf)
37595 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37598 con->http_status = 307;
37601 return HANDLER_FINISHED;
37608 /* set a new timeout */
37609 - if (0 != mc_set(p->conf.mc,
37610 + if (0 != mc_set(p->conf.mc,
37611 CONST_BUF_LEN(p->tmp_buf),
37612 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37613 p->conf.trigger_timeout, 0)) {
37614 @@ -507,13 +504,13 @@
37627 return HANDLER_GO_ON;
37630 @@ -521,21 +518,21 @@
37631 TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
37632 plugin_data *p = p_d;
37636 /* check DB each minute */
37637 if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
37641 for (i = 0; i < srv->config_context->used; i++) {
37642 plugin_config *s = p->config_storage[i];
37643 datum key, val, okey;
37646 if (!s->db) continue;
37651 - /* according to the manual this loop + delete does delete all entries on its way
37654 + /* according to the manual this loop + delete does delete all entries on its way
37656 * we don't care as the next round will remove them. We don't have to perfect here.
37658 for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
37659 @@ -544,21 +541,21 @@
37665 val = gdbm_fetch(s->db, key);
37668 last_hit = *(time_t *)(val.dptr);
37674 if (srv->cur_ts - last_hit > s->trigger_timeout) {
37675 gdbm_delete(s->db, key);
37681 if (okey.dptr) free(okey.dptr);
37684 /* reorg once a day */
37685 if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
37687 @@ -571,7 +568,7 @@
37688 int mod_trigger_b4_dl_plugin_init(plugin *p) {
37689 p->version = LIGHTTPD_VERSION_ID;
37690 p->name = buffer_init_string("trigger_b4_dl");
37693 p->init = mod_trigger_b4_dl_init;
37694 p->handle_uri_clean = mod_trigger_b4_dl_uri_handler;
37695 p->set_defaults = mod_trigger_b4_dl_set_defaults;
37696 @@ -579,8 +576,8 @@
37697 p->handle_trigger = mod_trigger_b4_dl_handle_trigger;
37699 p->cleanup = mod_trigger_b4_dl_free;
37707 --- lighttpd-1.4.11/src/mod_userdir.c 2005-10-28 16:48:28.000000000 +0300
37708 +++ lighttpd-1.4.12/src/mod_userdir.c 2006-07-11 22:07:52.000000000 +0300
37710 #include "response.h"
37712 #include "plugin.h"
37713 +#include "sys-files.h"
37717 @@ -25,54 +26,54 @@
37727 plugin_config **config_storage;
37729 - plugin_config conf;
37731 + plugin_config conf;
37734 /* init the plugin data */
37735 INIT_FUNC(mod_userdir_init) {
37739 p = calloc(1, sizeof(*p));
37742 p->username = buffer_init();
37743 p->temp_path = buffer_init();
37749 /* detroy the plugin data */
37750 FREE_FUNC(mod_userdir_free) {
37751 plugin_data *p = p_d;
37754 if (!p) return HANDLER_GO_ON;
37757 if (p->config_storage) {
37761 for (i = 0; i < srv->config_context->used; i++) {
37762 plugin_config *s = p->config_storage[i];
37765 array_free(s->include_user);
37766 array_free(s->exclude_user);
37767 buffer_free(s->path);
37768 buffer_free(s->basepath);
37773 free(p->config_storage);
37777 buffer_free(p->username);
37778 buffer_free(p->temp_path);
37784 return HANDLER_GO_ON;
37787 @@ -81,81 +82,78 @@
37788 SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
37789 plugin_data *p = p_d;
37792 - config_values_t cv[] = {
37794 + config_values_t cv[] = {
37795 { "userdir.path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
37796 { "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
37797 { "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
37798 { "userdir.basepath", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
37799 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37803 if (!p) return HANDLER_ERROR;
37806 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37809 for (i = 0; i < srv->config_context->used; i++) {
37813 s = calloc(1, sizeof(plugin_config));
37814 s->exclude_user = array_init();
37815 s->include_user = array_init();
37816 s->path = buffer_init();
37817 s->basepath = buffer_init();
37820 cv[0].destination = s->path;
37821 cv[1].destination = s->exclude_user;
37822 cv[2].destination = s->include_user;
37823 cv[3].destination = s->basepath;
37826 p->config_storage[i] = s;
37829 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37830 return HANDLER_ERROR;
37835 return HANDLER_GO_ON;
37838 -#define PATCH(x) \
37839 - p->conf.x = s->x;
37840 static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
37842 plugin_config *s = p->config_storage[0];
37845 - PATCH(exclude_user);
37846 - PATCH(include_user);
37850 + PATCH_OPTION(path);
37851 + PATCH_OPTION(exclude_user);
37852 + PATCH_OPTION(include_user);
37853 + PATCH_OPTION(basepath);
37855 /* skip the first, the global context */
37856 for (i = 1; i < srv->config_context->used; i++) {
37857 data_config *dc = (data_config *)srv->config_context->data[i];
37858 s = p->config_storage[i];
37861 /* condition didn't match */
37862 if (!config_check_cond(srv, con, dc)) continue;
37866 for (j = 0; j < dc->value->used; j++) {
37867 data_unset *du = dc->value->data[j];
37870 if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
37872 + PATCH_OPTION(path);
37873 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
37874 - PATCH(exclude_user);
37875 + PATCH_OPTION(exclude_user);
37876 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
37877 - PATCH(include_user);
37878 + PATCH_OPTION(include_user);
37879 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
37881 + PATCH_OPTION(basepath);
37891 URIHANDLER_FUNC(mod_userdir_docroot_handler) {
37892 plugin_data *p = p_d;
37893 @@ -169,18 +167,18 @@
37894 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37896 mod_userdir_patch_connection(srv, con, p);
37899 uri_len = con->uri.path->used - 1;
37902 /* /~user/foo.html -> /home/user/public_html/foo.html */
37905 if (con->uri.path->ptr[0] != '/' ||
37906 con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
37909 if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
37910 /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
37911 http_response_redirect_to_directory(srv, con);
37914 return HANDLER_FINISHED;
37917 @@ -188,10 +186,10 @@
37918 if (0 == rel_url - (con->uri.path->ptr + 2)) {
37919 return HANDLER_GO_ON;
37923 buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
37925 - if (buffer_is_empty(p->conf.basepath)
37927 + if (buffer_is_empty(p->conf.basepath)
37929 && NULL == (pwd = getpwnam(p->username->ptr))
37931 @@ -200,31 +198,31 @@
37932 return HANDLER_GO_ON;
37937 for (k = 0; k < p->conf.exclude_user->used; k++) {
37938 data_string *ds = (data_string *)p->conf.exclude_user->data[k];
37941 if (buffer_is_equal(ds->value, p->username)) {
37942 /* user in exclude list */
37943 return HANDLER_GO_ON;
37948 if (p->conf.include_user->used) {
37949 int found_user = 0;
37950 for (k = 0; k < p->conf.include_user->used; k++) {
37951 data_string *ds = (data_string *)p->conf.include_user->data[k];
37954 if (buffer_is_equal(ds->value, p->username)) {
37955 /* user in include list */
37962 if (!found_user) return HANDLER_GO_ON;
37966 /* we build the physical path */
37968 if (buffer_is_empty(p->conf.basepath)) {
37969 @@ -252,23 +250,23 @@
37972 buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
37973 - BUFFER_APPEND_SLASH(p->temp_path);
37974 + PATHNAME_APPEND_SLASH(p->temp_path);
37975 buffer_append_string_buffer(p->temp_path, p->username);
37977 - BUFFER_APPEND_SLASH(p->temp_path);
37978 - buffer_append_string_buffer(p->temp_path, p->conf.path);
37979 + PATHNAME_APPEND_SLASH(p->temp_path);
37980 + buffer_append_string_buffer(p->temp_path, p->conf.path);
37982 if (buffer_is_empty(p->conf.basepath)) {
37987 ret = stat(p->temp_path->ptr, &st);
37988 if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
37989 return HANDLER_GO_ON;
37994 - BUFFER_APPEND_SLASH(p->temp_path);
37995 + PATHNAME_APPEND_SLASH(p->temp_path);
37996 buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
37997 buffer_copy_string_buffer(con->physical.path, p->temp_path);
37999 @@ -282,13 +280,13 @@
38000 int mod_userdir_plugin_init(plugin *p) {
38001 p->version = LIGHTTPD_VERSION_ID;
38002 p->name = buffer_init_string("userdir");
38005 p->init = mod_userdir_init;
38006 p->handle_physical = mod_userdir_docroot_handler;
38007 p->set_defaults = mod_userdir_set_defaults;
38008 p->cleanup = mod_userdir_free;
38016 --- lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200
38017 +++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-11 22:07:53.000000000 +0300
38018 @@ -24,44 +24,44 @@
38024 plugin_config **config_storage;
38026 - plugin_config conf;
38028 + plugin_config conf;
38031 /* init the plugin data */
38032 INIT_FUNC(mod_usertrack_init) {
38036 p = calloc(1, sizeof(*p));
38042 /* detroy the plugin data */
38043 FREE_FUNC(mod_usertrack_free) {
38044 plugin_data *p = p_d;
38050 if (!p) return HANDLER_GO_ON;
38053 if (p->config_storage) {
38055 for (i = 0; i < srv->config_context->used; i++) {
38056 plugin_config *s = p->config_storage[i];
38059 buffer_free(s->cookie_name);
38060 buffer_free(s->cookie_domain);
38065 free(p->config_storage);
38072 return HANDLER_GO_ON;
38075 @@ -70,38 +70,38 @@
38076 SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
38077 plugin_data *p = p_d;
38080 - config_values_t cv[] = {
38082 + config_values_t cv[] = {
38083 { "usertrack.cookie-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
38084 { "usertrack.cookie-max-age", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
38085 { "usertrack.cookie-domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
38087 - { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38089 + { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38090 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38094 if (!p) return HANDLER_ERROR;
38097 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38100 for (i = 0; i < srv->config_context->used; i++) {
38104 s = calloc(1, sizeof(plugin_config));
38105 s->cookie_name = buffer_init();
38106 s->cookie_domain = buffer_init();
38107 s->cookie_max_age = 0;
38110 cv[0].destination = s->cookie_name;
38111 cv[1].destination = &(s->cookie_max_age);
38112 cv[2].destination = s->cookie_domain;
38115 p->config_storage[i] = s;
38118 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38119 return HANDLER_ERROR;
38123 if (buffer_is_empty(s->cookie_name)) {
38124 buffer_copy_string(s->cookie_name, "TRACKID");
38126 @@ -109,68 +109,65 @@
38127 for (j = 0; j < s->cookie_name->used - 1; j++) {
38128 char c = s->cookie_name->ptr[j] | 32;
38129 if (c < 'a' || c > 'z') {
38130 - log_error_write(srv, __FILE__, __LINE__, "sb",
38131 - "invalid character in usertrack.cookie-name:",
38132 + log_error_write(srv, __FILE__, __LINE__, "sb",
38133 + "invalid character in usertrack.cookie-name:",
38137 return HANDLER_ERROR;
38143 if (!buffer_is_empty(s->cookie_domain)) {
38145 for (j = 0; j < s->cookie_domain->used - 1; j++) {
38146 char c = s->cookie_domain->ptr[j];
38147 if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
38148 - log_error_write(srv, __FILE__, __LINE__, "sb",
38149 - "invalid character in usertrack.cookie-domain:",
38150 + log_error_write(srv, __FILE__, __LINE__, "sb",
38151 + "invalid character in usertrack.cookie-domain:",
38155 return HANDLER_ERROR;
38162 return HANDLER_GO_ON;
38165 -#define PATCH(x) \
38166 - p->conf.x = s->x;
38167 static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
38169 plugin_config *s = p->config_storage[0];
38171 - PATCH(cookie_name);
38172 - PATCH(cookie_domain);
38173 - PATCH(cookie_max_age);
38176 + PATCH_OPTION(cookie_name);
38177 + PATCH_OPTION(cookie_domain);
38178 + PATCH_OPTION(cookie_max_age);
38180 /* skip the first, the global context */
38181 for (i = 1; i < srv->config_context->used; i++) {
38182 data_config *dc = (data_config *)srv->config_context->data[i];
38183 s = p->config_storage[i];
38186 /* condition didn't match */
38187 if (!config_check_cond(srv, con, dc)) continue;
38191 for (j = 0; j < dc->value->used; j++) {
38192 data_unset *du = dc->value->data[j];
38195 if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
38196 - PATCH(cookie_name);
38197 + PATCH_OPTION(cookie_name);
38198 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
38199 - PATCH(cookie_max_age);
38200 + PATCH_OPTION(cookie_max_age);
38201 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
38202 - PATCH(cookie_domain);
38203 + PATCH_OPTION(cookie_domain);
38213 URIHANDLER_FUNC(mod_usertrack_uri_handler) {
38214 plugin_data *p = p_d;
38215 @@ -178,38 +175,38 @@
38216 unsigned char h[16];
38221 if (con->uri.path->used == 0) return HANDLER_GO_ON;
38224 mod_usertrack_patch_connection(srv, con, p);
38227 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
38229 /* we have a cookie, does it contain a valid name ? */
38231 - /* parse the cookie
38234 + /* parse the cookie
38236 * check for cookiename + (WS | '=')
38242 if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
38247 for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
38251 /* ok, found the key of our own cookie */
38254 if (strlen(nc) > 32) {
38256 return HANDLER_GO_ON;
38265 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
38266 ds = data_response_init();
38267 @@ -217,39 +214,39 @@
38268 buffer_copy_string(ds->key, "Set-Cookie");
38269 buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
38270 buffer_append_string(ds->value, "=");
38274 /* taken from mod_auth.c */
38277 /* generate shared-secret */
38279 MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
38280 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
38283 /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
38284 ltostr(hh, srv->cur_ts);
38285 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38286 ltostr(hh, rand());
38287 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38290 MD5_Final(h, &Md5Ctx);
38293 buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
38294 buffer_append_string(ds->value, "; Path=/");
38295 buffer_append_string(ds->value, "; Version=1");
38298 if (!buffer_is_empty(p->conf.cookie_domain)) {
38299 buffer_append_string(ds->value, "; Domain=");
38300 buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
38304 if (p->conf.cookie_max_age) {
38305 buffer_append_string(ds->value, "; max-age=");
38306 buffer_append_long(ds->value, p->conf.cookie_max_age);
38310 array_insert_unique(con->response.headers, (data_unset *)ds);
38313 return HANDLER_GO_ON;
38316 @@ -258,13 +255,13 @@
38317 int mod_usertrack_plugin_init(plugin *p) {
38318 p->version = LIGHTTPD_VERSION_ID;
38319 p->name = buffer_init_string("usertrack");
38322 p->init = mod_usertrack_init;
38323 p->handle_uri_clean = mod_usertrack_uri_handler;
38324 p->set_defaults = mod_usertrack_set_defaults;
38325 p->cleanup = mod_usertrack_free;
38333 --- lighttpd-1.4.11/src/mod_webdav.c 2006-03-03 01:28:58.000000000 +0200
38334 +++ lighttpd-1.4.12/src/mod_webdav.c 2006-07-11 22:07:53.000000000 +0300
38337 #include <stdlib.h>
38338 #include <string.h>
38339 -#include <dirent.h>
38341 -#include <unistd.h>
38344 #include <assert.h>
38345 -#include <sys/mman.h>
38347 #ifdef HAVE_CONFIG_H
38348 #include "config.h"
38350 #include <sqlite3.h>
38353 +#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
38355 +#include <uuid/uuid.h>
38360 #include "buffer.h"
38361 @@ -33,13 +35,16 @@
38362 #include "stream.h"
38363 #include "stat_cache.h"
38365 +#include "sys-files.h"
38366 +#include "sys-mmap.h"
38367 +#include "sys-strings.h"
38370 * this is a webdav for a lighttpd plugin
38372 - * at least a very basic one.
38373 + * at least a very basic one.
38374 * - for now it is read-only and we only support PROPFIND
38380 @@ -58,64 +63,70 @@
38381 sqlite3_stmt *stmt_delete_prop;
38382 sqlite3_stmt *stmt_select_prop;
38383 sqlite3_stmt *stmt_select_propnames;
38386 sqlite3_stmt *stmt_delete_uri;
38387 sqlite3_stmt *stmt_move_uri;
38388 sqlite3_stmt *stmt_copy_uri;
38390 + sqlite3_stmt *stmt_remove_lock;
38391 + sqlite3_stmt *stmt_create_lock;
38392 + sqlite3_stmt *stmt_read_lock;
38393 + sqlite3_stmt *stmt_read_lock_by_uri;
38394 + sqlite3_stmt *stmt_refresh_lock;
38406 plugin_config **config_storage;
38408 - plugin_config conf;
38410 + plugin_config conf;
38413 /* init the plugin data */
38414 INIT_FUNC(mod_webdav_init) {
38418 p = calloc(1, sizeof(*p));
38421 p->tmp_buf = buffer_init();
38423 p->uri.scheme = buffer_init();
38424 p->uri.path_raw = buffer_init();
38425 p->uri.path = buffer_init();
38426 p->uri.authority = buffer_init();
38429 p->physical.path = buffer_init();
38430 p->physical.rel_path = buffer_init();
38431 p->physical.doc_root = buffer_init();
38432 p->physical.basedir = buffer_init();
38438 /* detroy the plugin data */
38439 FREE_FUNC(mod_webdav_free) {
38440 plugin_data *p = p_d;
38445 if (!p) return HANDLER_GO_ON;
38448 if (p->config_storage) {
38450 for (i = 0; i < srv->config_context->used; i++) {
38451 plugin_config *s = p->config_storage[i];
38456 buffer_free(s->sqlite_db_name);
38457 #ifdef USE_PROPPATCH
38460 sqlite3_finalize(s->stmt_delete_prop);
38461 sqlite3_finalize(s->stmt_delete_uri);
38462 sqlite3_finalize(s->stmt_copy_uri);
38463 @@ -123,9 +134,15 @@
38464 sqlite3_finalize(s->stmt_update_prop);
38465 sqlite3_finalize(s->stmt_select_prop);
38466 sqlite3_finalize(s->stmt_select_propnames);
38468 + sqlite3_finalize(s->stmt_read_lock);
38469 + sqlite3_finalize(s->stmt_read_lock_by_uri);
38470 + sqlite3_finalize(s->stmt_create_lock);
38471 + sqlite3_finalize(s->stmt_remove_lock);
38472 + sqlite3_finalize(s->stmt_refresh_lock);
38473 sqlite3_close(s->sql);
38479 free(p->config_storage);
38480 @@ -135,16 +152,16 @@
38481 buffer_free(p->uri.path_raw);
38482 buffer_free(p->uri.path);
38483 buffer_free(p->uri.authority);
38486 buffer_free(p->physical.path);
38487 buffer_free(p->physical.rel_path);
38488 buffer_free(p->physical.doc_root);
38489 buffer_free(p->physical.basedir);
38492 buffer_free(p->tmp_buf);
38498 return HANDLER_GO_ON;
38501 @@ -153,32 +170,32 @@
38502 SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
38503 plugin_data *p = p_d;
38506 - config_values_t cv[] = {
38508 + config_values_t cv[] = {
38509 { "webdav.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
38510 { "webdav.is-readonly", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
38511 { "webdav.sqlite-db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
38512 { "webdav.log-xml", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
38513 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38517 if (!p) return HANDLER_ERROR;
38520 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38523 for (i = 0; i < srv->config_context->used; i++) {
38527 s = calloc(1, sizeof(plugin_config));
38528 s->sqlite_db_name = buffer_init();
38531 cv[0].destination = &(s->enabled);
38532 cv[1].destination = &(s->is_readonly);
38533 cv[2].destination = s->sqlite_db_name;
38534 cv[3].destination = &(s->log_xml);
38537 p->config_storage[i] = s;
38540 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38541 return HANDLER_ERROR;
38543 @@ -193,8 +210,26 @@
38544 return HANDLER_ERROR;
38547 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38548 - CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38549 + if (SQLITE_OK != sqlite3_exec(s->sql,
38550 + "CREATE TABLE properties ("
38551 + " resource TEXT NOT NULL,"
38552 + " prop TEXT NOT NULL,"
38553 + " ns TEXT NOT NULL,"
38554 + " value TEXT NOT NULL,"
38555 + " PRIMARY KEY(resource, prop, ns))",
38556 + NULL, NULL, &err)) {
38558 + if (0 != strcmp(err, "table properties already exists")) {
38559 + log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38560 + sqlite3_free(err);
38562 + return HANDLER_ERROR;
38564 + sqlite3_free(err);
38567 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38568 + CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38569 &(s->stmt_select_prop), &next_stmt)) {
38570 /* prepare failed */
38572 @@ -202,8 +237,8 @@
38573 return HANDLER_ERROR;
38576 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38577 - CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
38578 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38579 + CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
38580 &(s->stmt_select_propnames), &next_stmt)) {
38581 /* prepare failed */
38583 @@ -211,16 +246,67 @@
38584 return HANDLER_ERROR;
38587 - if (SQLITE_OK != sqlite3_exec(s->sql,
38588 - "CREATE TABLE properties ("
38590 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38591 + CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
38592 + &(s->stmt_update_prop), &next_stmt)) {
38593 + /* prepare failed */
38595 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38596 + return HANDLER_ERROR;
38599 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38600 + CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38601 + &(s->stmt_delete_prop), &next_stmt)) {
38602 + /* prepare failed */
38603 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38605 + return HANDLER_ERROR;
38608 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38609 + CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
38610 + &(s->stmt_delete_uri), &next_stmt)) {
38611 + /* prepare failed */
38612 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38614 + return HANDLER_ERROR;
38617 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38618 + CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
38619 + &(s->stmt_copy_uri), &next_stmt)) {
38620 + /* prepare failed */
38621 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38623 + return HANDLER_ERROR;
38626 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38627 + CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
38628 + &(s->stmt_move_uri), &next_stmt)) {
38629 + /* prepare failed */
38630 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38632 + return HANDLER_ERROR;
38637 + if (SQLITE_OK != sqlite3_exec(s->sql,
38638 + "CREATE TABLE locks ("
38639 + " locktoken TEXT NOT NULL,"
38640 " resource TEXT NOT NULL,"
38641 - " prop TEXT NOT NULL,"
38642 - " ns TEXT NOT NULL,"
38643 - " value TEXT NOT NULL,"
38644 - " PRIMARY KEY(resource, prop, ns))",
38645 + " lockscope TEXT NOT NULL,"
38646 + " locktype TEXT NOT NULL,"
38647 + " owner TEXT NOT NULL,"
38648 + " depth INT NOT NULL,"
38649 + " timeout TIMESTAMP NOT NULL,"
38650 + " PRIMARY KEY(locktoken))",
38651 NULL, NULL, &err)) {
38653 - if (0 != strcmp(err, "table properties already exists")) {
38654 + if (0 != strcmp(err, "table locks already exists")) {
38655 log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38658 @@ -228,127 +314,138 @@
38663 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38664 - CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
38665 - &(s->stmt_update_prop), &next_stmt)) {
38667 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38668 + CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
38669 + &(s->stmt_create_lock), &next_stmt)) {
38670 /* prepare failed */
38671 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38673 - log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38674 return HANDLER_ERROR;
38677 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38678 - CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38679 - &(s->stmt_delete_prop), &next_stmt)) {
38680 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38681 + CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
38682 + &(s->stmt_remove_lock), &next_stmt)) {
38683 /* prepare failed */
38684 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38686 return HANDLER_ERROR;
38689 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38690 - CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
38691 - &(s->stmt_delete_uri), &next_stmt)) {
38692 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38693 + CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
38694 + &(s->stmt_read_lock), &next_stmt)) {
38695 /* prepare failed */
38696 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38698 return HANDLER_ERROR;
38701 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38702 - CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
38703 - &(s->stmt_copy_uri), &next_stmt)) {
38704 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38705 + CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
38706 + &(s->stmt_read_lock_by_uri), &next_stmt)) {
38707 /* prepare failed */
38708 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38710 return HANDLER_ERROR;
38713 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38714 - CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
38715 - &(s->stmt_move_uri), &next_stmt)) {
38716 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38717 + CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
38718 + &(s->stmt_refresh_lock), &next_stmt)) {
38719 /* prepare failed */
38720 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38722 return HANDLER_ERROR;
38727 log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
38728 return HANDLER_ERROR;
38734 return HANDLER_GO_ON;
38737 -#define PATCH(x) \
38738 - p->conf.x = s->x;
38739 static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
38741 plugin_config *s = p->config_storage[0];
38744 - PATCH(is_readonly);
38748 + PATCH_OPTION(enabled);
38749 + PATCH_OPTION(is_readonly);
38750 + PATCH_OPTION(log_xml);
38752 #ifdef USE_PROPPATCH
38754 - PATCH(stmt_update_prop);
38755 - PATCH(stmt_delete_prop);
38756 - PATCH(stmt_select_prop);
38757 - PATCH(stmt_select_propnames);
38759 - PATCH(stmt_delete_uri);
38760 - PATCH(stmt_move_uri);
38761 - PATCH(stmt_copy_uri);
38762 + PATCH_OPTION(sql);
38763 + PATCH_OPTION(stmt_update_prop);
38764 + PATCH_OPTION(stmt_delete_prop);
38765 + PATCH_OPTION(stmt_select_prop);
38766 + PATCH_OPTION(stmt_select_propnames);
38768 + PATCH_OPTION(stmt_delete_uri);
38769 + PATCH_OPTION(stmt_move_uri);
38770 + PATCH_OPTION(stmt_copy_uri);
38772 + PATCH_OPTION(stmt_remove_lock);
38773 + PATCH_OPTION(stmt_refresh_lock);
38774 + PATCH_OPTION(stmt_create_lock);
38775 + PATCH_OPTION(stmt_read_lock);
38776 + PATCH_OPTION(stmt_read_lock_by_uri);
38778 /* skip the first, the global context */
38779 for (i = 1; i < srv->config_context->used; i++) {
38780 data_config *dc = (data_config *)srv->config_context->data[i];
38781 s = p->config_storage[i];
38784 /* condition didn't match */
38785 if (!config_check_cond(srv, con, dc)) continue;
38789 for (j = 0; j < dc->value->used; j++) {
38790 data_unset *du = dc->value->data[j];
38793 if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
38795 + PATCH_OPTION(enabled);
38796 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
38797 - PATCH(is_readonly);
38798 + PATCH_OPTION(is_readonly);
38799 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
38801 + PATCH_OPTION(log_xml);
38802 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
38803 #ifdef USE_PROPPATCH
38805 - PATCH(stmt_update_prop);
38806 - PATCH(stmt_delete_prop);
38807 - PATCH(stmt_select_prop);
38808 - PATCH(stmt_select_propnames);
38810 - PATCH(stmt_delete_uri);
38811 - PATCH(stmt_move_uri);
38812 - PATCH(stmt_copy_uri);
38813 + PATCH_OPTION(sql);
38814 + PATCH_OPTION(stmt_update_prop);
38815 + PATCH_OPTION(stmt_delete_prop);
38816 + PATCH_OPTION(stmt_select_prop);
38817 + PATCH_OPTION(stmt_select_propnames);
38819 + PATCH_OPTION(stmt_delete_uri);
38820 + PATCH_OPTION(stmt_move_uri);
38821 + PATCH_OPTION(stmt_copy_uri);
38823 + PATCH_OPTION(stmt_remove_lock);
38824 + PATCH_OPTION(stmt_refresh_lock);
38825 + PATCH_OPTION(stmt_create_lock);
38826 + PATCH_OPTION(stmt_read_lock);
38827 + PATCH_OPTION(stmt_read_lock_by_uri);
38838 URIHANDLER_FUNC(mod_webdav_uri_handler) {
38839 plugin_data *p = p_d;
38844 if (con->uri.path->used == 0) return HANDLER_GO_ON;
38847 mod_webdav_patch_connection(srv, con, p);
38849 if (!p->conf.enabled) return HANDLER_GO_ON;
38850 @@ -362,20 +459,20 @@
38851 if (p->conf.is_readonly) {
38852 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
38854 - response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
38855 + response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
38864 return HANDLER_GO_ON;
38866 -static int webdav_gen_prop_tag(server *srv, connection *con,
38870 +static int webdav_gen_prop_tag(server *srv, connection *con,
38877 @@ -414,7 +511,7 @@
38878 buffer_append_string_buffer(b, dst->rel_path);
38879 buffer_append_string(b,"</D:href>\n");
38880 buffer_append_string(b,"<D:status>\n");
38883 if (con->request.http_version == HTTP_VERSION_1_1) {
38884 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
38886 @@ -458,11 +555,11 @@
38888 /* bind the values to the insert */
38890 - sqlite3_bind_text(stmt, 1,
38891 - dst->rel_path->ptr,
38892 + sqlite3_bind_text(stmt, 1,
38893 + dst->rel_path->ptr,
38894 dst->rel_path->used - 1,
38898 if (SQLITE_DONE != sqlite3_step(stmt)) {
38901 @@ -493,14 +590,14 @@
38902 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38904 /* ignore the parent dir */
38908 buffer_copy_string_buffer(d.path, dst->path);
38909 - BUFFER_APPEND_SLASH(d.path);
38910 + PATHNAME_APPEND_SLASH(d.path);
38911 buffer_append_string(d.path, de->d_name);
38914 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
38915 - BUFFER_APPEND_SLASH(d.rel_path);
38916 + PATHNAME_APPEND_SLASH(d.rel_path);
38917 buffer_append_string(d.rel_path, de->d_name);
38919 /* stat and unlink afterwards */
38920 @@ -508,7 +605,7 @@
38921 /* don't about it yet, rmdir will fail too */
38922 } else if (S_ISDIR(st.st_mode)) {
38923 have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
38926 /* try to unlink it */
38927 if (-1 == rmdir(d.path->ptr)) {
38929 @@ -535,11 +632,11 @@
38931 /* bind the values to the insert */
38933 - sqlite3_bind_text(stmt, 1,
38935 + sqlite3_bind_text(stmt, 1,
38937 d.rel_path->used - 1,
38941 if (SQLITE_DONE != sqlite3_step(stmt)) {
38944 @@ -569,7 +666,7 @@
38945 if (stream_open(&s, src->path)) {
38950 if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) {
38951 /* opening the destination failed for some reason */
38953 @@ -601,7 +698,7 @@
38962 @@ -614,16 +711,16 @@
38963 sqlite3_reset(stmt);
38965 /* bind the values to the insert */
38966 - sqlite3_bind_text(stmt, 1,
38967 - dst->rel_path->ptr,
38968 + sqlite3_bind_text(stmt, 1,
38969 + dst->rel_path->ptr,
38970 dst->rel_path->used - 1,
38973 - sqlite3_bind_text(stmt, 2,
38974 - src->rel_path->ptr,
38975 + sqlite3_bind_text(stmt, 2,
38976 + src->rel_path->ptr,
38977 src->rel_path->used - 1,
38981 if (SQLITE_DONE != sqlite3_step(stmt)) {
38984 @@ -655,21 +752,21 @@
38985 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38990 buffer_copy_string_buffer(s.path, src->path);
38991 - BUFFER_APPEND_SLASH(s.path);
38992 + PATHNAME_APPEND_SLASH(s.path);
38993 buffer_append_string(s.path, de->d_name);
38995 buffer_copy_string_buffer(d.path, dst->path);
38996 - BUFFER_APPEND_SLASH(d.path);
38997 + PATHNAME_APPEND_SLASH(d.path);
38998 buffer_append_string(d.path, de->d_name);
39000 buffer_copy_string_buffer(s.rel_path, src->rel_path);
39001 - BUFFER_APPEND_SLASH(s.rel_path);
39002 + PATHNAME_APPEND_SLASH(s.rel_path);
39003 buffer_append_string(s.rel_path, de->d_name);
39005 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39006 - BUFFER_APPEND_SLASH(d.rel_path);
39007 + PATHNAME_APPEND_SLASH(d.rel_path);
39008 buffer_append_string(d.rel_path, de->d_name);
39010 if (-1 == stat(s.path->ptr, &st)) {
39011 @@ -692,16 +789,16 @@
39012 sqlite3_reset(stmt);
39014 /* bind the values to the insert */
39015 - sqlite3_bind_text(stmt, 1,
39016 - dst->rel_path->ptr,
39017 + sqlite3_bind_text(stmt, 1,
39018 + dst->rel_path->ptr,
39019 dst->rel_path->used - 1,
39022 - sqlite3_bind_text(stmt, 2,
39023 - src->rel_path->ptr,
39024 + sqlite3_bind_text(stmt, 2,
39025 + src->rel_path->ptr,
39026 src->rel_path->used - 1,
39030 if (SQLITE_DONE != sqlite3_step(stmt)) {
39033 @@ -721,7 +818,7 @@
39034 buffer_free(s.rel_path);
39035 buffer_free(d.path);
39036 buffer_free(d.rel_path);
39042 @@ -748,12 +845,12 @@
39043 if (S_ISDIR(sce->st.st_mode)) {
39044 buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
39046 - } else if(S_ISREG(sce->st.st_mode)) {
39047 + } else if(S_ISREG(sce->st.st_mode)) {
39048 for (k = 0; k < con->conf.mimetypes->used; k++) {
39049 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
39052 if (ds->key->used == 0) continue;
39055 if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
39056 buffer_append_string(b,"<D:getcontenttype>");
39057 buffer_append_string_buffer(b, ds->value);
39058 @@ -807,23 +904,23 @@
39060 /* bind the values to the insert */
39062 - sqlite3_bind_text(stmt, 1,
39063 - dst->rel_path->ptr,
39064 + sqlite3_bind_text(stmt, 1,
39065 + dst->rel_path->ptr,
39066 dst->rel_path->used - 1,
39068 - sqlite3_bind_text(stmt, 2,
39069 + sqlite3_bind_text(stmt, 2,
39073 - sqlite3_bind_text(stmt, 3,
39074 + sqlite3_bind_text(stmt, 3,
39080 - while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
39081 + while (SQLITE_ROW == sqlite3_step(stmt)) {
39082 /* there is a row for us, we only expect a single col 'value' */
39083 - webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
39084 + webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
39088 @@ -840,7 +937,7 @@
39092 -webdav_property live_properties[] = {
39093 +webdav_property live_properties[] = {
39094 { "DAV:", "creationdate" },
39095 { "DAV:", "displayname" },
39096 { "DAV:", "getcontentlanguage" },
39097 @@ -871,8 +968,8 @@
39098 webdav_property *prop;
39100 prop = props->ptr[i];
39102 - if (0 != webdav_get_property(srv, con, p,
39104 + if (0 != webdav_get_property(srv, con, p,
39105 dst, prop->prop, prop->ns, b_200)) {
39106 webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
39108 @@ -916,12 +1013,12 @@
39109 if (-1 == c->file.fd && /* open the file if not already open */
39110 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39111 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39118 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39119 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39120 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39121 strerror(errno), c->file.name, c->file.fd);
39124 @@ -938,7 +1035,7 @@
39125 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
39126 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39130 c->offset += weHave;
39131 cq->bytes_out += weHave;
39133 @@ -956,7 +1053,7 @@
39134 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
39135 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39139 c->offset += weHave;
39140 cq->bytes_out += weHave;
39142 @@ -991,6 +1088,113 @@
39146 +int webdav_lockdiscovery(server *srv, connection *con,
39147 + buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
39151 + response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
39153 + response_header_overwrite(srv, con,
39154 + CONST_STR_LEN("Content-Type"),
39155 + CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39157 + b = chunkqueue_get_append_buffer(con->write_queue);
39159 + buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39161 + buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39162 + buffer_append_string(b,"<D:lockdiscovery>\n");
39163 + buffer_append_string(b,"<D:activelock>\n");
39165 + buffer_append_string(b,"<D:lockscope>");
39166 + buffer_append_string(b,"<D:");
39167 + buffer_append_string(b, lockscope);
39168 + buffer_append_string(b, "/>");
39169 + buffer_append_string(b,"</D:lockscope>\n");
39171 + buffer_append_string(b,"<D:locktype>");
39172 + buffer_append_string(b,"<D:");
39173 + buffer_append_string(b, locktype);
39174 + buffer_append_string(b, "/>");
39175 + buffer_append_string(b,"</D:locktype>\n");
39177 + buffer_append_string(b,"<D:depth>");
39178 + buffer_append_string(b, depth == 0 ? "0" : "infinity");
39179 + buffer_append_string(b,"</D:depth>\n");
39181 + buffer_append_string(b,"<D:timeout>");
39182 + buffer_append_string(b, "Second-600");
39183 + buffer_append_string(b,"</D:timeout>\n");
39185 + buffer_append_string(b,"<D:owner>");
39186 + buffer_append_string(b,"</D:owner>\n");
39188 + buffer_append_string(b,"<D:locktoken>");
39189 + buffer_append_string(b, "<D:href>");
39190 + buffer_append_string_buffer(b, locktoken);
39191 + buffer_append_string(b, "</D:href>");
39192 + buffer_append_string(b,"</D:locktoken>\n");
39194 + buffer_append_string(b,"</D:activelock>\n");
39195 + buffer_append_string(b,"</D:lockdiscovery>\n");
39196 + buffer_append_string(b,"</D:prop>\n");
39201 + * check if resource is having the right locks to access to resource
39206 +int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
39207 + int has_lock = 1;
39217 + * there is NOT, AND and OR
39218 + * and a list can be tagged
39220 + * (<lock-token>) is untagged
39221 + * <tag> (<lock-token>) is tagged
39223 + * as long as we don't handle collections it is simple. :)
39225 + * X-Litmus: locks: 11 (owner_modify)
39226 + * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
39228 + * X-Litmus: locks: 16 (fail_cond_put)
39229 + * If: (<DAV:no-lock> ["-1622396671"])
39231 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39233 + /* we didn't provided a lock-token -> */
39234 + /* if the resource is locked -> 423 */
39236 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39238 + sqlite3_reset(stmt);
39240 + sqlite3_bind_text(stmt, 1,
39241 + CONST_BUF_LEN(uri),
39242 + SQLITE_TRANSIENT);
39244 + while (SQLITE_ROW == sqlite3_step(stmt)) {
39253 URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
39254 plugin_data *p = p_d;
39256 @@ -1001,7 +1205,8 @@
39259 webdav_properties *req_props;
39261 + stat_cache_entry *sce = NULL;
39265 if (!p->conf.enabled) return HANDLER_GO_ON;
39266 @@ -1019,7 +1224,19 @@
39269 /* is there a content-body ? */
39272 + switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
39273 + case HANDLER_ERROR:
39274 + if (errno == ENOENT) {
39275 + con->http_status = 404;
39276 + return HANDLER_FINISHED;
39284 #ifdef USE_PROPPATCH
39285 /* any special requests or just allprop ? */
39286 if (con->request.content_length) {
39287 @@ -1087,12 +1304,12 @@
39288 /* get all property names (EMPTY) */
39289 sqlite3_reset(stmt);
39290 /* bind the values to the insert */
39292 - sqlite3_bind_text(stmt, 1,
39293 - con->uri.path->ptr,
39295 + sqlite3_bind_text(stmt, 1,
39296 + con->uri.path->ptr,
39297 con->uri.path->used - 1,
39301 if (SQLITE_DONE != sqlite3_step(stmt)) {
39304 @@ -1115,13 +1332,13 @@
39305 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39307 b = chunkqueue_get_append_buffer(con->write_queue);
39310 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39312 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39317 prop_200 = buffer_init();
39318 prop_404 = buffer_init();
39320 @@ -1129,7 +1346,7 @@
39323 webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
39326 buffer_append_string(b,"<D:response>\n");
39327 buffer_append_string(b,"<D:href>");
39328 buffer_append_string_buffer(b, con->uri.scheme);
39329 @@ -1145,9 +1362,9 @@
39330 buffer_append_string_buffer(b, prop_200);
39332 buffer_append_string(b,"</D:prop>\n");
39335 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39338 buffer_append_string(b,"</D:propstat>\n");
39340 if (!buffer_is_empty(prop_404)) {
39341 @@ -1157,16 +1374,16 @@
39342 buffer_append_string_buffer(b, prop_404);
39344 buffer_append_string(b,"</D:prop>\n");
39347 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39350 buffer_append_string(b,"</D:propstat>\n");
39353 buffer_append_string(b,"</D:response>\n");
39358 if (NULL != (dir = opendir(con->physical.path->ptr))) {
39361 @@ -1179,16 +1396,16 @@
39362 if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
39364 /* ignore the parent dir */
39368 buffer_copy_string_buffer(d.path, dst->path);
39369 - BUFFER_APPEND_SLASH(d.path);
39370 + PATHNAME_APPEND_SLASH(d.path);
39372 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39373 - BUFFER_APPEND_SLASH(d.rel_path);
39374 + PATHNAME_APPEND_SLASH(d.rel_path);
39376 if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
39377 - /* don't append the . */
39378 + /* don't append the . */
39380 buffer_append_string(d.path, de->d_name);
39381 buffer_append_string(d.rel_path, de->d_name);
39382 @@ -1198,7 +1415,7 @@
39383 buffer_reset(prop_404);
39385 webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
39388 buffer_append_string(b,"<D:response>\n");
39389 buffer_append_string(b,"<D:href>");
39390 buffer_append_string_buffer(b, con->uri.scheme);
39391 @@ -1214,9 +1431,9 @@
39392 buffer_append_string_buffer(b, prop_200);
39394 buffer_append_string(b,"</D:prop>\n");
39397 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39400 buffer_append_string(b,"</D:propstat>\n");
39402 if (!buffer_is_empty(prop_404)) {
39403 @@ -1226,9 +1443,9 @@
39404 buffer_append_string_buffer(b, prop_404);
39406 buffer_append_string(b,"</D:prop>\n");
39409 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39412 buffer_append_string(b,"</D:propstat>\n");
39415 @@ -1275,7 +1492,7 @@
39417 return HANDLER_FINISHED;
39421 /* let's create the directory */
39423 if (-1 == mkdir(con->physical.path->ptr, 0700)) {
39424 @@ -1303,7 +1520,13 @@
39425 con->http_status = 403;
39426 return HANDLER_FINISHED;
39430 + /* does the client have a lock for this connection ? */
39431 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39432 + con->http_status = 423;
39433 + return HANDLER_FINISHED;
39436 /* stat and unlink afterwards */
39437 if (-1 == stat(con->physical.path->ptr, &st)) {
39438 /* don't about it yet, unlink will fail too */
39439 @@ -1323,7 +1546,7 @@
39440 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39442 b = chunkqueue_get_append_buffer(con->write_queue);
39445 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39447 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
39448 @@ -1331,7 +1554,7 @@
39449 buffer_append_string_buffer(b, multi_status_resp);
39451 buffer_append_string(b,"</D:multistatus>\n");
39454 if (p->conf.log_xml) {
39455 log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
39457 @@ -1340,7 +1563,7 @@
39458 con->file_finished = 1;
39460 /* everything went fine, remove the directory */
39463 if (-1 == rmdir(con->physical.path->ptr)) {
39466 @@ -1375,97 +1598,174 @@
39467 case HTTP_METHOD_PUT: {
39469 chunkqueue *cq = con->request_content_queue;
39471 + data_string *ds_range;
39473 if (p->conf.is_readonly) {
39474 con->http_status = 403;
39475 return HANDLER_FINISHED;
39478 + /* is a exclusive lock set on the source */
39479 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39480 + con->http_status = 423;
39481 + return HANDLER_FINISHED;
39485 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
39487 - /* taken what we have in the request-body and write it to a file */
39488 - if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
39489 - /* we can't open the file */
39490 - con->http_status = 403;
39493 + /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
39494 + * - most important Content-Range
39497 + * Example: Content-Range: bytes 100-1037/1038 */
39499 - con->http_status = 201; /* created */
39500 - con->file_finished = 1;
39501 + if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
39502 + const char *num = ds_range->value->ptr;
39504 + char *err = NULL;
39506 - for (c = cq->first; c; c = cq->first) {
39508 + if (0 != strncmp(num, "bytes ", 6)) {
39509 + con->http_status = 501; /* not implemented */
39511 - /* copy all chunks */
39512 - switch(c->type) {
39515 - if (c->file.mmap.start == MAP_FAILED) {
39516 - if (-1 == c->file.fd && /* open the file if not already open */
39517 - -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39518 - log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39523 - if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39524 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39525 - strerror(errno), c->file.name, c->file.fd);
39526 + return HANDLER_FINISHED;
39531 + /* we only support <num>- ... */
39533 - c->file.mmap.length = c->file.length;
39536 - close(c->file.fd);
39539 - /* chunk_reset() or chunk_free() will cleanup for us */
39542 - if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39545 - con->http_status = 507;
39549 - con->http_status = 403;
39555 - if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39558 - con->http_status = 507;
39562 - con->http_status = 403;
39567 + while (*num == ' ' || *num == '\t') num++;
39569 + if (*num == '\0') {
39570 + con->http_status = 501; /* not implemented */
39572 + return HANDLER_FINISHED;
39575 + offset = strtoll(num, &err, 10);
39577 + if (*err != '-' || offset < 0) {
39578 + con->http_status = 501; /* not implemented */
39580 + return HANDLER_FINISHED;
39583 + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
39586 + con->http_status = 404; /* not found */
39588 - case UNUSED_CHUNK:
39590 + con->http_status = 403; /* not found */
39593 + return HANDLER_FINISHED;
39596 + if (-1 == lseek(fd, offset, SEEK_SET)) {
39597 + con->http_status = 501; /* not implemented */
39601 + return HANDLER_FINISHED;
39603 + con->http_status = 200; /* modified */
39605 + /* take what we have in the request-body and write it to a file */
39607 + /* if the file doesn't exist, create it */
39608 + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
39609 + if (errno == ENOENT &&
39610 + -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
39611 + /* we can't open the file */
39612 + con->http_status = 403;
39616 - cq->bytes_out += r;
39617 + return HANDLER_FINISHED;
39620 + con->http_status = 201; /* created */
39623 + con->http_status = 200; /* modified */
39627 + con->file_finished = 1;
39629 + for (c = cq->first; c; c = cq->first) {
39632 + /* copy all chunks */
39633 + switch(c->type) {
39636 + if (c->file.mmap.start == MAP_FAILED) {
39637 + if (-1 == c->file.fd && /* open the file if not already open */
39638 + -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39639 + log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39644 + if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39645 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39646 + strerror(errno), c->file.name, c->file.fd);
39651 + c->file.mmap.length = c->file.length;
39653 + close(c->file.fd);
39656 + /* chunk_reset() or chunk_free() will cleanup for us */
39659 + if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39662 + con->http_status = 507;
39666 + con->http_status = 403;
39670 - chunkqueue_remove_finished_chunks(cq);
39673 + if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39676 + con->http_status = 507;
39680 + con->http_status = 403;
39685 + case UNUSED_CHUNK:
39692 + cq->bytes_out += r;
39696 + chunkqueue_remove_finished_chunks(cq);
39700 return HANDLER_FINISHED;
39702 - case HTTP_METHOD_MOVE:
39703 + case HTTP_METHOD_MOVE:
39704 case HTTP_METHOD_COPY: {
39705 buffer *destination = NULL;
39707 @@ -1475,7 +1775,15 @@
39708 con->http_status = 403;
39709 return HANDLER_FINISHED;
39713 + /* is a exclusive lock set on the source */
39714 + if (con->request.http_method == HTTP_METHOD_MOVE) {
39715 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39716 + con->http_status = 423;
39717 + return HANDLER_FINISHED;
39721 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
39722 destination = ds->value;
39724 @@ -1549,10 +1857,10 @@
39727 buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
39728 - BUFFER_APPEND_SLASH(p->physical.path);
39729 + PATHNAME_APPEND_SLASH(p->physical.path);
39730 buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
39732 - /* don't add a second / */
39733 + /* don't add a second / */
39734 if (p->physical.rel_path->ptr[0] == '/') {
39735 buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
39737 @@ -1613,6 +1921,12 @@
39738 /* it is just a file, good */
39741 + /* does the client have a lock for this connection ? */
39742 + if (!webdav_has_lock(srv, con, p, p->uri.path)) {
39743 + con->http_status = 423;
39744 + return HANDLER_FINISHED;
39747 /* destination exists */
39748 if (0 == (r = stat(p->physical.path->ptr, &st))) {
39749 if (S_ISDIR(st.st_mode)) {
39750 @@ -1636,7 +1950,7 @@
39751 return HANDLER_FINISHED;
39753 } else if (overwrite == 0) {
39754 - /* destination exists, but overwrite is not set */
39755 + /* destination exists, but overwrite is not set */
39756 con->http_status = 412;
39757 return HANDLER_FINISHED;
39759 @@ -1655,16 +1969,16 @@
39760 sqlite3_reset(stmt);
39762 /* bind the values to the insert */
39763 - sqlite3_bind_text(stmt, 1,
39764 - p->uri.path->ptr,
39765 + sqlite3_bind_text(stmt, 1,
39766 + p->uri.path->ptr,
39767 p->uri.path->used - 1,
39770 - sqlite3_bind_text(stmt, 2,
39771 - con->uri.path->ptr,
39772 + sqlite3_bind_text(stmt, 2,
39773 + con->uri.path->ptr,
39774 con->uri.path->used - 1,
39778 if (SQLITE_DONE != sqlite3_step(stmt)) {
39779 log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
39781 @@ -1691,12 +2005,17 @@
39783 return HANDLER_FINISHED;
39785 - case HTTP_METHOD_PROPPATCH: {
39786 + case HTTP_METHOD_PROPPATCH:
39787 if (p->conf.is_readonly) {
39788 con->http_status = 403;
39789 return HANDLER_FINISHED;
39792 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39793 + con->http_status = 423;
39794 + return HANDLER_FINISHED;
39797 /* check if destination exists */
39798 if (-1 == stat(con->physical.path->ptr, &st)) {
39800 @@ -1737,7 +2056,7 @@
39802 sqlite3_stmt *stmt;
39804 - stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
39805 + stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
39806 p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
39808 for (props = cmd->children; props; props = props->next) {
39809 @@ -1762,34 +2081,35 @@
39811 /* bind the values to the insert */
39813 - sqlite3_bind_text(stmt, 1,
39814 - con->uri.path->ptr,
39815 + sqlite3_bind_text(stmt, 1,
39816 + con->uri.path->ptr,
39817 con->uri.path->used - 1,
39819 - sqlite3_bind_text(stmt, 2,
39820 + sqlite3_bind_text(stmt, 2,
39821 (char *)prop->name,
39822 strlen((char *)prop->name),
39825 - sqlite3_bind_text(stmt, 3,
39826 + sqlite3_bind_text(stmt, 3,
39827 (char *)prop->ns->href,
39828 strlen((char *)prop->ns->href),
39831 - sqlite3_bind_text(stmt, 3,
39832 + sqlite3_bind_text(stmt, 3,
39837 if (stmt == p->conf.stmt_update_prop) {
39838 - sqlite3_bind_text(stmt, 4,
39839 + sqlite3_bind_text(stmt, 4,
39840 (char *)xmlNodeGetContent(prop),
39841 strlen((char *)xmlNodeGetContent(prop)),
39846 if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
39847 - log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39848 + log_error_write(srv, __FILE__, __LINE__, "ss",
39849 + "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39853 @@ -1804,7 +2124,7 @@
39855 goto propmatch_cleanup;
39859 con->http_status = 400;
39861 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
39862 @@ -1821,6 +2141,7 @@
39869 con->http_status = 400;
39870 @@ -1830,11 +2151,307 @@
39872 con->http_status = 501;
39873 return HANDLER_FINISHED;
39875 + case HTTP_METHOD_LOCK:
39877 + * a mac wants to write
39879 + * LOCK /dav/expire.txt HTTP/1.1\r\n
39880 + * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
39881 + * Accept: * / *\r\n
39883 + * Timeout: Second-600\r\n
39884 + * Content-Type: text/xml; charset=\"utf-8\"\r\n
39885 + * Content-Length: 229\r\n
39886 + * Connection: keep-alive\r\n
39887 + * Host: 192.168.178.23:1025\r\n
39889 + * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
39890 + * <D:lockinfo xmlns:D=\"DAV:\">\n
39891 + * <D:lockscope><D:exclusive/></D:lockscope>\n
39892 + * <D:locktype><D:write/></D:locktype>\n
39894 + * <D:href>http://www.apple.com/webdav_fs/</D:href>\n
39896 + * </D:lockinfo>\n
39899 + if (depth != 0 && depth != -1) {
39900 + con->http_status = 400;
39902 + return HANDLER_FINISHED;
39906 + if (con->request.content_length) {
39908 + buffer *hdr_if = NULL;
39910 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39911 + hdr_if = ds->value;
39914 + /* we don't support Depth: Infinity on locks */
39915 + if (hdr_if == NULL && depth == -1) {
39916 + con->http_status = 409; /* Conflict */
39918 + return HANDLER_FINISHED;
39921 + if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
39922 + xmlNode *rootnode = xmlDocGetRootElement(xml);
39924 + assert(rootnode);
39926 + if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
39927 + xmlNode *lockinfo;
39928 + const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
39930 + for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
39931 + if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
39933 + for (value = lockinfo->children; value; value = value->next) {
39934 + if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
39935 + (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
39936 + lockscope = value->name;
39938 + con->http_status = 400;
39941 + return HANDLER_FINISHED;
39944 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
39946 + for (value = lockinfo->children; value; value = value->next) {
39947 + if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
39948 + locktype = value->name;
39950 + con->http_status = 400;
39953 + return HANDLER_FINISHED;
39957 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
39961 + if (lockscope && locktype) {
39962 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39964 + /* is this resourse already locked ? */
39966 + /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
39968 + * WHERE resource = ? */
39972 + sqlite3_reset(stmt);
39974 + sqlite3_bind_text(stmt, 1,
39975 + p->uri.path->ptr,
39976 + p->uri.path->used - 1,
39977 + SQLITE_TRANSIENT);
39979 + /* it is the PK */
39980 + while (SQLITE_ROW == sqlite3_step(stmt)) {
39981 + /* we found a lock
39982 + * 1. is it compatible ?
39983 + * 2. is it ours */
39984 + char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
39986 + if (strcmp(sql_lockscope, "exclusive")) {
39987 + con->http_status = 423;
39988 + } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
39989 + /* resourse is locked with a shared lock
39990 + * client wants exclusive */
39991 + con->http_status = 423;
39994 + if (con->http_status == 423) {
39996 + return HANDLER_FINISHED;
40000 + stmt = p->conf.stmt_create_lock;
40002 + /* create a lock-token */
40004 + char uuid[37] /* 36 + \0 */;
40006 + uuid_generate(id);
40007 + uuid_unparse(id, uuid);
40009 + buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
40010 + buffer_append_string(p->tmp_buf, uuid);
40012 + /* "CREATE TABLE locks ("
40013 + * " locktoken TEXT NOT NULL,"
40014 + * " resource TEXT NOT NULL,"
40015 + * " lockscope TEXT NOT NULL,"
40016 + * " locktype TEXT NOT NULL,"
40017 + * " owner TEXT NOT NULL,"
40018 + * " depth INT NOT NULL,"
40021 + sqlite3_reset(stmt);
40023 + sqlite3_bind_text(stmt, 1,
40024 + CONST_BUF_LEN(p->tmp_buf),
40025 + SQLITE_TRANSIENT);
40027 + sqlite3_bind_text(stmt, 2,
40028 + CONST_BUF_LEN(con->uri.path),
40029 + SQLITE_TRANSIENT);
40031 + sqlite3_bind_text(stmt, 3,
40033 + xmlStrlen(lockscope),
40034 + SQLITE_TRANSIENT);
40036 + sqlite3_bind_text(stmt, 4,
40038 + xmlStrlen(locktype),
40039 + SQLITE_TRANSIENT);
40042 + sqlite3_bind_text(stmt, 5,
40045 + SQLITE_TRANSIENT);
40048 + sqlite3_bind_int(stmt, 6,
40052 + if (SQLITE_DONE != sqlite3_step(stmt)) {
40053 + log_error_write(srv, __FILE__, __LINE__, "ss",
40054 + "create lock:", sqlite3_errmsg(p->conf.sql));
40057 + /* looks like we survived */
40058 + webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
40060 + con->http_status = 201;
40061 + con->file_finished = 1;
40067 + return HANDLER_FINISHED;
40069 + con->http_status = 400;
40070 + return HANDLER_FINISHED;
40074 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
40075 + buffer *locktoken = ds->value;
40076 + sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
40078 + /* remove the < > around the token */
40079 + if (locktoken->used < 6) {
40080 + con->http_status = 400;
40082 + return HANDLER_FINISHED;
40085 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
40087 + sqlite3_reset(stmt);
40089 + sqlite3_bind_text(stmt, 1,
40090 + CONST_BUF_LEN(p->tmp_buf),
40091 + SQLITE_TRANSIENT);
40093 + if (SQLITE_DONE != sqlite3_step(stmt)) {
40094 + log_error_write(srv, __FILE__, __LINE__, "ss",
40095 + "refresh lock:", sqlite3_errmsg(p->conf.sql));
40098 + webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
40100 + con->http_status = 200;
40101 + con->file_finished = 1;
40102 + return HANDLER_FINISHED;
40104 + /* we need a lock-token to refresh */
40105 + con->http_status = 400;
40107 + return HANDLER_FINISHED;
40112 + con->http_status = 501;
40113 + return HANDLER_FINISHED;
40115 + case HTTP_METHOD_UNLOCK:
40117 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
40118 + buffer *locktoken = ds->value;
40119 + sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
40121 + /* remove the < > around the token */
40122 + if (locktoken->used < 4) {
40123 + con->http_status = 400;
40125 + return HANDLER_FINISHED;
40131 + * if the resourse is locked:
40132 + * - by us: unlock
40133 + * - by someone else: 401
40134 + * if the resource is not locked:
40138 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
40140 + sqlite3_reset(stmt);
40142 + sqlite3_bind_text(stmt, 1,
40143 + CONST_BUF_LEN(p->tmp_buf),
40144 + SQLITE_TRANSIENT);
40146 + sqlite3_bind_text(stmt, 2,
40147 + CONST_BUF_LEN(con->uri.path),
40148 + SQLITE_TRANSIENT);
40150 + if (SQLITE_DONE != sqlite3_step(stmt)) {
40151 + log_error_write(srv, __FILE__, __LINE__, "ss",
40152 + "remove lock:", sqlite3_errmsg(p->conf.sql));
40155 + if (0 == sqlite3_changes(p->conf.sql)) {
40156 + con->http_status = 401;
40158 + con->http_status = 204;
40160 + return HANDLER_FINISHED;
40162 + /* we need a lock-token to unlock */
40163 + con->http_status = 400;
40165 + return HANDLER_FINISHED;
40169 + con->http_status = 501;
40170 + return HANDLER_FINISHED;
40178 return HANDLER_GO_ON;
40180 @@ -1845,14 +2462,14 @@
40181 int mod_webdav_plugin_init(plugin *p) {
40182 p->version = LIGHTTPD_VERSION_ID;
40183 p->name = buffer_init_string("webdav");
40186 p->init = mod_webdav_init;
40187 p->handle_uri_clean = mod_webdav_uri_handler;
40188 p->handle_physical = mod_webdav_subrequest_handler;
40189 p->set_defaults = mod_webdav_set_defaults;
40190 p->cleanup = mod_webdav_free;
40198 --- lighttpd-1.4.11/src/network.c 2006-03-04 16:45:46.000000000 +0200
40199 +++ lighttpd-1.4.12/src/network.c 2006-07-11 22:07:51.000000000 +0300
40201 #include <sys/types.h>
40202 #include <sys/stat.h>
40203 -#include <sys/time.h>
40207 -#include <unistd.h>
40208 #include <string.h>
40209 #include <stdlib.h>
40210 #include <assert.h>
40212 +#include <stdio.h>
40214 #include "network.h"
40215 #include "fdevent.h"
40217 @@ -19,11 +19,12 @@
40218 #include "network_backends.h"
40219 #include "sys-mmap.h"
40220 #include "sys-socket.h"
40221 +#include "sys-files.h"
40224 -# include <openssl/ssl.h>
40225 -# include <openssl/err.h>
40226 -# include <openssl/rand.h>
40227 +# include <openssl/ssl.h>
40228 +# include <openssl/err.h>
40229 +# include <openssl/rand.h>
40232 handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
40233 @@ -31,11 +32,11 @@
40234 server_socket *srv_socket = (server_socket *)context;
40242 if (revents != FDEVENT_IN) {
40243 - log_error_write(srv, __FILE__, __LINE__, "sdd",
40244 + log_error_write(srv, __FILE__, __LINE__, "sdd",
40245 "strange event for server socket",
40248 @@ -44,12 +45,12 @@
40250 /* accept()s at most 100 connections directly
40252 - * we jump out after 100 to give the waiting connections a chance */
40253 + * we jump out after 100 to give the waiting connections a chance */
40254 for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
40258 connection_state_machine(srv, con);
40261 switch(r = plugins_call_handle_joblist(srv, con)) {
40262 case HANDLER_FINISHED:
40263 case HANDLER_GO_ON:
40264 @@ -72,18 +73,18 @@
40266 int is_unix_domain_socket = 0;
40270 #ifdef SO_ACCEPTFILTER
40271 struct accept_filter_arg afa;
40276 WORD wVersionRequested;
40281 wVersionRequested = MAKEWORD( 2, 2 );
40284 err = WSAStartup( wVersionRequested, &wsaData );
40286 /* Tell the user that we could not find a usable */
40287 @@ -91,37 +92,37 @@
40293 srv_socket = calloc(1, sizeof(*srv_socket));
40294 srv_socket->fd = -1;
40297 srv_socket->srv_token = buffer_init();
40298 buffer_copy_string_buffer(srv_socket->srv_token, host_token);
40302 buffer_copy_string_buffer(b, host_token);
40309 if (NULL == (sp = strrchr(b->ptr, ':'))) {
40310 log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
40320 /* check for [ and ] */
40321 if (b->ptr[0] == '[' && *(sp-1) == ']') {
40333 port = strtol(sp, NULL, 10);
40335 if (host[0] == '/') {
40336 @@ -129,17 +130,17 @@
40337 is_unix_domain_socket = 1;
40338 } else if (port == 0 || port > 65535) {
40339 log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
40346 if (*host == '\0') host = NULL;
40348 if (is_unix_domain_socket) {
40349 #ifdef HAVE_SYS_UN_H
40351 srv_socket->addr.plain.sa_family = AF_UNIX;
40354 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
40355 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40357 @@ -154,7 +155,7 @@
40360 srv_socket->addr.plain.sa_family = AF_INET6;
40363 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40364 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40366 @@ -162,7 +163,7 @@
40367 srv_socket->use_ipv6 = 1;
40372 if (srv_socket->fd == -1) {
40373 srv_socket->addr.plain.sa_family = AF_INET;
40374 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40375 @@ -170,16 +171,16 @@
40382 srv->cur_fds = srv_socket->fd;
40386 if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
40387 log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
40392 switch(srv_socket->addr.plain.sa_family) {
40395 @@ -190,23 +191,23 @@
40397 struct addrinfo hints, *res;
40401 memset(&hints, 0, sizeof(hints));
40404 hints.ai_family = AF_INET6;
40405 hints.ai_socktype = SOCK_STREAM;
40406 hints.ai_protocol = IPPROTO_TCP;
40409 if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
40410 - log_error_write(srv, __FILE__, __LINE__,
40411 - "sssss", "getaddrinfo failed: ",
40412 + log_error_write(srv, __FILE__, __LINE__,
40413 + "sssss", "getaddrinfo failed: ",
40414 gai_strerror(r), "'", host, "'");
40421 memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
40426 srv_socket->addr.ipv6.sin6_port = htons(port);
40427 @@ -221,33 +222,34 @@
40429 struct hostent *he;
40430 if (NULL == (he = gethostbyname(host))) {
40431 - log_error_write(srv, __FILE__, __LINE__,
40432 - "sds", "gethostbyname failed: ",
40433 + log_error_write(srv, __FILE__, __LINE__,
40434 + "sds", "gethostbyname failed: ",
40440 if (he->h_addrtype != AF_INET) {
40441 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
40446 if (he->h_length != sizeof(struct in_addr)) {
40447 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
40452 memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
40454 srv_socket->addr.ipv4.sin_port = htons(port);
40457 addr_len = sizeof(struct sockaddr_in);
40463 srv_socket->addr.un.sun_family = AF_UNIX;
40464 strcpy(srv_socket->addr.un.sun_path, host);
40468 addr_len = SUN_LEN(&srv_socket->addr.un);
40470 @@ -259,8 +261,8 @@
40471 if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
40474 - log_error_write(srv, __FILE__, __LINE__, "ss",
40475 - "server socket is still in use:",
40476 + log_error_write(srv, __FILE__, __LINE__, "ss",
40477 + "server socket is still in use:",
40481 @@ -275,88 +277,89 @@
40485 - log_error_write(srv, __FILE__, __LINE__, "sds",
40486 - "testing socket failed:",
40487 + log_error_write(srv, __FILE__, __LINE__, "sds",
40488 + "testing socket failed:",
40489 host, strerror(errno));
40504 if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
40505 switch(srv_socket->addr.plain.sa_family) {
40507 - log_error_write(srv, __FILE__, __LINE__, "sds",
40508 - "can't bind to socket:",
40509 + log_error_write(srv, __FILE__, __LINE__, "sds",
40510 + "can't bind to socket:",
40511 host, strerror(errno));
40514 - log_error_write(srv, __FILE__, __LINE__, "ssds",
40515 - "can't bind to port:",
40516 + log_error_write(srv, __FILE__, __LINE__, "ssds",
40517 + "can't bind to port:",
40518 host, port, strerror(errno));
40525 if (-1 == listen(srv_socket->fd, 128 * 8)) {
40526 log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
40533 if (srv->ssl_is_init == 0) {
40534 SSL_load_error_strings();
40535 SSL_library_init();
40536 srv->ssl_is_init = 1;
40539 if (0 == RAND_status()) {
40540 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40541 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40542 "not enough entropy in the pool");
40548 if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
40549 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40550 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40551 ERR_error_string(ERR_get_error(), NULL));
40556 if (buffer_is_empty(s->ssl_pemfile)) {
40557 log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
40562 if (!buffer_is_empty(s->ssl_ca_file)) {
40563 if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
40564 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40565 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40566 ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
40572 if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40573 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40574 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40575 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40580 if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40581 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40582 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40583 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40588 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
40589 - log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
40590 + log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
40591 "Private key does not match the certificate public key, reason:",
40592 ERR_error_string(ERR_get_error(), NULL),
40594 @@ -364,15 +367,15 @@
40596 srv_socket->ssl_ctx = s->ssl_ctx;
40600 buffer_free(srv_socket->srv_token);
40606 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40608 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40609 "ssl requested but openssl support is not compiled in");
40615 @@ -390,10 +393,10 @@
40621 srv_socket->is_ssl = s->is_ssl;
40622 srv_socket->fde_ndx = -1;
40625 if (srv->srv_sockets.size == 0) {
40626 srv->srv_sockets.size = 4;
40627 srv->srv_sockets.used = 0;
40628 @@ -402,11 +405,10 @@
40629 srv->srv_sockets.size += 4;
40630 srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
40634 srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
40642 @@ -414,45 +416,58 @@
40644 for (i = 0; i < srv->srv_sockets.used; i++) {
40645 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40648 if (srv_socket->fd != -1) {
40649 /* check if server fd are already registered */
40650 if (srv_socket->fde_ndx != -1) {
40651 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
40652 fdevent_unregister(srv->ev, srv_socket->fd);
40656 close(srv_socket->fd);
40660 + if (srv_socket->is_ssl) {
40661 +#ifdef USE_OPENSSL
40662 + SSL_CTX_free(srv_socket->ssl_ctx);
40666 buffer_free(srv_socket->srv_token);
40673 +#ifdef USE_OPENSSL
40674 + ERR_free_strings();
40676 free(srv->srv_sockets.ptr);
40683 NETWORK_BACKEND_UNSET,
40685 NETWORK_BACKEND_WRITE,
40686 NETWORK_BACKEND_WRITEV,
40687 NETWORK_BACKEND_LINUX_SENDFILE,
40688 NETWORK_BACKEND_FREEBSD_SENDFILE,
40689 - NETWORK_BACKEND_SOLARIS_SENDFILEV
40690 + NETWORK_BACKEND_SOLARIS_SENDFILEV,
40692 + NETWORK_BACKEND_WIN32_SEND,
40693 + NETWORK_BACKEND_WIN32_TRANSMITFILE,
40694 } network_backend_t;
40696 int network_init(server *srv) {
40699 network_backend_t backend;
40702 - network_backend_t nb;
40703 - const char *name;
40704 - } network_backends[] = {
40707 + network_backend_t nb;
40708 + const char *name;
40709 + } network_backends[] = {
40710 /* lowest id wins */
40711 #if defined USE_LINUX_SENDFILE
40712 { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" },
40713 @@ -466,21 +481,30 @@
40714 #if defined USE_WRITEV
40715 { NETWORK_BACKEND_WRITEV, "writev" },
40717 +#if defined USE_WRITE
40718 { NETWORK_BACKEND_WRITE, "write" },
40720 +#if defined USE_WIN32_TRANSMITFILE
40721 + { NETWORK_BACKEND_WIN32_TRANSMITFILE, "win32-transmitfile" },
40723 +#if defined USE_WIN32_SEND
40724 + { NETWORK_BACKEND_WIN32_SEND, "win32-send" },
40727 { NETWORK_BACKEND_UNSET, NULL }
40734 buffer_copy_string_buffer(b, srv->srvconf.bindhost);
40735 buffer_append_string(b, ":");
40736 buffer_append_long(b, srv->srvconf.port);
40739 if (0 != network_server_init(srv, b, srv->config_storage[0])) {
40746 srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
40748 @@ -500,54 +524,80 @@
40749 if (NULL == network_backends[i].name) {
40750 /* we don't know it */
40752 - log_error_write(srv, __FILE__, __LINE__, "sb",
40753 - "server.network-backend has a unknown value:",
40754 + log_error_write(srv, __FILE__, __LINE__, "sb",
40755 + "server.network-backend has a unknown value:",
40756 srv->srvconf.network_backend);
40762 +#define SET_NETWORK_BACKEND(read, write) \
40763 + srv->network_backend_write = network_write_chunkqueue_##write;\
40764 + srv->network_backend_read = network_read_chunkqueue_##read
40766 +#define SET_NETWORK_BACKEND_SSL(read, write) \
40767 + srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
40768 + srv->network_ssl_backend_read = network_read_chunkqueue_##read
40772 +#ifdef USE_WIN32_SEND
40773 + case NETWORK_BACKEND_WIN32_SEND:
40774 + SET_NETWORK_BACKEND(win32recv, win32send);
40776 +#ifdef USE_WIN32_TRANSMITFILE
40777 + case NETWORK_BACKEND_WIN32_TRANSMITFILE:
40778 + SET_NETWORK_BACKEND(win32recv, win32transmitfile);
40784 case NETWORK_BACKEND_WRITE:
40785 - srv->network_backend_write = network_write_chunkqueue_write;
40786 + SET_NETWORK_BACKEND(read, write);
40790 case NETWORK_BACKEND_WRITEV:
40791 - srv->network_backend_write = network_write_chunkqueue_writev;
40792 + SET_NETWORK_BACKEND(read, writev);
40795 #ifdef USE_LINUX_SENDFILE
40796 case NETWORK_BACKEND_LINUX_SENDFILE:
40797 - srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
40798 + SET_NETWORK_BACKEND(read, linuxsendfile);
40801 #ifdef USE_FREEBSD_SENDFILE
40802 case NETWORK_BACKEND_FREEBSD_SENDFILE:
40803 - srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
40804 + SET_NETWORK_BACKEND(read, freebsdsendfile);
40807 #ifdef USE_SOLARIS_SENDFILEV
40808 case NETWORK_BACKEND_SOLARIS_SENDFILEV:
40809 - srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
40810 + SET_NETWORK_BACKEND(read, solarissendfilev);
40817 +#ifdef USE_OPENSSL
40818 + SET_NETWORK_BACKEND_SSL(openssl, openssl);
40821 /* check for $SERVER["socket"] */
40822 for (i = 1; i < srv->config_context->used; i++) {
40823 data_config *dc = (data_config *)srv->config_context->data[i];
40824 specific_config *s = srv->config_storage[i];
40828 /* not our stage */
40829 if (COMP_SERVER_SOCKET != dc->comp) continue;
40832 if (dc->cond != CONFIG_COND_EQ) {
40833 log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
40839 @@ -558,36 +608,47 @@
40845 if (j == srv->srv_sockets.used) {
40846 if (0 != network_server_init(srv, dc->string, s)) return -1;
40854 int network_register_fdevents(server *srv) {
40857 if (-1 == fdevent_reset(srv->ev)) {
40861 /* register fdevents after reset */
40862 for (i = 0; i < srv->srv_sockets.used; i++) {
40863 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40865 fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
40866 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
40871 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40873 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40874 + server_socket *srv_socket = con->srv_socket;
40876 + if (srv_socket->is_ssl) {
40877 +#ifdef USE_OPENSSL
40878 + return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
40880 + return NETWORK_STATUS_FATAL_ERROR;
40883 + return srv->network_backend_read(srv, con, con->fd, cq);
40887 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40888 + network_status_t ret = NETWORK_STATUS_UNSET;
40894 server_socket *srv_socket = con->srv_socket;
40895 @@ -600,11 +661,11 @@
40896 joblist_append(srv, con);
40902 written = cq->bytes_out;
40906 /* Linux: put a cork into the socket as we want to combine the write() calls
40907 * but only if we really have multiple chunks
40909 @@ -613,7 +674,7 @@
40910 setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
40915 if (srv_socket->is_ssl) {
40917 ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
40918 @@ -621,12 +682,17 @@
40920 ret = srv->network_backend_write(srv, con, con->fd, cq);
40926 + case NETWORK_STATUS_WAIT_FOR_EVENT:
40927 + case NETWORK_STATUS_SUCCESS:
40928 chunkqueue_remove_finished_chunks(cq);
40929 - ret = chunkqueue_is_empty(cq) ? 0 : 1;
40940 @@ -639,13 +705,13 @@
40941 con->bytes_written_cur_second += written;
40943 *(con->conf.global_bytes_per_second_cnt_ptr) += written;
40946 if (con->conf.kbytes_per_second &&
40947 (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
40948 /* we reached the traffic limit */
40950 con->traffic_limit_reached = 1;
40951 joblist_append(srv, con);
40956 --- lighttpd-1.4.11/src/network.h 2005-08-11 01:26:42.000000000 +0300
40957 +++ lighttpd-1.4.12/src/network.h 2006-07-11 22:07:51.000000000 +0300
40960 #include "server.h"
40962 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
40963 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
40964 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
40966 int network_init(server *srv);
40967 int network_close(server *srv);
40968 --- lighttpd-1.4.11/src/network_backends.h 2005-10-24 15:13:51.000000000 +0300
40969 +++ lighttpd-1.4.12/src/network_backends.h 2006-07-11 22:07:52.000000000 +0300
40970 @@ -43,16 +43,52 @@
40971 # define USE_AIX_SENDFILE
40975 +* unix can use read/write or recv/send on sockets
40976 +* win32 only recv/send
40979 +# define USE_WIN32_SEND
40980 +/* wait for async-io support
40981 +# define USE_WIN32_TRANSMITFILE
40984 +# define USE_WRITE
40988 +#include "network.h"
40990 +#define NETWORK_BACKEND_WRITE_CHUNK(x) \
40991 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c)
40993 +#define NETWORK_BACKEND_WRITE(x) \
40994 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
40995 +#define NETWORK_BACKEND_READ(x) \
40996 + network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
40998 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
41000 +NETWORK_BACKEND_WRITE(write);
41001 +NETWORK_BACKEND_WRITE(writev);
41002 +NETWORK_BACKEND_WRITE(linuxsendfile);
41003 +NETWORK_BACKEND_WRITE(freebsdsendfile);
41004 +NETWORK_BACKEND_WRITE(solarissendfilev);
41006 +NETWORK_BACKEND_WRITE(win32transmitfile);
41007 +NETWORK_BACKEND_WRITE(win32send);
41009 +NETWORK_BACKEND_READ(read);
41010 +NETWORK_BACKEND_READ(win32recv);
41012 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
41013 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
41014 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
41015 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
41016 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
41018 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
41019 +#define NETWORK_BACKEND_WRITE_SSL(x) \
41020 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
41021 +#define NETWORK_BACKEND_READ_SSL(x) \
41022 + network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
41024 +NETWORK_BACKEND_WRITE_SSL(openssl);
41025 +NETWORK_BACKEND_READ_SSL(openssl);
41029 --- lighttpd-1.4.11/src/network_freebsd_sendfile.c 2005-10-22 12:28:18.000000000 +0300
41030 +++ lighttpd-1.4.12/src/network_freebsd_sendfile.c 2006-07-11 22:07:52.000000000 +0300
41031 @@ -26,142 +26,61 @@
41034 # ifdef __FreeBSD__
41035 -/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
41036 +/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
41037 # define UIO_MAXIOV 1024
41041 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41042 +NETWORK_BACKEND_WRITE(freebsdsendfile) {
41044 size_t chunks_written = 0;
41047 for(c = cq->first; c; c = c->next, chunks_written++) {
41048 int chunk_finished = 0;
41050 + network_status_t ret;
41053 - case MEM_CHUNK: {
41058 - size_t num_chunks, i;
41059 - struct iovec chunks[UIO_MAXIOV];
41061 - size_t num_bytes = 0;
41063 - /* we can't send more then SSIZE_MAX bytes in one chunk */
41065 - /* build writev list
41067 - * 1. limit: num_chunks < UIO_MAXIOV
41068 - * 2. limit: num_bytes < SSIZE_MAX
41070 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41072 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41073 - if (tc->mem->used == 0) {
41074 - chunks[i].iov_base = tc->mem->ptr;
41075 - chunks[i].iov_len = 0;
41077 - offset = tc->mem->ptr + tc->offset;
41078 - toSend = tc->mem->used - 1 - tc->offset;
41080 - chunks[i].iov_base = offset;
41082 - /* protect the return value of writev() */
41083 - if (toSend > SSIZE_MAX ||
41084 - num_bytes + toSend > SSIZE_MAX) {
41085 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
41087 - num_chunks = i + 1;
41090 - chunks[i].iov_len = toSend;
41093 - num_bytes += toSend;
41097 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
41107 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41108 - "writev failed:", strerror(errno), fd);
41113 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41118 - /* check which chunks have been written */
41119 - cq->bytes_out += r;
41121 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41122 - if (r >= (ssize_t)chunks[i].iov_len) {
41124 - r -= chunks[i].iov_len;
41125 - tc->offset += chunks[i].iov_len;
41127 - if (chunk_finished) {
41128 - /* skip the chunks from further touches */
41129 - chunks_written++;
41132 - /* chunks_written + c = c->next is done in the for()*/
41133 - chunk_finished++;
41136 - /* partially written */
41139 - chunk_finished = 0;
41143 + if (ret != NETWORK_STATUS_SUCCESS) {
41148 + chunk_finished = 1;
41155 stat_cache_entry *sce = NULL;
41159 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41160 log_error_write(srv, __FILE__, __LINE__, "sb",
41161 strerror(errno), c->file.name);
41163 + return NETWORK_STATUS_FATAL_ERROR;
41167 offset = c->file.start + c->offset;
41168 /* limit the toSend to 2^31-1 bytes in a chunk */
41169 - toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41170 + toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41171 ((1 << 30) - 1) : c->file.length - c->offset;
41174 if (offset > sce->st.st_size) {
41175 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41179 + return NETWORK_STATUS_FATAL_ERROR;
41183 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41184 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41188 + return NETWORK_STATUS_FATAL_ERROR;
41195 /* FreeBSD sendfile() */
41196 if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
41198 @@ -169,39 +88,39 @@
41203 + return NETWORK_STATUS_CONNECTION_CLOSE;
41205 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41208 + return NETWORK_STATUS_FATAL_ERROR;
41215 cq->bytes_out += r;
41218 if (c->offset == c->file.length) {
41219 chunk_finished = 1;
41228 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41235 if (!chunk_finished) {
41236 /* not finished yet */
41243 - return chunks_written;
41244 + return NETWORK_STATUS_SUCCESS;
41248 --- lighttpd-1.4.11/src/network_linux_sendfile.c 2006-02-15 20:02:36.000000000 +0200
41249 +++ lighttpd-1.4.12/src/network_linux_sendfile.c 2006-07-11 22:07:53.000000000 +0300
41250 @@ -26,122 +26,54 @@
41251 /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
41252 #undef HAVE_POSIX_FADVISE
41254 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41256 +NETWORK_BACKEND_WRITE(linuxsendfile) {
41258 size_t chunks_written = 0;
41261 for(c = cq->first; c; c = c->next, chunks_written++) {
41262 int chunk_finished = 0;
41264 + network_status_t ret;
41267 - case MEM_CHUNK: {
41272 - size_t num_chunks, i;
41273 - struct iovec chunks[UIO_MAXIOV];
41275 - size_t num_bytes = 0;
41277 - /* we can't send more then SSIZE_MAX bytes in one chunk */
41279 - /* build writev list
41281 - * 1. limit: num_chunks < UIO_MAXIOV
41282 - * 2. limit: num_bytes < SSIZE_MAX
41284 - for (num_chunks = 0, tc = c;
41285 - tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
41286 - tc = tc->next, num_chunks++);
41288 - for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41289 - if (tc->mem->used == 0) {
41290 - chunks[i].iov_base = tc->mem->ptr;
41291 - chunks[i].iov_len = 0;
41293 - offset = tc->mem->ptr + tc->offset;
41294 - toSend = tc->mem->used - 1 - tc->offset;
41296 - chunks[i].iov_base = offset;
41298 - /* protect the return value of writev() */
41299 - if (toSend > SSIZE_MAX ||
41300 - num_bytes + toSend > SSIZE_MAX) {
41301 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
41303 - num_chunks = i + 1;
41306 - chunks[i].iov_len = toSend;
41309 - num_bytes += toSend;
41313 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
41323 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41324 - "writev failed:", strerror(errno), fd);
41330 - /* check which chunks have been written */
41331 - cq->bytes_out += r;
41333 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
41335 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41336 - if (r >= (ssize_t)chunks[i].iov_len) {
41338 - r -= chunks[i].iov_len;
41339 - tc->offset += chunks[i].iov_len;
41341 + /* check which chunks are finished now */
41342 + for (tc = c; tc; tc = tc->next) {
41343 + /* finished the chunk */
41344 + if (tc->offset == tc->mem->used - 1) {
41345 + /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
41346 if (chunk_finished) {
41347 - /* skip the chunks from further touches */
41348 - chunks_written++;
41351 - /* chunks_written + c = c->next is done in the for()*/
41352 - chunk_finished++;
41353 + chunk_finished = 1;
41356 - /* partially written */
41359 - chunk_finished = 0;
41366 + if (ret != NETWORK_STATUS_SUCCESS) {
41376 stat_cache_entry *sce = NULL;
41379 offset = c->file.start + c->offset;
41380 /* limit the toSend to 2^31-1 bytes in a chunk */
41381 - toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41382 + toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41383 ((1 << 30) - 1) : c->file.length - c->offset;
41385 - /* open file if not already opened */
41387 + /* open file if not already opened */
41388 if (-1 == c->file.fd) {
41389 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
41390 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41397 /* tell the kernel that we want to stream the file */
41398 if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
41399 if (ENOSYS != errno) {
41400 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41401 + log_error_write(srv, __FILE__, __LINE__, "ssd",
41402 "posix_fadvise failed:", strerror(errno), c->file.fd);
41405 @@ -168,7 +100,7 @@
41409 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41410 + log_error_write(srv, __FILE__, __LINE__, "ssd",
41411 "sendfile failed:", strerror(errno), fd);
41414 @@ -179,7 +111,7 @@
41416 * - the file shrinked -> error
41417 * - the remote side closed inbetween -> remote-close */
41420 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41421 /* file is gone ? */
41423 @@ -196,22 +128,22 @@
41424 #ifdef HAVE_POSIX_FADVISE
41427 -#define M * 1024 K
41428 +#define M * 1024 K
41429 #define READ_AHEAD 4 M
41430 /* check if we need a new chunk */
41431 if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
41432 /* tell the kernel that we want to stream the file */
41433 if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
41434 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41435 + log_error_write(srv, __FILE__, __LINE__, "ssd",
41436 "posix_fadvise failed:", strerror(errno), c->file.fd);
41444 cq->bytes_out += r;
41447 if (c->offset == c->file.length) {
41448 chunk_finished = 1;
41450 @@ -222,19 +154,19 @@
41461 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41468 if (!chunk_finished) {
41469 /* not finished yet */
41475 --- lighttpd-1.4.11/src/network_openssl.c 2005-11-17 14:53:29.000000000 +0200
41476 +++ lighttpd-1.4.12/src/network_openssl.c 2006-07-11 22:07:52.000000000 +0300
41477 @@ -23,17 +23,87 @@
41479 #include "stat_cache.h"
41481 -# include <openssl/ssl.h>
41482 -# include <openssl/err.h>
41483 +# include <openssl/ssl.h>
41484 +# include <openssl/err.h>
41486 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
41487 +NETWORK_BACKEND_READ_SSL(openssl) {
41491 + b = chunkqueue_get_append_buffer(cq);
41492 + buffer_prepare_copy(b, 8192);
41493 + len = SSL_read(ssl, b->ptr, b->size - 1);
41495 + log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
41500 + switch ((r = SSL_get_error(con->ssl, len))) {
41501 + case SSL_ERROR_WANT_READ:
41502 + return NETWORK_STATUS_WAIT_FOR_EVENT;
41503 + case SSL_ERROR_SYSCALL:
41505 + * man SSL_get_error()
41507 + * SSL_ERROR_SYSCALL
41508 + * Some I/O error occurred. The OpenSSL error queue may contain more
41509 + * information on the error. If the error queue is empty (i.e.
41510 + * ERR_get_error() returns 0), ret can be used to find out more about
41511 + * the error: If ret == 0, an EOF was observed that violates the
41512 + * protocol. If ret == -1, the underlying BIO reported an I/O error
41513 + * (for socket I/O on Unix systems, consult errno for details).
41516 + while((ssl_err = ERR_get_error())) {
41517 + /* get all errors from the error-queue */
41518 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41519 + r, ERR_error_string(ssl_err, NULL));
41524 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41526 + strerror(errno));
41531 + case SSL_ERROR_ZERO_RETURN:
41532 + /* clean shutdown on the remote side */
41535 + /* FIXME: later */
41538 + /* fall thourgh */
41540 + while((ssl_err = ERR_get_error())) {
41541 + /* get all errors from the error-queue */
41542 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41543 + r, ERR_error_string(ssl_err, NULL));
41551 + b->ptr[b->used - 1] = '\0';
41553 + return NETWORK_STATUS_SUCCESS;
41557 +NETWORK_BACKEND_WRITE_SSL(openssl) {
41560 size_t chunks_written = 0;
41562 /* this is a 64k sendbuffer
41564 - * it has to stay at the same location all the time to satisfy the needs
41565 + * it has to stay at the same location all the time to satisfy the needs
41566 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
41568 * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
41569 @@ -43,14 +113,14 @@
41570 * In reality we would like to use mmap() but we don't have a guarantee that
41571 * we get the same mmap() address for each call. On openbsd the mmap() address
41573 - * That means either we keep the mmap() open or we do a read() into a
41574 - * constant buffer
41575 + * That means either we keep the mmap() open or we do a read() into a
41576 + * constant buffer
41578 #define LOCAL_SEND_BUFSIZE (64 * 1024)
41579 static char *local_send_buffer = NULL;
41581 /* the remote side closed the connection before without shutdown request
41585 * if keep-alive is disabled */
41587 @@ -60,32 +130,34 @@
41589 for(c = cq->first; c; c = c->next) {
41590 int chunk_finished = 0;
41601 if (c->mem->used == 0) {
41602 chunk_finished = 1;
41607 offset = c->mem->ptr + c->offset;
41608 toSend = c->mem->used - 1 - c->offset;
41612 * SSL_write man-page
41616 * When an SSL_write() operation has to be repeated because of
41617 * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
41618 * repeated with the same arguments.
41621 + * SSL_write(..., 0) return 0 which is handle as an error (Success)
41622 + * checking toSend and not calling SSL_write() is simpler
41625 - if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
41627 + if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
41630 switch ((ssl_r = SSL_get_error(ssl, r))) {
41632 /* perhaps we have error waiting in our error-queue */
41633 if (0 != (err = ERR_get_error())) {
41635 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41636 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41638 ERR_error_string(err, NULL));
41639 } while((err = ERR_get_error()));
41640 @@ -105,43 +177,43 @@
41644 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41645 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41651 /* neither error-queue nor errno ? */
41652 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41653 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41660 case SSL_ERROR_ZERO_RETURN:
41661 /* clean shutdown on the remote side */
41664 if (r == 0) return -2;
41669 while((err = ERR_get_error())) {
41670 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41671 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41673 ERR_error_string(err, NULL));
41681 cq->bytes_out += r;
41685 if (c->offset == (off_t)c->mem->used - 1) {
41686 chunk_finished = 1;
41693 @@ -150,7 +222,7 @@
41694 stat_cache_entry *sce = NULL;
41696 int write_wait = 0;
41699 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41700 log_error_write(srv, __FILE__, __LINE__, "sb",
41701 strerror(errno), c->file.name);
41702 @@ -164,13 +236,13 @@
41705 off_t offset = c->file.start + c->offset;
41706 - off_t toSend = c->file.length - c->offset;
41707 + off_t toSend = c->file.length - c->offset;
41709 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
41712 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41713 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
41719 @@ -183,9 +255,9 @@
41722 s = local_send_buffer;
41728 if ((r = SSL_write(ssl, s, toSend)) <= 0) {
41731 @@ -197,7 +269,7 @@
41732 /* perhaps we have error waiting in our error-queue */
41733 if (0 != (err = ERR_get_error())) {
41735 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41736 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41738 ERR_error_string(err, NULL));
41739 } while((err = ERR_get_error()));
41740 @@ -207,58 +279,58 @@
41744 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41745 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41751 /* neither error-queue nor errno ? */
41752 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41753 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41760 case SSL_ERROR_ZERO_RETURN:
41761 /* clean shutdown on the remote side */
41764 if (r == 0) return -2;
41769 while((err = ERR_get_error())) {
41770 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41771 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41773 ERR_error_string(err, NULL));
41781 cq->bytes_out += r;
41785 if (c->offset == c->file.length) {
41786 chunk_finished = 1;
41788 } while(!chunk_finished && !write_wait);
41794 log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
41801 if (!chunk_finished) {
41802 /* not finished yet */
41812 --- lighttpd-1.4.11/src/network_solaris_sendfilev.c 2005-10-22 12:28:27.000000000 +0300
41813 +++ lighttpd-1.4.12/src/network_solaris_sendfilev.c 2006-07-11 22:07:53.000000000 +0300
41814 @@ -29,114 +29,34 @@
41818 - * a very simple sendfilev() interface for solaris which can be optimised a lot more
41819 + * a very simple sendfilev() interface for solaris which can be optimised a lot more
41820 * as solaris sendfilev() supports 'sending everythin in one syscall()'
41822 - * If you want such an interface and need the performance, just give me an account on
41825 + * If you want such an interface and need the performance, just give me an account on
41827 * - jan@kneschke.de
41831 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
41832 +NETWORK_BACKEND_WRITE(solarissendfilev) {
41834 size_t chunks_written = 0;
41837 for(c = cq->first; c; c = c->next, chunks_written++) {
41838 int chunk_finished = 0;
41840 + network_status_t ret;
41843 - case MEM_CHUNK: {
41848 - size_t num_chunks, i;
41849 - struct iovec chunks[UIO_MAXIOV];
41852 - size_t num_bytes = 0;
41854 - /* we can't send more then SSIZE_MAX bytes in one chunk */
41856 - /* build writev list
41858 - * 1. limit: num_chunks < UIO_MAXIOV
41859 - * 2. limit: num_bytes < SSIZE_MAX
41861 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41863 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41864 - if (tc->mem->used == 0) {
41865 - chunks[i].iov_base = tc->mem->ptr;
41866 - chunks[i].iov_len = 0;
41868 - offset = tc->mem->ptr + tc->offset;
41869 - toSend = tc->mem->used - 1 - tc->offset;
41871 - chunks[i].iov_base = offset;
41873 - /* protect the return value of writev() */
41874 - if (toSend > SSIZE_MAX ||
41875 - num_bytes + toSend > SSIZE_MAX) {
41876 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
41878 - num_chunks = i + 1;
41881 - chunks[i].iov_len = toSend;
41884 - num_bytes += toSend;
41888 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
41898 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41899 - "writev failed:", strerror(errno), fd);
41905 - /* check which chunks have been written */
41906 - cq->bytes_out += r;
41908 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41909 - if (r >= (ssize_t)chunks[i].iov_len) {
41911 - r -= chunks[i].iov_len;
41912 - tc->offset += chunks[i].iov_len;
41914 - if (chunk_finished) {
41915 - /* skip the chunks from further touches */
41916 - chunks_written++;
41919 - /* chunks_written + c = c->next is done in the for()*/
41920 - chunk_finished++;
41923 - /* partially written */
41926 - chunk_finished = 0;
41931 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41933 + if (ret != NETWORK_STATUS_SUCCESS) {
41938 + chunk_finished = 1;
41945 @@ -144,25 +64,25 @@
41946 sendfilevec_t fvec;
41947 stat_cache_entry *sce = NULL;
41951 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41952 log_error_write(srv, __FILE__, __LINE__, "sb",
41953 strerror(errno), c->file.name);
41958 offset = c->file.start + c->offset;
41959 toSend = c->file.length - c->offset;
41962 if (offset > sce->st.st_size) {
41963 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41969 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41970 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41976 @@ -170,44 +90,43 @@
41978 fvec.sfv_off = offset;
41979 fvec.sfv_len = toSend;
41982 /* Solaris sendfilev() */
41983 if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
41984 if (errno != EAGAIN) {
41985 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41990 + return NETWORK_STATUS_FATAL_ERROR;
41999 c->offset += written;
42000 cq->bytes_out += written;
42003 if (c->offset == c->file.length) {
42004 chunk_finished = 1;
42012 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42016 + return NETWORK_STATUS_FATAL_ERROR;
42020 if (!chunk_finished) {
42021 /* not finished yet */
42028 - return chunks_written;
42029 + return NETWORK_STATUS_SUCCESS;
42033 --- lighttpd-1.4.11/src/network_write.c 2005-10-22 12:27:56.000000000 +0300
42034 +++ lighttpd-1.4.12/src/network_write.c 2006-07-11 22:07:51.000000000 +0300
42036 #include <sys/types.h>
42037 #include <sys/stat.h>
42038 -#include <sys/time.h>
42042 -#include <unistd.h>
42043 #include <string.h>
42044 #include <stdlib.h>
42045 +#include <assert.h>
42047 #include "network.h"
42048 #include "fdevent.h"
42050 #include "stat_cache.h"
42052 #include "sys-socket.h"
42053 +#include "sys-files.h"
42055 #include "network_backends.h"
42059 #ifdef HAVE_SYS_FILIO_H
42060 # include <sys/filio.h>
42062 @@ -24,47 +27,86 @@
42063 #include <sys/resource.h>
42066 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
42068 +* fill the chunkqueue will all the data that we can get
42070 +* this might be optimized into a readv() which uses the chunks
42073 +NETWORK_BACKEND_READ(read) {
42078 + /* check how much we have to read */
42079 + if (ioctl(fd, FIONREAD, &toread)) {
42080 + log_error_write(srv, __FILE__, __LINE__, "sd",
42081 + "ioctl failed: ",
42083 + return NETWORK_STATUS_FATAL_ERROR;
42086 + if (toread == 0) return NETWORK_STATUS_WAIT_FOR_EVENT;
42089 + * our chunk queue is quiet large already
42091 + * let's buffer it to disk
42094 + b = chunkqueue_get_append_buffer(cq);
42096 + buffer_prepare_copy(b, toread);
42098 + if (-1 == (r = read(fd, b->ptr, toread))) {
42099 + log_error_write(srv, __FILE__, __LINE__, "sds",
42100 + "unexpected end-of-file (perhaps the proxy process died):",
42101 + fd, strerror(errno));
42102 + return NETWORK_STATUS_FATAL_ERROR;
42105 + /* this should be catched by the b > 0 above */
42107 + b->used += r + 1;
42108 + b->ptr[b->used - 1] = '\0';
42110 + return NETWORK_STATUS_SUCCESS;
42113 +NETWORK_BACKEND_WRITE(write) {
42115 size_t chunks_written = 0;
42118 for(c = cq->first; c; c = c->next) {
42119 int chunk_finished = 0;
42129 if (c->mem->used == 0) {
42130 chunk_finished = 1;
42135 offset = c->mem->ptr + c->offset;
42136 toSend = c->mem->used - 1 - c->offset;
42138 - if ((r = send(fd, offset, toSend, 0)) < 0) {
42139 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42145 if ((r = write(fd, offset, toSend)) < 0) {
42146 log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42150 + return NETWORK_STATUS_FATAL_ERROR;
42156 cq->bytes_out += r;
42159 if (c->offset == (off_t)c->mem->used - 1) {
42160 chunk_finished = 1;
42167 @@ -76,93 +118,89 @@
42169 stat_cache_entry *sce = NULL;
42173 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42174 log_error_write(srv, __FILE__, __LINE__, "sb",
42175 strerror(errno), c->file.name);
42177 + return NETWORK_STATUS_FATAL_ERROR;
42181 offset = c->file.start + c->offset;
42182 toSend = c->file.length - c->offset;
42185 if (offset > sce->st.st_size) {
42186 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42190 + return NETWORK_STATUS_FATAL_ERROR;
42193 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42194 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42198 + return NETWORK_STATUS_FATAL_ERROR;
42202 #if defined USE_MMAP
42203 if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
42204 log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
42210 + return NETWORK_STATUS_FATAL_ERROR;
42214 if ((r = write(fd, p + offset, toSend)) <= 0) {
42215 log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
42216 munmap(p, sce->st.st_size);
42218 + return NETWORK_STATUS_FATAL_ERROR;
42222 munmap(p, sce->st.st_size);
42224 buffer_prepare_copy(srv->tmp_buf, toSend);
42227 lseek(ifd, offset, SEEK_SET);
42228 if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
42229 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
42234 + return NETWORK_STATUS_FATAL_ERROR;
42238 if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
42239 log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
42243 + return NETWORK_STATUS_FATAL_ERROR;
42247 cq->bytes_out += r;
42250 if (c->offset == c->file.length) {
42251 chunk_finished = 1;
42260 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42264 + return NETWORK_STATUS_FATAL_ERROR;
42268 if (!chunk_finished) {
42269 /* not finished yet */
42279 - return chunks_written;
42280 + return NETWORK_STATUS_SUCCESS;
42284 -network_write_init(void) {
42285 - p->write = network_write_write_chunkset;
42288 --- lighttpd-1.4.11/src/network_writev.c 2006-02-15 01:02:36.000000000 +0200
42289 +++ lighttpd-1.4.12/src/network_writev.c 2006-07-11 22:07:52.000000000 +0300
42290 @@ -28,10 +28,10 @@
42293 # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
42294 -/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42295 +/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42296 # define UIO_MAXIOV 1024
42297 # elif defined(__sgi)
42298 -/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42299 +/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42300 # define UIO_MAXIOV 512
42301 # elif defined(__sun)
42302 /* Solaris (and SunOS?) defines IOV_MAX instead */
42303 @@ -51,105 +51,119 @@
42304 #define LOCAL_BUFFERING 1
42307 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
42309 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
42314 + size_t num_chunks, i;
42315 + struct iovec chunks[UIO_MAXIOV];
42316 + chunk *tc; /* transfer chunks */
42317 + size_t num_bytes = 0;
42319 + /* we can't send more then SSIZE_MAX bytes in one chunk */
42321 + /* build writev list
42323 + * 1. limit: num_chunks < UIO_MAXIOV
42324 + * 2. limit: num_bytes < SSIZE_MAX
42326 + for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42328 + for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42329 + if (tc->mem->used == 0) {
42330 + chunks[i].iov_base = tc->mem->ptr;
42331 + chunks[i].iov_len = 0;
42333 + offset = tc->mem->ptr + tc->offset;
42334 + toSend = tc->mem->used - 1 - tc->offset;
42336 + chunks[i].iov_base = offset;
42338 + /* protect the return value of writev() */
42339 + if (toSend > SSIZE_MAX ||
42340 + num_bytes + toSend > SSIZE_MAX) {
42341 + chunks[i].iov_len = SSIZE_MAX - num_bytes;
42343 + num_chunks = i + 1;
42346 + chunks[i].iov_len = toSend;
42349 + num_bytes += toSend;
42353 + if ((r = writev(fd, chunks, num_chunks)) < 0) {
42361 + return NETWORK_STATUS_CONNECTION_CLOSE;
42363 + log_error_write(srv, __FILE__, __LINE__, "ssd",
42364 + "writev failed:", strerror(errno), fd);
42366 + return NETWORK_STATUS_FATAL_ERROR;
42370 + cq->bytes_out += r;
42372 + /* check which chunks have been written */
42374 + for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42375 + if (r >= (ssize_t)chunks[i].iov_len) {
42377 + r -= chunks[i].iov_len;
42378 + tc->offset += chunks[i].iov_len;
42380 + /* partially written */
42387 + return NETWORK_STATUS_SUCCESS;
42390 +NETWORK_BACKEND_WRITE(writev) {
42392 size_t chunks_written = 0;
42395 for(c = cq->first; c; c = c->next) {
42396 int chunk_finished = 0;
42398 + network_status_t ret;
42401 - case MEM_CHUNK: {
42406 - size_t num_chunks, i;
42407 - struct iovec chunks[UIO_MAXIOV];
42409 - size_t num_bytes = 0;
42411 - /* we can't send more then SSIZE_MAX bytes in one chunk */
42413 - /* build writev list
42415 - * 1. limit: num_chunks < UIO_MAXIOV
42416 - * 2. limit: num_bytes < SSIZE_MAX
42418 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42420 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42421 - if (tc->mem->used == 0) {
42422 - chunks[i].iov_base = tc->mem->ptr;
42423 - chunks[i].iov_len = 0;
42425 - offset = tc->mem->ptr + tc->offset;
42426 - toSend = tc->mem->used - 1 - tc->offset;
42428 - chunks[i].iov_base = offset;
42430 - /* protect the return value of writev() */
42431 - if (toSend > SSIZE_MAX ||
42432 - num_bytes + toSend > SSIZE_MAX) {
42433 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
42435 - num_chunks = i + 1;
42438 - chunks[i].iov_len = toSend;
42441 - num_bytes += toSend;
42445 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
42455 - log_error_write(srv, __FILE__, __LINE__, "ssd",
42456 - "writev failed:", strerror(errno), fd);
42462 - cq->bytes_out += r;
42464 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
42466 - /* check which chunks have been written */
42468 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42469 - if (r >= (ssize_t)chunks[i].iov_len) {
42471 - r -= chunks[i].iov_len;
42472 - tc->offset += chunks[i].iov_len;
42474 + /* check which chunks are finished now */
42475 + for (tc = c; tc; tc = tc->next) {
42476 + /* finished the chunk */
42477 + if (tc->offset == tc->mem->used - 1) {
42478 + /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
42479 if (chunk_finished) {
42480 - /* skip the chunks from further touches */
42481 - chunks_written++;
42484 - /* chunks_written + c = c->next is done in the for()*/
42485 - chunk_finished++;
42486 + chunk_finished = 1;
42489 - /* partially written */
42492 - chunk_finished = 0;
42499 + if (ret != NETWORK_STATUS_SUCCESS) {
42508 @@ -159,26 +173,26 @@
42509 #define KByte * 1024
42510 #define MByte * 1024 KByte
42511 #define GByte * 1024 MByte
42512 - const off_t we_want_to_mmap = 512 KByte;
42513 + const off_t we_want_to_mmap = 512 KByte;
42514 char *start = NULL;
42516 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42517 log_error_write(srv, __FILE__, __LINE__, "sb",
42518 strerror(errno), c->file.name);
42520 + return NETWORK_STATUS_FATAL_ERROR;
42523 abs_offset = c->file.start + c->offset;
42526 if (abs_offset > sce->st.st_size) {
42527 - log_error_write(srv, __FILE__, __LINE__, "sb",
42528 + log_error_write(srv, __FILE__, __LINE__, "sb",
42529 "file was shrinked:", c->file.name);
42533 + return NETWORK_STATUS_FATAL_ERROR;
42536 - /* mmap the buffer
42538 + /* mmap the buffer
42540 * - new mmap as the we are at the end of the last one */
42541 if (c->file.mmap.start == MAP_FAILED ||
42542 abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
42543 @@ -188,7 +202,7 @@
42544 * adaptive mem-mapping
42546 * we mmap() the whole file. If someone has alot large files and 32bit
42547 - * machine the virtual address area will be unrun and we will have a failing
42548 + * machine the virtual address area will be unrun and we will have a failing
42551 * only mmap 16M in one chunk and move the window as soon as we have finished
42552 @@ -234,8 +248,8 @@
42553 if (-1 == c->file.fd) { /* open the file if not already open */
42554 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
42555 log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
42559 + return NETWORK_STATUS_FATAL_ERROR;
42562 fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
42563 @@ -245,10 +259,10 @@
42564 if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
42565 /* close it here, otherwise we'd have to set FD_CLOEXEC */
42567 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
42568 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
42569 strerror(errno), c->file.name, c->file.fd);
42572 + return NETWORK_STATUS_FATAL_ERROR;
42575 c->file.mmap.length = to_mmap;
42576 @@ -258,7 +272,7 @@
42577 #ifdef HAVE_MADVISE
42578 /* don't advise files < 64Kb */
42579 if (c->file.mmap.length > (64 KByte)) {
42580 - /* darwin 7 is returning EINVAL all the time and I don't know how to
42581 + /* darwin 7 is returning EINVAL all the time and I don't know how to
42582 * detect this at runtime.i
42584 * ignore the return value for now */
42585 @@ -274,12 +288,12 @@
42586 toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
42589 - log_error_write(srv, __FILE__, __LINE__, "soooo",
42590 + log_error_write(srv, __FILE__, __LINE__, "soooo",
42591 "toSend is negative:",
42593 c->file.mmap.length,
42595 - c->file.mmap.offset);
42596 + c->file.mmap.offset);
42597 assert(toSend < 0);
42600 @@ -297,18 +311,18 @@
42605 + return NETWORK_STATUS_CONNECTION_CLOSE;
42607 - log_error_write(srv, __FILE__, __LINE__, "ssd",
42608 + log_error_write(srv, __FILE__, __LINE__, "ssd",
42609 "write failed:", strerror(errno), fd);
42613 + return NETWORK_STATUS_FATAL_ERROR;
42619 cq->bytes_out += r;
42622 if (c->offset == c->file.length) {
42623 chunk_finished = 1;
42625 @@ -318,26 +332,26 @@
42626 c->file.mmap.start = MAP_FAILED;
42636 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42640 + return NETWORK_STATUS_FATAL_ERROR;
42644 if (!chunk_finished) {
42645 /* not finished yet */
42655 - return chunks_written;
42656 + return NETWORK_STATUS_SUCCESS;
42660 --- lighttpd-1.4.11/src/plugin.c 2006-02-08 14:00:54.000000000 +0200
42661 +++ lighttpd-1.4.12/src/plugin.c 2006-07-11 22:07:52.000000000 +0300
42662 @@ -13,27 +13,27 @@
42663 #include <valgrind/valgrind.h>
42673 * if you change this enum to add a new callback, be sure
42674 * - that PLUGIN_FUNC_SIZEOF is the last entry
42675 * - that you add PLUGIN_TO_SLOT twice:
42676 - * 1. as callback-dispatcher
42677 + * 1. as callback-dispatcher
42678 * 2. in plugins_call_init()
42690 - PLUGIN_FUNC_HANDLE_URI_CLEAN,
42691 - PLUGIN_FUNC_HANDLE_URI_RAW,
42692 + PLUGIN_FUNC_HANDLE_URI_CLEAN,
42693 + PLUGIN_FUNC_HANDLE_URI_RAW,
42694 PLUGIN_FUNC_HANDLE_REQUEST_DONE,
42695 PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
42696 PLUGIN_FUNC_HANDLE_TRIGGER,
42697 @@ -44,38 +44,42 @@
42698 PLUGIN_FUNC_HANDLE_DOCROOT,
42699 PLUGIN_FUNC_HANDLE_PHYSICAL,
42700 PLUGIN_FUNC_CONNECTION_RESET,
42701 - PLUGIN_FUNC_INIT,
42702 + PLUGIN_FUNC_INIT,
42703 PLUGIN_FUNC_CLEANUP,
42704 PLUGIN_FUNC_SET_DEFAULTS,
42710 static plugin *plugin_init(void) {
42714 p = calloc(1, sizeof(*p));
42717 + p->required_plugins = array_init();
42722 static void plugin_free(plugin *p) {
42723 int use_dlclose = 1;
42724 if (p->name) buffer_free(p->name);
42726 + array_free(p->required_plugins);
42727 #ifdef HAVE_VALGRIND_VALGRIND_H
42728 /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
42731 #ifndef LIGHTTPD_STATIC
42732 - if (use_dlclose && p->lib) {
42734 + if (use_dlclose && p->lib) {
42736 FreeLibrary(p->lib);
42747 @@ -89,17 +93,17 @@
42748 srv->plugins.size += 4;
42749 srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
42753 ps = srv->plugins.ptr;
42754 ps[srv->plugins.used++] = p;
42769 #ifdef LIGHTTPD_STATIC
42770 @@ -121,30 +125,35 @@
42772 int plugins_load(server *srv) {
42777 int (*init)(plugin *pl);
42785 for (i = 0; i < srv->srvconf.modules->used; i++) {
42786 data_string *d = (data_string *)srv->srvconf.modules->data[i];
42787 char *modules = d->value->ptr;
42790 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
42792 buffer_append_string(srv->tmp_buf, "/");
42793 buffer_append_string(srv->tmp_buf, modules);
42794 -#if defined(__WIN32) || defined(__CYGWIN__)
42795 +#if defined(_WIN32) || defined(__CYGWIN__)
42796 buffer_append_string(srv->tmp_buf, ".dll");
42798 buffer_append_string(srv->tmp_buf, ".so");
42805 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
42808 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
42809 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
42810 FORMAT_MESSAGE_FROM_SYSTEM,
42813 @@ -152,36 +161,36 @@
42814 (LPTSTR) &lpMsgBuf,
42817 - log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
42818 + log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
42819 lpMsgBuf, srv->tmp_buf);
42830 if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
42831 - log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
42832 + log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
42833 srv->tmp_buf, dlerror());
42844 buffer_reset(srv->tmp_buf);
42845 buffer_copy_string(srv->tmp_buf, modules);
42846 buffer_append_string(srv->tmp_buf, "_plugin_init");
42850 init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
42852 if (init == NULL) {
42855 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
42856 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
42857 FORMAT_MESSAGE_FROM_SYSTEM,
42860 @@ -190,7 +199,7 @@
42863 log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
42869 @@ -203,24 +212,43 @@
42871 if ((error = dlerror()) != NULL) {
42872 log_error_write(srv, __FILE__, __LINE__, "s", error);
42882 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
42889 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
42891 + /* check if the required plugin is loaded */
42892 + for (k = 0; k < p->required_plugins->used; k++) {
42893 + data_string *req = (data_string *)p->required_plugins->data[k];
42895 + for (j = 0; j < i; j++) {
42896 + data_string *mod = (data_string *)srv->srvconf.modules->data[j];
42898 + if (buffer_is_equal(req->value, mod->value)) break;
42903 + log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
42910 plugins_register(srv, p);
42917 @@ -253,8 +281,8 @@
42921 - * plugins that use
42923 + * plugins that use
42926 * - connection *con
42927 * - void *p_d (plugin_data *)
42928 @@ -301,12 +329,12 @@
42932 - * plugins that use
42934 + * plugins that use
42937 * - void *p_d (plugin_data *)
42941 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
42942 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
42943 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
42944 @@ -314,18 +342,18 @@
42946 #undef PLUGIN_TO_SLOT
42957 handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
42962 ps = srv->plugins.ptr;
42965 for (i = 0; i < srv->plugins.used; i++) {
42967 if (p->handle_fdevent) {
42968 @@ -344,34 +372,34 @@
42974 return HANDLER_GO_ON;
42980 * - call init function of all plugins to init the plugin-internals
42981 * - added each plugin that supports has callback to the corresponding slot
42984 * - is only called once.
42987 handler_t plugins_call_init(server *srv) {
42992 ps = srv->plugins.ptr;
42998 srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
43001 for (i = 0; i < srv->plugins.used; i++) {
43003 /* check which calls are supported */
43009 #define PLUGIN_TO_SLOT(x, y) \
43011 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
43012 @@ -384,11 +412,11 @@
43019 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
43020 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
43024 + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
43025 + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
43026 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
43027 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
43028 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
43029 @@ -402,19 +430,19 @@
43030 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
43031 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
43032 #undef PLUGIN_TO_SLOT
43036 if (NULL == (p->data = p->init())) {
43037 - log_error_write(srv, __FILE__, __LINE__, "sb",
43038 + log_error_write(srv, __FILE__, __LINE__, "sb",
43039 "plugin-init failed for module", p->name);
43040 return HANDLER_ERROR;
43044 /* used for con->mode, DIRECT == 0, plugins above that */
43045 ((plugin_data *)(p->data))->id = i + 1;
43048 if (p->version != LIGHTTPD_VERSION_ID) {
43049 - log_error_write(srv, __FILE__, __LINE__, "sb",
43050 + log_error_write(srv, __FILE__, __LINE__, "sb",
43051 "plugin-version doesn't match lighttpd-version for", p->name);
43052 return HANDLER_ERROR;
43054 @@ -422,29 +450,46 @@
43060 return HANDLER_GO_ON;
43064 + * get the config-storage of the named plugin
43066 +void *plugin_get_config(server *srv, const char *name) {
43069 + for (i = 0; i < srv->plugins.used; i++) {
43070 + plugin *p = ((plugin **)srv->plugins.ptr)[i];
43072 + if (buffer_is_equal_string(p->name, name, strlen(name))) {
43080 void plugins_free(server *srv) {
43082 plugins_call_cleanup(srv);
43085 for (i = 0; i < srv->plugins.used; i++) {
43086 plugin *p = ((plugin **)srv->plugins.ptr)[i];
43093 for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
43094 plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
43097 if (slot) free(slot);
43101 free(srv->plugin_slots);
43102 srv->plugin_slots = NULL;
43105 free(srv->plugins.ptr);
43106 srv->plugins.ptr = NULL;
43107 srv->plugins.used = 0;
43108 --- lighttpd-1.4.11/src/plugin.h 2005-08-15 12:28:56.000000000 +0300
43109 +++ lighttpd-1.4.12/src/plugin.h 2006-07-11 22:07:52.000000000 +0300
43112 #define INIT_FUNC(x) \
43115 + * The PATCH_OPTION() macro is used in the patch_connection() functions
43116 + * of the modules to update the config object for the current request.
43118 +#define PATCH_OPTION(x) \
43121 #define FREE_FUNC SERVER_FUNC
43122 #define TRIGGER_FUNC SERVER_FUNC
43123 @@ -25,19 +31,19 @@
43124 #define URIHANDLER_FUNC CONNECTION_FUNC
43126 #define PLUGIN_DATA size_t id
43133 buffer *name; /* name of the plugin */
43137 handler_t (* set_defaults) (server *srv, void *p_d);
43138 handler_t (* cleanup) (server *srv, void *p_d);
43139 /* is called ... */
43140 handler_t (* handle_trigger) (server *srv, void *p_d); /* once a second */
43141 handler_t (* handle_sighup) (server *srv, void *p_d); /* at a signup */
43144 handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d); /* after uri_raw is set */
43145 handler_t (* handle_uri_clean) (server *srv, connection *con, void *p_d); /* after uri is set */
43146 handler_t (* handle_docroot) (server *srv, connection *con, void *p_d); /* getting the document-root */
43147 @@ -45,20 +51,22 @@
43148 handler_t (* handle_request_done) (server *srv, connection *con, void *p_d); /* at the end of a request */
43149 handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d); /* at the end of a connection */
43150 handler_t (* handle_joblist) (server *srv, connection *con, void *p_d); /* after all events are handled */
43154 - handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43156 - /* when a handler for the request
43160 + handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43162 + /* when a handler for the request
43165 handler_t (* handle_subrequest) (server *srv, connection *con, void *p_d); /* */
43166 handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* */
43170 /* dlopen handle */
43173 + array *required_plugins;
43176 int plugins_load(server *srv);
43178 int config_patch_connection(server *srv, connection *con, comp_key_t comp);
43179 int config_check_cond(server *srv, connection *con, data_config *dc);
43180 int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
43181 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
43183 +void *plugin_get_config(server *srv, const char *name);
43186 --- lighttpd-1.4.11/src/proc_open.c 2005-08-11 01:26:39.000000000 +0300
43187 +++ lighttpd-1.4.12/src/proc_open.c 2006-07-11 22:07:53.000000000 +0300
43188 @@ -13,13 +13,13 @@
43194 /* {{{ win32 stuff */
43195 # define SHELLENV "ComSpec"
43196 # define SECURITY_DC , SECURITY_ATTRIBUTES *security
43197 # define SECURITY_CC , security
43198 # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
43199 -static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43200 +static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43202 HANDLE copy, self = GetCurrentProcess();
43204 @@ -148,11 +148,14 @@
43207 SECURITY_ATTRIBUTES security;
43208 - const char *shell;
43209 + const char *shell = NULL;
43210 + const char *windir = NULL;
43213 - if (NULL == (shell = getenv(SHELLENV))) {
43214 - fprintf(stderr, "env %s is required", SHELLENV);
43215 + if (NULL == (shell = getenv(SHELLENV)) &&
43216 + NULL == (windir = getenv("SystemRoot")) &&
43217 + NULL == (windir = getenv("windir"))) {
43218 + fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
43222 @@ -177,17 +180,23 @@
43223 memset(&pi, 0, sizeof(pi));
43225 cmdline = buffer_init();
43226 - buffer_append_string(cmdline, shell);
43228 + buffer_append_string(cmdline, shell);
43230 + buffer_append_string(cmdline, windir);
43231 + buffer_append_string(cmdline, "\\system32\\cmd.exe");
43233 buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
43234 buffer_append_string(cmdline, command);
43235 procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
43236 NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
43237 - buffer_free(cmdline);
43239 if (FALSE == procok) {
43240 - fprintf(stderr, "failed to CreateProcess");
43241 + fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
43242 + buffer_free(cmdline);
43245 + buffer_free(cmdline);
43247 proc->child = pi.hProcess;
43248 CloseHandle(pi.hThread);
43249 @@ -226,8 +235,7 @@
43252 if (NULL == (shell = getenv(SHELLENV))) {
43253 - fprintf(stderr, "env %s is required", SHELLENV);
43255 + shell = "/bin/sh";
43258 if (proc_open_pipes(proc) != 0) {
43259 @@ -262,11 +270,11 @@
43263 -#endif /* WIN32 */
43264 +#endif /* _WIN32 */
43266 /* {{{ proc_read_fd_to_buffer */
43267 static void proc_read_fd_to_buffer(int fd, buffer *b) {
43269 + int s; /* win32 has not ssize_t */
43272 buffer_prepare_append(b, 512);
43273 --- lighttpd-1.4.11/src/proc_open.h 2005-08-11 01:26:39.000000000 +0300
43274 +++ lighttpd-1.4.12/src/proc_open.h 2006-07-11 22:07:53.000000000 +0300
43277 #include "buffer.h"
43281 #include <windows.h>
43282 typedef HANDLE descriptor_t;
43283 typedef HANDLE proc_pid_t;
43284 --- lighttpd-1.4.11/src/request.c 2006-03-05 11:58:09.000000000 +0200
43285 +++ lighttpd-1.4.12/src/request.c 2006-07-11 22:07:52.000000000 +0300
43286 @@ -10,15 +10,17 @@
43287 #include "keyvalue.h"
43290 +#include "sys-strings.h"
43292 static int request_check_hostname(server *srv, connection *con, buffer *host) {
43293 enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
43298 - int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
43299 + int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
43306 @@ -32,17 +34,17 @@
43307 * IPv6address = "[" ... "]"
43313 if (!host || host->used == 0) return 0;
43316 host_len = host->used - 1;
43320 if (host->ptr[0] == '[') {
43321 char *c = host->ptr + 1;
43325 /* check portnumber */
43326 for (; *c && *c != ']'; c++) {
43328 @@ -53,12 +55,12 @@
43341 if (*(c+1) == ':') {
43342 for (c += 2; *c; c++) {
43343 @@ -69,39 +71,39 @@
43349 if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
43350 char *c = colon + 1;
43353 /* check portnumber */
43355 if (!light_isdigit(*c)) return -1;
43359 /* remove the port from the host-len */
43360 host_len = colon - host->ptr;
43364 /* Host is empty */
43365 if (host_len == 0) return -1;
43368 /* scan from the right and skip the \0 */
43369 for (i = host_len - 1; i + 1 > 0; i--) {
43370 const char c = host->ptr[i];
43376 /* only switch stage, if this is not the last character */
43377 if (i != host_len - 1) {
43378 if (label_len == 0) {
43383 /* check the first character at right of the dot */
43385 if (!light_isalpha(host->ptr[i+1])) {
43389 } else if (!light_isdigit(host->ptr[i+1])) {
43391 @@ -111,9 +113,9 @@
43397 stage = DOMAINLABEL;
43402 } else if (i == 0) {
43403 @@ -135,7 +137,7 @@
43412 @@ -143,7 +145,7 @@
43413 if (label_len == 0) {
43420 } else if (!light_isdigit(c)) {
43421 @@ -156,12 +158,12 @@
43422 if (label_len == 0) {
43427 /* c is either - or alphanum here */
43428 if ('-' == host->ptr[i+1]) {
43435 } else if (i == 0) {
43436 @@ -176,20 +178,20 @@
43447 /* a IP has to consist of 4 parts */
43448 if (is_ip == 1 && level != 3) {
43453 if (label_len == 0) {
43461 @@ -201,53 +203,53 @@
43471 * val1, val2, val3, val4
43474 * into a array (more or less a explode() incl. striping of whitespaces
43478 if (b->used == 0) return 0;
43484 for (i =0; i < b->used - 1; ) {
43485 char *start = NULL, *end = NULL;
43494 for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
43501 case 1: /* value */
43505 for (; *s != ',' && i < b->used - 1; i++, s++);
43509 for (; (*end == ' ' || *end == '\t') && end > start; end--);
43512 if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
43513 ds = data_string_init();
43516 buffer_copy_string_len(ds->value, start, end-start+1);
43517 array_insert_unique(vals, (data_unset *)ds);
43525 /* end of string */
43531 @@ -263,7 +265,7 @@
43532 if (c <= 32) return 0;
43533 if (c == 127) return 0;
43534 if (c == 255) return 0;
43540 @@ -271,28 +273,28 @@
43541 char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
43542 int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
43543 char *value = NULL, *key = NULL;
43546 enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
43552 int request_line_stage = 0;
43559 data_string *ds = NULL;
43562 - * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43563 - * Option : "^([-a-zA-Z]+): (.+)$"
43566 + * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43567 + * Option : "^([-a-zA-Z]+): (.+)$"
43571 if (con->conf.log_request_header) {
43572 - log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43574 - "request-len:", con->request.request->used,
43575 + log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43577 + "request-len:", con->request.request->used,
43578 "\n", con->request.request);
43581 @@ -300,13 +302,13 @@
43582 con->request.request->ptr[0] == '\r' &&
43583 con->request.request->ptr[1] == '\n') {
43584 /* we are in keep-alive and might get \r\n after a previous POST request.*/
43587 buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
43589 /* fill the local request buffer */
43590 buffer_copy_string_buffer(con->parse_request, con->request.request);
43594 keep_alive_set = 0;
43595 con_length_set = 0;
43597 @@ -318,25 +320,25 @@
43599 for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
43600 char *cur = con->parse_request->ptr + i;
43606 if (con->parse_request->ptr[i+1] == '\n') {
43613 con->parse_request->ptr[i] = '\0';
43614 con->parse_request->ptr[i+1] = '\0';
43617 buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
43620 if (request_line_stage != 2) {
43621 con->http_status = 400;
43622 con->response.keep_alive = 0;
43623 con->keep_alive = 0;
43626 if (srv->srvconf.log_request_header_on_error) {
43627 log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
43628 log_error_write(srv, __FILE__, __LINE__, "Sb",
43629 @@ -345,36 +347,36 @@
43635 proto = con->parse_request->ptr + first;
43639 *(proto - 1) = '\0';
43642 /* we got the first one :) */
43643 if (-1 == (r = get_http_method_key(method))) {
43644 con->http_status = 501;
43645 con->response.keep_alive = 0;
43646 con->keep_alive = 0;
43649 if (srv->srvconf.log_request_header_on_error) {
43650 log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
43651 log_error_write(srv, __FILE__, __LINE__, "Sb",
43652 "request-header:\n",
43653 con->request.request);
43661 con->request.http_method = r;
43668 * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
43672 if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
43673 char * major = proto + sizeof("HTTP/") - 1;
43674 char * minor = strchr(major, '.');
43675 @@ -413,10 +415,10 @@
43678 if (major_num == 1 && minor_num == 1) {
43679 - con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
43680 + con->request.http_version = HTTP_VERSION_1_1;
43681 } else if (major_num == 1 && minor_num == 0) {
43682 con->request.http_version = HTTP_VERSION_1_0;
43685 con->http_status = 505;
43687 if (srv->srvconf.log_request_header_on_error) {
43688 @@ -439,30 +441,30 @@
43694 if (0 == strncmp(uri, "http://", 7) &&
43695 NULL != (nuri = strchr(uri + 7, '/'))) {
43696 /* ignore the host-part */
43699 buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
43701 /* everything looks good so far */
43702 buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
43706 /* check uri for invalid characters */
43707 for (j = 0; j < con->request.uri->used - 1; j++) {
43708 if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
43709 unsigned char buf[2];
43710 con->http_status = 400;
43711 con->keep_alive = 0;
43714 if (srv->srvconf.log_request_header_on_error) {
43715 buf[0] = con->request.uri->ptr[j];
43719 if (con->request.uri->ptr[j] > 32 &&
43720 - con->request.uri->ptr[j] != 127) {
43721 + con->request.uri->ptr[j] != 127) {
43722 /* the character is printable -> print it */
43723 log_error_write(srv, __FILE__, __LINE__, "ss",
43724 "invalid character in URI -> 400",
43725 @@ -473,20 +475,20 @@
43726 "invalid character in URI -> 400",
43727 con->request.uri->ptr[j]);
43731 log_error_write(srv, __FILE__, __LINE__, "Sb",
43732 "request-header:\n",
43733 con->request.request);
43742 buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
43745 con->http_status = 0;
43751 @@ -494,14 +496,14 @@
43754 switch(request_line_stage) {
43758 - method = con->parse_request->ptr + first;
43759 + method = con->parse_request->ptr + first;
43764 - uri = con->parse_request->ptr + first;
43765 + uri = con->parse_request->ptr + first;
43769 @@ -509,7 +511,7 @@
43770 con->http_status = 400;
43771 con->response.keep_alive = 0;
43772 con->keep_alive = 0;
43775 if (srv->srvconf.log_request_header_on_error) {
43776 log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
43777 log_error_write(srv, __FILE__, __LINE__, "Sb",
43778 @@ -518,12 +520,12 @@
43784 request_line_stage++;
43792 if (con->request.uri->used == 1) {
43793 @@ -540,30 +542,30 @@
43799 for (; i < con->parse_request->used && !done; i++) {
43800 char *cur = con->parse_request->ptr + i;
43809 * 1*<any CHAR except CTLs or separators>
43810 * CTLs == 0-31 + 127
43822 if (is_ws_after_key == 0) {
43823 key_len = i - first;
43825 is_ws_after_key = 0;
43831 @@ -584,8 +586,8 @@
43832 con->http_status = 400;
43833 con->keep_alive = 0;
43834 con->response.keep_alive = 0;
43836 - log_error_write(srv, __FILE__, __LINE__, "sbsds",
43838 + log_error_write(srv, __FILE__, __LINE__, "sbsds",
43839 "invalid character in key", con->request.request, cur, *cur, "-> 400");
43842 @@ -594,13 +596,13 @@
43854 key_len = i - first;
43857 /* skip every thing up to the : */
43858 for (j = 1; !got_colon; j++) {
43859 switch(con->parse_request->ptr[j + i]) {
43860 @@ -610,40 +612,40 @@
43875 if (srv->srvconf.log_request_header_on_error) {
43876 log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
43877 log_error_write(srv, __FILE__, __LINE__, "Sb",
43878 "request-header:\n",
43879 con->request.request);
43883 con->http_status = 400;
43884 con->response.keep_alive = 0;
43885 con->keep_alive = 0;
43895 if (con->parse_request->ptr[i+1] == '\n' && i == first) {
43896 /* End of Header */
43897 con->parse_request->ptr[i] = '\0';
43898 con->parse_request->ptr[i+1] = '\0';
43909 if (srv->srvconf.log_request_header_on_error) {
43910 @@ -652,7 +654,7 @@
43911 "request-header:\n",
43912 con->request.request);
43916 con->http_status = 400;
43917 con->keep_alive = 0;
43918 con->response.keep_alive = 0;
43919 @@ -693,16 +695,16 @@
43920 con->http_status = 400;
43921 con->keep_alive = 0;
43922 con->response.keep_alive = 0;
43925 if (srv->srvconf.log_request_header_on_error) {
43926 - log_error_write(srv, __FILE__, __LINE__, "sbsds",
43927 + log_error_write(srv, __FILE__, __LINE__, "sbsds",
43928 "CTL character in key", con->request.request, cur, *cur, "-> 400");
43930 log_error_write(srv, __FILE__, __LINE__, "Sb",
43931 "request-header:\n",
43932 con->request.request);
43939 @@ -710,25 +712,25 @@
43945 if (con->parse_request->ptr[i+1] == '\n') {
43946 /* End of Headerline */
43947 con->parse_request->ptr[i] = '\0';
43948 con->parse_request->ptr[i+1] = '\0';
43956 if (srv->srvconf.log_request_header_on_error) {
43957 log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
43960 log_error_write(srv, __FILE__, __LINE__, "Sb",
43961 "request-header:\n",
43962 con->request.request);
43967 con->http_status = 400;
43968 con->keep_alive = 0;
43969 con->response.keep_alive = 0;
43970 @@ -738,9 +740,9 @@
43973 key = con->parse_request->ptr + first;
43976 s_len = cur - value;
43981 if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
43982 @@ -748,86 +750,87 @@
43984 buffer_copy_string_len(ds->key, key, key_len);
43985 buffer_copy_string_len(ds->value, value, s_len);
43987 - /* retreive values
43991 + /* retreive values
43994 * the list of options is sorted to simplify the search
43998 if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
44006 vals = srv->split_vals;
44011 http_request_split_value(vals, ds->value);
44014 for (vi = 0; vi < vals->used; vi++) {
44015 data_string *dsv = (data_string *)vals->data[vi];
44018 if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
44019 keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
44023 } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
44024 keep_alive_set = HTTP_CONNECTION_CLOSE;
44032 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
44034 unsigned long int r;
44038 if (con_length_set) {
44039 con->http_status = 400;
44040 con->keep_alive = 0;
44043 if (srv->srvconf.log_request_header_on_error) {
44044 - log_error_write(srv, __FILE__, __LINE__, "s",
44045 + log_error_write(srv, __FILE__, __LINE__, "s",
44046 "duplicate Content-Length-header -> 400");
44047 log_error_write(srv, __FILE__, __LINE__, "Sb",
44048 "request-header:\n",
44049 con->request.request);
44051 + ds->free((data_unset *) ds);
44056 if (ds->value->used == 0) SEGFAULT();
44059 for (j = 0; j < ds->value->used - 1; j++) {
44060 char c = ds->value->ptr[j];
44061 if (!isdigit((unsigned char)c)) {
44062 - log_error_write(srv, __FILE__, __LINE__, "sbs",
44063 + log_error_write(srv, __FILE__, __LINE__, "sbs",
44064 "content-length broken:", ds->value, "-> 400");
44067 con->http_status = 400;
44068 con->keep_alive = 0;
44071 array_insert_unique(con->request.headers, (data_unset *)ds);
44077 r = strtoul(ds->value->ptr, &err, 10);
44080 if (*err == '\0') {
44081 con_length_set = 1;
44082 con->request.content_length = r;
44084 - log_error_write(srv, __FILE__, __LINE__, "sbs",
44085 + log_error_write(srv, __FILE__, __LINE__, "sbs",
44086 "content-length broken:", ds->value, "-> 400");
44089 con->http_status = 400;
44090 con->keep_alive = 0;
44093 array_insert_unique(con->request.headers, (data_unset *)ds);
44096 @@ -838,23 +841,24 @@
44098 con->http_status = 400;
44099 con->keep_alive = 0;
44102 if (srv->srvconf.log_request_header_on_error) {
44103 - log_error_write(srv, __FILE__, __LINE__, "s",
44104 + log_error_write(srv, __FILE__, __LINE__, "s",
44105 "duplicate Content-Type-header -> 400");
44106 log_error_write(srv, __FILE__, __LINE__, "Sb",
44107 "request-header:\n",
44108 con->request.request);
44110 + ds->free((data_unset *) ds);
44113 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
44114 - /* HTTP 2616 8.2.3
44115 + /* HTTP 2616 8.2.3
44116 * Expect: 100-continue
44119 * -> (10.1.1) 100 (read content, process request, send final status-code)
44120 * -> (10.4.18) 417 (close)
44123 * (not handled at all yet, we always send 417 here)
44125 * What has to be added ?
44126 @@ -863,10 +867,10 @@
44132 con->http_status = 417;
44133 con->keep_alive = 0;
44136 array_insert_unique(con->request.headers, (data_unset *)ds);
44138 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
44139 @@ -875,14 +879,15 @@
44141 con->http_status = 400;
44142 con->keep_alive = 0;
44145 if (srv->srvconf.log_request_header_on_error) {
44146 - log_error_write(srv, __FILE__, __LINE__, "s",
44147 + log_error_write(srv, __FILE__, __LINE__, "s",
44148 "duplicate Host-header -> 400");
44149 log_error_write(srv, __FILE__, __LINE__, "Sb",
44150 "request-header:\n",
44151 con->request.request);
44153 + ds->free((data_unset *) ds);
44156 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
44157 @@ -897,14 +902,15 @@
44159 con->http_status = 400;
44160 con->keep_alive = 0;
44163 if (srv->srvconf.log_request_header_on_error) {
44164 - log_error_write(srv, __FILE__, __LINE__, "s",
44165 + log_error_write(srv, __FILE__, __LINE__, "s",
44166 "duplicate If-Modified-Since header -> 400");
44167 log_error_write(srv, __FILE__, __LINE__, "Sb",
44168 "request-header:\n",
44169 con->request.request);
44171 + ds->free((data_unset *) ds);
44174 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
44175 @@ -914,47 +920,49 @@
44177 con->http_status = 400;
44178 con->keep_alive = 0;
44181 if (srv->srvconf.log_request_header_on_error) {
44182 - log_error_write(srv, __FILE__, __LINE__, "s",
44183 + log_error_write(srv, __FILE__, __LINE__, "s",
44184 "duplicate If-None-Match-header -> 400");
44185 log_error_write(srv, __FILE__, __LINE__, "Sb",
44186 "request-header:\n",
44187 con->request.request);
44189 + ds->free((data_unset *) ds);
44192 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
44193 if (!con->request.http_range) {
44197 if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
44198 NULL != strchr(ds->value->ptr+6, '-')) {
44201 /* if dup, only the first one will survive */
44202 con->request.http_range = ds->value->ptr + 6;
44205 con->http_status = 400;
44206 con->keep_alive = 0;
44209 if (srv->srvconf.log_request_header_on_error) {
44210 - log_error_write(srv, __FILE__, __LINE__, "s",
44211 + log_error_write(srv, __FILE__, __LINE__, "s",
44212 "duplicate Range-header -> 400");
44213 log_error_write(srv, __FILE__, __LINE__, "Sb",
44214 "request-header:\n",
44215 con->request.request);
44217 + ds->free((data_unset *) ds);
44223 array_insert_unique(con->request.headers, (data_unset *)ds);
44225 /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
44233 @@ -963,10 +971,10 @@
44236 if (srv->srvconf.log_request_header_on_error) {
44237 - log_error_write(srv, __FILE__, __LINE__, "sbs",
44238 + log_error_write(srv, __FILE__, __LINE__, "sbs",
44239 "CR without LF", con->request.request, "-> 400");
44243 con->http_status = 400;
44244 con->keep_alive = 0;
44245 con->response.keep_alive = 0;
44246 @@ -982,28 +990,28 @@
44252 con->header_len = i;
44255 /* do some post-processing */
44257 if (con->request.http_version == HTTP_VERSION_1_1) {
44258 if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
44259 /* no Connection-Header sent */
44262 /* HTTP/1.1 -> keep-alive default TRUE */
44263 con->keep_alive = 1;
44265 con->keep_alive = 0;
44269 /* RFC 2616, 14.23 */
44270 if (con->request.http_host == NULL ||
44271 buffer_is_empty(con->request.http_host)) {
44272 con->http_status = 400;
44273 con->response.keep_alive = 0;
44274 con->keep_alive = 0;
44277 if (srv->srvconf.log_request_header_on_error) {
44278 log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
44279 log_error_write(srv, __FILE__, __LINE__, "Sb",
44280 @@ -1015,18 +1023,18 @@
44282 if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
44283 /* no Connection-Header sent */
44286 /* HTTP/1.0 -> keep-alive default FALSE */
44287 con->keep_alive = 1;
44289 con->keep_alive = 0;
44294 /* check hostname field if it is set */
44295 if (NULL != con->request.http_host &&
44296 0 != request_check_hostname(srv, con, con->request.http_host)) {
44299 if (srv->srvconf.log_request_header_on_error) {
44300 log_error_write(srv, __FILE__, __LINE__, "s",
44301 "Invalid Hostname -> 400");
44302 @@ -1038,7 +1046,7 @@
44303 con->http_status = 400;
44304 con->response.keep_alive = 0;
44305 con->keep_alive = 0;
44311 @@ -1048,7 +1056,7 @@
44312 /* content-length is forbidden for those */
44313 if (con_length_set && con->request.content_length != 0) {
44314 /* content-length is missing */
44315 - log_error_write(srv, __FILE__, __LINE__, "s",
44316 + log_error_write(srv, __FILE__, __LINE__, "s",
44317 "GET/HEAD with content-length -> 400");
44319 con->keep_alive = 0;
44320 @@ -1060,7 +1068,7 @@
44321 /* content-length is required for them */
44322 if (!con_length_set) {
44323 /* content-length is missing */
44324 - log_error_write(srv, __FILE__, __LINE__, "s",
44325 + log_error_write(srv, __FILE__, __LINE__, "s",
44326 "POST-request, but content-length missing -> 411");
44328 con->keep_alive = 0;
44329 @@ -1073,16 +1081,16 @@
44330 /* the may have a content-length */
44337 /* check if we have read post data */
44338 if (con_length_set) {
44339 /* don't handle more the SSIZE_MAX bytes in content-length */
44340 if (con->request.content_length > SSIZE_MAX) {
44341 - con->http_status = 413;
44342 + con->http_status = 413;
44343 con->keep_alive = 0;
44345 - log_error_write(srv, __FILE__, __LINE__, "sds",
44346 + log_error_write(srv, __FILE__, __LINE__, "sds",
44347 "request-size too long:", con->request.content_length, "-> 413");
44350 @@ -1090,25 +1098,25 @@
44351 /* divide by 1024 as srvconf.max_request_size is in kBytes */
44352 if (srv->srvconf.max_request_size != 0 &&
44353 (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
44354 - /* the request body itself is larger then
44355 + /* the request body itself is larger then
44356 * our our max_request_size
44360 con->http_status = 413;
44361 con->keep_alive = 0;
44363 - log_error_write(srv, __FILE__, __LINE__, "sds",
44365 + log_error_write(srv, __FILE__, __LINE__, "sds",
44366 "request-size too long:", con->request.content_length, "-> 413");
44373 /* we have content */
44374 if (con->request.content_length != 0) {
44383 @@ -1116,9 +1124,9 @@
44386 if (con->request.request->used < 5) return 0;
44389 if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
44390 if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
44395 --- lighttpd-1.4.11/src/response.c 2006-03-04 16:41:39.000000000 +0200
44396 +++ lighttpd-1.4.12/src/response.c 2006-07-11 22:07:52.000000000 +0300
44398 #include <stdlib.h>
44399 #include <string.h>
44401 -#include <unistd.h>
44403 #include <assert.h>
44405 @@ -24,15 +23,17 @@
44406 #include "plugin.h"
44408 #include "sys-socket.h"
44409 +#include "sys-files.h"
44410 +#include "sys-strings.h"
44412 int http_response_write_header(server *srv, connection *con) {
44416 int have_server = 0;
44419 b = chunkqueue_get_prepend_buffer(con->write_queue);
44422 if (con->request.http_version == HTTP_VERSION_1_1) {
44423 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
44425 @@ -41,25 +42,26 @@
44426 buffer_append_long(b, con->http_status);
44427 BUFFER_APPEND_STRING_CONST(b, " ");
44428 buffer_append_string(b, get_http_status_name(con->http_status));
44431 if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
44432 BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
44433 buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
44437 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
44438 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
44444 /* add all headers */
44445 for (i = 0; i < con->response.headers->used; i++) {
44449 ds = (data_string *)con->response.headers->data[i];
44452 if (ds->value->used && ds->key->used &&
44453 - 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
44454 + 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
44455 + 0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
44456 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
44457 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
44459 @@ -68,28 +70,28 @@
44460 BUFFER_APPEND_STRING_CONST(b, ": ");
44461 buffer_append_string_buffer(b, ds->value);
44463 - log_error_write(srv, __FILE__, __LINE__, "bb",
44464 + log_error_write(srv, __FILE__, __LINE__, "bb",
44465 ds->key, ds->value);
44472 /* HTTP/1.1 requires a Date: header */
44473 BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
44476 /* cache the generated timestamp */
44477 if (srv->cur_ts != srv->last_generated_date_ts) {
44478 buffer_prepare_copy(srv->ts_date_str, 255);
44480 - strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
44482 + strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
44483 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
44486 srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
44489 srv->last_generated_date_ts = srv->cur_ts;
44493 buffer_append_string_buffer(b, srv->ts_date_str);
44496 @@ -101,16 +103,16 @@
44497 buffer_append_string_buffer(b, con->conf.server_tag);
44502 BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
44507 con->bytes_header = b->used - 1;
44510 if (con->conf.log_response_header) {
44511 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
44518 @@ -118,71 +120,71 @@
44520 handler_t http_response_prepare(server *srv, connection *con) {
44523 - /* looks like someone has already done a decision */
44524 - if (con->mode == DIRECT &&
44526 + /* looks like someone has already made a decision */
44527 + if (con->mode == DIRECT &&
44528 (con->http_status != 0 && con->http_status != 200)) {
44529 /* remove a packets in the queue */
44530 if (con->file_finished == 0) {
44531 chunkqueue_reset(con->write_queue);
44535 return HANDLER_FINISHED;
44539 /* no decision yet, build conf->filename */
44540 if (con->mode == DIRECT && con->physical.path->used == 0) {
44543 - /* we only come here when we have the parse the full request again
44545 - * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44546 + /* we only come here when we have to parse the full request again
44548 + * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44549 * problem here as mod_setenv might get called multiple times
44551 * fastcgi-auth might lead to a COMEBACK too
44552 * fastcgi again dead server too
44554 * mod_compress might add headers twice too
44560 if (con->conf.log_condition_handling) {
44561 log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
44563 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
44572 * - uri.path (secure)
44581 * Name according to RFC 2396
44590 * (scheme)://(authority)(path)?(query)
44598 buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
44599 buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
44600 buffer_to_lower(con->uri.authority);
44603 config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */
44604 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */
44605 config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
44606 config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */
44607 config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */
44610 /** extract query string from request.uri */
44611 if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
44612 buffer_copy_string (con->uri.query, qstr + 1);
44613 @@ -200,22 +202,22 @@
44614 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path_raw);
44615 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-query : ", con->uri.query);
44619 /* disable keep-alive if requested */
44622 if (con->request_count > con->conf.max_keep_alive_requests) {
44623 con->keep_alive = 0;
44636 * - based on the raw URL
44642 switch(r = plugins_call_handle_uri_raw(srv, con)) {
44643 case HANDLER_GO_ON:
44645 @@ -229,14 +231,14 @@
44649 - /* build filename
44650 + /* build filename
44652 * - decode url-encodings (e.g. %20 -> ' ')
44653 * - remove path-modifiers (e.g. /../)
44661 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44662 con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44663 /* OPTIONS * ... */
44664 @@ -253,15 +255,20 @@
44674 * - based on the clean URL
44680 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
44683 + /* do we have to downgrade to 1.0 ? */
44684 + if (!con->conf.allow_http11) {
44685 + con->request.http_version = HTTP_VERSION_1_0;
44688 switch(r = plugins_call_handle_uri_clean(srv, con)) {
44689 case HANDLER_GO_ON:
44691 @@ -274,11 +281,11 @@
44692 log_error_write(srv, __FILE__, __LINE__, "");
44697 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44698 con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44699 - /* option requests are handled directly without checking of the path */
44701 + /* option requests are handled directly without checking the path */
44703 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
44705 con->http_status = 200;
44706 @@ -288,46 +295,47 @@
44716 * logical filename (URI) becomes a physical filename here
44733 * ... ISREG() -> ok, go on
44734 * ... ISDIR() -> index-file -> redirect
44749 * SEARCH DOCUMENT ROOT
44753 /* set a default */
44756 buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
44757 buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
44759 -#if defined(__WIN32) || defined(__CYGWIN__)
44760 - /* strip dots from the end and spaces
44762 + filename_unix2local(con->physical.rel_path);
44763 +#if defined(_WIN32) || defined(__CYGWIN__)
44764 + /* strip dots and spaces from the end
44766 * windows/dos handle those filenames as the same file
44768 * foo == foo. == foo..... == "foo... " == "foo.. ./"
44770 - * This will affect in some cases PATHINFO
44771 + * This will affect PATHINFO in some cases
44773 * on native windows we could prepend the filename with \\?\ to circumvent
44774 * this behaviour. I have no idea how to push this through cygwin
44775 @@ -377,36 +385,41 @@
44776 log_error_write(srv, __FILE__, __LINE__, "");
44780 - /* MacOS X and Windows can't distiguish between upper and lower-case
44782 - * convert to lower-case
44784 + /* The default Mac OS X and Windows filesystems can't distiguish between
44785 + * upper- and lowercase, so convert to lowercase
44787 if (con->conf.force_lowercase_filenames) {
44788 buffer_to_lower(con->physical.rel_path);
44791 - /* the docroot plugins might set the servername, if they don't we take http-host */
44792 + /* the docroot plugins might set the servername; if they don't we take http-host */
44793 if (buffer_is_empty(con->server_name)) {
44794 buffer_copy_string_buffer(con->server_name, con->uri.authority);
44798 - * create physical filename
44801 + * create physical filename
44802 * -> physical.path = docroot + rel_path
44808 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
44809 - BUFFER_APPEND_SLASH(con->physical.path);
44810 + PATHNAME_APPEND_SLASH(con->physical.path);
44811 buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
44812 if (con->physical.rel_path->used &&
44813 - con->physical.rel_path->ptr[0] == '/') {
44814 + con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
44815 buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
44817 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
44820 + /* win32: directories can't have a trailing slash */
44821 + if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
44822 + con->physical.path->ptr[con->physical.path->used - 2] = '\0';
44823 + con->physical.path->used--;
44826 if (con->conf.log_request_handling) {
44827 log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root");
44828 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
44829 @@ -426,7 +439,7 @@
44830 log_error_write(srv, __FILE__, __LINE__, "");
44835 if (con->conf.log_request_handling) {
44836 log_error_write(srv, __FILE__, __LINE__, "s", "-- logical -> physical");
44837 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
44838 @@ -434,38 +447,38 @@
44839 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44844 - * Noone catched away the file from normal path of execution yet (like mod_access)
44848 + * No one took the file away from the normal path of execution yet (like mod_access)
44850 * Go on and check of the file exists at all
44854 if (con->mode == DIRECT) {
44855 char *slash = NULL;
44856 char *pathinfo = NULL;
44858 stat_cache_entry *sce = NULL;
44861 if (con->conf.log_request_handling) {
44862 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path");
44863 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44867 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
44871 if (con->conf.log_request_handling) {
44872 log_error_write(srv, __FILE__, __LINE__, "s", "-- file found");
44873 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44877 if (S_ISDIR(sce->st.st_mode)) {
44878 - if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
44879 + if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
44880 /* redirect to .../ */
44883 http_response_redirect_to_directory(srv, con);
44886 return HANDLER_FINISHED;
44888 } else if (!S_ISREG(sce->st.st_mode)) {
44889 @@ -477,12 +490,12 @@
44892 con->http_status = 403;
44895 if (con->conf.log_request_handling) {
44896 log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied");
44897 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44901 buffer_reset(con->physical.path);
44902 return HANDLER_FINISHED;
44904 @@ -499,77 +512,77 @@
44905 /* PATH_INFO ! :) */
44908 - /* we have no idea what happend. let's tell the user so. */
44909 + /* we have no idea what happened, so tell the user. */
44910 con->http_status = 500;
44911 buffer_reset(con->physical.path);
44914 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
44915 "file not found ... or so: ", strerror(errno),
44917 "->", con->physical.path);
44920 return HANDLER_FINISHED;
44924 /* not found, perhaps PATHINFO */
44927 buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
44935 buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
44937 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
44941 if (0 == stat(con->physical.path->ptr, &(st)) &&
44942 S_ISREG(st.st_mode)) {
44948 if (pathinfo != NULL) {
44951 slash = strrchr(srv->tmp_buf->ptr, '/');
44954 if (pathinfo != NULL) {
44960 if (slash) pathinfo = slash;
44961 } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
44965 - /* no it really doesn't exists */
44966 + /* no, it really doesn't exists */
44967 con->http_status = 404;
44970 if (con->conf.log_file_not_found) {
44971 log_error_write(srv, __FILE__, __LINE__, "sbsb",
44972 "file not found:", con->uri.path,
44973 "->", con->physical.path);
44977 buffer_reset(con->physical.path);
44980 return HANDLER_FINISHED;
44984 /* we have a PATHINFO */
44986 buffer_copy_string(con->request.pathinfo, pathinfo);
44994 con->uri.path->used -= strlen(pathinfo);
44995 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
44999 if (con->conf.log_request_handling) {
45000 log_error_write(srv, __FILE__, __LINE__, "s", "-- after pathinfo check");
45001 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
45002 @@ -577,12 +590,12 @@
45003 log_error_write(srv, __FILE__, __LINE__, "sb", "Pathinfo :", con->request.pathinfo);
45008 if (con->conf.log_request_handling) {
45009 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling subrequest");
45010 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
45014 /* call the handlers */
45015 switch(r = plugins_call_handle_subrequest_start(srv, con)) {
45016 case HANDLER_GO_ON:
45017 @@ -593,32 +606,32 @@
45018 if (con->conf.log_request_handling) {
45019 log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished");
45022 - /* something strange happend */
45024 + /* something strange happened */
45028 - /* if we are still here, no one wanted the file, status 403 is ok I think */
45031 + /* if we are still here, no one wanted the file; status 403 is ok I think */
45033 if (con->mode == DIRECT) {
45034 con->http_status = 403;
45037 return HANDLER_FINISHED;
45044 switch(r = plugins_call_handle_subrequest(srv, con)) {
45045 case HANDLER_GO_ON:
45046 - /* request was not handled, looks like we are done */
45047 + /* request was not handled; looks like we are done */
45048 return HANDLER_FINISHED;
45049 case HANDLER_FINISHED:
45050 /* request is finished */
45052 - /* something strange happend */
45053 + /* something strange happened */
45059 return HANDLER_COMEBACK;
45061 --- lighttpd-1.4.11/src/server.c 2006-03-04 19:12:17.000000000 +0200
45062 +++ lighttpd-1.4.12/src/server.c 2006-07-11 22:07:53.000000000 +0300
45064 #include <sys/types.h>
45065 -#include <sys/time.h>
45066 #include <sys/stat.h>
45068 #include <string.h>
45071 -#include <unistd.h>
45072 #include <stdlib.h>
45074 #include <signal.h>
45076 #include "plugin.h"
45077 #include "joblist.h"
45078 #include "network_backends.h"
45081 +/* use local getopt implementation */
45082 +# undef HAVE_GETOPT_H
45084 #ifdef HAVE_GETOPT_H
45085 #include <getopt.h>
45087 +#include "getopt.h"
45090 #ifdef HAVE_VALGRIND_VALGRIND_H
45092 /* #define USE_ALARM */
45096 +#undef HAVE_SIGNAL
45099 +#include "sys-files.h"
45100 +#include "sys-process.h"
45102 static volatile sig_atomic_t srv_shutdown = 0;
45103 static volatile sig_atomic_t graceful_shutdown = 0;
45104 +static volatile sig_atomic_t graceful_restart = 0;
45105 static volatile sig_atomic_t handle_sig_alarm = 1;
45106 static volatile sig_atomic_t handle_sig_hup = 0;
45111 case SIGTERM: srv_shutdown = 1; break;
45114 if (graceful_shutdown) srv_shutdown = 1;
45115 - else graceful_shutdown = 1;
45116 + else graceful_shutdown = 1;
45119 case SIGALRM: handle_sig_alarm = 1; break;
45121 static void signal_handler(int sig) {
45123 case SIGTERM: srv_shutdown = 1; break;
45126 if (graceful_shutdown) srv_shutdown = 1;
45127 - else graceful_shutdown = 1;
45128 + else graceful_shutdown = 1;
45131 case SIGALRM: handle_sig_alarm = 1; break;
45132 @@ -110,25 +121,26 @@
45133 signal(SIGTSTP, SIG_IGN);
45135 if (0 != fork()) exit(0);
45138 if (-1 == setsid()) exit(0);
45140 signal(SIGHUP, SIG_IGN);
45142 if (0 != fork()) exit(0);
45145 if (0 != chdir("/")) exit(0);
45149 static server *server_init(void) {
45153 server *srv = calloc(1, sizeof(*srv));
45155 + srv->max_fds = 1024;
45157 srv->x = buffer_init();
45160 CLEAN(response_header);
45161 CLEAN(parse_full_path);
45162 CLEAN(ts_debug_str);
45163 @@ -138,7 +150,7 @@
45165 srv->empty_string = buffer_init_string("");
45166 CLEAN(cond_check_buf);
45169 CLEAN(srvconf.errorlog_file);
45170 CLEAN(srvconf.groupname);
45171 CLEAN(srvconf.username);
45172 @@ -146,58 +158,58 @@
45173 CLEAN(srvconf.bindhost);
45174 CLEAN(srvconf.event_handler);
45175 CLEAN(srvconf.pid_file);
45178 CLEAN(tmp_chunk_len);
45183 srv->x = array_init();
45186 CLEAN(config_context);
45187 CLEAN(config_touched);
45192 for (i = 0; i < FILE_CACHE_MAX; i++) {
45193 srv->mtime_cache[i].str = buffer_init();
45197 srv->cur_ts = time(NULL);
45198 srv->startup_ts = srv->cur_ts;
45201 srv->conns = calloc(1, sizeof(*srv->conns));
45202 assert(srv->conns);
45205 srv->joblist = calloc(1, sizeof(*srv->joblist));
45206 assert(srv->joblist);
45209 srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
45210 assert(srv->fdwaitqueue);
45213 srv->srvconf.modules = array_init();
45214 srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
45215 srv->srvconf.network_backend = buffer_init();
45216 srv->srvconf.upload_tempdirs = array_init();
45220 srv->errorlog_fd = -1;
45221 srv->errorlog_mode = ERRORLOG_STDERR;
45223 srv->split_vals = array_init();
45229 static void server_free(server *srv) {
45233 for (i = 0; i < FILE_CACHE_MAX; i++) {
45234 buffer_free(srv->mtime_cache[i].str);
45239 buffer_free(srv->x);
45242 CLEAN(response_header);
45243 CLEAN(parse_full_path);
45244 CLEAN(ts_debug_str);
45245 @@ -207,7 +219,7 @@
45247 CLEAN(empty_string);
45248 CLEAN(cond_check_buf);
45251 CLEAN(srvconf.errorlog_file);
45252 CLEAN(srvconf.groupname);
45253 CLEAN(srvconf.username);
45254 @@ -217,7 +229,7 @@
45255 CLEAN(srvconf.pid_file);
45256 CLEAN(srvconf.modules_dir);
45257 CLEAN(srvconf.network_backend);
45260 CLEAN(tmp_chunk_len);
45263 @@ -225,15 +237,15 @@
45264 fdevent_unregister(srv->ev, srv->fd);
45266 fdevent_free(srv->ev);
45272 if (srv->config_storage) {
45273 for (i = 0; i < srv->config_context->used; i++) {
45274 specific_config *s = srv->config_storage[i];
45279 buffer_free(s->document_root);
45280 buffer_free(s->server_name);
45281 buffer_free(s->server_tag);
45282 @@ -242,32 +254,32 @@
45283 buffer_free(s->error_handler);
45284 buffer_free(s->errorfile_prefix);
45285 array_free(s->mimetypes);
45290 free(srv->config_storage);
45291 srv->config_storage = NULL;
45296 array_free(srv->x);
45299 CLEAN(config_context);
45300 CLEAN(config_touched);
45302 CLEAN(srvconf.upload_tempdirs);
45306 joblist_free(srv, srv->joblist);
45307 fdwaitqueue_free(srv, srv->fdwaitqueue);
45310 if (srv->stat_cache) {
45311 stat_cache_free(srv->stat_cache);
45314 array_free(srv->srvconf.modules);
45315 array_free(srv->split_vals);
45321 @@ -281,14 +293,12 @@
45322 " - a light and fast webserver\n" \
45323 "Build-Date: " __DATE__ " " __TIME__ "\n";
45327 write(STDOUT_FILENO, b, strlen(b));
45330 static void show_features (void) {
45332 - printf("\nEvent Handlers:\n\n%s",
45334 + const char *s = ""
45336 "\t+ select (generic)\n"
45338 @@ -355,11 +365,6 @@
45340 "\t- crypt support\n"
45343 - "\t+ PAM support\n"
45345 - "\t- PAM support\n"
45348 "\t+ SSL Support\n"
45350 @@ -371,9 +376,9 @@
45351 "\t- PCRE support\n"
45354 - "\t+ mySQL support\n"
45355 + "\t+ MySQL support\n"
45357 - "\t- mySQL support\n"
45358 + "\t- MySQL support\n"
45360 #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
45361 "\t+ LDAP support\n"
45362 @@ -410,8 +415,11 @@
45364 "\t- GDBM support\n"
45372 + printf("\nEvent Handlers:\n\n%s", s);
45375 static void show_help (void) {
45376 @@ -433,12 +441,12 @@
45377 " -h show this help\n" \
45383 write(STDOUT_FILENO, b, strlen(b));
45386 -int main (int argc, char **argv) {
45387 +int main (int argc, char **argv, char **envp) {
45388 server *srv = NULL;
45389 int print_config = 0;
45390 int test_config = 0;
45391 @@ -447,33 +455,37 @@
45392 int num_childs = 0;
45393 int pid_fd = -1, fd;
45396 + char *optarg = NULL;
45399 #ifdef HAVE_SIGACTION
45400 struct sigaction act;
45402 #ifdef HAVE_GETRLIMIT
45403 struct rlimit rlim;
45408 struct itimerval interval;
45411 interval.it_interval.tv_sec = 1;
45412 interval.it_interval.tv_usec = 0;
45413 interval.it_value.tv_sec = 1;
45414 interval.it_value.tv_usec = 0;
45420 /* for nice %b handling in strfime() */
45421 setlocale(LC_TIME, "C");
45424 if (NULL == (srv = server_init())) {
45425 fprintf(stderr, "did this really happen?\n");
45430 /* init structs done */
45433 srv->srvconf.port = 0;
45435 i_am_root = (getuid() == 0);
45436 @@ -481,14 +493,19 @@
45439 srv->srvconf.dont_daemonize = 0;
45442 while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
45445 - if (config_read(srv, optarg)) {
45448 + /* evil HACK for windows, optarg is not set */
45449 + optarg = argv[optind-1];
45451 + if (config_read(srv, optarg)) {
45458 buffer_copy_string(srv->srvconf.modules_dir, optarg);
45459 @@ -497,23 +514,23 @@
45460 case 't': test_config = 1; break;
45461 case 'D': srv->srvconf.dont_daemonize = 1; break;
45462 case 'v': show_version(); return 0;
45463 - case 'V': show_features(); return 0;
45464 + case 'V': show_features(); return 0;
45465 case 'h': show_help(); return 0;
45475 if (!srv->config_storage) {
45476 log_error_write(srv, __FILE__, __LINE__, "s",
45477 "No configuration available. Try using -f option.");
45485 if (print_config) {
45486 data_unset *dc = srv->config_context->data[0];
45488 @@ -533,7 +550,7 @@
45494 /* close stdin and stdout, as they are not needed */
45495 /* move stdin to /dev/null */
45496 if (-1 != (fd = open("/dev/null", O_RDONLY))) {
45497 @@ -541,54 +558,55 @@
45498 dup2(fd, STDIN_FILENO);
45503 /* move stdout to /dev/null */
45504 if (-1 != (fd = open("/dev/null", O_WRONLY))) {
45505 close(STDOUT_FILENO);
45506 dup2(fd, STDOUT_FILENO);
45511 if (0 != config_set_defaults(srv)) {
45512 - log_error_write(srv, __FILE__, __LINE__, "s",
45513 + log_error_write(srv, __FILE__, __LINE__, "s",
45514 "setting default values failed");
45522 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
45523 /* we are setuid-root */
45525 - log_error_write(srv, __FILE__, __LINE__, "s",
45527 + log_error_write(srv, __FILE__, __LINE__, "s",
45528 "Are you nuts ? Don't apply a SUID bit to this binary");
45537 /* check document-root */
45538 if (srv->config_storage[0]->document_root->used <= 1) {
45539 - log_error_write(srv, __FILE__, __LINE__, "s",
45540 + log_error_write(srv, __FILE__, __LINE__, "s",
45541 "document-root is not set\n");
45551 if (plugins_load(srv)) {
45552 log_error_write(srv, __FILE__, __LINE__, "s",
45553 "loading plugins finally failed");
45565 /* open pid file BEFORE chroot */
45566 if (srv->srvconf.pid_file->used) {
45567 if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
45568 @@ -598,18 +616,18 @@
45569 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45574 if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
45575 log_error_write(srv, __FILE__, __LINE__, "sbs",
45576 "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45580 if (!S_ISREG(st.st_mode)) {
45581 log_error_write(srv, __FILE__, __LINE__, "sb",
45582 "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
45587 if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
45588 log_error_write(srv, __FILE__, __LINE__, "sbs",
45589 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45590 @@ -617,13 +635,14 @@
45596 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45597 /* select limits itself
45599 * as it is a hard limit and will lead to a segfault we add some safety
45601 - srv->max_fds = FD_SETSIZE - 200;
45602 + fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
45603 + srv->max_fds = FD_SETSIZE - 4;
45605 srv->max_fds = 4096;
45607 @@ -636,7 +655,7 @@
45608 #ifdef HAVE_VALGRIND_VALGRIND_H
45609 if (RUNNING_ON_VALGRIND) use_rlimit = 0;
45613 #ifdef HAVE_GETRLIMIT
45614 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
45615 log_error_write(srv, __FILE__, __LINE__,
45616 @@ -644,13 +663,13 @@
45622 if (use_rlimit && srv->srvconf.max_fds) {
45626 rlim.rlim_cur = srv->srvconf.max_fds;
45627 rlim.rlim_max = srv->srvconf.max_fds;
45630 if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
45631 log_error_write(srv, __FILE__, __LINE__,
45632 "ss", "couldn't set 'max filedescriptors'",
45633 @@ -659,7 +678,7 @@
45637 - /* #372: solaris need some fds extra for devpoll */
45638 + /* #372: solaris need some fds extra for devpoll */
45639 if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
45641 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45642 @@ -677,33 +696,33 @@
45643 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45644 /* don't raise the limit above FD_SET_SIZE */
45645 if (srv->max_fds > FD_SETSIZE - 200) {
45646 - log_error_write(srv, __FILE__, __LINE__, "sd",
45647 + log_error_write(srv, __FILE__, __LINE__, "sd",
45648 "can't raise max filedescriptors above", FD_SETSIZE - 200,
45649 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45657 /* set user and group */
45658 if (srv->srvconf.username->used) {
45659 if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
45660 - log_error_write(srv, __FILE__, __LINE__, "sb",
45661 + log_error_write(srv, __FILE__, __LINE__, "sb",
45662 "can't find username", srv->srvconf.username);
45667 if (pwd->pw_uid == 0) {
45668 log_error_write(srv, __FILE__, __LINE__, "s",
45669 "I will not set uid to 0\n");
45675 if (srv->srvconf.groupname->used) {
45676 if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
45677 - log_error_write(srv, __FILE__, __LINE__, "sb",
45678 + log_error_write(srv, __FILE__, __LINE__, "sb",
45679 "can't find groupname", srv->srvconf.groupname);
45682 @@ -713,15 +732,15 @@
45688 /* we need root-perms for port < 1024 */
45689 if (0 != network_init(srv)) {
45696 -#ifdef HAVE_CHROOT
45697 +#ifdef HAVE_CHROOT
45698 if (srv->srvconf.changeroot->used) {
45701 @@ -761,7 +780,7 @@
45704 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45705 - srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
45706 + srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
45708 srv->max_fds = rlim.rlim_cur;
45710 @@ -775,18 +794,18 @@
45712 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45713 /* don't raise the limit above FD_SET_SIZE */
45714 - if (srv->max_fds > FD_SETSIZE - 200) {
45715 - log_error_write(srv, __FILE__, __LINE__, "sd",
45716 - "can't raise max filedescriptors above", FD_SETSIZE - 200,
45717 + if (srv->max_fds > FD_SETSIZE - 4) {
45718 + log_error_write(srv, __FILE__, __LINE__, "sd",
45719 + "can't raise max filedescriptors above", FD_SETSIZE - 4,
45720 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45726 if (0 != network_init(srv)) {
45734 @@ -802,25 +821,27 @@
45735 /* or use the default */
45736 srv->max_conns = srv->max_fds;
45740 if (HANDLER_GO_ON != plugins_call_init(srv)) {
45741 log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
45745 network_close(srv);
45754 /* network is up, let's deamonize ourself */
45755 if (srv->srvconf.dont_daemonize == 0) daemonize();
45759 srv->gid = getgid();
45760 srv->uid = getuid();
45764 /* write pid file */
45765 if (pid_fd != -1) {
45766 buffer_copy_long(srv->tmp_buf, getpid());
45767 @@ -829,17 +850,17 @@
45773 if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
45774 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
45778 network_close(srv);
45786 /* dump unused config-keys */
45787 for (i = 0; i < srv->config_context->used; i++) {
45788 array *config = ((data_config *)srv->config_context->data[i])->value;
45789 @@ -847,43 +868,42 @@
45791 for (j = 0; config && j < config->used; j++) {
45792 data_unset *du = config->data[j];
45795 /* all var.* is known as user defined variable */
45796 if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
45800 if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
45801 - log_error_write(srv, __FILE__, __LINE__, "sbs",
45802 + log_error_write(srv, __FILE__, __LINE__, "sbs",
45803 "WARNING: unknown config-key:",
45811 if (srv->config_deprecated) {
45812 - log_error_write(srv, __FILE__, __LINE__, "s",
45813 + log_error_write(srv, __FILE__, __LINE__, "s",
45814 "Configuration contains deprecated keys. Going down.");
45818 network_close(srv);
45826 if (-1 == log_error_open(srv)) {
45827 - log_error_write(srv, __FILE__, __LINE__, "s",
45828 + log_error_write(srv, __FILE__, __LINE__, "s",
45829 "opening errorlog failed, dying");
45833 network_close(srv);
45840 #ifdef HAVE_SIGACTION
45841 memset(&act, 0, sizeof(act));
45842 act.sa_handler = SIG_IGN;
45843 @@ -903,7 +923,7 @@
45844 sigaction(SIGHUP, &act, NULL);
45845 sigaction(SIGALRM, &act, NULL);
45846 sigaction(SIGCHLD, &act, NULL);
45849 #elif defined(HAVE_SIGNAL)
45850 /* ignore the SIGPIPE from sendfile() */
45851 signal(SIGPIPE, SIG_IGN);
45852 @@ -914,20 +934,20 @@
45853 signal(SIGCHLD, signal_handler);
45854 signal(SIGINT, signal_handler);
45859 signal(SIGALRM, signal_handler);
45862 /* setup periodic timer (1 second) */
45863 if (setitimer(ITIMER_REAL, &interval, NULL)) {
45864 log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
45869 getitimer(ITIMER_REAL, &interval);
45874 /* start watcher and workers */
45875 num_childs = srv->srvconf.max_worker;
45876 if (num_childs > 0) {
45877 @@ -957,13 +977,13 @@
45881 - if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
45882 + if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
45883 log_error_write(srv, __FILE__, __LINE__,
45884 "s", "fdevent_init failed");
45888 - * kqueue() is called here, select resets its internals,
45890 + * kqueue() is called here, select resets its internals,
45891 * all server sockets get their handlers
45894 @@ -971,7 +991,7 @@
45896 network_close(srv);
45903 @@ -986,7 +1006,7 @@
45905 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
45906 if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
45907 - log_error_write(srv, __FILE__, __LINE__, "s",
45908 + log_error_write(srv, __FILE__, __LINE__, "s",
45909 "could not open a fam connection, dieing.");
45912 @@ -1018,16 +1038,40 @@
45918 if (handle_sig_hup) {
45922 /* reset notification */
45923 handle_sig_hup = 0;
45930 + /* send the old process into a graceful-shutdown and start a
45931 + * new process right away
45934 + * - if webserver is running on port < 1024 (e.g. 80, 433)
45935 + * we don't have the permissions to bind to that port anymore
45939 + if (0 == (pid = fork())) {
45940 + execve(argv[0], argv, envp);
45943 + } else if (pid == -1) {
45948 + graceful_shutdown = 1; /* shutdown without killing running connections */
45949 + graceful_restart = 1; /* don't delete pid file */
45952 /* cycle logfiles */
45955 switch(r = plugins_call_handle_sighup(srv)) {
45956 case HANDLER_GO_ON:
45958 @@ -1035,30 +1079,31 @@
45959 log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
45964 if (-1 == log_error_cycle(srv)) {
45965 log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
45974 if (handle_sig_alarm) {
45979 /* reset notification */
45980 handle_sig_alarm = 0;
45984 /* get current time */
45985 min_ts = time(NULL);
45988 if (min_ts != srv->cur_ts) {
45990 connections *conns = srv->conns;
45994 switch(r = plugins_call_handle_trigger(srv)) {
45995 case HANDLER_GO_ON:
45997 @@ -1069,21 +1114,21 @@
45998 log_error_write(srv, __FILE__, __LINE__, "d", r);
46003 /* trigger waitpid */
46004 srv->cur_ts = min_ts;
46006 - /* cleanup stat-cache */
46008 + /* cleanup stat-cache */
46009 stat_cache_trigger_cleanup(srv);
46011 - * check all connections for timeouts
46013 + * check all connections for timeouts
46016 for (ndx = 0; ndx < conns->used; ndx++) {
46022 con = conns->ptr[ndx];
46024 if (con->state == CON_STATE_READ ||
46025 @@ -1092,7 +1137,7 @@
46026 if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
46029 - log_error_write(srv, __FILE__, __LINE__, "sd",
46030 + log_error_write(srv, __FILE__, __LINE__, "sd",
46031 "connection closed - read-timeout:", con->fd);
46033 connection_set_state(srv, con, CON_STATE_ERROR);
46034 @@ -1102,7 +1147,7 @@
46035 if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
46038 - log_error_write(srv, __FILE__, __LINE__, "sd",
46039 + log_error_write(srv, __FILE__, __LINE__, "sd",
46040 "connection closed - read-timeout:", con->fd);
46042 connection_set_state(srv, con, CON_STATE_ERROR);
46043 @@ -1110,20 +1155,20 @@
46049 if ((con->state == CON_STATE_WRITE) &&
46050 - (con->write_request_ts != 0)) {
46051 + (con->write_request_ts != 0)) {
46053 if (srv->cur_ts - con->write_request_ts > 60) {
46054 - log_error_write(srv, __FILE__, __LINE__, "sdd",
46055 + log_error_write(srv, __FILE__, __LINE__, "sdd",
46056 "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
46061 if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
46064 - log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46065 + log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46066 "NOTE: a request for",
46068 "timed out after writing",
46069 @@ -1138,35 +1183,35 @@
46071 /* we don't like div by zero */
46072 if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
46074 - if (con->traffic_limit_reached &&
46075 - (con->conf.kbytes_per_second == 0 ||
46077 + if (con->traffic_limit_reached &&
46078 + (con->conf.kbytes_per_second == 0 ||
46079 ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
46080 /* enable connection again */
46081 con->traffic_limit_reached = 0;
46089 connection_state_machine(srv, con);
46091 con->bytes_written_cur_second = 0;
46092 *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
46097 fprintf(stderr, "connection-state: ");
46102 fprintf(stderr, "c[%d,%d]: %s ",
46105 connection_get_state(con->state));
46110 if (cs == 1) fprintf(stderr, "\n");
46113 @@ -1181,18 +1226,18 @@
46114 server_socket *srv_socket = srv->srv_sockets.ptr[i];
46115 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
46119 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
46122 srv->sockets_disabled = 0;
46125 if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
46126 (srv->conns->used > srv->max_conns) || /* out of connections */
46127 - (graceful_shutdown)) { /* graceful_shutdown */
46128 + (graceful_shutdown)) { /* graceful_shutdown */
46130 /* disable server-fds */
46133 for (i = 0; i < srv->srv_sockets.used; i++) {
46134 server_socket *srv_socket = srv->srv_sockets.ptr[i];
46135 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
46136 @@ -1211,7 +1256,7 @@
46137 /* network_close() will cleanup after us */
46142 if (graceful_shutdown) {
46143 log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
46144 } else if (srv->conns->used > srv->max_conns) {
46145 @@ -1219,7 +1264,7 @@
46147 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
46151 srv->sockets_disabled = 1;
46154 @@ -1229,16 +1274,16 @@
46155 * we are ready to terminate without harming anyone */
46160 /* we still have some fds to share */
46161 - if (srv->want_fds) {
46162 + if (srv->want_fds) {
46163 /* check the fdwaitqueue for waiting fds */
46164 int free_fds = srv->max_fds - srv->cur_fds - 16;
46168 for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
46169 connection_state_machine(srv, con);
46175 @@ -1249,27 +1294,27 @@
46179 - log_error_write(srv, __FILE__, __LINE__, "sd",
46180 + log_error_write(srv, __FILE__, __LINE__, "sd",
46187 fdevent_handler handler;
46192 fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx);
46193 revents = fdevent_event_get_revent (srv->ev, fd_ndx);
46194 fd = fdevent_event_get_fd (srv->ev, fd_ndx);
46195 handler = fdevent_get_handler(srv->ev, fd);
46196 context = fdevent_get_context(srv->ev, fd);
46199 /* connection_handle_fdevent needs a joblist_append */
46201 - log_error_write(srv, __FILE__, __LINE__, "sdd",
46202 + log_error_write(srv, __FILE__, __LINE__, "sdd",
46203 "event for", fd, revents);
46206 switch (r = (*handler)(srv, context, revents)) {
46207 case HANDLER_FINISHED:
46208 case HANDLER_GO_ON:
46209 @@ -1286,17 +1331,17 @@
46212 } else if (n < 0 && errno != EINTR) {
46213 - log_error_write(srv, __FILE__, __LINE__, "ss",
46214 - "fdevent_poll failed:",
46215 + log_error_write(srv, __FILE__, __LINE__, "ss",
46216 + "fdevent_poll failed:",
46221 for (ndx = 0; ndx < srv->joblist->used; ndx++) {
46222 connection *con = srv->joblist->ptr[ndx];
46226 connection_state_machine(srv, con);
46229 switch(r = plugins_call_handle_joblist(srv, con)) {
46230 case HANDLER_FINISHED:
46231 case HANDLER_GO_ON:
46232 @@ -1305,32 +1350,33 @@
46233 log_error_write(srv, __FILE__, __LINE__, "d", r);
46238 con->in_joblist = 0;
46242 srv->joblist->used = 0;
46245 - if (srv->srvconf.pid_file->used &&
46247 + if (0 == graceful_restart &&
46248 + srv->srvconf.pid_file->used &&
46249 srv->srvconf.changeroot->used == 0) {
46250 if (0 != unlink(srv->srvconf.pid_file->ptr)) {
46251 if (errno != EACCES && errno != EPERM) {
46252 - log_error_write(srv, __FILE__, __LINE__, "sbds",
46253 - "unlink failed for:",
46254 + log_error_write(srv, __FILE__, __LINE__, "sbds",
46255 + "unlink failed for:",
46256 srv->srvconf.pid_file,
46265 log_error_close(srv);
46266 network_close(srv);
46267 connections_free(srv);
46274 --- lighttpd-1.4.11/src/settings.h 2005-08-11 01:26:41.000000000 +0300
46275 +++ lighttpd-1.4.12/src/settings.h 2006-07-11 22:07:53.000000000 +0300
46278 * max size of a buffer which will just be reset
46279 * to ->used = 0 instead of really freeing the buffer
46282 * 64kB (no real reason, just a guess)
46284 #define BUFFER_MAX_REUSE_SIZE (4 * 1024)
46287 * max size of the HTTP request header
46290 * 32k should be enough for everything (just a guess)
46294 #define MAX_HTTP_REQUEST_HEADER (32 * 1024)
46296 -typedef enum { HANDLER_UNSET,
46298 +typedef enum { HANDLER_UNSET,
46301 - HANDLER_COMEBACK,
46302 - HANDLER_WAIT_FOR_EVENT,
46303 + HANDLER_COMEBACK,
46304 + HANDLER_WAIT_FOR_EVENT,
46306 HANDLER_WAIT_FOR_FD
46308 --- lighttpd-1.4.11/src/spawn-fcgi.c 2006-03-07 14:18:10.000000000 +0200
46309 +++ lighttpd-1.4.12/src/spawn-fcgi.c 2006-07-11 22:07:53.000000000 +0300
46311 #include <sys/types.h>
46312 -#include <sys/time.h>
46313 #include <sys/stat.h>
46315 #include <stdlib.h>
46316 #include <string.h>
46319 -#include <unistd.h>
46323 #ifdef HAVE_CONFIG_H
46324 #include "config.h"
46334 #include "sys-socket.h"
46335 +#include "sys-files.h"
46337 #ifdef HAVE_SYS_WAIT_H
46338 #include <sys/wait.h>
46339 @@ -45,28 +43,28 @@
46341 int socket_type, status;
46342 struct timeval tv = { 0, 100 * 1000 };
46345 struct sockaddr_un fcgi_addr_un;
46346 struct sockaddr_in fcgi_addr_in;
46347 struct sockaddr *fcgi_addr;
46353 if (child_count < 2) {
46358 if (child_count > 256) {
46366 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
46369 fcgi_addr_un.sun_family = AF_UNIX;
46370 strcpy(fcgi_addr_un.sun_path, unixsocket);
46374 servlen = SUN_LEN(&fcgi_addr_un);
46376 @@ -84,50 +82,50 @@
46378 fcgi_addr_in.sin_port = htons(port);
46379 servlen = sizeof(fcgi_addr_in);
46382 socket_type = AF_INET;
46383 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
46387 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46388 - fprintf(stderr, "%s.%d\n",
46389 + fprintf(stderr, "%s.%d\n",
46390 __FILE__, __LINE__);
46395 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
46396 /* server is not up, spawn in */
46401 if (unixsocket) unlink(unixsocket);
46407 /* reopen socket */
46408 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46409 - fprintf(stderr, "%s.%d\n",
46410 + fprintf(stderr, "%s.%d\n",
46411 __FILE__, __LINE__);
46416 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
46417 - fprintf(stderr, "%s.%d\n",
46418 + fprintf(stderr, "%s.%d\n",
46419 __FILE__, __LINE__);
46423 /* create socket */
46424 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
46425 - fprintf(stderr, "%s.%d: bind failed: %s\n",
46426 + fprintf(stderr, "%s.%d: bind failed: %s\n",
46427 __FILE__, __LINE__,
46433 if (-1 == listen(fcgi_fd, 1024)) {
46434 - fprintf(stderr, "%s.%d: fd = -1\n",
46435 + fprintf(stderr, "%s.%d: fd = -1\n",
46436 __FILE__, __LINE__);
46439 @@ -137,42 +135,45 @@
46447 char cgi_childs[64];
46454 + /* loose control terminal */
46457 /* is save as we limit to 256 childs */
46458 sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
46461 if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
46462 close(FCGI_LISTENSOCK_FILENO);
46463 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
46468 /* we don't need the client socket */
46469 for (i = 3; i < 256; i++) {
46474 /* create environment */
46477 putenv(cgi_childs);
46480 /* fork and replace shell */
46481 b = malloc(strlen("exec ") + strlen(appPath) + 1);
46482 strcpy(b, "exec ");
46483 strcat(b, appPath);
46487 execl("/bin/sh", "sh", "-c", b, NULL);
46496 @@ -180,47 +181,47 @@
46503 select(0, NULL, NULL, NULL, &tv);
46506 switch (waitpid(child, &status, WNOHANG)) {
46508 - fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
46509 + fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
46510 __FILE__, __LINE__,
46514 /* write pid file */
46515 if (pid_fd != -1) {
46516 /* assume a 32bit pid_t */
46520 snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
46523 write(pid_fd, pidbuf, strlen(pidbuf));
46533 if (WIFEXITED(status)) {
46534 - fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
46535 + fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
46536 __FILE__, __LINE__,
46537 WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
46538 } else if (WIFSIGNALED(status)) {
46539 - fprintf(stderr, "%s.%d: child signaled: %d\n",
46540 + fprintf(stderr, "%s.%d: child signaled: %d\n",
46541 __FILE__, __LINE__,
46544 - fprintf(stderr, "%s.%d: child died somehow: %d\n",
46545 + fprintf(stderr, "%s.%d: child died somehow: %d\n",
46546 __FILE__, __LINE__,
46555 @@ -228,16 +229,16 @@
46556 __FILE__, __LINE__);
46568 void show_version () {
46569 char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
46570 -" - spawns fastcgi processes\n"
46571 +" - spawns fastcgi processes\n"
46573 write(1, b, strlen(b));
46575 @@ -265,7 +266,7 @@
46578 int main(int argc, char **argv) {
46579 - char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
46580 + char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
46581 *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
46583 unsigned short port = 0;
46584 @@ -273,9 +274,9 @@
46590 i_am_root = (getuid() == 0);
46593 while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
46595 case 'f': fcgi_app = optarg; break;
46596 @@ -290,137 +291,137 @@
46597 case 'P': pid_file = optarg; /* PID file */ break;
46598 case 'v': show_version(); return 0;
46599 case 'h': show_help(); return 0;
46608 if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
46614 if (unixsocket && port) {
46615 - fprintf(stderr, "%s.%d: %s\n",
46616 + fprintf(stderr, "%s.%d: %s\n",
46617 __FILE__, __LINE__,
46618 "either a unix domain socket or a tcp-port, but not both\n");
46625 if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) {
46626 - fprintf(stderr, "%s.%d: %s\n",
46627 + fprintf(stderr, "%s.%d: %s\n",
46628 __FILE__, __LINE__,
46629 "path of the unix socket is too long\n");
46636 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
46637 /* we are setuid-root */
46639 - fprintf(stderr, "%s.%d: %s\n",
46641 + fprintf(stderr, "%s.%d: %s\n",
46642 __FILE__, __LINE__,
46643 "Are you nuts ? Don't apply a SUID bit to this binary\n");
46652 (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
46654 if (errno != EEXIST) {
46655 - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46656 + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46657 __FILE__, __LINE__,
46658 pid_file, strerror(errno));
46665 /* ok, file exists */
46668 if (0 != stat(pid_file, &st)) {
46669 - fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
46670 + fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
46671 __FILE__, __LINE__,
46672 pid_file, strerror(errno));
46679 /* is it a regular file ? */
46682 if (!S_ISREG(st.st_mode)) {
46683 - fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
46684 + fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
46685 __FILE__, __LINE__,
46693 if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
46694 - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46695 + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46696 __FILE__, __LINE__,
46697 pid_file, strerror(errno));
46706 struct group *grp = NULL;
46707 struct passwd *pwd = NULL;
46710 /* set user and group */
46714 if (NULL == (pwd = getpwnam(username))) {
46715 - fprintf(stderr, "%s.%d: %s, %s\n",
46716 + fprintf(stderr, "%s.%d: %s, %s\n",
46717 __FILE__, __LINE__,
46718 "can't find username", username);
46723 if (pwd->pw_uid == 0) {
46724 - fprintf(stderr, "%s.%d: %s\n",
46725 + fprintf(stderr, "%s.%d: %s\n",
46726 __FILE__, __LINE__,
46727 "I will not set uid to 0\n");
46734 if (NULL == (grp = getgrnam(groupname))) {
46735 - fprintf(stderr, "%s.%d: %s %s\n",
46736 + fprintf(stderr, "%s.%d: %s %s\n",
46737 __FILE__, __LINE__,
46738 - "can't find groupname",
46739 + "can't find groupname",
46743 if (grp->gr_gid == 0) {
46744 - fprintf(stderr, "%s.%d: %s\n",
46745 + fprintf(stderr, "%s.%d: %s\n",
46746 __FILE__, __LINE__,
46747 "I will not set gid to 0\n");
46754 if (-1 == chroot(changeroot)) {
46755 - fprintf(stderr, "%s.%d: %s %s\n",
46756 + fprintf(stderr, "%s.%d: %s %s\n",
46757 __FILE__, __LINE__,
46758 "chroot failed: ", strerror(errno));
46761 if (-1 == chdir("/")) {
46762 - fprintf(stderr, "%s.%d: %s %s\n",
46763 + fprintf(stderr, "%s.%d: %s %s\n",
46764 __FILE__, __LINE__,
46765 "chdir failed: ", strerror(errno));
46771 /* drop root privs */
46773 setgid(grp->gr_gid);
46774 @@ -428,7 +429,7 @@
46776 if (username) setuid(pwd->pw_uid);
46780 return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
46783 --- lighttpd-1.4.11/src/splaytree.c 2005-09-12 21:51:28.000000000 +0300
46784 +++ lighttpd-1.4.12/src/splaytree.c 2006-07-11 22:07:51.000000000 +0300
46785 @@ -56,19 +56,19 @@
46787 #define node_size splaytree_size
46789 -/* Splay using the key i (which may or may not be in the tree.)
46790 - * The starting root is t, and the tree used is defined by rat
46791 +/* Splay using the key i (which may or may not be in the tree.)
46792 + * The starting root is t, and the tree used is defined by rat
46793 * size fields are maintained */
46794 splay_tree * splaytree_splay (splay_tree *t, int i) {
46795 splay_tree N, *l, *r, *y;
46796 int comp, root_size, l_size, r_size;
46799 if (t == NULL) return t;
46800 N.left = N.right = NULL;
46802 root_size = node_size(t);
46803 l_size = r_size = 0;
46807 comp = compare(i, t->key);
46809 @@ -120,7 +120,7 @@
46811 r_size -= 1+node_size(y->right);
46815 l->right = t->left; /* assemble */
46816 r->left = t->right;
46818 --- lighttpd-1.4.11/src/splaytree.h 2005-09-12 21:51:13.000000000 +0300
46819 +++ lighttpd-1.4.12/src/splaytree.h 2006-07-11 22:07:51.000000000 +0300
46821 /* This macro returns the size of a node. Unlike "x->size", */
46822 /* it works even if x=NULL. The test could be avoided by using */
46823 /* a special version of NULL which was a real node with size 0. */
46828 --- lighttpd-1.4.11/src/stat_cache.c 2005-11-22 15:23:51.000000000 +0200
46829 +++ lighttpd-1.4.12/src/stat_cache.c 2006-07-11 22:07:52.000000000 +0300
46831 #include <stdlib.h>
46832 #include <string.h>
46834 -#include <unistd.h>
46837 #include <assert.h>
46841 #include "sys-mmap.h"
46843 -/* NetBSD 1.3.x needs it */
46844 -#ifndef MAP_FAILED
46845 -# define MAP_FAILED -1
46848 -#ifndef O_LARGEFILE
46849 -# define O_LARGEFILE 0
46852 -#ifndef HAVE_LSTAT
46853 -#define lstat stat
46855 +#include "sys-files.h"
46856 +#include "sys-strings.h"
46859 /* enables debug code for testing if all nodes in the stat-cache as accessable */
46862 * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
46864 - * if the stat()-cache is queried we check if the version id for the directory is the
46865 - * same and return immediatly.
46866 + * if the stat()-cache is queried we check if the version id for the directory is the
46867 + * same and return immediatly.
46871 @@ -62,17 +50,17 @@
46872 * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
46874 * stat <<-> directory <-> FAMRequest
46876 - * if file is deleted, directory is dirty, file is rechecked ...
46878 + * if file is deleted, directory is dirty, file is rechecked ...
46879 * if directory is deleted, directory mapping is removed
46893 @@ -83,16 +71,16 @@
46895 * - the hash-key is used as sorting criteria for a tree
46896 * - a splay-tree is used as we can use the caching effect of it
46900 /* we want to cleanup the stat-cache every few seconds, let's say 10
46902 * - remove entries which are outdated since 30s
46903 * - remove entries which are fresh but havn't been used since 60s
46904 * - if we don't have a stat-cache entry for a directory, release it from the monitor
46908 -#ifdef DEBUG_STAT_CACHE
46909 +#ifdef DEBUG_STAT_CACHE
46913 @@ -105,15 +93,15 @@
46915 stat_cache *stat_cache_init(void) {
46916 stat_cache *fc = NULL;
46919 fc = calloc(1, sizeof(*fc));
46922 fc->dir_name = buffer_init();
46924 fc->fam = calloc(1, sizeof(*fc->fam));
46927 -#ifdef DEBUG_STAT_CACHE
46928 +#ifdef DEBUG_STAT_CACHE
46932 @@ -122,24 +110,24 @@
46934 static stat_cache_entry * stat_cache_entry_init(void) {
46935 stat_cache_entry *sce = NULL;
46938 sce = calloc(1, sizeof(*sce));
46941 sce->name = buffer_init();
46942 sce->etag = buffer_init();
46943 sce->content_type = buffer_init();
46949 static void stat_cache_entry_free(void *data) {
46950 stat_cache_entry *sce = data;
46954 buffer_free(sce->etag);
46955 buffer_free(sce->name);
46956 buffer_free(sce->content_type);
46962 @@ -148,22 +136,22 @@
46963 fam_dir_entry *fam_dir = NULL;
46965 fam_dir = calloc(1, sizeof(*fam_dir));
46968 fam_dir->name = buffer_init();
46974 static void fam_dir_entry_free(void *data) {
46975 fam_dir_entry *fam_dir = data;
46978 if (!fam_dir) return;
46981 FAMCancelMonitor(fam_dir->fc, fam_dir->req);
46984 buffer_free(fam_dir->name);
46985 free(fam_dir->req);
46991 @@ -174,7 +162,7 @@
46992 splay_tree *node = sc->files;
46994 osize = sc->files->size;
46997 stat_cache_entry_free(node->data);
46998 sc->files = splaytree_delete(sc->files, node->key);
47000 @@ -187,12 +175,12 @@
47003 splay_tree *node = sc->dirs;
47006 osize = sc->dirs->size;
47008 fam_dir_entry_free(node->data);
47009 sc->dirs = splaytree_delete(sc->dirs, node->key);
47013 assert(NULL == sc->dirs);
47015 @@ -212,7 +200,7 @@
47016 static int stat_cache_attr_get(buffer *buf, char *name) {
47022 buffer_prepare_copy(buf, attrlen);
47024 @@ -251,15 +239,15 @@
47027 events = FAMPending(sc->fam);
47030 for (i = 0; i < events; i++) {
47032 fam_dir_entry *fam_dir;
47037 FAMNextEvent(sc->fam, &fe);
47043 @@ -280,7 +268,7 @@
47045 sc->dirs = splaytree_splay(sc->dirs, ndx);
47049 if (node && (node->key == ndx)) {
47050 int osize = splaytree_size(sc->dirs);
47052 @@ -308,7 +296,7 @@
47058 return HANDLER_GO_ON;
47061 @@ -332,7 +320,7 @@
47067 * - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
47068 * - HANDLER_ERROR on stat() failed -> see errno for problem
47070 @@ -348,16 +336,16 @@
47074 -#ifdef DEBUG_STAT_CACHE
47075 +#ifdef DEBUG_STAT_CACHE
47080 splay_tree *file_node = NULL;
47087 * check if the directory for this file has changed
47090 @@ -366,23 +354,23 @@
47091 file_ndx = hashme(name);
47092 sc->files = splaytree_splay(sc->files, file_ndx);
47094 -#ifdef DEBUG_STAT_CACHE
47095 +#ifdef DEBUG_STAT_CACHE
47096 for (i = 0; i < ctrl.used; i++) {
47097 if (ctrl.ptr[i] == file_ndx) break;
47101 if (sc->files && (sc->files->key == file_ndx)) {
47102 -#ifdef DEBUG_STAT_CACHE
47103 +#ifdef DEBUG_STAT_CACHE
47104 /* it was in the cache */
47105 assert(i < ctrl.used);
47108 - /* we have seen this file already and
47110 + /* we have seen this file already and
47111 * don't stat() it again in the same second */
47113 file_node = sc->files;
47116 sce = file_node->data;
47118 /* check if the name is the same, we might have a collision */
47119 @@ -390,7 +378,7 @@
47120 if (buffer_is_equal(name, sce->name)) {
47121 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
47122 if (sce->stat_ts == srv->cur_ts) {
47125 return HANDLER_GO_ON;
47128 @@ -400,15 +388,15 @@
47129 * file_node is used by the FAM check below to see if we know this file
47130 * and if we can save a stat().
47132 - * BUT, the sce is not reset here as the entry into the cache is ok, we
47133 + * BUT, the sce is not reset here as the entry into the cache is ok, we
47134 * it is just not pointing to our requested file.
47142 -#ifdef DEBUG_STAT_CACHE
47143 +#ifdef DEBUG_STAT_CACHE
47144 if (i != ctrl.used) {
47145 fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr);
47147 @@ -424,23 +412,23 @@
47150 dir_ndx = hashme(sc->dir_name);
47153 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
47156 if (sc->dirs && (sc->dirs->key == dir_ndx)) {
47157 dir_node = sc->dirs;
47161 if (dir_node && file_node) {
47162 /* we found a file */
47165 sce = file_node->data;
47166 fam_dir = dir_node->data;
47169 if (fam_dir->version == sce->dir_version) {
47170 /* the stat()-cache entry is still ok */
47175 return HANDLER_GO_ON;
47178 @@ -448,7 +436,7 @@
47184 * - open() + fstat() on a named-pipe results in a (intended) hang.
47185 * - stat() if regualar file + open() to see if we can read from it is better
47187 @@ -469,16 +457,16 @@
47194 osize = sc->files->size;
47197 sce = stat_cache_entry_init();
47198 buffer_copy_string_buffer(sce->name, name);
47200 - sc->files = splaytree_insert(sc->files, file_ndx, sce);
47201 -#ifdef DEBUG_STAT_CACHE
47203 + sc->files = splaytree_insert(sc->files, file_ndx, sce);
47204 +#ifdef DEBUG_STAT_CACHE
47205 if (ctrl.size == 0) {
47208 @@ -499,29 +487,29 @@
47210 sce->stat_ts = srv->cur_ts;
47212 - /* catch the obvious symlinks
47213 + /* catch the obvious symlinks
47215 * this is not a secure check as we still have a race-condition between
47216 - * the stat() and the open. We can only solve this by
47217 + * the stat() and the open. We can only solve this by
47218 * 1. open() the file
47219 * 2. fstat() the fd
47221 * and keeping the file open for the rest of the time. But this can
47222 * only be done at network level.
47226 if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
47227 return HANDLER_ERROR;
47230 - if (S_ISREG(st.st_mode)) {
47231 + if (S_ISREG(st.st_mode)) {
47232 /* determine mimetype */
47233 buffer_reset(sce->content_type);
47236 for (k = 0; k < con->conf.mimetypes->used; k++) {
47237 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
47238 buffer *type = ds->key;
47241 if (type->used == 0) continue;
47243 /* check if the right side is the same */
47244 @@ -539,7 +527,7 @@
47252 (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
47253 @@ -549,19 +537,19 @@
47254 fam_dir->fc = sc->fam;
47256 buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
47259 fam_dir->version = 1;
47262 fam_dir->req = calloc(1, sizeof(FAMRequest));
47264 - if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47266 + if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47267 fam_dir->req, fam_dir)) {
47269 - log_error_write(srv, __FILE__, __LINE__, "sbs",
47270 - "monitoring dir failed:",
47273 + log_error_write(srv, __FILE__, __LINE__, "sbs",
47274 + "monitoring dir failed:",
47276 FamErrlist[FAMErrno]);
47279 fam_dir_entry_free(fam_dir);
47282 @@ -570,7 +558,7 @@
47283 osize = sc->dirs->size;
47286 - sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47287 + sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47289 assert(sc->dirs->data == fam_dir);
47290 assert(osize == (sc->dirs->size - 1));
47291 @@ -578,9 +566,9 @@
47293 fam_dir = dir_node->data;
47297 /* bind the fam_fc to the stat() cache entry */
47301 sce->dir_version = fam_dir->version;
47302 sce->dir_ndx = dir_ndx;
47303 @@ -594,11 +582,11 @@
47307 - * remove stat() from cache which havn't been stat()ed for
47308 + * remove stat() from cache which havn't been stat()ed for
47309 * more than 10 seconds
47312 - * walk though the stat-cache, collect the ids which are too old
47314 + * walk though the stat-cache, collect the ids which are too old
47315 * and remove them in a second loop
47318 @@ -639,9 +627,9 @@
47319 sc->files = splaytree_splay(sc->files, ndx);
47324 if (node && (node->key == ndx)) {
47325 -#ifdef DEBUG_STAT_CACHE
47326 +#ifdef DEBUG_STAT_CACHE
47328 int osize = splaytree_size(sc->files);
47329 stat_cache_entry *sce = node->data;
47330 @@ -649,7 +637,7 @@
47331 stat_cache_entry_free(node->data);
47332 sc->files = splaytree_delete(sc->files, ndx);
47334 -#ifdef DEBUG_STAT_CACHE
47335 +#ifdef DEBUG_STAT_CACHE
47336 for (j = 0; j < ctrl.used; j++) {
47337 if (ctrl.ptr[j] == ndx) {
47338 ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
47339 --- lighttpd-1.4.11/src/stream.c 2005-09-23 21:50:15.000000000 +0300
47340 +++ lighttpd-1.4.12/src/stream.c 2006-07-11 22:07:53.000000000 +0300
47342 #include <sys/types.h>
47343 #include <sys/stat.h>
47345 -#include <unistd.h>
47348 #include "stream.h"
47352 #include "sys-mmap.h"
47353 +#include "sys-files.h"
47356 # define O_BINARY 0
47357 @@ -19,39 +19,39 @@
47361 -#elif defined __WIN32
47362 +#elif defined _WIN32
47370 if (-1 == stat(fn->ptr, &st)) {
47375 f->size = st.st_size;
47378 if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
47383 f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
47389 if (MAP_FAILED == f->start) {
47393 -#elif defined __WIN32
47394 - fh = CreateFile(fn->ptr,
47399 - FILE_ATTRIBUTE_READONLY,
47400 +#elif defined _WIN32
47401 + fh = CreateFile(fn->ptr,
47406 + FILE_ATTRIBUTE_READONLY,
47409 if (!fh) return -1;
47414 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
47415 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
47416 FORMAT_MESSAGE_FROM_SYSTEM,
47425 p = MapViewOfFile(mh,
47432 -# error no mmap found
47433 +# error no mmap found
47440 --- lighttpd-1.4.11/src/sys-files.h 1970-01-01 03:00:00.000000000 +0300
47441 +++ lighttpd-1.4.12/src/sys-files.h 2006-07-11 22:07:53.000000000 +0300
47443 +#ifndef _SYS_FILES_H_
47444 +#define _SYS_FILES_H_
47446 +#define DIR_SEPERATOR_UNIX '/'
47447 +#define DIR_SEPERATOR_WIN '\\'
47450 +#include <windows.h>
47451 +#include <io.h> /* open */
47452 +#include <direct.h> /* chdir */
47454 +#include "buffer.h"
47456 +#define DIR_SEPERATOR DIR_SEPERATOR_WIN
47458 +#define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
47460 +#define S_ISDIR(mode) __S_ISTYPE((mode), _S_IFDIR)
47461 +#define S_ISCHR(mode) __S_ISTYPE((mode), _S_IFCHR)
47462 +#define S_ISBLK(mode) __S_ISTYPE((mode), _S_IFBLK)
47463 +#define S_ISREG(mode) __S_ISTYPE((mode), _S_IFREG)
47464 +/* we don't support symlinks */
47465 +#define S_ISLNK(mode) 0
47467 +#define lstat stat
47468 +#define mkstemp mktemp
47469 +#define mkdir(x, y) mkdir(x)
47472 + const char *d_name;
47477 + WIN32_FIND_DATA finddata;
47478 + struct dirent dent;
47481 +DIR *opendir(const char *dn);
47482 +struct dirent *readdir(DIR *d);
47483 +void closedir(DIR *d);
47485 +buffer *filename_unix2local(buffer *b);
47486 +buffer *pathname_unix2local(buffer *b);
47489 +#include <unistd.h>
47490 +#include <dirent.h>
47492 +#define DIR_SEPERATOR DIR_SEPERATOR_UNIX
47494 +#define filename_unix2local(x) (x)
47495 +#define pathname_unix2local(x) (x)
47498 +#define PATHNAME_APPEND_SLASH(x) \
47499 + if (x->used > 1 && x->ptr[x->used - 2] != DIR_SEPERATOR) { \
47500 + char sl[2] = { DIR_SEPERATOR, 0 }; \
47501 + BUFFER_APPEND_STRING_CONST(x, sl); \
47504 +#ifndef O_LARGEFILE
47505 +# define O_LARGEFILE 0
47510 --- lighttpd-1.4.11/src/sys-mmap.h 2005-08-11 01:26:34.000000000 +0300
47511 +++ lighttpd-1.4.12/src/sys-mmap.h 2006-07-11 22:07:52.000000000 +0300
47513 #ifndef WIN32_MMAP_H
47514 #define WIN32_MMAP_H
47519 #define MAP_FAILED -1
47520 #define PROT_SHARED 0
47521 --- lighttpd-1.4.11/src/sys-process.h 1970-01-01 03:00:00.000000000 +0300
47522 +++ lighttpd-1.4.12/src/sys-process.h 2006-07-11 22:07:52.000000000 +0300
47524 +#ifndef _SYS_PROCESS_H_
47525 +#define _SYS_PROCESS_H_
47528 +#include <process.h>
47530 +/* win32 has no fork() */
47531 +#define kill(x, y)
47534 +#include <sys/wait.h>
47535 +#include <unistd.h>
47540 --- lighttpd-1.4.11/src/sys-socket.h 2005-08-11 01:26:39.000000000 +0300
47541 +++ lighttpd-1.4.12/src/sys-socket.h 2006-07-11 22:07:52.000000000 +0300
47543 #ifndef WIN32_SOCKET_H
47544 #define WIN32_SOCKET_H
47549 #include <winsock2.h>
47551 #define ECONNRESET WSAECONNRESET
47552 #define EINPROGRESS WSAEINPROGRESS
47553 #define EALREADY WSAEALREADY
47554 +#define ENOTCONN WSAENOTCONN
47555 +#define EWOULDBLOCK WSAEWOULDBLOCK
47556 #define ioctl ioctlsocket
47557 #define hstrerror(x) ""
47558 +#define STDIN_FILENO 0
47559 +#define STDOUT_FILENO 1
47560 +#define STDERR_FILENO 2
47561 +#define ssize_t int
47563 +int inet_aton(const char *cp, struct in_addr *inp);
47564 +#define HAVE_INET_ADDR
47565 +#undef HAVE_INET_ATON
47568 #include <sys/socket.h>
47569 #include <sys/ioctl.h>
47571 #include <sys/un.h>
47572 #include <arpa/inet.h>
47575 +#define SUN_LEN(su) \
47576 + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
47582 --- lighttpd-1.4.11/src/sys-strings.h 1970-01-01 03:00:00.000000000 +0300
47583 +++ lighttpd-1.4.12/src/sys-strings.h 2006-07-11 22:07:51.000000000 +0300
47585 +#ifndef _SYS_STRINGS_H_
47586 +#define _SYS_STRINGS_H_
47589 +#define strcasecmp stricmp
47590 +#define strncasecmp strnicmp
47591 +#define strtoll(p, e, b) _strtoi64(p, e, b)
47596 --- lighttpd-1.4.11/tests/LightyTest.pm 2006-01-14 20:32:31.000000000 +0200
47597 +++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-11 22:07:53.000000000 +0300
47598 @@ -87,14 +87,14 @@
47599 # pre-process configfile if necessary
47602 - unlink($self->{TESTDIR}."/tmp/cfg.file");
47603 - system("cat ".$self->{SRCDIR}."/".$self->{CONFIGFILE}.' | perl -pe "s#\@SRCDIR\@#'.$self->{BASEDIR}.'/tests/#" > '.$self->{TESTDIR}.'/tmp/cfg.file');
47604 + $ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
47605 + $ENV{'PORT'} = $self->{PORT};
47607 unlink($self->{LIGHTTPD_PIDFILE});
47609 - system($self->{LIGHTTPD_PATH}." -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH});
47610 + system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH});
47612 - system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=foo ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH}." &");
47613 + system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=foo ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
47616 select(undef, undef, undef, 0.1);
47617 @@ -184,7 +184,7 @@
47618 (my $h = $1) =~ tr/[A-Z]/[a-z]/;
47620 if (defined $resp_hdr{$h}) {
47621 - diag(sprintf("header %s is duplicated: %s and %s\n",
47622 + diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
47623 $h, $resp_hdr{$h}, $2));
47625 $resp_hdr{$h} = $2;
47626 @@ -196,6 +196,9 @@
47630 + $t->{etag} = $resp_hdr{'etag'};
47631 + $t->{date} = $resp_hdr{'date'};
47634 if (defined $resp_hdr{"content-length"}) {
47635 $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
47636 --- lighttpd-1.4.11/tests/Makefile.am 2005-09-16 15:48:40.000000000 +0300
47637 +++ lighttpd-1.4.12/tests/Makefile.am 2006-07-11 22:07:53.000000000 +0300
47638 @@ -39,10 +39,15 @@
47654 TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
47655 --- lighttpd-1.4.11/tests/Makefile.in 2006-03-07 14:21:03.000000000 +0200
47656 +++ lighttpd-1.4.12/tests/Makefile.in 2006-07-11 21:48:14.000000000 +0300
47658 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
47659 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
47660 # @configure_input@
47662 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
47664 # PARTICULAR PURPOSE.
47667 -SOURCES = $(fcgi_auth_SOURCES) $(fcgi_responder_SOURCES)
47670 top_srcdir = @top_srcdir@
47673 am__aclocal_m4_deps = $(top_srcdir)/configure.in
47674 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
47676 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
47677 +mkinstalldirs = $(install_sh) -d
47678 CONFIG_HEADER = $(top_builddir)/config.h
47679 CONFIG_CLEAN_FILES =
47680 am__fcgi_auth_SOURCES_DIST = fcgi-auth.c
47682 $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
47683 $(AM_CFLAGS) $(CFLAGS)
47685 -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
47686 - $(AM_LDFLAGS) $(LDFLAGS) -o $@
47687 +LINK = $(LIBTOOL) --tag=CC --mode=link "$(CCLD)" $(AM_CFLAGS) \
47688 + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
47689 SOURCES = $(fcgi_auth_SOURCES) $(fcgi_responder_SOURCES)
47690 DIST_SOURCES = $(am__fcgi_auth_SOURCES_DIST) \
47691 $(am__fcgi_responder_SOURCES_DIST)
47692 @@ -134,7 +132,6 @@
47693 LIBTOOL = @LIBTOOL@
47695 LTLIBOBJS = @LTLIBOBJS@
47696 -LUACONFIG = @LUACONFIG@
47697 LUA_CFLAGS = @LUA_CFLAGS@
47698 LUA_LIBS = @LUA_LIBS@
47700 @@ -177,6 +174,7 @@
47701 ac_ct_F77 = @ac_ct_F77@
47702 ac_ct_RANLIB = @ac_ct_RANLIB@
47703 ac_ct_STRIP = @ac_ct_STRIP@
47704 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
47705 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
47706 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
47707 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
47708 @@ -253,10 +251,15 @@
47723 TESTS_ENVIRONMENT = $(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
47724 EXTRA_DIST = wrapper.sh lighttpd.conf \
47725 --- lighttpd-1.4.11/tests/bug-06.conf 2005-08-27 17:44:19.000000000 +0300
47726 +++ lighttpd-1.4.12/tests/bug-06.conf 2006-07-11 22:07:53.000000000 +0300
47728 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47729 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47730 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47731 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47733 ## bind to port (default: 80)
47737 ## bind to localhost (default: all interfaces)
47738 server.bind = "localhost"
47739 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47740 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47741 server.name = "www.example.org"
47742 server.tag = "Apache 1.3.29"
47745 ######################## MODULE CONFIG ############################
47748 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47749 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47751 mimetype.assign = ( ".png" => "image/png",
47752 ".jpg" => "image/jpeg",
47754 ".c" => "text/plain",
47755 ".conf" => "text/plain" )
47757 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47758 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47759 compress.filetype = ("text/plain", "text/html")
47761 setenv.add-environment = ( "TRAC_ENV" => "foo")
47763 "host" => "127.0.0.1",
47765 # "mode" => "authorizer",
47766 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47767 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47771 @@ -106,7 +106,7 @@
47772 ssl.pemfile = "server.pem"
47774 auth.backend = "plain"
47775 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47776 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47777 auth.backend.plain.groupfile = "lighttpd.group"
47779 auth.backend.ldap.hostname = "localhost"
47780 @@ -149,15 +149,15 @@
47781 status.config-url = "/server-config"
47783 simple-vhost.document-root = "pages"
47784 -simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
47785 +simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
47786 simple-vhost.default-host = "www.example.org"
47788 $HTTP["host"] == "vvv.example.org" {
47789 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47790 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47793 $HTTP["host"] == "zzz.example.org" {
47794 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47795 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47796 server.name = "zzz.example.org"
47799 --- lighttpd-1.4.11/tests/bug-12.conf 2005-08-27 17:44:19.000000000 +0300
47800 +++ lighttpd-1.4.12/tests/bug-12.conf 2006-07-11 22:07:53.000000000 +0300
47802 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47803 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47804 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47805 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47807 ## bind to port (default: 80)
47811 ## bind to localhost (default: all interfaces)
47812 server.bind = "localhost"
47813 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47814 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47815 server.name = "www.example.org"
47816 server.tag = "Apache 1.3.29"
47819 ######################## MODULE CONFIG ############################
47822 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47823 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47825 mimetype.assign = ( ".png" => "image/png",
47826 ".jpg" => "image/jpeg",
47828 ".c" => "text/plain",
47829 ".conf" => "text/plain" )
47831 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47832 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47833 compress.filetype = ("text/plain", "text/html")
47835 setenv.add-environment = ( "TRAC_ENV" => "foo")
47837 "host" => "127.0.0.1",
47839 # "mode" => "authorizer",
47840 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47841 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47845 @@ -108,7 +108,7 @@
47846 ssl.pemfile = "server.pem"
47848 auth.backend = "plain"
47849 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47850 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47851 auth.backend.plain.groupfile = "lighttpd.group"
47853 auth.backend.ldap.hostname = "localhost"
47854 @@ -151,15 +151,15 @@
47855 status.config-url = "/server-config"
47857 simple-vhost.document-root = "pages"
47858 -simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
47859 +simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
47860 simple-vhost.default-host = "www.example.org"
47862 $HTTP["host"] == "vvv.example.org" {
47863 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47864 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47867 $HTTP["host"] == "zzz.example.org" {
47868 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47869 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47870 server.name = "zzz.example.org"
47873 --- lighttpd-1.4.11/tests/cachable.t 1970-01-01 03:00:00.000000000 +0300
47874 +++ lighttpd-1.4.12/tests/cachable.t 2006-07-11 22:07:53.000000000 +0300
47876 +#!/usr/bin/env perl
47878 + # add current source dir to the include-path
47879 + # we need this for make distcheck
47880 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
47881 + unshift @INC, $srcdir;
47886 +use Test::More tests => 12;
47889 +my $tf = LightyTest->new();
47892 +$tf->{CONFIGFILE} = 'lighttpd.conf';
47894 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
47896 +## check if If-Modified-Since, If-None-Match works
47898 +$t->{REQUEST} = ( <<EOF
47900 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
47903 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47904 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
47906 +$t->{REQUEST} = ( <<EOF
47908 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47911 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47912 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
47914 +my $now = $t->{date};
47916 +$t->{REQUEST} = ( <<EOF
47918 +If-Modified-Since: $now
47921 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47922 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
47924 +$t->{REQUEST} = ( <<EOF
47926 +If-Modified-Since: $now; foo
47929 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47930 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
47932 +$t->{REQUEST} = ( <<EOF
47934 +If-None-Match: foo
47937 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47938 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47940 +my $etag = $t->{etag};
47942 +$t->{REQUEST} = ( <<EOF
47944 +If-None-Match: $etag
47947 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47948 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47950 +$t->{REQUEST} = ( <<EOF
47952 +If-None-Match: $etag
47953 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47956 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47957 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
47959 +$t->{REQUEST} = ( <<EOF
47961 +If-None-Match: $etag
47962 +If-Modified-Since: $now; foo
47965 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47966 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
47968 +$t->{REQUEST} = ( <<EOF
47970 +If-None-Match: Foo
47971 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47974 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47975 +ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
47977 +$t->{REQUEST} = ( <<EOF
47979 +If-None-Match: $etag
47980 +If-Modified-Since: $now foo
47983 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
47984 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
47986 +ok($tf->stop_proc == 0, "Stopping lighttpd");
47988 --- lighttpd-1.4.11/tests/condition.conf 2005-08-27 17:44:19.000000000 +0300
47989 +++ lighttpd-1.4.12/tests/condition.conf 2006-07-11 22:07:53.000000000 +0300
47991 debug.log-request-handling = "enable"
47992 debug.log-condition-handling = "enable"
47994 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47995 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47996 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47997 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47999 ## bind to port (default: 80)
48002 ## bind to localhost (default: all interfaces)
48003 server.bind = "localhost"
48004 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48005 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48006 server.name = "www.example.org"
48007 server.tag = "Apache 1.3.29"
48009 @@ -22,25 +22,25 @@
48010 ######################## MODULE CONFIG ############################
48013 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48014 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48016 mimetype.assign = ( ".html" => "text/html" )
48018 url.redirect = ("^" => "/default")
48020 $HTTP["host"] == "www.example.org" {
48021 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48022 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48023 server.name = "www.example.org"
48024 url.redirect = ("^" => "/match_1")
48026 else $HTTP["host"] == "test1.example.org" {
48027 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48028 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48029 server.name = "test1.example.org"
48030 url.redirect = ("^" => "/match_2")
48033 else $HTTP["host"] == "test2.example.org" {
48034 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48035 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48036 server.name = "test2.example.org"
48037 url.redirect = ("^" => "/match_3")
48042 else $HTTP["host"] == "test3.example.org" {
48043 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48044 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48045 server.name = "test3.example.org"
48046 url.redirect = ("^" => "/match_4")
48048 --- lighttpd-1.4.11/tests/core-keepalive.t 2005-11-17 15:54:19.000000000 +0200
48049 +++ lighttpd-1.4.12/tests/core-keepalive.t 2006-07-11 22:07:53.000000000 +0300
48052 GET /12345.txt HTTP/1.0
48053 Host: 123.example.org
48054 -Connection: keep-alive
48058 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48059 --- lighttpd-1.4.11/tests/docroot/123/Makefile.in 2006-03-07 14:21:03.000000000 +0200
48060 +++ lighttpd-1.4.12/tests/docroot/123/Makefile.in 2006-07-11 21:48:15.000000000 +0300
48062 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48063 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48064 # @configure_input@
48066 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48068 am__aclocal_m4_deps = $(top_srcdir)/configure.in
48069 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48071 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48072 +mkinstalldirs = $(install_sh) -d
48073 CONFIG_HEADER = $(top_builddir)/config.h
48074 CONFIG_CLEAN_FILES =
48076 @@ -100,7 +100,6 @@
48077 LIBTOOL = @LIBTOOL@
48079 LTLIBOBJS = @LTLIBOBJS@
48080 -LUACONFIG = @LUACONFIG@
48081 LUA_CFLAGS = @LUA_CFLAGS@
48082 LUA_LIBS = @LUA_LIBS@
48084 @@ -143,6 +142,7 @@
48085 ac_ct_F77 = @ac_ct_F77@
48086 ac_ct_RANLIB = @ac_ct_RANLIB@
48087 ac_ct_STRIP = @ac_ct_STRIP@
48088 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48089 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48090 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48091 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48092 --- lighttpd-1.4.11/tests/docroot/Makefile.in 2006-03-07 14:21:04.000000000 +0200
48093 +++ lighttpd-1.4.12/tests/docroot/Makefile.in 2006-07-11 21:48:15.000000000 +0300
48095 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48096 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48097 # @configure_input@
48099 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48101 am__aclocal_m4_deps = $(top_srcdir)/configure.in
48102 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48104 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48105 +mkinstalldirs = $(install_sh) -d
48106 CONFIG_HEADER = $(top_builddir)/config.h
48107 CONFIG_CLEAN_FILES =
48109 @@ -109,7 +109,6 @@
48110 LIBTOOL = @LIBTOOL@
48112 LTLIBOBJS = @LTLIBOBJS@
48113 -LUACONFIG = @LUACONFIG@
48114 LUA_CFLAGS = @LUA_CFLAGS@
48115 LUA_LIBS = @LUA_LIBS@
48117 @@ -152,6 +151,7 @@
48118 ac_ct_F77 = @ac_ct_F77@
48119 ac_ct_RANLIB = @ac_ct_RANLIB@
48120 ac_ct_STRIP = @ac_ct_STRIP@
48121 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48122 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48123 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48124 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48125 --- lighttpd-1.4.11/tests/docroot/www/Makefile.in 2006-03-07 14:21:05.000000000 +0200
48126 +++ lighttpd-1.4.12/tests/docroot/www/Makefile.in 2006-07-11 21:48:15.000000000 +0300
48128 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48129 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48130 # @configure_input@
48132 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48134 am__aclocal_m4_deps = $(top_srcdir)/configure.in
48135 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48137 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48138 +mkinstalldirs = $(install_sh) -d
48139 CONFIG_HEADER = $(top_builddir)/config.h
48140 CONFIG_CLEAN_FILES =
48142 @@ -109,7 +109,6 @@
48143 LIBTOOL = @LIBTOOL@
48145 LTLIBOBJS = @LTLIBOBJS@
48146 -LUACONFIG = @LUACONFIG@
48147 LUA_CFLAGS = @LUA_CFLAGS@
48148 LUA_LIBS = @LUA_LIBS@
48150 @@ -152,6 +151,7 @@
48151 ac_ct_F77 = @ac_ct_F77@
48152 ac_ct_RANLIB = @ac_ct_RANLIB@
48153 ac_ct_STRIP = @ac_ct_STRIP@
48154 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48155 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48156 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48157 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48158 --- lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries 2006-03-09 19:21:49.000000000 +0200
48159 +++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries 2006-07-11 22:07:54.000000000 +0300
48163 uuid="152afb58-edef-0310-8abb-c4023f1b3aa9"
48164 - revision="1040"/>
48165 + repos="svn://svn.lighttpd.net/lighttpd"
48166 + revision="1154"/>
48168 --- lighttpd-1.4.11/tests/docroot/www/expire/Makefile.in 2006-03-07 14:21:05.000000000 +0200
48169 +++ lighttpd-1.4.12/tests/docroot/www/expire/Makefile.in 2006-07-11 21:48:15.000000000 +0300
48171 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48172 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48173 # @configure_input@
48175 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48177 am__aclocal_m4_deps = $(top_srcdir)/configure.in
48178 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48180 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48181 +mkinstalldirs = $(install_sh) -d
48182 CONFIG_HEADER = $(top_builddir)/config.h
48183 CONFIG_CLEAN_FILES =
48185 @@ -100,7 +100,6 @@
48186 LIBTOOL = @LIBTOOL@
48188 LTLIBOBJS = @LTLIBOBJS@
48189 -LUACONFIG = @LUACONFIG@
48190 LUA_CFLAGS = @LUA_CFLAGS@
48191 LUA_LIBS = @LUA_LIBS@
48193 @@ -143,6 +142,7 @@
48194 ac_ct_F77 = @ac_ct_F77@
48195 ac_ct_RANLIB = @ac_ct_RANLIB@
48196 ac_ct_STRIP = @ac_ct_STRIP@
48197 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48198 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48199 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48200 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48201 --- lighttpd-1.4.11/tests/docroot/www/go/Makefile.in 2006-03-07 14:21:06.000000000 +0200
48202 +++ lighttpd-1.4.12/tests/docroot/www/go/Makefile.in 2006-07-11 21:48:16.000000000 +0300
48204 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48205 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48206 # @configure_input@
48208 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48210 am__aclocal_m4_deps = $(top_srcdir)/configure.in
48211 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48213 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48214 +mkinstalldirs = $(install_sh) -d
48215 CONFIG_HEADER = $(top_builddir)/config.h
48216 CONFIG_CLEAN_FILES =
48218 @@ -100,7 +100,6 @@
48219 LIBTOOL = @LIBTOOL@
48221 LTLIBOBJS = @LTLIBOBJS@
48222 -LUACONFIG = @LUACONFIG@
48223 LUA_CFLAGS = @LUA_CFLAGS@
48224 LUA_LIBS = @LUA_LIBS@
48226 @@ -143,6 +142,7 @@
48227 ac_ct_F77 = @ac_ct_F77@
48228 ac_ct_RANLIB = @ac_ct_RANLIB@
48229 ac_ct_STRIP = @ac_ct_STRIP@
48230 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48231 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48232 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48233 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48234 --- lighttpd-1.4.11/tests/docroot/www/indexfile/Makefile.in 2006-03-07 14:21:07.000000000 +0200
48235 +++ lighttpd-1.4.12/tests/docroot/www/indexfile/Makefile.in 2006-07-11 21:48:16.000000000 +0300
48237 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48238 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48239 # @configure_input@
48241 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48243 am__aclocal_m4_deps = $(top_srcdir)/configure.in
48244 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48246 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48247 +mkinstalldirs = $(install_sh) -d
48248 CONFIG_HEADER = $(top_builddir)/config.h
48249 CONFIG_CLEAN_FILES =
48251 @@ -100,7 +100,6 @@
48252 LIBTOOL = @LIBTOOL@
48254 LTLIBOBJS = @LTLIBOBJS@
48255 -LUACONFIG = @LUACONFIG@
48256 LUA_CFLAGS = @LUA_CFLAGS@
48257 LUA_LIBS = @LUA_LIBS@
48259 @@ -143,6 +142,7 @@
48260 ac_ct_F77 = @ac_ct_F77@
48261 ac_ct_RANLIB = @ac_ct_RANLIB@
48262 ac_ct_STRIP = @ac_ct_STRIP@
48263 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48264 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48265 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48266 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48267 --- lighttpd-1.4.11/tests/fastcgi-10.conf 2005-08-31 23:36:34.000000000 +0300
48268 +++ lighttpd-1.4.12/tests/fastcgi-10.conf 2006-07-11 22:07:53.000000000 +0300
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"
48275 ## bind to port (default: 80)
48278 ## bind to localhost (default: all interfaces)
48279 server.bind = "localhost"
48280 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48281 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48282 server.name = "www.example.org"
48283 server.tag = "Apache 1.3.29"
48286 ######################## MODULE CONFIG ############################
48289 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48290 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48292 mimetype.assign = ( ".png" => "image/png",
48293 ".jpg" => "image/jpeg",
48295 ".c" => "text/plain",
48296 ".conf" => "text/plain" )
48298 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48299 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48300 compress.filetype = ("text/plain", "text/html")
48304 ssl.pemfile = "server.pem"
48306 auth.backend = "plain"
48307 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48308 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48309 auth.backend.plain.groupfile = "lighttpd.group"
48311 auth.backend.ldap.hostname = "localhost"
48312 @@ -128,11 +128,11 @@
48313 status.config-url = "/server-config"
48315 $HTTP["host"] == "vvv.example.org" {
48316 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48317 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48320 $HTTP["host"] == "zzz.example.org" {
48321 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48322 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48323 server.name = "zzz.example.org"
48326 --- lighttpd-1.4.11/tests/fastcgi-13.conf 2006-01-03 12:38:17.000000000 +0200
48327 +++ lighttpd-1.4.12/tests/fastcgi-13.conf 2006-07-11 22:07:53.000000000 +0300
48329 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48330 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48331 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48332 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48334 debug.log-request-header = "enable"
48335 debug.log-response-header = "enable"
48338 ## bind to localhost (default: all interfaces)
48339 server.bind = "localhost"
48340 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48341 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48342 server.name = "www.example.org"
48343 server.tag = "Apache 1.3.29"
48346 ######################## MODULE CONFIG ############################
48349 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48350 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48352 mimetype.assign = ( ".png" => "image/png",
48353 ".jpg" => "image/jpeg",
48355 ".c" => "text/plain",
48356 ".conf" => "text/plain" )
48358 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48359 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48360 compress.filetype = ("text/plain", "text/html")
48363 @@ -102,7 +102,7 @@
48364 ssl.pemfile = "server.pem"
48366 auth.backend = "plain"
48367 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48368 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48369 auth.backend.plain.groupfile = "lighttpd.group"
48371 auth.backend.ldap.hostname = "localhost"
48372 @@ -145,11 +145,11 @@
48373 status.config-url = "/server-config"
48375 $HTTP["host"] == "vvv.example.org" {
48376 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48377 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48380 $HTTP["host"] == "zzz.example.org" {
48381 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48382 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48383 server.name = "zzz.example.org"
48386 --- lighttpd-1.4.11/tests/fastcgi-auth.conf 2005-08-27 17:44:19.000000000 +0300
48387 +++ lighttpd-1.4.12/tests/fastcgi-auth.conf 2006-07-11 22:07:53.000000000 +0300
48389 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48390 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48391 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48392 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48394 debug.log-request-header = "enable"
48395 debug.log-response-header = "enable"
48398 ## bind to localhost (default: all interfaces)
48399 server.bind = "localhost"
48400 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48401 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48402 server.name = "www.example.org"
48403 server.tag = "Apache 1.3.29"
48406 ######################## MODULE CONFIG ############################
48409 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48410 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48412 mimetype.assign = ( ".png" => "image/png",
48413 ".jpg" => "image/jpeg",
48415 ".c" => "text/plain",
48416 ".conf" => "text/plain" )
48418 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48419 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48420 compress.filetype = ("text/plain", "text/html")
48425 "host" => "127.0.0.1",
48427 - "bin-path" => "@SRCDIR@/fcgi-auth",
48428 + "bin-path" => env.SRCDIR + "/fcgi-auth",
48429 "mode" => "authorizer",
48430 - "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
48431 + "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
48435 @@ -106,7 +106,7 @@
48436 ssl.pemfile = "server.pem"
48438 auth.backend = "plain"
48439 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48440 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48441 auth.backend.plain.groupfile = "lighttpd.group"
48443 auth.backend.ldap.hostname = "localhost"
48444 @@ -149,11 +149,11 @@
48445 status.config-url = "/server-config"
48447 $HTTP["host"] == "vvv.example.org" {
48448 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48449 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48452 $HTTP["host"] == "zzz.example.org" {
48453 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48454 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48455 server.name = "zzz.example.org"
48458 --- lighttpd-1.4.11/tests/fastcgi-responder.conf 2005-08-27 17:44:19.000000000 +0300
48459 +++ lighttpd-1.4.12/tests/fastcgi-responder.conf 2006-07-11 22:07:53.000000000 +0300
48461 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48462 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48463 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48464 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48466 #debug.log-request-header = "enable"
48467 #debug.log-response-header = "enable"
48470 ## bind to localhost (default: all interfaces)
48471 server.bind = "localhost"
48472 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48473 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48474 server.name = "www.example.org"
48475 server.tag = "Apache 1.3.29"
48478 ######################## MODULE CONFIG ############################
48481 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48482 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48484 mimetype.assign = ( ".png" => "image/png",
48485 ".jpg" => "image/jpeg",
48487 ".c" => "text/plain",
48488 ".conf" => "text/plain" )
48490 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48491 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48492 compress.filetype = ("text/plain", "text/html")
48495 @@ -90,10 +90,11 @@
48497 "host" => "127.0.0.1",
48499 - "bin-path" => "@SRCDIR@/fcgi-responder",
48500 + "bin-path" => env.SRCDIR + "/fcgi-responder",
48501 "check-local" => "disable",
48504 + "min-procs" => 1,
48505 + "allow-x-send-file" => "enable",
48509 @@ -109,7 +110,7 @@
48510 ssl.pemfile = "server.pem"
48512 auth.backend = "plain"
48513 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48514 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48515 auth.backend.plain.groupfile = "lighttpd.group"
48517 auth.backend.ldap.hostname = "localhost"
48518 @@ -152,11 +153,11 @@
48519 status.config-url = "/server-config"
48521 $HTTP["host"] == "vvv.example.org" {
48522 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48523 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48526 $HTTP["host"] == "zzz.example.org" {
48527 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48528 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48529 server.name = "zzz.example.org"
48532 --- lighttpd-1.4.11/tests/fcgi-responder.c 2005-08-11 01:26:55.000000000 +0300
48533 +++ lighttpd-1.4.12/tests/fcgi-responder.c 2006-07-11 22:07:53.000000000 +0300
48536 int num_requests = 2;
48538 - while (num_requests > 0 &&
48539 - FCGI_Accept() >= 0) {
48542 - if (NULL != (p = getenv("QUERY_STRING"))) {
48543 + while (num_requests > 0 && FCGI_Accept() >= 0) {
48545 + char* doc_root = NULL;
48546 + char fname[4096];
48547 + char* pfname = (char *)fname;
48549 + doc_root = getenv("DOCUMENT_ROOT");
48550 + p = getenv("QUERY_STRING");
48552 + if (NULL != p && NULL != doc_root) {
48553 + snprintf(pfname, sizeof(fname), "%s/phpinfo.php", doc_root);
48554 if (0 == strcmp(p, "lf")) {
48555 printf("Status: 200 OK\n\n");
48556 } else if (0 == strcmp(p, "crlf")) {
48558 printf("Status: 200 OK\r\n");
48561 + } else if (0 == strcmp(p,"x-lighttpd-send-file")) {
48562 + printf("Status: 200 OK\r\n");
48563 + printf("X-LIGHTTPD-send-file: %s\r\n", pfname);
48565 + } else if (0 == strcmp(p,"xsendfile")) {
48566 + printf("Status: 200 OK\r\n");
48567 + printf("X-Sendfile: %s\r\n", pfname);
48569 + } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
48570 + printf("Status: 200 OK\r\n");
48571 + printf("X-SeNdFiLe: %s\r\n", pfname);
48573 } else if (0 == strcmp(p, "die-at-end")) {
48574 printf("Status: 200 OK\r\n\r\n");
48576 --- lighttpd-1.4.11/tests/lighttpd.conf 2006-03-09 15:26:58.000000000 +0200
48577 +++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-11 22:07:53.000000000 +0300
48579 -debug.log-request-handling = "enable"
48580 -debug.log-condition-handling = "enable"
48581 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48582 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48583 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48584 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48585 +server.tag = "Apache 1.3.29"
48587 ## 64 Mbyte ... nice limit
48588 server.max-request-size = 65000
48590 -## bind to port (default: 80)
48591 -server.port = 2048
48592 +include "default.conf"
48594 -## bind to localhost (default: all interfaces)
48595 -server.bind = "localhost"
48596 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48597 -server.name = "www.example.org"
48598 -server.tag = "Apache 1.3.29"
48600 -server.dir-listing = "enable"
48602 -#server.event-handler = "linux-sysepoll"
48603 -#server.event-handler = "linux-rtsig"
48605 -#server.modules.path = ""
48606 -server.modules = (
48609 - "mod_secdownload",
48615 - "mod_simple_vhost",
48618 -# "mod_localizer",
48624 - "mod_accesslog" )
48626 -server.indexfiles = ( "index.php", "index.html",
48627 - "index.htm", "default.htm" )
48630 -######################## MODULE CONFIG ############################
48632 -ssi.extension = ( ".shtml" )
48634 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48636 -mimetype.assign = ( ".png" => "image/png",
48637 - ".jpg" => "image/jpeg",
48638 - ".jpeg" => "image/jpeg",
48639 - ".gif" => "image/gif",
48640 - ".html" => "text/html",
48641 - ".htm" => "text/html",
48642 - ".pdf" => "application/pdf",
48643 - ".swf" => "application/x-shockwave-flash",
48644 - ".spl" => "application/futuresplash",
48645 - ".txt" => "text/plain",
48646 - ".tar.gz" => "application/x-tgz",
48647 - ".tgz" => "application/x-tgz",
48648 - ".gz" => "application/x-gzip",
48649 - ".c" => "text/plain",
48650 - ".conf" => "text/plain" )
48651 +setenv.add-request-header = ( "FOO" => "foo")
48652 +setenv.add-response-header = ( "BAR" => "foo")
48654 $HTTP["host"] == "cache.example.org" {
48655 - compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48656 + compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48658 -compress.filetype = ("text/plain", "text/html")
48660 -setenv.add-environment = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
48661 -setenv.add-request-header = ( "FOO" => "foo")
48662 -setenv.add-response-header = ( "BAR" => "foo")
48664 $HTTP["url"] =~ "\.pdf$" {
48665 server.range-requests = "disable"
48666 @@ -85,76 +23,31 @@
48667 "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48671 -cgi.assign = ( ".pl" => "/usr/bin/perl",
48672 - ".cgi" => "/usr/bin/perl",
48673 - ".py" => "/usr/bin/python" )
48675 -userdir.include-user = ( "jan" )
48676 -userdir.path = "/"
48678 -ssl.engine = "disable"
48679 -ssl.pemfile = "server.pem"
48681 $HTTP["host"] == "auth-htpasswd.example.org" {
48682 auth.backend = "htpasswd"
48685 -auth.backend = "plain"
48686 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48688 -auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
48691 -auth.require = ( "/server-status" =>
48693 - "method" => "digest",
48694 - "realm" => "download archiv",
48695 - "require" => "group=www|user=jan|host=192.168.2.10"
48697 - "/server-config" =>
48699 - "method" => "basic",
48700 - "realm" => "download archiv",
48701 - "require" => "valid-user"
48705 -url.access-deny = ( "~", ".inc")
48707 -url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
48708 - "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48710 -expire.url = ( "/expire/access" => "access 2 hours",
48711 - "/expire/modification" => "access plus 1 seconds 2 minutes")
48713 -#cache.cache-dir = "/home/weigon/wwwroot/cache/"
48715 -#### status module
48716 -status.status-url = "/server-status"
48717 -status.config-url = "/server-config"
48719 $HTTP["host"] == "vvv.example.org" {
48720 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48721 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48722 secdownload.secret = "verysecret"
48723 - secdownload.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48724 + secdownload.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48725 secdownload.uri-prefix = "/sec/"
48726 secdownload.timeout = 120
48729 $HTTP["host"] == "zzz.example.org" {
48730 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48731 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48732 server.name = "zzz.example.org"
48735 $HTTP["host"] == "no-simple.example.org" {
48736 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
48737 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/123.example.org/pages/"
48738 server.name = "zzz.example.org"
48741 $HTTP["host"] !~ "(no-simple\.example\.org)" {
48742 simple-vhost.document-root = "pages"
48743 - simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
48744 + simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
48745 simple-vhost.default-host = "www.example.org"
48748 --- lighttpd-1.4.11/tests/lowercase.conf 1970-01-01 03:00:00.000000000 +0300
48749 +++ lighttpd-1.4.12/tests/lowercase.conf 2006-07-11 22:07:53.000000000 +0300
48751 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48752 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48754 +## bind to port (default: 80)
48755 +server.port = 2048
48757 +## bind to localhost (default: all interfaces)
48758 +server.bind = "localhost"
48759 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48761 +server.force-lowercase-filenames = "enable"
48763 +server.dir-listing = "enable"
48765 +server.modules = (
48768 + "mod_secdownload",
48777 +server.indexfiles = ( "index.php", "index.html",
48778 + "index.htm", "default.htm" )
48781 +######################## MODULE CONFIG ############################
48783 +mimetype.assign = ( ".png" => "image/png",
48784 + ".jpg" => "image/jpeg",
48785 + ".jpeg" => "image/jpeg",
48786 + ".gif" => "image/gif",
48787 + ".html" => "text/html",
48788 + ".htm" => "text/html",
48789 + ".pdf" => "application/pdf",
48790 + ".swf" => "application/x-shockwave-flash",
48791 + ".spl" => "application/futuresplash",
48792 + ".txt" => "text/plain",
48793 + ".tar.gz" => "application/x-tgz",
48794 + ".tgz" => "application/x-tgz",
48795 + ".gz" => "application/x-gzip",
48796 + ".c" => "text/plain",
48797 + ".conf" => "text/plain" )
48800 +fastcgi.server = ( ".php" => ( ( "host" => "127.0.0.1", "port" => 1026, "broken-scriptfilename" => "enable" ) ),
48801 + "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48805 +cgi.assign = ( ".pl" => "/usr/bin/perl",
48806 + ".cgi" => "/usr/bin/perl",
48807 + ".py" => "/usr/bin/python" )
48809 +auth.backend = "plain"
48810 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48812 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
48814 +$HTTP["host"] == "lowercase-auth" {
48815 + auth.require = ( "/image.jpg" =>
48817 + "method" => "digest",
48818 + "realm" => "download archiv",
48819 + "require" => "valid-user"
48824 +$HTTP["host"] == "lowercase-deny" {
48825 + url.access-deny = ( ".jpg")
48828 +$HTTP["host"] == "lowercase-exclude" {
48829 + static-file.exclude-extensions = ( ".jpg" )
48831 --- lighttpd-1.4.11/tests/lowercase.t 1970-01-01 03:00:00.000000000 +0300
48832 +++ lighttpd-1.4.12/tests/lowercase.t 2006-07-11 22:07:53.000000000 +0300
48834 +#!/usr/bin/env perl
48836 + # add current source dir to the include-path
48837 + # we need this for make distcheck
48838 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
48839 + unshift @INC, $srcdir;
48844 +use Test::More tests => 10;
48847 +my $tf = LightyTest->new();
48850 +$tf->{CONFIGFILE} = 'lowercase.conf';
48852 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
48854 +## check if lower-casing works
48856 +$t->{REQUEST} = ( <<EOF
48857 +GET /image.JPG HTTP/1.0
48860 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48861 +ok($tf->handle_http($t) == 0, 'uppercase access');
48863 +$t->{REQUEST} = ( <<EOF
48864 +GET /image.jpg HTTP/1.0
48867 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48868 +ok($tf->handle_http($t) == 0, 'lowercase access');
48870 +## check that mod-auth works
48872 +$t->{REQUEST} = ( <<EOF
48873 +GET /image.JPG HTTP/1.0
48874 +Host: lowercase-auth
48877 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48878 +ok($tf->handle_http($t) == 0, 'uppercase access');
48880 +$t->{REQUEST} = ( <<EOF
48881 +GET /image.jpg HTTP/1.0
48882 +Host: lowercase-auth
48885 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48886 +ok($tf->handle_http($t) == 0, 'lowercase access');
48889 +## check that mod-staticfile exclude works
48890 +$t->{REQUEST} = ( <<EOF
48891 +GET /image.JPG HTTP/1.0
48892 +Host: lowercase-exclude
48895 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48896 +ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
48898 +$t->{REQUEST} = ( <<EOF
48899 +GET /image.jpg HTTP/1.0
48900 +Host: lowercase-exclude
48903 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48904 +ok($tf->handle_http($t) == 0, 'lowercase access');
48907 +## check that mod-access exclude works
48908 +$t->{REQUEST} = ( <<EOF
48909 +GET /image.JPG HTTP/1.0
48910 +Host: lowercase-deny
48913 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48914 +ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
48916 +$t->{REQUEST} = ( <<EOF
48917 +GET /image.jpg HTTP/1.0
48918 +Host: lowercase-deny
48921 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48922 +ok($tf->handle_http($t) == 0, 'lowercase access');
48926 +ok($tf->stop_proc == 0, "Stopping lighttpd");
48928 --- lighttpd-1.4.11/tests/mod-fastcgi.t 2006-03-09 15:30:45.000000000 +0200
48929 +++ lighttpd-1.4.12/tests/mod-fastcgi.t 2006-07-11 22:07:53.000000000 +0300
48934 -use Test::More tests => 47;
48935 +use Test::More tests => 49;
48938 my $tf = LightyTest->new();
48943 - skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
48944 + skip "no PHP running on port 1026", 29 unless $tf->listening_on(1026);
48946 ok($tf->start_proc == 0, "Starting lighttpd") or die();
48948 @@ -223,7 +223,7 @@
48952 - skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48953 + skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48954 $tf->{CONFIGFILE} = 'fastcgi-13.conf';
48955 ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
48956 $t->{REQUEST} = ( <<EOF
48957 @@ -285,6 +285,34 @@
48958 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
48959 ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
48961 + # X-LIGHTTPD-send-file
48962 + $t->{REQUEST} = ( <<EOF
48963 +GET /index.fcgi?x-lighttpd-send-file HTTP/1.0
48964 +Host: www.example.org
48967 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48969 + ok($tf->handle_http($t) == 0, 'X-LIGHTTPD-send-file');
48971 + $t->{REQUEST} = ( <<EOF
48972 +GET /index.fcgi?xsendfile HTTP/1.0
48973 +Host: www.example.org
48976 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48978 + ok($tf->handle_http($t) == 0, 'X-Sendfile');
48980 + $t->{REQUEST} = ( <<EOF
48981 +GET /index.fcgi?xsendfile-mixed-case HTTP/1.0
48982 +Host: www.example.org
48985 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48987 + ok($tf->handle_http($t) == 0, 'X-SeNdFiLe in mixed case');
48989 $t->{REQUEST} = ( <<EOF
48990 GET /index.fcgi?die-at-end HTTP/1.0
48991 Host: www.example.org
48992 --- lighttpd-1.4.11/tests/mod-proxy.t 1970-01-01 03:00:00.000000000 +0300
48993 +++ lighttpd-1.4.12/tests/mod-proxy.t 2006-07-11 22:07:53.000000000 +0300
48995 +#!/usr/bin/env perl
48997 + # add current source dir to the include-path
48998 + # we need this for make distcheck
48999 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
49000 + unshift @INC, $srcdir;
49005 +use Test::More tests => 21;
49008 +my $tf_proxy = LightyTest->new();
49009 +my $tf_backend1 = LightyTest->new();
49010 +my $tf_backend2 = LightyTest->new();
49014 +## we need two procs
49015 +## 1. the real webserver
49016 +## 2. the proxy server
49018 +$tf_proxy->{PORT} = 2048;
49019 +$tf_proxy->{CONFIGFILE} = 'proxy.conf';
49020 +$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
49022 +$tf_backend1->{PORT} = 2050;
49023 +$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
49024 +$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
49026 +$tf_backend2->{PORT} = 2051;
49027 +$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
49028 +$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
49031 +ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
49033 +ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
49037 +$t->{REQUEST} = ( <<EOF
49038 +GET /index.html HTTP/1.0
49039 +Host: www.example.org
49042 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
49043 +ok($tf_proxy->handle_http($t) == 0, 'valid request');
49045 +$t->{REQUEST} = ( <<EOF
49046 +GET /index.html HTTP/1.0
49047 +Host: www.example.org
49050 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'proxy-backend-1' } ];
49051 +ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
49053 +$t->{REQUEST} = ( <<EOF
49054 +GET /balance-rr/foo HTTP/1.0
49055 +Host: www.example.org
49058 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49059 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
49061 +$t->{REQUEST} = ( <<EOF
49062 +GET /balance-rr/foo HTTP/1.0
49063 +Host: www.example.org
49066 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49067 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
49069 +$t->{REQUEST} = ( <<EOF
49070 +GET /balance-fair/foo HTTP/1.0
49071 +Host: www.example.org
49074 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49075 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
49077 +## backend 2 starting
49078 +ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
49080 +$t->{REQUEST} = ( <<EOF
49081 +GET /balance-rr/foo HTTP/1.0
49082 +Host: www.example.org
49085 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49086 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
49088 +$t->{REQUEST} = ( <<EOF
49089 +GET /balance-rr/foo HTTP/1.0
49090 +Host: www.example.org
49093 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49094 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
49096 +$t->{REQUEST} = ( <<EOF
49097 +GET /balance-hash/foo HTTP/1.0
49098 +Host: www.example.org
49101 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49102 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
49104 +$t->{REQUEST} = ( <<EOF
49105 +GET /balance-hash/foo HTTP/1.0
49106 +Host: www.example.org
49109 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49110 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
49112 +$t->{REQUEST} = ( <<EOF
49113 +GET /balance-hash/bar HTTP/1.0
49114 +Host: www.example.org
49117 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49118 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
49120 +$t->{REQUEST} = ( <<EOF
49121 +GET /balance-hash/bar HTTP/1.0
49122 +Host: www.example.org
49125 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49126 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
49128 +## backend 1 stopping, failover
49129 +ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
49131 +$t->{REQUEST} = ( <<EOF
49132 +GET /balance-hash/foo HTTP/1.0
49133 +Host: www.example.org
49136 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49137 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
49139 +$t->{REQUEST} = ( <<EOF
49140 +GET /balance-hash/bar HTTP/1.0
49141 +Host: www.example.org
49144 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49145 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
49147 +$t->{REQUEST} = ( <<EOF
49148 +GET /balance-rr/foo HTTP/1.0
49149 +Host: www.example.org
49152 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49153 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
49155 +$t->{REQUEST} = ( <<EOF
49156 +GET /balance-fair/foo HTTP/1.0
49157 +Host: www.example.org
49160 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49161 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
49164 +ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
49166 +ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
49168 --- lighttpd-1.4.11/tests/proxy.conf 1970-01-01 03:00:00.000000000 +0300
49169 +++ lighttpd-1.4.12/tests/proxy.conf 2006-07-11 22:07:53.000000000 +0300
49171 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49172 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
49173 +server.tag = "proxy"
49175 +include "default.conf"
49177 +## 127.0.0.1 and 127.0.0.2 are the same host
49179 + "" => (( "host" => "127.0.0.1",
49180 + "port" => 2050 ),
49181 + ( "host" => "127.0.0.2",
49185 +$HTTP["url"] =~ "^/balance-rr/" {
49186 + proxy.balance = "round-robin"
49189 +$HTTP["url"] =~ "^/balance-hash/" {
49190 + proxy.balance = "hash"
49193 +$HTTP["url"] =~ "^/balance-fair/" {
49194 + proxy.balance = "fair"
49197 --- lighttpd-1.4.11/tests/var-include.conf 2005-08-27 17:44:19.000000000 +0300
49198 +++ lighttpd-1.4.12/tests/var-include.conf 2006-07-11 22:07:53.000000000 +0300
49200 debug.log-request-handling = "enable"
49201 debug.log-condition-handling = "enable"
49203 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49204 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
49205 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49206 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
49208 ## bind to port (default: 80)
49211 ## bind to localhost (default: all interfaces)
49212 server.bind = "localhost"
49213 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
49214 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
49215 server.name = "www.example.org"
49216 server.tag = "Apache 1.3.29"
49218 @@ -21,19 +21,19 @@
49219 ######################## MODULE CONFIG ############################
49222 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
49223 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
49225 mimetype.assign = ( ".html" => "text/html" )
49227 url.redirect = ("^" => "/default")
49229 $HTTP["host"] == "www.example.org" {
49230 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49231 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49232 server.name = "www.example.org"
49233 url.redirect = ("^" => "/redirect")
49235 $HTTP["host"] == "test.example.org" {
49236 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49237 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49238 server.name = "test.example.org"