+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/Makefile.in lighttpd-1.4.12/Makefile.in
+--- lighttpd-1.4.11/Makefile.in 2006-03-07 14:21:08.000000000 +0200
++++ lighttpd-1.4.12/Makefile.in 2006-07-11 21:48:16.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -41,7 +41,7 @@
+ $(srcdir)/distribute.sh.in $(srcdir)/lighttpd.spec.in \
+ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
+ compile config.guess config.sub depcomp install-sh ltmain.sh \
+- missing mkinstalldirs
++ missing
+ subdir = .
+ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+@@ -49,7 +49,7 @@
+ $(ACLOCAL_M4)
+ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = config.h
+ CONFIG_CLEAN_FILES = lighttpd.spec distribute.sh
+ SOURCES =
+@@ -126,7 +126,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -169,6 +168,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/NEWS lighttpd-1.4.12/NEWS
--- lighttpd-1.4.11/NEWS 2006-03-09 19:34:33.000000000 +0200
-+++ lighttpd/NEWS 2006-07-11 21:23:42.928033114 +0300
++++ lighttpd-1.4.12/NEWS 2006-07-11 21:23:42.000000000 +0300
@@ -3,6 +3,23 @@
NEWS
====
- 1.4.11 - 2006-03-09
* added ability to specify which ip address spawn-fci listens on
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/configure.in lighttpd-1.4.12/configure.in
--- lighttpd-1.4.11/configure.in 2006-03-04 16:32:38.000000000 +0200
-+++ lighttpd/configure.in 2006-07-11 21:23:42.880030107 +0300
++++ lighttpd-1.4.12/configure.in 2006-07-11 21:23:42.000000000 +0300
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
- if test x"$LUACONFIG" != x; then
- LUA_CFLAGS=`$LUACONFIG --include`
- LUA_LIBS=`$LUACONFIG --libs --extralibs`
-- AC_DEFINE([HAVE_LUA], [1], [liblua])
-- AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
++ # try pkgconfig
++ PKG_CHECK_MODULES(LUA, lua >= 5.1, [
+ AC_DEFINE([HAVE_LUA], [1], [liblua])
+ AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
- else
- AC_CHECK_LIB(lua, lua_open, [
- AC_CHECK_HEADERS([lua.h],[
- fi
-
- if test x"$LUA_LIBS" = x; then
- # try pkgconfig
+- # try pkgconfig
- PKG_CHECK_MODULES(LUA, lua, [
-+ PKG_CHECK_MODULES(LUA, lua >= 5.1, [
- AC_DEFINE([HAVE_LUA], [1], [liblua])
- AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
- ])
+- AC_DEFINE([HAVE_LUA], [1], [liblua])
+- AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
+- ])
- fi
++ ])
AC_SUBST(LUA_CFLAGS)
AC_SUBST(LUA_LIBS)
## output
$ECHO
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/cygwin/Makefile.in lighttpd-1.4.12/cygwin/Makefile.in
+--- lighttpd-1.4.11/cygwin/Makefile.in 2006-03-07 14:20:57.000000000 +0200
++++ lighttpd-1.4.12/cygwin/Makefile.in 2006-07-11 21:48:12.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -43,7 +43,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES = lighttpd.README
+ SOURCES =
+@@ -101,7 +101,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -144,6 +143,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/cygwin/lighttpd.README lighttpd-1.4.12/cygwin/lighttpd.README
+--- lighttpd-1.4.11/cygwin/lighttpd.README 2006-03-07 14:22:19.000000000 +0200
++++ lighttpd-1.4.12/cygwin/lighttpd.README 2006-07-11 21:49:09.000000000 +0300
+@@ -1,114 +1,114 @@
+-lighttpd\r
+-------------------------------------------\r
+-A fast, secure and flexible webserver\r
+-\r
+-Runtime requirements:\r
+- cygwin-1.5.10 or newer\r
+- crypt-1.1 or newer\r
+- libbz2_1-1.0.2 or newer\r
+- libpcre0-4.5 or newer\r
+- openssl-0.9.7d or newer\r
+- zlib-1.2.1 or newer\r
+-\r
+-Build requirements:\r
+- cygwin-1.5.10 or newer\r
+- gcc-3.3.1-3 or newer\r
+- binutils-20030901-1 or newer\r
+- crypt\r
+- openssl-devel\r
+- openssl\r
+- openldap\r
+- openldap-devel\r
+- zlib\r
+- bzip2\r
+-\r
+-Canonical homepage:\r
+- http://jan.kneschke.de/projects/lighttpd/\r
+-\r
+-Canonical download:\r
+- http://jan.kneschke.de/projects/lighttpd/download\r
+-\r
+-------------------------------------\r
+-\r
+-Build instructions:\r
+- unpack lighttpd-1.4.11-<REL>-src.tar.bz2\r
+- if you use setup to install this src package, it will be\r
+- unpacked under /usr/src automatically\r
+- cd /usr/src\r
+- ./lighttpd-1.4.11-<REL>.sh all\r
+-\r
+-This will create:\r
+- /usr/src/lighttpd-1.4.11-<REL>.tar.bz2\r
+- /usr/src/lighttpd-1.4.11-<REL>-src.tar.bz2\r
+-\r
+-Or use './lighttpd-1.4.11-<REL>.sh prep' to get a patched source directory\r
+-\r
+--------------------------------------------\r
+-\r
+-Files included in the binary distribution:\r
+-\r
+- /etc/lighttpd/lighttpd.conf.default\r
+- /usr/lib/cyglightcomp.dll\r
+- /usr/lib/lighttpd/mod_access.dll\r
+- /usr/lib/lighttpd/mod_accesslog.dll\r
+- /usr/lib/lighttpd/mod_auth.dll\r
+- /usr/lib/lighttpd/mod_cgi.dll\r
+- /usr/lib/lighttpd/mod_compress.dll\r
+- /usr/lib/lighttpd/mod_evhost.dll\r
+- /usr/lib/lighttpd/mod_expire.dll\r
+- /usr/lib/lighttpd/mod_fastcgi.dll\r
+- /usr/lib/lighttpd/mod_httptls.dll\r
+- /usr/lib/lighttpd/mod_maps.dll\r
+- /usr/lib/lighttpd/mod_proxy.dll\r
+- /usr/lib/lighttpd/mod_redirect.dll\r
+- /usr/lib/lighttpd/mod_rewrite.dll\r
+- /usr/lib/lighttpd/mod_rrdtool.dll\r
+- /usr/lib/lighttpd/mod_secdownload.dll\r
+- /usr/lib/lighttpd/mod_simple_vhost.dll\r
+- /usr/lib/lighttpd/mod_ssi.dll\r
+- /usr/lib/lighttpd/mod_status.dll\r
+- /usr/lib/lighttpd/mod_usertrack.dll\r
+- /usr/sbin/lighttpd.exe\r
+- /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
+- /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
+- /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
+- /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
+- /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
+- /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
+- /usr/share/doc/lighttpd-1.3.0/compress.txt\r
+- /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
+- /usr/share/doc/lighttpd-1.3.0/COPYING\r
+- /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
+- /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
+- /usr/share/doc/lighttpd-1.3.0/features.txt\r
+- /usr/share/doc/lighttpd-1.3.0/INSTALL\r
+- /usr/share/doc/lighttpd-1.3.0/NEWS\r
+- /usr/share/doc/lighttpd-1.3.0/performance.txt\r
+- /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
+- /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
+- /usr/share/doc/lighttpd-1.3.0/README\r
+- /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
+- /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
+- /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
+- /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
+- /usr/share/doc/lighttpd-1.3.0/security.txt\r
+- /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
+- /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
+- /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
+- /usr/share/doc/lighttpd-1.3.0/state.txt\r
+- /usr/share/man/man1/lighttpd.1.gz\r
+-\r
+-------------------\r
+-\r
+-Port Notes:\r
+-\r
+----------- lighttpd-1.3.1-1 -----------\r
+-\r
+-Updated to 1.3.1\r
+-\r
+----------- lighttpd-1.3.0-1 -----------\r
+-Initial release\r
+-\r
+-Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
+-Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
+-\r
++lighttpd
++------------------------------------------
++A fast, secure and flexible webserver
++
++Runtime requirements:
++ cygwin-1.5.10 or newer
++ crypt-1.1 or newer
++ libbz2_1-1.0.2 or newer
++ libpcre0-4.5 or newer
++ openssl-0.9.7d or newer
++ zlib-1.2.1 or newer
++
++Build requirements:
++ cygwin-1.5.10 or newer
++ gcc-3.3.1-3 or newer
++ binutils-20030901-1 or newer
++ crypt
++ openssl-devel
++ openssl
++ openldap
++ openldap-devel
++ zlib
++ bzip2
++
++Canonical homepage:
++ http://jan.kneschke.de/projects/lighttpd/
++
++Canonical download:
++ http://jan.kneschke.de/projects/lighttpd/download
++
++------------------------------------
++
++Build instructions:
++ unpack lighttpd-1.4.12-<REL>-src.tar.bz2
++ if you use setup to install this src package, it will be
++ unpacked under /usr/src automatically
++ cd /usr/src
++ ./lighttpd-1.4.12-<REL>.sh all
++
++This will create:
++ /usr/src/lighttpd-1.4.12-<REL>.tar.bz2
++ /usr/src/lighttpd-1.4.12-<REL>-src.tar.bz2
++
++Or use './lighttpd-1.4.12-<REL>.sh prep' to get a patched source directory
++
++-------------------------------------------
++
++Files included in the binary distribution:
++
++ /etc/lighttpd/lighttpd.conf.default
++ /usr/lib/cyglightcomp.dll
++ /usr/lib/lighttpd/mod_access.dll
++ /usr/lib/lighttpd/mod_accesslog.dll
++ /usr/lib/lighttpd/mod_auth.dll
++ /usr/lib/lighttpd/mod_cgi.dll
++ /usr/lib/lighttpd/mod_compress.dll
++ /usr/lib/lighttpd/mod_evhost.dll
++ /usr/lib/lighttpd/mod_expire.dll
++ /usr/lib/lighttpd/mod_fastcgi.dll
++ /usr/lib/lighttpd/mod_httptls.dll
++ /usr/lib/lighttpd/mod_maps.dll
++ /usr/lib/lighttpd/mod_proxy.dll
++ /usr/lib/lighttpd/mod_redirect.dll
++ /usr/lib/lighttpd/mod_rewrite.dll
++ /usr/lib/lighttpd/mod_rrdtool.dll
++ /usr/lib/lighttpd/mod_secdownload.dll
++ /usr/lib/lighttpd/mod_simple_vhost.dll
++ /usr/lib/lighttpd/mod_ssi.dll
++ /usr/lib/lighttpd/mod_status.dll
++ /usr/lib/lighttpd/mod_usertrack.dll
++ /usr/sbin/lighttpd.exe
++ /usr/share/doc/Cygwin/lighttpd-1.3.0.README
++ /usr/share/doc/lighttpd-1.3.0/accesslog.txt
++ /usr/share/doc/lighttpd-1.3.0/authentification.txt
++ /usr/share/doc/lighttpd-1.3.0/AUTHORS
++ /usr/share/doc/lighttpd-1.3.0/cgi.txt
++ /usr/share/doc/lighttpd-1.3.0/ChangeLog
++ /usr/share/doc/lighttpd-1.3.0/compress.txt
++ /usr/share/doc/lighttpd-1.3.0/configuration.txt
++ /usr/share/doc/lighttpd-1.3.0/COPYING
++ /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
++ /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
++ /usr/share/doc/lighttpd-1.3.0/features.txt
++ /usr/share/doc/lighttpd-1.3.0/INSTALL
++ /usr/share/doc/lighttpd-1.3.0/NEWS
++ /usr/share/doc/lighttpd-1.3.0/performance.txt
++ /usr/share/doc/lighttpd-1.3.0/plugins.txt
++ /usr/share/doc/lighttpd-1.3.0/proxy.txt
++ /usr/share/doc/lighttpd-1.3.0/README
++ /usr/share/doc/lighttpd-1.3.0/redirect.txt
++ /usr/share/doc/lighttpd-1.3.0/rewrite.txt
++ /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
++ /usr/share/doc/lighttpd-1.3.0/secdownload.txt
++ /usr/share/doc/lighttpd-1.3.0/security.txt
++ /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
++ /usr/share/doc/lighttpd-1.3.0/skeleton.txt
++ /usr/share/doc/lighttpd-1.3.0/ssi.txt
++ /usr/share/doc/lighttpd-1.3.0/state.txt
++ /usr/share/man/man1/lighttpd.1.gz
++
++------------------
++
++Port Notes:
++
++---------- lighttpd-1.3.1-1 -----------
++
++Updated to 1.3.1
++
++---------- lighttpd-1.3.0-1 -----------
++Initial release
++
++Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
++Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
++
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/cygwin/lighttpd.README.in lighttpd-1.4.12/cygwin/lighttpd.README.in
+--- lighttpd-1.4.11/cygwin/lighttpd.README.in 2005-08-11 01:26:59.000000000 +0300
++++ lighttpd-1.4.12/cygwin/lighttpd.README.in 2006-07-11 21:23:40.000000000 +0300
+@@ -1,114 +1,114 @@
+-lighttpd\r
+-------------------------------------------\r
+-A fast, secure and flexible webserver\r
+-\r
+-Runtime requirements:\r
+- cygwin-1.5.10 or newer\r
+- crypt-1.1 or newer\r
+- libbz2_1-1.0.2 or newer\r
+- libpcre0-4.5 or newer\r
+- openssl-0.9.7d or newer\r
+- zlib-1.2.1 or newer\r
+-\r
+-Build requirements:\r
+- cygwin-1.5.10 or newer\r
+- gcc-3.3.1-3 or newer\r
+- binutils-20030901-1 or newer\r
+- crypt\r
+- openssl-devel\r
+- openssl\r
+- openldap\r
+- openldap-devel\r
+- zlib\r
+- bzip2\r
+-\r
+-Canonical homepage:\r
+- http://jan.kneschke.de/projects/lighttpd/\r
+-\r
+-Canonical download:\r
+- http://jan.kneschke.de/projects/lighttpd/download\r
+-\r
+-------------------------------------\r
+-\r
+-Build instructions:\r
+- unpack lighttpd-@VERSION@-<REL>-src.tar.bz2\r
+- if you use setup to install this src package, it will be\r
+- unpacked under /usr/src automatically\r
+- cd /usr/src\r
+- ./lighttpd-@VERSION@-<REL>.sh all\r
+-\r
+-This will create:\r
+- /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2\r
+- /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2\r
+-\r
+-Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory\r
+-\r
+--------------------------------------------\r
+-\r
+-Files included in the binary distribution:\r
+-\r
+- /etc/lighttpd/lighttpd.conf.default\r
+- /usr/lib/cyglightcomp.dll\r
+- /usr/lib/lighttpd/mod_access.dll\r
+- /usr/lib/lighttpd/mod_accesslog.dll\r
+- /usr/lib/lighttpd/mod_auth.dll\r
+- /usr/lib/lighttpd/mod_cgi.dll\r
+- /usr/lib/lighttpd/mod_compress.dll\r
+- /usr/lib/lighttpd/mod_evhost.dll\r
+- /usr/lib/lighttpd/mod_expire.dll\r
+- /usr/lib/lighttpd/mod_fastcgi.dll\r
+- /usr/lib/lighttpd/mod_httptls.dll\r
+- /usr/lib/lighttpd/mod_maps.dll\r
+- /usr/lib/lighttpd/mod_proxy.dll\r
+- /usr/lib/lighttpd/mod_redirect.dll\r
+- /usr/lib/lighttpd/mod_rewrite.dll\r
+- /usr/lib/lighttpd/mod_rrdtool.dll\r
+- /usr/lib/lighttpd/mod_secdownload.dll\r
+- /usr/lib/lighttpd/mod_simple_vhost.dll\r
+- /usr/lib/lighttpd/mod_ssi.dll\r
+- /usr/lib/lighttpd/mod_status.dll\r
+- /usr/lib/lighttpd/mod_usertrack.dll\r
+- /usr/sbin/lighttpd.exe\r
+- /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
+- /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
+- /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
+- /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
+- /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
+- /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
+- /usr/share/doc/lighttpd-1.3.0/compress.txt\r
+- /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
+- /usr/share/doc/lighttpd-1.3.0/COPYING\r
+- /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
+- /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
+- /usr/share/doc/lighttpd-1.3.0/features.txt\r
+- /usr/share/doc/lighttpd-1.3.0/INSTALL\r
+- /usr/share/doc/lighttpd-1.3.0/NEWS\r
+- /usr/share/doc/lighttpd-1.3.0/performance.txt\r
+- /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
+- /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
+- /usr/share/doc/lighttpd-1.3.0/README\r
+- /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
+- /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
+- /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
+- /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
+- /usr/share/doc/lighttpd-1.3.0/security.txt\r
+- /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
+- /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
+- /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
+- /usr/share/doc/lighttpd-1.3.0/state.txt\r
+- /usr/share/man/man1/lighttpd.1.gz\r
+-\r
+-------------------\r
+-\r
+-Port Notes:\r
+-\r
+----------- lighttpd-1.3.1-1 -----------\r
+-\r
+-Updated to 1.3.1\r
+-\r
+----------- lighttpd-1.3.0-1 -----------\r
+-Initial release\r
+-\r
+-Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
+-Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
+-\r
++lighttpd
++------------------------------------------
++A fast, secure and flexible webserver
++
++Runtime requirements:
++ cygwin-1.5.10 or newer
++ crypt-1.1 or newer
++ libbz2_1-1.0.2 or newer
++ libpcre0-4.5 or newer
++ openssl-0.9.7d or newer
++ zlib-1.2.1 or newer
++
++Build requirements:
++ cygwin-1.5.10 or newer
++ gcc-3.3.1-3 or newer
++ binutils-20030901-1 or newer
++ crypt
++ openssl-devel
++ openssl
++ openldap
++ openldap-devel
++ zlib
++ bzip2
++
++Canonical homepage:
++ http://jan.kneschke.de/projects/lighttpd/
++
++Canonical download:
++ http://jan.kneschke.de/projects/lighttpd/download
++
++------------------------------------
++
++Build instructions:
++ unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
++ if you use setup to install this src package, it will be
++ unpacked under /usr/src automatically
++ cd /usr/src
++ ./lighttpd-@VERSION@-<REL>.sh all
++
++This will create:
++ /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
++ /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
++
++Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
++
++-------------------------------------------
++
++Files included in the binary distribution:
++
++ /etc/lighttpd/lighttpd.conf.default
++ /usr/lib/cyglightcomp.dll
++ /usr/lib/lighttpd/mod_access.dll
++ /usr/lib/lighttpd/mod_accesslog.dll
++ /usr/lib/lighttpd/mod_auth.dll
++ /usr/lib/lighttpd/mod_cgi.dll
++ /usr/lib/lighttpd/mod_compress.dll
++ /usr/lib/lighttpd/mod_evhost.dll
++ /usr/lib/lighttpd/mod_expire.dll
++ /usr/lib/lighttpd/mod_fastcgi.dll
++ /usr/lib/lighttpd/mod_httptls.dll
++ /usr/lib/lighttpd/mod_maps.dll
++ /usr/lib/lighttpd/mod_proxy.dll
++ /usr/lib/lighttpd/mod_redirect.dll
++ /usr/lib/lighttpd/mod_rewrite.dll
++ /usr/lib/lighttpd/mod_rrdtool.dll
++ /usr/lib/lighttpd/mod_secdownload.dll
++ /usr/lib/lighttpd/mod_simple_vhost.dll
++ /usr/lib/lighttpd/mod_ssi.dll
++ /usr/lib/lighttpd/mod_status.dll
++ /usr/lib/lighttpd/mod_usertrack.dll
++ /usr/sbin/lighttpd.exe
++ /usr/share/doc/Cygwin/lighttpd-1.3.0.README
++ /usr/share/doc/lighttpd-1.3.0/accesslog.txt
++ /usr/share/doc/lighttpd-1.3.0/authentification.txt
++ /usr/share/doc/lighttpd-1.3.0/AUTHORS
++ /usr/share/doc/lighttpd-1.3.0/cgi.txt
++ /usr/share/doc/lighttpd-1.3.0/ChangeLog
++ /usr/share/doc/lighttpd-1.3.0/compress.txt
++ /usr/share/doc/lighttpd-1.3.0/configuration.txt
++ /usr/share/doc/lighttpd-1.3.0/COPYING
++ /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
++ /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
++ /usr/share/doc/lighttpd-1.3.0/features.txt
++ /usr/share/doc/lighttpd-1.3.0/INSTALL
++ /usr/share/doc/lighttpd-1.3.0/NEWS
++ /usr/share/doc/lighttpd-1.3.0/performance.txt
++ /usr/share/doc/lighttpd-1.3.0/plugins.txt
++ /usr/share/doc/lighttpd-1.3.0/proxy.txt
++ /usr/share/doc/lighttpd-1.3.0/README
++ /usr/share/doc/lighttpd-1.3.0/redirect.txt
++ /usr/share/doc/lighttpd-1.3.0/rewrite.txt
++ /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
++ /usr/share/doc/lighttpd-1.3.0/secdownload.txt
++ /usr/share/doc/lighttpd-1.3.0/security.txt
++ /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
++ /usr/share/doc/lighttpd-1.3.0/skeleton.txt
++ /usr/share/doc/lighttpd-1.3.0/ssi.txt
++ /usr/share/doc/lighttpd-1.3.0/state.txt
++ /usr/share/man/man1/lighttpd.1.gz
++
++------------------
++
++Port Notes:
++
++---------- lighttpd-1.3.1-1 -----------
++
++Updated to 1.3.1
++
++---------- lighttpd-1.3.0-1 -----------
++Initial release
++
++Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
++Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
++
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/Makefile.in lighttpd-1.4.12/doc/Makefile.in
+--- lighttpd-1.4.11/doc/Makefile.in 2006-03-07 14:20:57.000000000 +0200
++++ lighttpd-1.4.12/doc/Makefile.in 2006-07-11 21:48:12.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -43,7 +43,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES =
+ SOURCES =
+@@ -105,7 +105,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -148,6 +147,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/authentication.txt lighttpd-1.4.12/doc/authentication.txt
--- lighttpd-1.4.11/doc/authentication.txt 2006-01-12 20:34:26.000000000 +0200
-+++ lighttpd/doc/authentication.txt 2006-07-11 21:23:42.708019334 +0300
++++ lighttpd-1.4.12/doc/authentication.txt 2006-07-11 21:23:42.000000000 +0300
@@ -7,8 +7,8 @@
----------------
:abstract:
The auth module provides ...
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/compress.txt lighttpd-1.4.12/doc/compress.txt
--- lighttpd-1.4.11/doc/compress.txt 2005-08-11 01:26:16.000000000 +0300
-+++ lighttpd/doc/compress.txt 2006-07-11 21:23:42.680017580 +0300
++++ lighttpd-1.4.12/doc/compress.txt 2006-07-11 21:23:42.000000000 +0300
@@ -22,12 +22,38 @@
===========
Options
=======
-@@ -47,14 +73,27 @@
+@@ -47,15 +73,28 @@
Default: not set, compress the file for every request
compress.filetype
+ This is meant to protect the server against DoSing as compressing large
+ (let's say 1Gbyte) takes a lot of time and would delay the whole operation
+ of the server.
-+
+
+ There is a hard upper limit of 128Mbyte.
+
+ Default: unlimited (== hard-limit of 128MByte)
-
++
Compressing Dynamic Content
===========================
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/configuration.txt lighttpd-1.4.12/doc/configuration.txt
--- lighttpd-1.4.11/doc/configuration.txt 2006-03-09 02:10:40.000000000 +0200
-+++ lighttpd/doc/configuration.txt 2006-07-11 21:23:42.696018582 +0300
++++ lighttpd-1.4.12/doc/configuration.txt 2006-07-11 21:23:42.000000000 +0300
@@ -7,8 +7,8 @@
------------
+debug.log-condition-cache-handling
+ for developers only
+ default: disabled
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/fastcgi.txt lighttpd-1.4.12/doc/fastcgi.txt
--- lighttpd-1.4.11/doc/fastcgi.txt 2006-02-16 17:03:52.000000000 +0200
-+++ lighttpd/doc/fastcgi.txt 2006-07-11 21:23:42.712019584 +0300
++++ lighttpd-1.4.12/doc/fastcgi.txt 2006-07-11 21:23:42.000000000 +0300
@@ -144,8 +144,8 @@
PHP can extract PATH_INFO from it (default: disabled)
:"disable-time": time to wait before a disabled backend is checked
If bin-path is set:
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/lighttpd.conf lighttpd-1.4.12/doc/lighttpd.conf
--- lighttpd-1.4.11/doc/lighttpd.conf 2006-03-04 14:41:12.000000000 +0200
-+++ lighttpd/doc/lighttpd.conf 2006-07-11 21:23:42.736021088 +0300
-@@ -176,6 +176,7 @@
- #debug.log-response-header = "enable"
- #debug.log-request-handling = "enable"
- #debug.log-file-not-found = "enable"
++++ lighttpd-1.4.12/doc/lighttpd.conf 2006-07-11 21:23:42.000000000 +0300
+@@ -172,10 +172,11 @@
+ #dir-listing.activate = "enable"
+
+ ## enable debugging
+-#debug.log-request-header = "enable"
+-#debug.log-response-header = "enable"
+-#debug.log-request-handling = "enable"
+-#debug.log-file-not-found = "enable"
++#debug.log-request-header = "enable"
++#debug.log-response-header = "enable"
++#debug.log-request-handling = "enable"
++#debug.log-file-not-found = "enable"
+#debug.log-condition-handling = "enable"
### only root can use these options
#
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/performance.txt lighttpd-1.4.12/doc/performance.txt
--- lighttpd-1.4.11/doc/performance.txt 2006-02-02 13:01:08.000000000 +0200
-+++ lighttpd/doc/performance.txt 2006-07-11 21:23:42.632014574 +0300
++++ lighttpd-1.4.12/doc/performance.txt 2006-07-11 21:23:42.000000000 +0300
@@ -183,6 +183,8 @@
server.stat-cache-engine = "fam" # either fam, simple or disabled
Platform-Specific Notes
=======================
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/secdownload.txt lighttpd-1.4.12/doc/secdownload.txt
--- lighttpd-1.4.11/doc/secdownload.txt 2005-12-20 15:58:58.000000000 +0200
-+++ lighttpd/doc/secdownload.txt 2006-07-11 21:23:42.640015075 +0300
++++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-11 21:23:42.000000000 +0300
@@ -118,7 +118,7 @@
$secret = "verysecret";
$uri_prefix = "/dl/";
$f = "/secret-file.txt";
# current timestamp
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/lighttpd.spec lighttpd-1.4.12/lighttpd.spec
+--- lighttpd-1.4.11/lighttpd.spec 2006-03-07 14:22:18.000000000 +0200
++++ lighttpd-1.4.12/lighttpd.spec 2006-07-11 21:49:09.000000000 +0300
+@@ -1,6 +1,6 @@
+ Summary: A fast webserver with minimal memory-footprint (lighttpd)
+ Name: lighttpd
+-Version: 1.4.11
++Version: 1.4.12
+ Release: 1
+ Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
+ Packager: Jan Kneschke <jan@kneschke.de>
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/openwrt/Makefile.in lighttpd-1.4.12/openwrt/Makefile.in
+--- lighttpd-1.4.11/openwrt/Makefile.in 2006-03-07 14:20:58.000000000 +0200
++++ lighttpd-1.4.12/openwrt/Makefile.in 2006-07-11 21:48:12.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -43,7 +43,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES = control lighttpd.mk
+ SOURCES =
+@@ -101,7 +101,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -144,6 +143,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/openwrt/control lighttpd-1.4.12/openwrt/control
+--- lighttpd-1.4.11/openwrt/control 2006-03-07 14:22:19.000000000 +0200
++++ lighttpd-1.4.12/openwrt/control 2006-07-11 21:49:10.000000000 +0300
+@@ -1,8 +1,8 @@
+ Package: lighttpd
+-Version: 1.4.11
++Version: 1.4.12
+ Architecture: mipsel
+ Maintainer: Jan Kneschke <jan@kneschke.de>
+-Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.11.tar.gz
++Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.12.tar.gz
+ Section: net
+ Priority: optional
+ Depends:
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/openwrt/lighttpd.mk lighttpd-1.4.12/openwrt/lighttpd.mk
+--- lighttpd-1.4.11/openwrt/lighttpd.mk 2006-03-07 14:22:19.000000000 +0200
++++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-11 21:49:10.000000000 +0300
+@@ -10,7 +10,7 @@
+
+ # For this example we'll use a fairly simple package that compiles easily
+ # and has sources available for download at sourceforge
+-LIGHTTPD=lighttpd-1.4.11
++LIGHTTPD=lighttpd-1.4.12
+ LIGHTTPD_TARGET=.built
+ LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
+ LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/Makefile.am lighttpd-1.4.12/src/Makefile.am
--- lighttpd-1.4.11/src/Makefile.am 2006-03-07 14:20:20.000000000 +0200
-+++ lighttpd/src/Makefile.am 2006-07-11 21:23:40.099855979 +0300
++++ lighttpd-1.4.12/src/Makefile.am 2006-07-11 21:23:40.000000000 +0300
@@ -16,14 +16,19 @@
else
configparser.y: lemon
src = server.c response.c connections.c network.c \
configfile.c configparser.c request.c proc_open.c
-@@ -84,7 +89,7 @@
+@@ -82,9 +87,9 @@
+
+ lib_LTLIBRARIES += mod_webdav.la
mod_webdav_la_SOURCES = mod_webdav.c
- mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
+-mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
++mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
+mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/Makefile.in lighttpd-1.4.12/src/Makefile.in
+--- lighttpd-1.4.11/src/Makefile.in 2006-03-07 14:21:02.000000000 +0200
++++ lighttpd-1.4.12/src/Makefile.in 2006-07-11 21:48:14.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -16,8 +16,6 @@
+
+
+
+-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)
+-
+ srcdir = @srcdir@
+ top_srcdir = @top_srcdir@
+ VPATH = @srcdir@
+@@ -57,7 +55,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES =
+ am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+@@ -84,7 +82,8 @@
+ inet_ntop_cache.c crc32.c connections-glue.c configfile-glue.c \
+ http-header-glue.c network_write.c network_linux_sendfile.c \
+ network_freebsd_sendfile.c network_writev.c \
+- network_solaris_sendfilev.c network_openssl.c splaytree.c
++ network_solaris_sendfilev.c network_openssl.c splaytree.c \
++ http_resp.c http_resp_parser.c
+ am__objects_1 = liblightcomp_la-buffer.lo liblightcomp_la-log.lo \
+ liblightcomp_la-keyvalue.lo liblightcomp_la-chunk.lo \
+ liblightcomp_la-http_chunk.lo liblightcomp_la-stream.lo \
+@@ -111,7 +110,8 @@
+ liblightcomp_la-network_writev.lo \
+ liblightcomp_la-network_solaris_sendfilev.lo \
+ liblightcomp_la-network_openssl.lo \
+- liblightcomp_la-splaytree.lo
++ liblightcomp_la-splaytree.lo liblightcomp_la-http_resp.lo \
++ liblightcomp_la-http_resp_parser.lo
+ @NO_RDYNAMIC_TRUE@am_liblightcomp_la_OBJECTS = $(am__objects_1)
+ liblightcomp_la_OBJECTS = $(am_liblightcomp_la_OBJECTS)
+ @NO_RDYNAMIC_TRUE@am_liblightcomp_la_rpath = -rpath $(libdir)
+@@ -193,6 +193,9 @@
+ mod_simple_vhost_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ am_mod_simple_vhost_la_OBJECTS = mod_simple_vhost.lo
+ mod_simple_vhost_la_OBJECTS = $(am_mod_simple_vhost_la_OBJECTS)
++mod_sql_vhost_core_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
++am_mod_sql_vhost_core_la_OBJECTS = mod_sql_vhost_core.lo
++mod_sql_vhost_core_la_OBJECTS = $(am_mod_sql_vhost_core_la_OBJECTS)
+ mod_ssi_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
+ am_mod_ssi_la_OBJECTS = mod_ssi_exprparser.lo mod_ssi_expr.lo \
+ mod_ssi.lo
+@@ -236,7 +239,8 @@
+ connections-glue.c configfile-glue.c http-header-glue.c \
+ network_write.c network_linux_sendfile.c \
+ network_freebsd_sendfile.c network_writev.c \
+- network_solaris_sendfilev.c network_openssl.c splaytree.c
++ network_solaris_sendfilev.c network_openssl.c splaytree.c \
++ http_resp.c http_resp_parser.c
+ am__objects_2 = buffer.$(OBJEXT) log.$(OBJEXT) keyvalue.$(OBJEXT) \
+ chunk.$(OBJEXT) http_chunk.$(OBJEXT) stream.$(OBJEXT) \
+ fdevent.$(OBJEXT) stat_cache.$(OBJEXT) plugin.$(OBJEXT) \
+@@ -254,7 +258,8 @@
+ network_linux_sendfile.$(OBJEXT) \
+ network_freebsd_sendfile.$(OBJEXT) network_writev.$(OBJEXT) \
+ network_solaris_sendfilev.$(OBJEXT) network_openssl.$(OBJEXT) \
+- splaytree.$(OBJEXT)
++ splaytree.$(OBJEXT) http_resp.$(OBJEXT) \
++ http_resp_parser.$(OBJEXT)
+ @NO_RDYNAMIC_FALSE@am__objects_3 = $(am__objects_2)
+ am__objects_4 = server.$(OBJEXT) response.$(OBJEXT) \
+ connections.$(OBJEXT) network.$(OBJEXT) configfile.$(OBJEXT) \
+@@ -282,8 +287,8 @@
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+ CCLD = $(CC)
+-LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
++LINK = $(LIBTOOL) --tag=CC --mode=link "$(CCLD)" $(AM_CFLAGS) \
++ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+ SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) \
+ $(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) \
+ $(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) \
+@@ -296,11 +301,12 @@
+ $(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)
++ $(mod_sql_vhost_core_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)
+ DIST_SOURCES = $(am__liblightcomp_la_SOURCES_DIST) \
+ $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) \
+ $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) \
+@@ -313,7 +319,8 @@
+ $(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_simple_vhost_la_SOURCES) \
++ $(mod_sql_vhost_core_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) \
+@@ -375,7 +382,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -418,6 +424,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+@@ -479,7 +486,7 @@
+ network_write.c network_linux_sendfile.c \
+ network_freebsd_sendfile.c network_writev.c \
+ network_solaris_sendfilev.c network_openssl.c \
+- splaytree.c
++ splaytree.c http_resp.c http_resp_parser.c
+
+ src = server.c response.c connections.c network.c configfile.c \
+ configparser.c request.c proc_open.c $(am__append_2)
+@@ -491,10 +498,11 @@
+ #mod_httptls_la_LIBADD = $(common_libadd)
+ lib_LTLIBRARIES = $(am__append_1) mod_flv_streaming.la mod_evasive.la \
+ mod_webdav.la mod_cml.la mod_trigger_b4_dl.la \
+- mod_mysql_vhost.la mod_cgi.la mod_scgi.la mod_staticfile.la \
+- mod_dirlisting.la mod_indexfile.la mod_setenv.la mod_alias.la \
+- mod_userdir.la mod_rrdtool.la mod_usertrack.la mod_proxy.la \
+- mod_ssi.la mod_secdownload.la mod_expire.la mod_evhost.la \
++ mod_mysql_vhost.la mod_sql_vhost_core.la mod_cgi.la \
++ mod_scgi.la mod_staticfile.la mod_dirlisting.la \
++ mod_indexfile.la mod_setenv.la mod_alias.la mod_userdir.la \
++ mod_rrdtool.la mod_usertrack.la mod_proxy.la mod_ssi.la \
++ mod_secdownload.la mod_expire.la mod_evhost.la \
+ mod_simple_vhost.la mod_fastcgi.la mod_access.la \
+ mod_compress.la mod_auth.la mod_rewrite.la mod_redirect.la \
+ mod_status.la mod_accesslog.la
+@@ -511,9 +519,9 @@
+ mod_evasive_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+ mod_evasive_la_LIBADD = $(common_libadd)
+ mod_webdav_la_SOURCES = mod_webdav.c
+-mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
++mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
+ mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+-mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
++mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
+ mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
+ mod_cml_la_CFLAGS = $(AM_CFLAGS) $(LUA_CFLAGS)
+ mod_cml_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+@@ -525,6 +533,9 @@
+ mod_mysql_vhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+ mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
+ mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
++mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
++mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
++mod_sql_vhost_core_la_LIBADD = $(common_libadd)
+ mod_cgi_la_SOURCES = mod_cgi.c
+ mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+ mod_cgi_la_LIBADD = $(common_libadd)
+@@ -608,7 +619,7 @@
+ mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
+ configparser.h mod_ssi_exprparser.h \
+ sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
+- splaytree.h proc_open.h
++ splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h
+
+ lighttpd_SOURCES = $(src)
+ lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS)
+@@ -739,6 +750,8 @@
+ $(LINK) -rpath $(libdir) $(mod_setenv_la_LDFLAGS) $(mod_setenv_la_OBJECTS) $(mod_setenv_la_LIBADD) $(LIBS)
+ mod_simple_vhost.la: $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(mod_simple_vhost_la_LDFLAGS) $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_LIBADD) $(LIBS)
++mod_sql_vhost_core.la: $(mod_sql_vhost_core_la_OBJECTS) $(mod_sql_vhost_core_la_DEPENDENCIES)
++ $(LINK) -rpath $(libdir) $(mod_sql_vhost_core_la_LDFLAGS) $(mod_sql_vhost_core_la_OBJECTS) $(mod_sql_vhost_core_la_LIBADD) $(LIBS)
+ mod_ssi.la: $(mod_ssi_la_OBJECTS) $(mod_ssi_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(mod_ssi_la_LDFLAGS) $(mod_ssi_la_OBJECTS) $(mod_ssi_la_LIBADD) $(LIBS)
+ mod_staticfile.la: $(mod_staticfile_la_OBJECTS) $(mod_staticfile_la_DEPENDENCIES)
+@@ -863,6 +876,8 @@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_auth.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_auth_digest.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_chunk.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_resp.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_resp_parser.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_ntop_cache.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joblist.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyvalue.Po@am__quote@
+@@ -890,6 +905,8 @@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_solaris_devpoll.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http-header-glue.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_chunk.Plo@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_resp.Plo@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_resp_parser.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-inet_ntop_cache.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-joblist.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-keyvalue.Plo@am__quote@
+@@ -932,6 +949,7 @@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_secure_download.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_setenv.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_simple_vhost.Plo@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_sql_vhost_core.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi_expr.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi_exprparser.Plo@am__quote@
+@@ -1247,6 +1265,20 @@
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ @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
+
++liblightcomp_la-http_resp.lo: http_resp.c
++@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; \
++@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
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='http_resp.c' object='liblightcomp_la-http_resp.lo' libtool=yes @AMDEPBACKSLASH@
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
++@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
++
++liblightcomp_la-http_resp_parser.lo: http_resp_parser.c
++@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; \
++@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
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='http_resp_parser.c' object='liblightcomp_la-http_resp_parser.lo' libtool=yes @AMDEPBACKSLASH@
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
++@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
++
+ mod_cml_la-mod_cml.lo: mod_cml.c
+ @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; \
+ @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
+@@ -1506,14 +1538,19 @@
+ @CROSS_COMPILING_TRUE@mod_ssi_exprparser.c mod_ssi_exprparser.h:
+ @CROSS_COMPILING_FALSE@configparser.y: lemon
+ @CROSS_COMPILING_FALSE@mod_ssi_exprparser.y: lemon
++@CROSS_COMPILING_FALSE@http_resp_parser.y: lemon
+
+ @CROSS_COMPILING_FALSE@configparser.c configparser.h: configparser.y
+ @CROSS_COMPILING_FALSE@ rm -f configparser.h
+-@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
++@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
++
++@CROSS_COMPILING_FALSE@http_resp_parser.c http_resp_parser.h: http_resp_parser.y
++@CROSS_COMPILING_FALSE@ rm -f http_resp_parser.h
++@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
+
+ @CROSS_COMPILING_FALSE@mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y
+ @CROSS_COMPILING_FALSE@ rm -f mod_ssi_exprparser.h
+-@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
++@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
+
+ configfile.c: configparser.h
+ mod_ssi_expr.c: mod_ssi_exprparser.h
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/array.c lighttpd-1.4.12/src/array.c
--- lighttpd-1.4.11/src/array.c 2005-11-18 13:58:32.000000000 +0200
-+++ lighttpd/src/array.c 2006-07-11 21:23:39.943846207 +0300
-@@ -165,7 +165,7 @@
++++ lighttpd-1.4.12/src/array.c 2006-07-11 21:23:39.000000000 +0300
+@@ -11,12 +11,12 @@
+
+ array *array_init(void) {
+ array *a;
+-
++
+ a = calloc(1, sizeof(*a));
+ assert(a);
+-
++
+ a->next_power_of_2 = 1;
+-
++
+ return a;
+ }
+
+@@ -43,29 +43,29 @@
+ void array_free(array *a) {
+ size_t i;
+ if (!a) return;
+-
++
+ if (!a->is_weakref) {
+ for (i = 0; i < a->size; i++) {
+ if (a->data[i]) a->data[i]->free(a->data[i]);
+ }
+ }
+-
++
+ if (a->data) free(a->data);
+ if (a->sorted) free(a->sorted);
+-
++
+ free(a);
+ }
+
+ void array_reset(array *a) {
+ size_t i;
+ if (!a) return;
+-
++
+ if (!a->is_weakref) {
+ for (i = 0; i < a->used; i++) {
+ a->data[i]->reset(a->data[i]);
+ }
+ }
+-
++
+ a->used = 0;
+ }
+
+@@ -84,20 +84,20 @@
+ static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
+ int ndx = -1;
+ int i, pos = 0;
+-
++
+ if (key == NULL) return -1;
+-
++
+ /* try to find the string */
+ for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
+ int cmp;
+-
++
+ if (pos < 0) {
+ pos += i;
+ } else if (pos >= (int)a->used) {
+ pos -= i;
+ } else {
+ cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
+-
++
+ if (cmp == 0) {
+ /* found */
+ ndx = a->sorted[pos];
+@@ -110,46 +110,46 @@
+ }
+ if (i == 0) break;
+ }
+-
++
+ if (rndx) *rndx = pos;
+-
++
+ return ndx;
+ }
+
+ data_unset *array_get_element(array *a, const char *key) {
+ int ndx;
+-
++
+ if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
+ /* found, leave here */
+-
++
+ return a->data[ndx];
+- }
+-
++ }
++
+ return NULL;
+ }
+
+ data_unset *array_get_unused_element(array *a, data_type_t t) {
+ data_unset *ds = NULL;
+-
++
+ UNUSED(t);
+
+ if (a->size == 0) return NULL;
+-
++
+ if (a->used == a->size) return NULL;
+
+ if (a->data[a->used]) {
+ ds = a->data[a->used];
+-
++
+ a->data[a->used] = NULL;
+ }
+-
++
+ return ds;
+ }
+
+ /* replace or insert data, return the old one with the same key */
+ data_unset *array_replace(array *a, data_unset *du) {
+ int ndx;
+-
++
+ if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
+ array_insert_unique(a, du);
+ return NULL;
+@@ -164,13 +164,13 @@
+ int ndx = -1;
int pos = 0;
size_t j;
-
+-
- /* generate unique index if neccesary */
++
+ /* generate unique index if necessary */
if (str->key->used == 0 || str->is_index_key) {
buffer_copy_long(str->key, a->unique_ndx++);
str->is_index_key = 1;
-@@ -215,7 +215,7 @@
+ }
+-
++
+ /* try to find the string */
+ if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
+ /* found, leave here */
+@@ -181,14 +181,14 @@
+ }
+ return 0;
+ }
+-
++
+ /* insert */
+-
++
+ if (a->used+1 > INT_MAX) {
+ /* we can't handle more then INT_MAX entries: see array_get_index() */
+ return -1;
+ }
+-
++
+ if (a->size == 0) {
+ a->size = 16;
+ a->data = malloc(sizeof(*a->data) * a->size);
+@@ -204,27 +204,27 @@
+ assert(a->sorted);
+ for (j = a->used; j < a->size; j++) a->data[j] = NULL;
+ }
+-
++
+ ndx = (int) a->used;
+-
++
+ a->data[a->used++] = str;
+-
++
+ if (pos != ndx &&
+- ((pos < 0) ||
++ ((pos < 0) ||
+ buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
pos++;
- }
-
+- }
+-
- /* move everything on step to the right */
++ }
++
+ /* move everything one step to the right */
if (pos != ndx) {
memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
}
+-
++
+ /* insert */
+ a->sorted[pos] = ndx;
+-
++
+ if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
+-
++
+ return 0;
+ }
+
+@@ -254,7 +254,7 @@
+ size_t i;
+ size_t maxlen;
+ int oneline = 1;
+-
++
+ if (a->used > 5) {
+ oneline = 0;
+ }
+@@ -314,7 +314,7 @@
+ }
+ array_print_indent(depth);
+ fprintf(stderr, ")");
+-
++
+ return 0;
+ }
+
+@@ -323,47 +323,47 @@
+ array *a;
+ data_string *ds;
+ data_count *dc;
+-
++
+ UNUSED(argc);
+ UNUSED(argv);
+
+ a = array_init();
+-
++
+ ds = data_string_init();
+ buffer_copy_string(ds->key, "abc");
+ buffer_copy_string(ds->value, "alfrag");
+-
++
+ array_insert_unique(a, (data_unset *)ds);
+-
++
+ ds = data_string_init();
+ buffer_copy_string(ds->key, "abc");
+ buffer_copy_string(ds->value, "hameplman");
+-
++
+ array_insert_unique(a, (data_unset *)ds);
+-
++
+ ds = data_string_init();
+ buffer_copy_string(ds->key, "123");
+ buffer_copy_string(ds->value, "alfrag");
+-
++
+ array_insert_unique(a, (data_unset *)ds);
+-
++
+ dc = data_count_init();
+ buffer_copy_string(dc->key, "def");
+-
++
+ array_insert_unique(a, (data_unset *)dc);
+-
++
+ dc = data_count_init();
+ buffer_copy_string(dc->key, "def");
+-
++
+ array_insert_unique(a, (data_unset *)dc);
+-
++
+ array_print(a, 0);
+-
++
+ array_free(a);
+-
++
+ fprintf(stderr, "%d\n",
+ buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
+-
++
+ return 0;
+ }
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/array.h lighttpd-1.4.12/src/array.h
--- lighttpd-1.4.11/src/array.h 2005-09-23 21:24:18.000000000 +0300
-+++ lighttpd/src/array.h 2006-07-11 21:23:39.963847460 +0300
++++ lighttpd-1.4.12/src/array.h 2006-07-11 21:23:39.000000000 +0300
@@ -16,7 +16,7 @@
#define DATA_UNSET \
data_type_t type; \
struct data_unset *(*copy)(const struct data_unset *src); \
void (* free)(struct data_unset *p); \
void (* reset)(struct data_unset *p); \
+@@ -29,21 +29,21 @@
+
+ typedef struct {
+ data_unset **data;
+-
++
+ size_t *sorted;
+-
++
+ size_t used;
+ size_t size;
+-
++
+ size_t unique_ndx;
+-
++
+ size_t next_power_of_2;
+ int is_weakref; /* data is weakref, don't bother the data */
+ } array;
+
+ typedef struct {
+ DATA_UNSET;
+-
++
+ int count;
+ } data_count;
+
+@@ -51,7 +51,7 @@
+
+ typedef struct {
+ DATA_UNSET;
+-
++
+ buffer *value;
+ } data_string;
+
+@@ -60,7 +60,7 @@
+
+ typedef struct {
+ DATA_UNSET;
+-
++
+ array *value;
+ } data_array;
+
+@@ -74,7 +74,7 @@
+ COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP
+ } comp_key_t;
+
+-/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
++/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
+ * for print: comp_key op string
+ * for compare: comp cond string/regex
+ */
+@@ -82,15 +82,15 @@
+ typedef struct _data_config data_config;
+ struct _data_config {
+ DATA_UNSET;
+-
++
+ array *value;
+-
++
+ buffer *comp_key;
+ comp_key_t comp;
+-
++
+ config_cond_t cond;
+ buffer *op;
+-
++
+ int context_ndx; /* more or less like an id */
+ array *childs;
+ /* nested */
+@@ -98,7 +98,7 @@
+ /* for chaining only */
+ data_config *prev;
+ data_config *next;
+-
++
+ buffer *string;
+ #ifdef HAVE_PCRE_H
+ pcre *regex;
+@@ -110,7 +110,7 @@
+
+ typedef struct {
+ DATA_UNSET;
+-
++
+ int value;
+ } data_integer;
+
+@@ -120,13 +120,13 @@
+ DATA_UNSET;
+
+ buffer *host;
+-
++
+ unsigned short port;
+
+ time_t disable_ts;
+ int is_disabled;
+ size_t balance;
+-
++
+ int usage; /* fair-balancing needs the no. of connections active on this host */
+ int last_used_ndx; /* round robin */
+ } data_fastcgi;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/base.h lighttpd-1.4.12/src/base.h
--- lighttpd-1.4.11/src/base.h 2006-01-11 16:51:04.000000000 +0200
-+++ lighttpd/src/base.h 2006-07-11 21:23:39.947846458 +0300
++++ lighttpd-1.4.12/src/base.h 2006-07-11 21:23:39.000000000 +0300
@@ -2,7 +2,6 @@
#define _BASE_H_
#include <sys/stat.h>
#ifdef HAVE_CONFIG_H
-@@ -26,7 +25,6 @@
+@@ -26,10 +25,9 @@
#include "sys-socket.h"
#include "splaytree.h"
-
#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
# define USE_OPENSSL
- # include <openssl/ssl.h>
+-# include <openssl/ssl.h>
++# include <openssl/ssl.h>
+ #endif
+
+ #ifdef HAVE_FAM_H
@@ -40,10 +38,6 @@
# define O_BINARY 0
#endif
#endif
-@@ -171,7 +166,7 @@
+@@ -80,24 +75,24 @@
+
+ #include "settings.h"
+
+-typedef enum { T_CONFIG_UNSET,
+- T_CONFIG_STRING,
+- T_CONFIG_SHORT,
+- T_CONFIG_BOOLEAN,
+- T_CONFIG_ARRAY,
+- T_CONFIG_LOCAL,
++typedef enum { T_CONFIG_UNSET,
++ T_CONFIG_STRING,
++ T_CONFIG_SHORT,
++ T_CONFIG_BOOLEAN,
++ T_CONFIG_ARRAY,
++ T_CONFIG_LOCAL,
+ T_CONFIG_DEPRECATED
+ } config_values_type_t;
+
+-typedef enum { T_CONFIG_SCOPE_UNSET,
+- T_CONFIG_SCOPE_SERVER,
++typedef enum { T_CONFIG_SCOPE_UNSET,
++ T_CONFIG_SCOPE_SERVER,
+ T_CONFIG_SCOPE_CONNECTION
+ } config_scope_type_t;
typedef struct {
- off_t content_length;
-- int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */
-+ int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
-
+ const char *key;
+ void *destination;
+-
++
+ config_values_type_t type;
+ config_scope_type_t scope;
+ } config_values_t;
+@@ -142,40 +137,40 @@
+ /* the request-line */
+ buffer *request;
+ buffer *uri;
+-
++
+ buffer *orig_uri;
+-
++
+ http_method_t http_method;
+ http_version_t http_version;
+-
++
+ buffer *request_line;
+-
++
+ /* strings to the header */
+ buffer *http_host; /* not alloced */
+ const char *http_range;
+ const char *http_content_type;
+ const char *http_if_modified_since;
+ const char *http_if_none_match;
+-
++
array *headers;
-
-@@ -215,7 +210,7 @@
+-
++
+ /* CONTENT */
+ size_t content_length; /* returned by strtoul() */
+-
++
+ /* internal representation */
+ int accept_encoding;
+-
++
+ /* internal */
+ buffer *pathinfo;
+ } request;
+
+ typedef struct {
+ off_t content_length;
+- int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */
+-
++ int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
++
+ array *headers;
+-
+- enum {
++
++ enum {
+ HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
+ } transfer_encoding;
+ } response;
+@@ -191,21 +186,21 @@
+ typedef struct {
+ buffer *path;
+ buffer *basedir; /* path = "(basedir)(.*)" */
+-
++
+ buffer *doc_root; /* path = doc_root + rel_path */
+ buffer *rel_path;
+-
++
+ buffer *etag;
+ } physical;
+
+ typedef struct {
+ buffer *name;
+ buffer *etag;
+-
++
+ struct stat st;
+-
++
+ time_t stat_ts;
+-
++
+ #ifdef HAVE_FAM_H
+ int dir_version;
+ int dir_ndx;
+@@ -215,8 +210,8 @@
} stat_cache_entry;
typedef struct {
- splay_tree *files; /* the nodes of the tree are stat_cache_entry's */
+-
+ splay_tree *files; /* the nodes of the tree are stat_cache_entries */
-
++
buffer *dir_name; /* for building the dirname from the filename */
#ifdef HAVE_FAM_H
-@@ -252,6 +247,7 @@
+ splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */
+@@ -228,7 +223,7 @@
+
+ typedef struct {
+ array *mimetypes;
+-
++
+ /* virtual-servers */
+ buffer *document_root;
+ buffer *server_name;
+@@ -236,7 +231,7 @@
+ buffer *server_tag;
+ buffer *dirlist_encoding;
+ buffer *errorfile_prefix;
+-
++
+ unsigned short max_keep_alive_requests;
+ unsigned short max_keep_alive_idle;
+ unsigned short max_read_idle;
+@@ -244,16 +239,17 @@
+ unsigned short use_xattr;
+ unsigned short follow_symlink;
+ unsigned short range_requests;
+-
++
+ /* debug */
+-
++
+ unsigned short log_file_not_found;
+ unsigned short log_request_header;
unsigned short log_request_handling;
unsigned short log_response_header;
unsigned short log_condition_handling;
+-
+-
+ unsigned short log_condition_cache_handling;
-
-
++
++
/* server wide */
-@@ -272,13 +268,13 @@
+ buffer *ssl_pemfile;
+ buffer *ssl_ca_file;
+@@ -268,22 +264,22 @@
+ /* configside */
+ unsigned short global_kbytes_per_second; /* */
+
+- off_t global_bytes_per_second_cnt;
++ off_t global_bytes_per_second_cnt;
/* server-wide traffic-shaper
- *
+- *
++ *
* each context has the counter which is inited once
- * a second by the global_kbytes_per_second config-var
+ * per second by the global_kbytes_per_second config-var
- * we somehow have to loose our "we are writable" signal
+ * we somehow have to lose our "we are writable" signal
* on the way.
- *
+- *
++ *
*/
-@@ -341,7 +337,7 @@
+ off_t *global_bytes_per_second_cnt_ptr; /* */
+-
++
+ #ifdef USE_OPENSSL
+ SSL_CTX *ssl_ctx;
+ #endif
+@@ -291,18 +287,18 @@
+
+ /* the order of the items should be the same as they are processed
+ * read before write as we use this later */
+-typedef enum {
+- CON_STATE_CONNECT,
+- CON_STATE_REQUEST_START,
+- CON_STATE_READ,
+- CON_STATE_REQUEST_END,
+- CON_STATE_READ_POST,
+- CON_STATE_HANDLE_REQUEST,
+- CON_STATE_RESPONSE_START,
+- CON_STATE_WRITE,
+- CON_STATE_RESPONSE_END,
+- CON_STATE_ERROR,
+- CON_STATE_CLOSE
++typedef enum {
++ CON_STATE_CONNECT,
++ CON_STATE_REQUEST_START,
++ CON_STATE_READ,
++ CON_STATE_REQUEST_END,
++ CON_STATE_READ_POST,
++ CON_STATE_HANDLE_REQUEST,
++ CON_STATE_RESPONSE_START,
++ CON_STATE_WRITE,
++ CON_STATE_RESPONSE_END,
++ CON_STATE_ERROR,
++ CON_STATE_CLOSE
+ } connection_state_t;
+
+ typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
+@@ -315,88 +311,88 @@
+
+ typedef struct {
+ connection_state_t state;
+-
++
+ /* timestamps */
+ time_t read_idle_ts;
+ time_t close_timeout_ts;
+ time_t write_request_ts;
+-
++
+ time_t connection_start;
+ time_t request_start;
+-
++
+ struct timeval start_tv;
+-
++
+ size_t request_count; /* number of requests handled in this connection */
+ size_t loops_per_request; /* to catch endless loops in a single request
+- *
++ *
+ * used by mod_rewrite, mod_fastcgi, ... and others
+ * this is self-protection
+ */
+-
++
+ int fd; /* the FD for this connection */
+ int fde_ndx; /* index for the fdevent-handler */
+ int ndx; /* reverse mapping to server->connection[ndx] */
+-
++
+ /* fd states */
int is_readable;
int is_writable;
-
+-
- int keep_alive; /* only request.c can enable it, all other just disable */
+-
++
+ int keep_alive; /* only request.c can enable it, all others just disable */
-
++
int file_started;
int file_finished;
-@@ -439,6 +435,15 @@
+-
++
+ chunkqueue *write_queue; /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
+ chunkqueue *read_queue; /* a small queue for low-level read ( HTTP request ) [ mem ] */
+ chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/
+-
++
+ int traffic_limit_reached;
+-
++
+ off_t bytes_written; /* used by mod_accesslog, mod_rrd */
+ off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */
+ off_t bytes_read; /* used by mod_accesslog, mod_rrd */
+ off_t bytes_header;
+-
++
+ int http_status;
+-
++
+ sock_addr dst_addr;
+ buffer *dst_addr_buf;
+
+ /* request */
+ buffer *parse_request;
+ unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */
+-
++
+ request request;
+ request_uri uri;
+- physical physical;
++ physical physical;
+ response response;
+-
++
+ size_t header_len;
+-
++
+ buffer *authed_user;
+ array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
+-
++
+ /* response */
+ int got_response;
+-
++
+ int in_joblist;
+-
++
+ connection_type mode;
+-
++
+ void **plugin_ctx; /* plugin connection specific config */
+-
++
+ specific_config conf; /* global connection specific config */
+ cond_cache_t *cond_cache;
+-
++
+ buffer *server_name;
+-
++
+ /* error-handler */
+ buffer *error_handler;
+ int error_handler_saved_status;
+ int in_error_handler;
+-
++
+ void *srv_socket; /* reference to the server-socket (typecast to server_socket) */
+-
++
+ #ifdef USE_OPENSSL
+ SSL *ssl;
+ #endif
+@@ -439,39 +435,48 @@
size_t size;
} buffer_plugin;
typedef struct {
unsigned short port;
buffer *bindhost;
-@@ -591,15 +596,17 @@
-
+-
++
+ buffer *errorlog_file;
+ unsigned short errorlog_use_syslog;
+-
++
+ unsigned short dont_daemonize;
+ buffer *changeroot;
+ buffer *username;
+ buffer *groupname;
+-
++
+ buffer *pid_file;
+-
++
+ buffer *event_handler;
+-
++
+ buffer *modules_dir;
+ buffer *network_backend;
+ array *modules;
+ array *upload_tempdirs;
+-
++
+ unsigned short max_worker;
+ unsigned short max_fds;
+ unsigned short max_conns;
+ unsigned short max_request_size;
+-
++
+ unsigned short log_request_header_on_error;
+ unsigned short log_state_handling;
+-
+- enum { STAT_CACHE_ENGINE_UNSET,
+- STAT_CACHE_ENGINE_NONE,
+- STAT_CACHE_ENGINE_SIMPLE,
+- STAT_CACHE_ENGINE_FAM
++
++ enum { STAT_CACHE_ENGINE_UNSET,
++ STAT_CACHE_ENGINE_NONE,
++ STAT_CACHE_ENGINE_SIMPLE,
++ STAT_CACHE_ENGINE_FAM
+ } stat_cache_engine;
+ unsigned short enable_cores;
+ } server_config;
+@@ -480,14 +485,14 @@
+ sock_addr addr;
+ int fd;
+ int fde_ndx;
+-
++
+ buffer *ssl_pemfile;
+ buffer *ssl_ca_file;
+ unsigned short use_ipv6;
+ unsigned short is_ssl;
+-
++
+ buffer *srv_token;
+-
++
+ #ifdef USE_OPENSSL
+ SSL_CTX *ssl_ctx;
+ #endif
+@@ -495,37 +500,37 @@
+
+ typedef struct {
+ server_socket **ptr;
+-
++
+ size_t size;
+ size_t used;
+ } server_socket_array;
+
+ typedef struct server {
+ server_socket_array srv_sockets;
+-
++
+ /* the errorlog */
+ int errorlog_fd;
+ enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
+ buffer *errorlog_buf;
+-
++
+ fdevents *ev, *ev_ins;
+-
++
+ buffer_plugin plugins;
+ void *plugin_slots;
+-
++
+ /* counters */
+ int con_opened;
+ int con_read;
+ int con_written;
+ int con_closed;
+-
++
+ int ssl_is_init;
+-
++
+ int max_fds; /* max possible fds */
+ int cur_fds; /* currently used fds */
+ int want_fds; /* waiting fds */
+ int sockets_disabled;
+-
++
+ size_t max_conns;
+
+ /* buffers */
+@@ -533,13 +538,13 @@
+ buffer *response_header;
+ buffer *response_range;
+ buffer *tmp_buf;
+-
++
+ buffer *tmp_chunk_len;
+-
++
+ buffer *empty_string; /* is necessary for cond_match */
+
+ buffer *cond_check_buf;
+-
++
+ /* caches */
+ #ifdef HAVE_IPV6
+ inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
+@@ -547,31 +552,31 @@
+ mtime_cache_type mtime_cache[FILE_CACHE_MAX];
+
+ array *split_vals;
+-
++
+ /* Timestamps */
+ time_t cur_ts;
+ time_t last_generated_date_ts;
+ time_t last_generated_debug_ts;
+ time_t startup_ts;
+-
++
+ buffer *ts_debug_str;
+ buffer *ts_date_str;
+-
++
+ /* config-file */
+ array *config;
+ array *config_touched;
+-
++
+ array *config_context;
+ specific_config **config_storage;
+-
++
+ server_config srvconf;
+-
++
+ int config_deprecated;
+-
++
+ connections *conns;
+ connections *joblist;
+ connections *fdwaitqueue;
+-
++
+ stat_cache *stat_cache;
+
+ /**
+@@ -588,18 +593,20 @@
+ * fastcgi.backend.<key>.disconnects = ...
+ */
+ array *status;
+-
++
fdevent_handler_t event_handler;
- int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
} server;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/buffer.c lighttpd-1.4.12/src/buffer.c
--- lighttpd-1.4.11/src/buffer.c 2006-01-13 00:00:45.000000000 +0200
-+++ lighttpd/src/buffer.c 2006-07-11 21:23:40.087855227 +0300
-@@ -63,7 +63,7 @@
++++ lighttpd-1.4.12/src/buffer.c 2006-07-11 21:23:40.000000000 +0300
+@@ -12,20 +12,20 @@
+
+
+ /**
+- * init the buffer
+- *
++ * init the buffer
++ *
+ */
+
+ buffer* buffer_init(void) {
+ buffer *b;
+-
++
+ b = malloc(sizeof(*b));
+ assert(b);
+-
++
+ b->ptr = NULL;
+ b->size = 0;
+ b->used = 0;
+-
++
+ return b;
+ }
+
+@@ -36,8 +36,8 @@
+ }
+
+ /**
+- * free the buffer
+- *
++ * free the buffer
++ *
+ */
+
+ void buffer_free(buffer *b) {
+@@ -49,39 +49,39 @@
+
+ void buffer_reset(buffer *b) {
+ if (!b) return;
+-
++
+ /* limit don't reuse buffer larger than ... bytes */
+ if (b->size > BUFFER_MAX_REUSE_SIZE) {
+ free(b->ptr);
+ b->ptr = NULL;
+ b->size = 0;
+ }
+-
++
+ b->used = 0;
+ }
+
/**
- *
+- *
- * allocate (if neccessary) enough space for 'size' bytes and
++ *
+ * allocate (if necessary) enough space for 'size' bytes and
* set the 'used' counter to 0
- *
+- *
++ *
*/
-@@ -79,7 +79,7 @@
-
+
+ #define BUFFER_PIECE_SIZE 64
+
+ int buffer_prepare_copy(buffer *b, size_t size) {
+ if (!b) return -1;
+-
+- if ((0 == b->size) ||
++
++ if ((0 == b->size) ||
+ (size > b->size)) {
+ if (b->size) free(b->ptr);
+-
++
b->size = size;
-
+-
- /* always allocate a multiply of BUFFER_PIECE_SIZE */
++
+ /* always allocate a multiple of BUFFER_PIECE_SIZE */
b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
-
+-
++
b->ptr = malloc(b->size);
-@@ -91,7 +91,7 @@
+ assert(b->ptr);
+ }
+@@ -90,30 +90,30 @@
+ }
/**
- *
+- *
- * increase the internal buffer (if neccessary) to append another 'size' byte
++ *
+ * increase the internal buffer (if necessary) to append another 'size' byte
* ->used isn't changed
- *
+- *
++ *
*/
-@@ -102,7 +102,7 @@
+
+ int buffer_prepare_append(buffer *b, size_t size) {
+ if (!b) return -1;
+-
++
if (0 == b->size) {
b->size = size;
-
+-
- /* always allocate a multiply of BUFFER_PIECE_SIZE */
++
+ /* always allocate a multiple of BUFFER_PIECE_SIZE */
b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
-
+-
++
b->ptr = malloc(b->size);
-@@ -111,7 +111,7 @@
+ b->used = 0;
+ assert(b->ptr);
} else if (b->used + size > b->size) {
b->size += size;
-
+-
- /* always allocate a multiply of BUFFER_PIECE_SIZE */
++
+ /* always allocate a multiple of BUFFER_PIECE_SIZE */
b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
-
+-
++
b->ptr = realloc(b->ptr, b->size);
-@@ -203,7 +203,7 @@
+ assert(b->ptr);
+ }
+@@ -122,7 +122,7 @@
+
+ int buffer_copy_string(buffer *b, const char *s) {
+ size_t s_len;
+-
++
+ if (!s || !b) return -1;
+
+ s_len = strlen(s) + 1;
+@@ -136,26 +136,26 @@
+
+ int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
+ if (!s || !b) return -1;
+-#if 0
+- /* removed optimization as we have to keep the empty string
++#if 0
++ /* removed optimization as we have to keep the empty string
+ * in some cases for the config handling
+- *
++ *
+ * url.access-deny = ( "" )
+ */
+ if (s_len == 0) return 0;
+-#endif
++#endif
+ buffer_prepare_copy(b, s_len + 1);
+-
++
+ memcpy(b->ptr, s, s_len);
+ b->ptr[s_len] = '\0';
+ b->used = s_len + 1;
+-
++
+ return 0;
+ }
+
+ int buffer_copy_string_buffer(buffer *b, const buffer *src) {
+ if (!src) return -1;
+-
++
+ if (src->used == 0) {
+ b->used = 0;
+ return 0;
+@@ -201,10 +201,10 @@
+
+ /**
* append a string to the end of the buffer
- *
- * the resulting buffer is terminated with a '\0'
+- *
+- * the resulting buffer is terminated with a '\0'
- * s is treated as a un-terminated string (a \0 is handled a normal character)
+- *
++ *
++ * the resulting buffer is terminated with a '\0'
+ * s is treated as an un-terminated string (a \0 is handled as a normal character)
- *
++ *
* @param b a buffer
* @param s the string
-@@ -402,6 +402,75 @@
+ * @param s_len size of the string (without the terminating \0)
+@@ -228,7 +228,7 @@
+ int buffer_append_string_buffer(buffer *b, const buffer *src) {
+ if (!src) return -1;
+ if (src->used == 0) return 0;
+-
++
+ return buffer_append_string_len(b, src->ptr, src->used - 1);
+ }
+
+@@ -245,9 +245,9 @@
+
+ int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
+ if (!s || !b) return -1;
+-
++
+ b->used = 0;
+-
++
+ return buffer_append_memory(b, s, s_len);
+ }
+
+@@ -402,46 +402,115 @@
/**
+- * init the buffer
+- *
+ * init the ptr buffer
+ *
+ */
+}
+
+/**
- * init the buffer
- *
++ * init the buffer
++ *
+ */
+
+ buffer_array* buffer_array_init(void) {
+ buffer_array *b;
+-
++
+ b = malloc(sizeof(*b));
+-
++
+ assert(b);
+ b->ptr = NULL;
+ b->size = 0;
+ b->used = 0;
+-
++
+ return b;
+ }
+
+ void buffer_array_reset(buffer_array *b) {
+ size_t i;
+-
++
+ if (!b) return;
+-
++
+ /* if they are too large, reduce them */
+ for (i = 0; i < b->used; i++) {
+ buffer_reset(b->ptr[i]);
+ }
+-
++
+ b->used = 0;
+ }
+
+
+ /**
+- * free the buffer_array
+- *
++ * free the buffer_array
++ *
*/
-@@ -507,7 +576,7 @@
+
+ void buffer_array_free(buffer_array *b) {
+ size_t i;
+ if (!b) return;
+-
++
+ for (i = 0; i < b->size; i++) {
+ if (b->ptr[i]) buffer_free(b->ptr[i]);
+ }
+@@ -451,7 +520,7 @@
+
+ buffer *buffer_array_append_get_buffer(buffer_array *b) {
+ size_t i;
+-
++
+ if (b->size == 0) {
+ b->size = 16;
+ b->ptr = malloc(sizeof(*b->ptr) * b->size);
+@@ -467,13 +536,13 @@
+ b->ptr[i] = NULL;
+ }
+ }
+-
++
+ if (b->ptr[b->used] == NULL) {
+ b->ptr[b->used] = buffer_init();
+ }
+-
++
+ b->ptr[b->used]->used = 0;
+-
++
+ return b->ptr[b->used++];
+ }
+
+@@ -482,23 +551,23 @@
+ size_t i;
+ if (len == 0) return NULL;
+ if (needle == NULL) return NULL;
+-
++
+ if (b->used < len) return NULL;
+-
++
+ for(i = 0; i < b->used - len; i++) {
+ if (0 == memcmp(b->ptr + i, needle, len)) {
+ return b->ptr + i;
+ }
+ }
+-
++
+ return NULL;
+ }
+
+ buffer *buffer_init_string(const char *str) {
+ buffer *b = buffer_init();
+-
++
+ buffer_copy_string(b, str);
+-
++
+ return b;
+ }
+
+@@ -507,8 +576,8 @@
}
/**
- * check if two buffer contain the same data
+- *
+ * check if two buffers contain the same data
- *
++ *
* HISTORY: this function was pretty much optimized, but didn't handled
* alignment properly.
-@@ -531,7 +600,7 @@
+ */
+@@ -522,100 +591,100 @@
+
+ int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
+ buffer b;
+-
++
+ b.ptr = (char *)s;
+ b.used = b_len + 1;
+-
++
+ return buffer_is_equal(a, &b);
+ }
/* simple-assumption:
- *
+- *
- * most parts are equal and doing a case conversion needs time
+- *
++ *
+ * most parts are equal and doing a case conversion takes time
- *
++ *
*/
int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
-@@ -592,7 +661,7 @@
+ size_t ndx = 0, max_ndx;
+ size_t *al, *bl;
+ size_t mask = sizeof(*al) - 1;
+-
++
+ al = (size_t *)a;
+ bl = (size_t *)b;
+-
+- /* is the alignment correct ? */
++
++ /* is the alignment correct? */
+ if ( ((size_t)al & mask) == 0 &&
+ ((size_t)bl & mask) == 0 ) {
+-
++
+ max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
+-
++
+ for (; ndx < max_ndx; ndx += sizeof(*al)) {
+ if (*al != *bl) break;
+ al++; bl++;
+-
++
+ }
+-
++
+ }
+-
++
+ a = (char *)al;
+ b = (char *)bl;
+-
++
+ max_ndx = ((a_len < b_len) ? a_len : b_len);
+-
++
+ for (; ndx < max_ndx; ndx++) {
+ char a1 = *a++, b1 = *b++;
+-
++
+ if (a1 != b1) {
+ if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z'))
+ a1 |= 32;
+ else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z'))
+ b1 |= 32;
+ if ((a1 - b1) != 0) return (a1 - b1);
+-
++
+ }
+ }
+-
++
+ return 0;
+ }
+
+
+ /**
+ * check if the rightmost bytes of the string are equal.
+- *
+- *
++ *
++ *
+ */
+
+ int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
+ /* no, len -> equal */
+ if (len == 0) return 1;
+-
++
+ /* len > 0, but empty buffers -> not equal */
if (b1->used == 0 || b2->used == 0) return 0;
-
+-
++
/* buffers too small -> not equal */
- if (b1->used - 1 < len || b1->used - 1 < len) return 0;
+-
+- if (0 == strncmp(b1->ptr + b1->used - 1 - len,
+ if (b1->used - 1 < len || b2->used - 1 < len) return 0;
-
- if (0 == strncmp(b1->ptr + b1->used - 1 - len,
++
++ if (0 == strncmp(b1->ptr + b1->used - 1 - len,
b2->ptr + b2->used - 1 - len, len)) {
+ return 1;
+ }
+-
++
+ return 0;
+ }
+
+ int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
+ size_t i;
+-
++
+ /* BO protection */
+ if (in_len * 2 < in_len) return -1;
+-
++
+ buffer_prepare_copy(b, in_len * 2 + 1);
+-
++
+ for (i = 0; i < in_len; i++) {
+ b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
+ b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
+ }
+ b->ptr[b->used++] = '\0';
+-
++
+ return 0;
+ }
+
+@@ -624,7 +693,7 @@
+ 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
+ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, /* 20 - 2F space " # $ % & ' + , / */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
+@@ -646,7 +715,7 @@
+ 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
+ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, /* 20 - 2F space " # $ % & ' + , / */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
+@@ -668,7 +737,7 @@
+ 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
+@@ -690,7 +759,7 @@
+ 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
+@@ -712,12 +781,12 @@
+ 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
+@@ -734,13 +803,13 @@
+ unsigned char *ds, *d;
+ size_t d_len, ndx;
+ const char *map = NULL;
+-
++
+ if (!s || !b) return -1;
+-
++
+ if (b->ptr[b->used - 1] != '\0') {
+ SEGFAULT();
+ }
+-
++
+ if (s_len == 0) return 0;
+
+ switch(encoding) {
@@ -760,12 +829,12 @@
map = encoded_chars_hex;
break;
}
assert(map != NULL);
-
+-
- /* count to-be-encoded-characters */
++
+ /* count to-be-encoded characters */
for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
if (map[*ds]) {
switch(encoding) {
-@@ -829,7 +898,7 @@
+@@ -787,9 +856,9 @@
+ d_len ++;
+ }
+ }
+-
++
+ buffer_prepare_append(b, d_len);
+-
++
+ for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
+ if (map[*ds]) {
+ switch(encoding) {
+@@ -820,16 +889,16 @@
+ }
+ }
+
+- /* terminate buffer and calculate new length */
++ /* terminate buffer and calculate new length */
+ b->ptr[b->used + d_len - 1] = '\0';
+-
++
+ b->used += d_len;
+
+ return 0;
}
* replaces non-printable characters with '_'
*/
-@@ -855,7 +924,7 @@
+@@ -854,10 +923,10 @@
+ low = hex2int(*(src + 2));
if (low != 0xFF) {
high = (high << 4) | low;
-
+-
- /* map control-characters out */
++
+ /* map out control characters */
if (high < 32 || high == 127) high = '_';
-
+-
++
*dst = high;
+ src += 2;
+ }
@@ -891,7 +960,7 @@
* /abc/./xyz gets /abc/xyz
* /abc//xyz gets /abc/xyz
* the operation is performed in-place.
*/
-@@ -993,6 +1062,31 @@
+@@ -979,7 +1048,7 @@
+
+ int light_isxdigit(int c) {
+ if (light_isdigit(c)) return 1;
+-
++
+ c |= 32;
+ return (c >= 'a' && c <= 'f');
+ }
+@@ -993,31 +1062,56 @@
return light_isdigit(c) || light_isalpha(c);
}
+
int buffer_to_lower(buffer *b) {
char *c;
-
+-
++
+ if (b->used == 0) return 0;
+-
++
+ for (c = b->ptr; *c; c++) {
+ if (*c >= 'A' && *c <= 'Z') {
+ *c |= 32;
+ }
+ }
+-
++
+ return 0;
+ }
+
+
+ int buffer_to_upper(buffer *b) {
+ char *c;
+-
++
+ if (b->used == 0) return 0;
+-
++
+ for (c = b->ptr; *c; c++) {
+ if (*c >= 'a' && *c <= 'z') {
+ *c &= ~32;
+ }
+ }
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/buffer.h lighttpd-1.4.12/src/buffer.h
--- lighttpd-1.4.11/src/buffer.h 2006-01-13 00:00:45.000000000 +0200
-+++ lighttpd/src/buffer.h 2006-07-11 21:23:40.095855728 +0300
-@@ -17,6 +17,16 @@
++++ lighttpd-1.4.12/src/buffer.h 2006-07-11 21:23:40.000000000 +0300
+@@ -12,27 +12,44 @@
+
+ typedef struct {
+ char *ptr;
+-
++
+ size_t used;
size_t size;
} buffer;
+
typedef struct {
buffer **ptr;
-
-@@ -27,12 +37,19 @@
- typedef struct {
- char *ptr;
-
+-
++
+ size_t used;
+ size_t size;
+ } buffer_array;
+
+ typedef struct {
+ char *ptr;
+-
- size_t offset; /* input-pointer */
-+ size_t offset; /* input pointer */
-
+-
- size_t used; /* output-pointer */
++
++ size_t offset; /* input pointer */
++
+ size_t used; /* output pointer */
size_t size;
} read_buffer;
buffer_array* buffer_array_init(void);
void buffer_array_free(buffer_array *b);
void buffer_array_reset(buffer_array *b);
+@@ -43,7 +60,7 @@
+ buffer* buffer_init_string(const char *str);
+ void buffer_free(buffer *b);
+ void buffer_reset(buffer *b);
+-
++
+ int buffer_prepare_copy(buffer *b, size_t size);
+ int buffer_prepare_append(buffer *b, size_t size);
+
@@ -85,9 +102,9 @@
typedef enum {
#define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0)
#define UNUSED(x) ( (void)(x) )
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/chunk.c lighttpd-1.4.12/src/chunk.c
--- lighttpd-1.4.11/src/chunk.c 2005-11-18 15:18:19.000000000 +0200
-+++ lighttpd/src/chunk.c 2006-07-11 21:23:39.995849464 +0300
-@@ -6,11 +6,9 @@
++++ lighttpd-1.4.12/src/chunk.c 2006-07-11 21:23:39.000000000 +0300
+@@ -1,16 +1,14 @@
+ /**
+ * the network chunk-API
+- *
+- *
++ *
++ *
+ */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
-@@ -18,6 +16,9 @@
+@@ -18,36 +16,39 @@
#include "chunk.h"
+
chunkqueue *chunkqueue_init(void) {
chunkqueue *cq;
-
-@@ -99,7 +100,7 @@
+-
++
+ cq = calloc(1, sizeof(*cq));
+-
++
+ cq->first = NULL;
+ cq->last = NULL;
+-
++
+ cq->unused = NULL;
+-
++
+ return cq;
+ }
+
+ static chunk *chunk_init(void) {
+ chunk *c;
+-
++
+ c = calloc(1, sizeof(*c));
+-
++
+ c->mem = buffer_init();
+ c->file.name = buffer_init();
+ c->file.fd = -1;
+ c->file.mmap.start = MAP_FAILED;
+ c->next = NULL;
+-
++
+ return c;
+ }
+
+ static void chunk_free(chunk *c) {
+ if (!c) return;
+-
++
+ buffer_free(c->mem);
+ buffer_free(c->file.name);
+
+@@ -56,13 +57,13 @@
+
+ static void chunk_reset(chunk *c) {
+ if (!c) return;
+-
++
+ buffer_reset(c->mem);
+
+ if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
+ unlink(c->file.name->ptr);
+ }
+-
++
+ buffer_reset(c->file.name);
+
+ if (c->file.fd != -1) {
+@@ -78,28 +79,28 @@
+
+ void chunkqueue_free(chunkqueue *cq) {
+ chunk *c, *pc;
+-
++
+ if (!cq) return;
+-
++
+ for (c = cq->first; c; ) {
+ pc = c;
+ c = c->next;
+ chunk_free(pc);
+ }
+-
++
+ for (c = cq->unused; c; ) {
+ pc = c;
+ c = c->next;
+ chunk_free(pc);
+ }
+-
++
+ free(cq);
+ }
+
static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) {
chunk *c;
-
+-
- /* check if we have a unused chunk */
++
+ /* check if we have an unused chunk */
if (!cq->unused) {
c = chunk_init();
} else {
-@@ -278,7 +279,7 @@
+@@ -109,18 +110,18 @@
+ c->next = NULL;
+ cq->unused_chunks--;
+ }
+-
++
+ return c;
+ }
+
+ static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
+ c->next = cq->first;
+ cq->first = c;
+-
++
+ if (cq->last == NULL) {
+ cq->last = c;
+ }
+-
++
+ return 0;
+ }
+
+@@ -129,19 +130,19 @@
+ cq->last->next = c;
+ }
+ cq->last = c;
+-
++
+ if (cq->first == NULL) {
+ cq->first = c;
+ }
+-
++
+ return 0;
+ }
+
+ void chunkqueue_reset(chunkqueue *cq) {
+ chunk *c;
+ /* move everything to the unused queue */
+-
+- /* mark all read written */
++
++ /* mark all read written */
+ for (c = cq->first; c; c = c->next) {
+ switch(c->type) {
+ case MEM_CHUNK:
+@@ -150,7 +151,7 @@
+ case FILE_CHUNK:
+ c->offset = c->file.length;
+ break;
+- default:
++ default:
+ break;
+ }
+ }
+@@ -162,93 +163,93 @@
+
+ int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
+ chunk *c;
+-
++
+ if (len == 0) return 0;
+-
++
+ c = chunkqueue_get_unused_chunk(cq);
+-
++
+ c->type = FILE_CHUNK;
+-
++
+ buffer_copy_string_buffer(c->file.name, fn);
+ c->file.start = offset;
+ c->file.length = len;
+ c->offset = 0;
+-
++
+ chunkqueue_append_chunk(cq, c);
+-
++
+ return 0;
+ }
+
+ int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
+ chunk *c;
+-
++
+ if (mem->used == 0) return 0;
+-
++
+ c = chunkqueue_get_unused_chunk(cq);
+ c->type = MEM_CHUNK;
+ c->offset = 0;
+ buffer_copy_string_buffer(c->mem, mem);
+-
++
+ chunkqueue_append_chunk(cq, c);
+-
++
+ return 0;
+ }
+
+ int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
+ chunk *c;
+-
++
+ if (mem->used == 0) return 0;
+-
++
+ c = chunkqueue_get_unused_chunk(cq);
+ c->type = MEM_CHUNK;
+ c->offset = 0;
+ buffer_copy_string_buffer(c->mem, mem);
+-
++
+ chunkqueue_prepend_chunk(cq, c);
+-
++
+ return 0;
+ }
+
+ int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
+ chunk *c;
+-
++
+ if (len == 0) return 0;
+-
++
+ c = chunkqueue_get_unused_chunk(cq);
+ c->type = MEM_CHUNK;
+ c->offset = 0;
+ buffer_copy_string_len(c->mem, mem, len - 1);
+-
++
+ chunkqueue_append_chunk(cq, c);
+-
++
+ return 0;
+ }
+
+ buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
+ chunk *c;
+-
++
+ c = chunkqueue_get_unused_chunk(cq);
+-
++
+ c->type = MEM_CHUNK;
+ c->offset = 0;
+ buffer_reset(c->mem);
+-
++
+ chunkqueue_prepend_chunk(cq, c);
+-
++
+ return c->mem;
+ }
+
+ buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
+ chunk *c;
+-
++
+ c = chunkqueue_get_unused_chunk(cq);
+-
++
+ c->type = MEM_CHUNK;
+ c->offset = 0;
+ buffer_reset(c->mem);
+-
++
+ chunkqueue_append_chunk(cq, c);
+-
++
+ return c->mem;
+ }
+
+@@ -263,7 +264,7 @@
+ chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
+ chunk *c;
+ buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
+-
++
+ c = chunkqueue_get_unused_chunk(cq);
+
+ c->type = FILE_CHUNK;
+@@ -273,12 +274,12 @@
+ size_t i;
+
+ /* we have several tempdirs, only if all of them fail we jump out */
+-
++
+ for (i = 0; i < cq->tempdirs->used; i++) {
data_string *ds = (data_string *)cq->tempdirs->data[i];
buffer_copy_string_buffer(template, ds->value);
BUFFER_APPEND_STRING_CONST(template, "lighttpd-upload-XXXXXX");
if (-1 != (c->file.fd = mkstemp(template->ptr))) {
+@@ -300,7 +301,7 @@
+ chunkqueue_append_chunk(cq, c);
+
+ buffer_free(template);
+-
++
+ return c;
+ }
+
+@@ -308,7 +309,7 @@
+ off_t chunkqueue_length(chunkqueue *cq) {
+ off_t len = 0;
+ chunk *c;
+-
++
+ for (c = cq->first; c; c = c->next) {
+ switch (c->type) {
+ case MEM_CHUNK:
+@@ -321,14 +322,14 @@
+ break;
+ }
+ }
+-
++
+ return len;
+ }
+
+ off_t chunkqueue_written(chunkqueue *cq) {
+ off_t len = 0;
+ chunk *c;
+-
++
+ for (c = cq->first; c; c = c->next) {
+ switch (c->type) {
+ case MEM_CHUNK:
+@@ -339,7 +340,7 @@
+ break;
+ }
+ }
+-
++
+ return len;
+ }
+
+@@ -358,9 +359,9 @@
+ if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
+ break;
+ case FILE_CHUNK:
+- if (c->offset == c->file.length) is_finished = 1;
++ if (c->offset == c->file.length) is_finished = 1;
+ break;
+- default:
++ default:
+ break;
+ }
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/chunk.h lighttpd-1.4.12/src/chunk.h
--- lighttpd-1.4.11/src/chunk.h 2005-11-01 09:32:21.000000000 +0200
-+++ lighttpd/src/chunk.h 2006-07-11 21:23:40.015850717 +0300
-@@ -19,10 +19,10 @@
- struct {
++++ lighttpd-1.4.12/src/chunk.h 2006-07-11 21:23:40.000000000 +0300
+@@ -6,7 +6,7 @@
+
+ typedef struct chunk {
+ enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
+-
++
+ buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
+
+ struct {
+@@ -16,28 +16,28 @@
+ off_t length; /* octets to send from the starting offset */
+
+ int fd;
+- struct {
++ struct {
char *start; /* the start pointer of the mmap'ed area */
size_t length; /* size of the mmap'ed area */
- off_t offset; /* start is <n> octet away from the start of the file */
- int is_temp; /* file is temporary and will be deleted if on cleanup */
+ int is_temp; /* file is temporary and will be deleted on cleanup */
} file;
-
- off_t offset; /* octets sent from this chunk
+-
+- off_t offset; /* octets sent from this chunk
+- the size of the chunk is either
++
++ off_t offset; /* octets sent from this chunk
++ the size of the chunk is either
+ - mem-chunk: mem->used - 1
+ - file-chunk: file.length
+ */
+-
++
+ struct chunk *next;
+ } chunk;
+
+ typedef struct {
+ chunk *first;
+ chunk *last;
+-
++
+ chunk *unused;
+ size_t unused_chunks;
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configfile-glue.c lighttpd-1.4.12/src/configfile-glue.c
--- lighttpd-1.4.11/src/configfile-glue.c 2006-03-03 20:14:56.000000000 +0200
-+++ lighttpd/src/configfile-glue.c 2006-07-11 21:23:39.879842199 +0300
++++ lighttpd-1.4.12/src/configfile-glue.c 2006-07-11 21:23:39.000000000 +0300
@@ -1,4 +1,5 @@
#include <string.h>
+#include <ctype.h>
#include "base.h"
#include "buffer.h"
-@@ -71,6 +72,10 @@
- data_string *ds = (data_string *)du;
-
- buffer_copy_string_buffer(cv[i].destination, ds->value);
-+ } else if (du->type == TYPE_INTEGER) {
-+ data_integer *di = (data_integer *)du;
+@@ -11,10 +12,10 @@
+ * are the external interface of lighttpd. The functions
+ * are used by the server itself and the plugins.
+ *
+- * The main-goal is to have a small library in the end
+- * which is linked against both and which will define
++ * The main-goal is to have a small library in the end
++ * which is linked against both and which will define
+ * the interface itself in the end.
+- *
++ *
+ */
+
+
+@@ -24,56 +25,60 @@
+ int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
+ size_t i;
+ data_unset *du;
+-
+
-+ buffer_copy_long(cv[i].destination, di->value);
- } else {
- log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
-
-@@ -88,6 +93,11 @@
- case TYPE_STRING: {
- data_string *ds = (data_string *)du;
-
-+ if (buffer_isdigit(ds->value)) {
-+ *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
-+ break;
-+ }
+ for (i = 0; cv[i].key; i++) {
+-
+
- log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
-
- return -1;
-@@ -230,7 +240,7 @@
- break;
- }
- } else {
-- l = NULL;
+ if (NULL == (du = array_get_element(ca, cv[i].key))) {
+ /* no found */
+-
++
+ continue;
+ }
+-
++
+ switch (cv[i].type) {
+ case T_CONFIG_ARRAY:
+ if (du->type == TYPE_ARRAY) {
+ size_t j;
+ data_array *da = (data_array *)du;
+-
++
+ for (j = 0; j < da->value->used; j++) {
+ if (da->value->data[j]->type == TYPE_STRING) {
+ data_string *ds = data_string_init();
+-
++
+ buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
+ if (!da->is_index_key) {
+ /* the id's were generated automaticly, as we copy now we might have to renumber them
+- * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
++ * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
+ * before mod_fastcgi and friends */
+ buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
+ }
+-
++
+ array_insert_unique(cv[i].destination, (data_unset *)ds);
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sssd",
+- "the key of and array can only be a string or a integer, variable:",
+- cv[i].key, "type:", da->value->data[j]->type);
+-
++ log_error_write(srv, __FILE__, __LINE__, "sssd",
++ "the key of and array can only be a string or a integer, variable:",
++ cv[i].key, "type:", da->value->data[j]->type);
++
+ return -1;
+ }
+ }
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
+-
++
+ return -1;
+ }
+ break;
+ case T_CONFIG_STRING:
+ if (du->type == TYPE_STRING) {
+ data_string *ds = (data_string *)du;
+-
++
+ buffer_copy_string_buffer(cv[i].destination, ds->value);
++ } else if (du->type == TYPE_INTEGER) {
++ data_integer *di = (data_integer *)du;
++
++ buffer_copy_long(cv[i].destination, di->value);
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
+-
++
+ return -1;
+ }
+ break;
+@@ -81,15 +86,20 @@
+ switch(du->type) {
+ case TYPE_INTEGER: {
+ data_integer *di = (data_integer *)du;
+-
++
+ *((unsigned short *)(cv[i].destination)) = di->value;
+ break;
+ }
+ case TYPE_STRING: {
+ data_string *ds = (data_string *)du;
+-
++
++ if (buffer_isdigit(ds->value)) {
++ *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
++ break;
++ }
++
+ log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
+-
++
+ return -1;
+ }
+ default:
+@@ -100,19 +110,19 @@
+ case T_CONFIG_BOOLEAN:
+ if (du->type == TYPE_STRING) {
+ data_string *ds = (data_string *)du;
+-
++
+ if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
+ *((unsigned short *)(cv[i].destination)) = 1;
+ } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
+ *((unsigned short *)(cv[i].destination)) = 0;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
+-
++
+ return -1;
+ }
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
+-
++
+ return -1;
+ }
+ break;
+@@ -121,9 +131,9 @@
+ break;
+ case T_CONFIG_DEPRECATED:
+ log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
+-
++
+ srv->config_deprecated = 1;
+-
++
+ break;
+ }
+ }
+@@ -133,25 +143,25 @@
+ int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
+ size_t i;
+ data_unset *du;
+-
++
+ for (i = 0; cv[i].key; i++) {
+ data_string *touched;
+-
++
+ if (NULL == (du = array_get_element(ca, cv[i].key))) {
+ /* no found */
+-
++
+ continue;
+ }
+-
++
+ /* touched */
+ touched = data_string_init();
+-
++
+ buffer_copy_string(touched->value, "");
+ buffer_copy_string_buffer(touched->key, du->key);
+-
++
+ array_insert_unique(srv->config_touched, (data_unset *)touched);
+ }
+-
++
+ return config_insert_values_internal(srv, ca, cv);
+ }
+
+@@ -191,25 +201,25 @@
+ }
+
+ /* pass the rules */
+-
++
+ switch (dc->comp) {
+ case COMP_HTTP_HOST: {
+ char *ck_colon = NULL, *val_colon = NULL;
+-
++
+ if (!buffer_is_empty(con->uri.authority)) {
+-
+- /*
++
++ /*
+ * append server-port to the HTTP_POST if necessary
+ */
+-
++
+ l = con->uri.authority;
+-
++
+ switch(dc->cond) {
+ case CONFIG_COND_NE:
+ case CONFIG_COND_EQ:
+ ck_colon = strchr(dc->string->ptr, ':');
+ val_colon = strchr(l->ptr, ':');
+-
++
+ if (ck_colon == val_colon) {
+ /* nothing to do with it */
+ break;
+@@ -230,21 +240,21 @@
+ break;
+ }
+ } else {
+- l = NULL;
+ l = srv->empty_string;
}
break;
}
-@@ -254,6 +264,13 @@
+ case COMP_HTTP_REMOTEIP: {
+ char *nm_slash;
+- /* handle remoteip limitations
+- *
++ /* handle remoteip limitations
++ *
+ * "10.0.0.1" is provided for all comparisions
+- *
++ *
+ * only for == and != we support
+- *
++ *
+ * "10.0.0.1/24"
+ */
+-
++
+ if ((dc->cond == CONFIG_COND_EQ ||
+ dc->cond == CONFIG_COND_NE) &&
+ (con->dst_addr.plain.sa_family == AF_INET) &&
+@@ -253,41 +263,48 @@
+ long nm;
char *err;
struct in_addr val_inp;
-
+-
++
+ if (con->conf.log_condition_handling) {
+ l = srv->empty_string;
+
+
if (*(nm_slash+1) == '\0') {
log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
-
-@@ -270,7 +287,7 @@
-
+-
++
+ return COND_RESULT_FALSE;
+ }
+-
++
+ nm_bits = strtol(nm_slash + 1, &err, 10);
+-
++
+ if (*err) {
+ log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
+-
++
+ return COND_RESULT_FALSE;
+ }
+-
++
/* take IP convert to the native */
buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
-#ifdef __WIN32
+#ifdef _WIN32
if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
-
+-
++
+ return COND_RESULT_FALSE;
+ }
+
+ #else
+ if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
+-
++
+ return COND_RESULT_FALSE;
+ }
+ #endif
+-
++
+ /* build netmask */
+ nm = htonl(~((1 << (32 - nm_bits)) - 1));
+-
++
+ if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
+ return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
+ } else {
+@@ -308,7 +325,7 @@
+
+ case COMP_HTTP_REFERER: {
+ data_string *ds;
+-
++
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
+ l = ds->value;
+ } else {
+@@ -338,7 +355,7 @@
+ default:
+ return COND_RESULT_FALSE;
+ }
+-
++
+ if (NULL == l) {
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key,
+@@ -346,10 +363,10 @@
+ }
+ return COND_RESULT_FALSE;
+ }
+-
++
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
+- "(", l, ") compare to ", dc->string);
++ "(", l, ") compare to", dc->string);
+ }
+ switch(dc->cond) {
+ case CONFIG_COND_NE:
+@@ -365,13 +382,13 @@
+ case CONFIG_COND_MATCH: {
+ cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
+ int n;
+-
++
+ #ifndef elementsof
+ #define elementsof(x) (sizeof(x) / sizeof(x[0]))
+ #endif
+ n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
+ cache->matches, elementsof(cache->matches));
+-
++
+ cache->patterncount = n;
+ if (n > 0) {
+ cache->comp_value = l;
+@@ -387,7 +404,7 @@
+ /* no way */
+ break;
+ }
+-
++
+ return COND_RESULT_FALSE;
+ }
+
@@ -395,6 +412,9 @@
cond_cache_t *caches = con->cond_cache;
+#endif
+}
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configfile.c lighttpd-1.4.12/src/configfile.c
--- lighttpd-1.4.11/src/configfile.c 2006-02-15 14:26:42.000000000 +0200
-+++ lighttpd/src/configfile.c 2006-07-11 21:23:39.987848963 +0300
++++ lighttpd-1.4.12/src/configfile.c 2006-07-11 21:23:39.000000000 +0300
@@ -2,7 +2,6 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
-@@ -13,14 +12,17 @@
+@@ -13,21 +12,24 @@
#include "log.h"
#include "stream.h"
#include "plugin.h"
static int config_insert(server *srv) {
size_t i;
-@@ -80,6 +82,7 @@
+ int ret = 0;
+ buffer *stat_cache_string;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "server.bind", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 */
+ { "server.errorlog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 */
+ { "server.errorfile-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 */
+@@ -38,7 +40,7 @@
+ { "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
+ { "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
+ { "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */
+-
++
+ { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */
+ { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */
+ { "server.max-request-size", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
+@@ -49,7 +51,7 @@
+ { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
+ { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */
+ { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */
+-
++
+ { "server.max-read-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 20 */
+ { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */
+ { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */
+@@ -60,19 +62,19 @@
+ { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
+ { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */
+ { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 29 */
+-
++
+ { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */
+-
++
+ { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 31 */
+ { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 32 */
+ { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 33 */
+ { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 34 */
+-
++
+ { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 35 */
+ { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
+ { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */
+ { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 38 */
+-
++
+ { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 39 */
+ { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
+ { "server.stat-cache-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
+@@ -80,7 +82,8 @@
{ "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 43 */
{ "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 44 */
{ "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
+-
+ { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 46 */
-
++
{ "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
{ "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
-@@ -165,6 +168,7 @@
+ { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+@@ -90,11 +93,11 @@
+ { "server.groupid", "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.use-keep-alive", "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.force-lower-case-files", "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+-
++
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+
+-
++
+ /* 0 */
+ cv[0].destination = srv->srvconf.bindhost;
+ cv[1].destination = srv->srvconf.errorlog_file;
+@@ -102,33 +105,33 @@
+ cv[4].destination = srv->srvconf.username;
+ cv[5].destination = srv->srvconf.groupname;
+ cv[6].destination = &(srv->srvconf.port);
+-
++
+ cv[9].destination = srv->srvconf.modules;
+ cv[10].destination = srv->srvconf.event_handler;
+ cv[11].destination = srv->srvconf.pid_file;
+-
++
+ cv[13].destination = &(srv->srvconf.max_worker);
+ cv[23].destination = &(srv->srvconf.max_fds);
+ cv[36].destination = &(srv->srvconf.log_request_header_on_error);
+ cv[37].destination = &(srv->srvconf.log_state_handling);
+-
++
+ cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
+-
++
+ stat_cache_string = buffer_init();
+ cv[41].destination = stat_cache_string;
+ cv[43].destination = srv->srvconf.network_backend;
+ cv[44].destination = srv->srvconf.upload_tempdirs;
+ cv[45].destination = &(srv->srvconf.enable_cores);
+-
++
+ cv[42].destination = &(srv->srvconf.max_conns);
+ cv[12].destination = &(srv->srvconf.max_request_size);
+ srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+ assert(srv->config_storage);
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ specific_config *s;
+-
++
+ s = calloc(1, sizeof(specific_config));
+ assert(s);
+ s->document_root = buffer_init();
+@@ -154,17 +157,18 @@
+ s->global_kbytes_per_second = 0;
+ s->global_bytes_per_second_cnt = 0;
+ s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
+-
++
+ cv[2].destination = s->errorfile_prefix;
+-
++
+ cv[7].destination = s->server_tag;
+ cv[8].destination = &(s->use_ipv6);
+-
+-
++
++
+ /* 13 max-worker */
cv[14].destination = s->document_root;
cv[15].destination = &(s->force_lowercase_filenames);
cv[16].destination = &(s->log_condition_handling);
cv[17].destination = &(s->max_keep_alive_requests);
cv[18].destination = s->server_name;
cv[19].destination = &(s->max_keep_alive_idle);
-@@ -216,8 +220,8 @@
-
- }
+@@ -179,23 +183,23 @@
+ cv[28].destination = s->mimetypes;
+ cv[29].destination = s->ssl_pemfile;
+ cv[30].destination = &(s->is_ssl);
+-
++
+ cv[31].destination = &(s->log_file_not_found);
+ cv[32].destination = &(s->log_request_handling);
+ cv[33].destination = &(s->log_response_header);
+ cv[34].destination = &(s->log_request_header);
+-
++
+ cv[35].destination = &(s->allow_http11);
+ cv[38].destination = s->ssl_ca_file;
+ cv[40].destination = &(s->range_requests);
+-
++
+ srv->config_storage[i] = s;
+-
++
+ if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
+ break;
+ }
+ }
+-
++
+ if (buffer_is_empty(stat_cache_string)) {
+ srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
+ } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
+@@ -205,22 +209,22 @@
+ } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
+ srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string);
+ ret = HANDLER_ERROR;
+ }
+-
++
+ buffer_free(stat_cache_string);
+-
++
+ return ret;
+-
+-}
+
++}
--
-#define PATCH(x) con->conf.x = s->x
+#define PATCH(x) \
+ con->conf.x = s->x
int config_setup_connection(server *srv, connection *con) {
specific_config *s = srv->config_storage[0];
-
-@@ -244,6 +248,7 @@
- PATCH(log_response_header);
- PATCH(log_request_handling);
- PATCH(log_condition_handling);
-+ PATCH(log_condition_cache_handling);
+-
++
+ PATCH(allow_http11);
+ PATCH(mimetypes);
+ PATCH(document_root);
+@@ -236,20 +240,21 @@
+ PATCH(kbytes_per_second);
+ PATCH(global_kbytes_per_second);
+ PATCH(global_bytes_per_second_cnt);
+-
++
+ con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
+ buffer_copy_string_buffer(con->server_name, s->server_name);
+-
++
+ PATCH(log_request_header);
+ PATCH(log_response_header);
+ PATCH(log_request_handling);
+ PATCH(log_condition_handling);
++ PATCH(log_condition_cache_handling);
PATCH(log_file_not_found);
-
+-
++
PATCH(range_requests);
-@@ -315,6 +320,8 @@
+ PATCH(force_lowercase_filenames);
+ PATCH(is_ssl);
+-
++
+ PATCH(ssl_pemfile);
+ PATCH(ssl_ca_file);
+ return 0;
+@@ -257,22 +262,22 @@
+
+ int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
+ size_t i, j;
+-
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ specific_config *s = srv->config_storage[i];
+-
++
+ /* not our stage */
+ if (comp != dc->comp) continue;
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
+ PATCH(document_root);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
+@@ -315,11 +320,13 @@
PATCH(log_response_header);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
PATCH(log_condition_handling);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
PATCH(log_file_not_found);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
-@@ -699,21 +706,13 @@
+ PATCH(allow_http11);
+- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
++ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
+ PATCH(force_lowercase_filenames);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
+ PATCH(global_kbytes_per_second);
+@@ -328,7 +335,7 @@
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+ #undef PATCH
+@@ -336,15 +343,15 @@
+ typedef struct {
+ int foo;
+ int bar;
+-
++
+ const buffer *source;
+ const char *input;
+ size_t offset;
+ size_t size;
+-
++
+ int line_pos;
+ int line;
+-
++
+ int in_key;
+ int in_brace;
+ int in_cond;
+@@ -362,7 +369,7 @@
+ }
+
+ if (0 != stream_open(&(t->s), t->file)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening configfile ", t->file, "failed:", strerror(errno));
+ buffer_free(t->file);
+ return -1;
+@@ -373,7 +380,7 @@
+ t->size = t->s.size;
+ t->line = 1;
+ t->line_pos = 1;
+-
++
+ t->in_key = 1;
+ t->in_brace = 0;
+ t->in_cond = 0;
+@@ -401,7 +408,7 @@
+ static int config_skip_comment(tokenizer_t *t) {
+ int i;
+ assert(t->input[t->offset] == '#');
+- for (i = 1; t->input[t->offset + i] &&
++ for (i = 1; t->input[t->offset + i] &&
+ (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
+ i++);
+ t->offset += i;
+@@ -411,44 +418,44 @@
+ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
+ int tid = 0;
+ size_t i;
+-
++
+ for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
+ char c = t->input[t->offset];
+ const char *start = NULL;
+-
++
+ switch (c) {
+- case '=':
++ case '=':
+ if (t->in_brace) {
+ if (t->input[t->offset + 1] == '>') {
+ t->offset += 2;
+-
++
+ buffer_copy_string(token, "=>");
+-
++
+ tid = TK_ARRAY_ASSIGN;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+- "line:", t->line, "pos:", t->line_pos,
++ "line:", t->line, "pos:", t->line_pos,
+ "use => for assignments in arrays");
+ return -1;
+ }
+ } else if (t->in_cond) {
+ if (t->input[t->offset + 1] == '=') {
+ t->offset += 2;
+-
++
+ buffer_copy_string(token, "==");
+-
++
+ tid = TK_EQ;
+ } else if (t->input[t->offset + 1] == '~') {
+ t->offset += 2;
+-
++
+ buffer_copy_string(token, "=~");
+-
++
+ tid = TK_MATCH;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+- "line:", t->line, "pos:", t->line_pos,
++ "line:", t->line, "pos:", t->line_pos,
+ "only =~ and == are allowed in the condition");
+ return -1;
+ }
+@@ -456,51 +463,51 @@
+ t->in_cond = 0;
+ } else if (t->in_key) {
+ tid = TK_ASSIGN;
+-
++
+ buffer_copy_string_len(token, t->input + t->offset, 1);
+-
++
+ t->offset++;
+ t->line_pos++;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+- "line:", t->line, "pos:", t->line_pos,
++ "line:", t->line, "pos:", t->line_pos,
+ "unexpected equal-sign: =");
+ return -1;
+ }
+-
++
+ break;
+- case '!':
++ case '!':
+ if (t->in_cond) {
+ if (t->input[t->offset + 1] == '=') {
+ t->offset += 2;
+-
++
+ buffer_copy_string(token, "!=");
+-
++
+ tid = TK_NE;
+ } else if (t->input[t->offset + 1] == '~') {
+ t->offset += 2;
+-
++
+ buffer_copy_string(token, "!~");
+-
++
+ tid = TK_NOMATCH;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+- "line:", t->line, "pos:", t->line_pos,
++ "line:", t->line, "pos:", t->line_pos,
+ "only !~ and != are allowed in the condition");
+ return -1;
+ }
+ t->in_key = 1;
+ t->in_cond = 0;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+- "line:", t->line, "pos:", t->line_pos,
++ "line:", t->line, "pos:", t->line_pos,
+ "unexpected exclamation-marks: !");
+ return -1;
+ }
+-
++
+ break;
+ case '\t':
+ case ' ':
+@@ -546,10 +553,10 @@
+ case ',':
+ if (t->in_brace > 0) {
+ tid = TK_COMMA;
+-
++
+ buffer_copy_string(token, "(COMMA)");
+ }
+-
++
+ t->offset++;
+ t->line_pos++;
+ break;
+@@ -557,70 +564,70 @@
+ /* search for the terminating " */
+ start = t->input + t->offset + 1;
+ buffer_copy_string(token, "");
+-
++
+ for (i = 1; t->input[t->offset + i]; i++) {
+ if (t->input[t->offset + i] == '\\' &&
+ t->input[t->offset + i + 1] == '"') {
+-
++
+ buffer_append_string_len(token, start, t->input + t->offset + i - start);
+-
++
+ start = t->input + t->offset + i + 1;
+-
++
+ /* skip the " */
+ i++;
+ continue;
+ }
+-
+-
++
++
+ if (t->input[t->offset + i] == '"') {
+ tid = TK_STRING;
+-
++
+ buffer_append_string_len(token, start, t->input + t->offset + i - start);
+-
++
+ break;
+ }
+ }
+
+ if (t->input[t->offset + i] == '\0') {
+ /* ERROR */
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+- "line:", t->line, "pos:", t->line_pos,
++ "line:", t->line, "pos:", t->line_pos,
+ "missing closing quote");
+-
++
+ return -1;
+ }
+-
++
+ t->offset += i + 1;
+ t->line_pos += i + 1;
+-
++
+ break;
+ case '(':
+ t->offset++;
+ t->in_brace++;
+-
++
+ tid = TK_LPARAN;
+-
++
+ buffer_copy_string(token, "(");
+ break;
+ case ')':
+ t->offset++;
+ t->in_brace--;
+-
++
+ tid = TK_RPARAN;
+-
++
+ buffer_copy_string(token, ")");
+ break;
+ case '$':
+ t->offset++;
+-
++
+ tid = TK_DOLLAR;
+ t->in_cond = 1;
+ t->in_key = 0;
+-
++
+ buffer_copy_string(token, "$");
+-
++
+ break;
+
+ case '+':
+@@ -637,96 +644,88 @@
+
+ case '{':
+ t->offset++;
+-
++
+ tid = TK_LCURLY;
+-
++
+ buffer_copy_string(token, "{");
+-
++
+ break;
+-
++
+ case '}':
+ t->offset++;
+-
++
+ tid = TK_RCURLY;
+-
++
+ buffer_copy_string(token, "}");
+-
++
+ break;
+
+ case '[':
+ t->offset++;
+-
++
+ tid = TK_LBRACKET;
+-
++
+ buffer_copy_string(token, "[");
+-
++
+ break;
+-
++
+ case ']':
+ t->offset++;
+-
++
+ tid = TK_RBRACKET;
+-
++
+ buffer_copy_string(token, "]");
+-
++
+ break;
+ case '#':
+ t->line_pos += config_skip_comment(t);
+-
++
+ break;
+ default:
+ if (t->in_cond) {
+- for (i = 0; t->input[t->offset + i] &&
++ for (i = 0; t->input[t->offset + i] &&
+ (isalpha((unsigned char)t->input[t->offset + i])
+ ); i++);
+-
++
+ if (i && t->input[t->offset + i]) {
+ tid = TK_SRVVARNAME;
+ buffer_copy_string_len(token, t->input + t->offset, i);
+-
++
+ t->offset += i;
+ t->line_pos += i;
+ } else {
+ /* ERROR */
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+- "line:", t->line, "pos:", t->line_pos,
++ "line:", t->line, "pos:", t->line_pos,
+ "invalid character in condition");
+ return -1;
+ }
+ } else if (isdigit((unsigned char)c)) {
+ /* take all digits */
for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
-
+-
++
/* was there it least a digit ? */
- if (i && t->input[t->offset + i]) {
+ if (i) {
tid = TK_INTEGER;
-
+-
++
buffer_copy_string_len(token, t->input + t->offset, i);
-
+-
++
t->offset += i;
t->line_pos += i;
- } else {
}
} else {
/* the key might consist of [-.0-9a-z] */
-@@ -781,6 +780,7 @@
+- for (i = 0; t->input[t->offset + i] &&
+- (isalnum((unsigned char)t->input[t->offset + i]) ||
++ for (i = 0; t->input[t->offset + i] &&
++ (isalnum((unsigned char)t->input[t->offset + i]) ||
+ t->input[t->offset + i] == '.' ||
+ t->input[t->offset + i] == '_' || /* for env.* */
+ t->input[t->offset + i] == '-'
+ ); i++);
+-
++
+ if (i && t->input[t->offset + i]) {
+ buffer_copy_string_len(token, t->input + t->offset, i);
+-
++
+ if (strcmp(token->ptr, "include") == 0) {
+ tid = TK_INCLUDE;
+ } else if (strcmp(token->ptr, "include_shell") == 0) {
+@@ -738,14 +737,14 @@
+ } else {
+ tid = TK_LKEY;
+ }
+-
++
+ t->offset += i;
+ t->line_pos += i;
+ } else {
+ /* ERROR */
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+- "line:", t->line, "pos:", t->line_pos,
++ "line:", t->line, "pos:", t->line_pos,
+ "invalid character in variable name");
+ return -1;
+ }
+@@ -753,16 +752,16 @@
+ break;
+ }
+ }
+-
++
+ if (tid) {
+ *token_id = tid;
+ #if 0
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ token, token->used - 1, tid);
+ #endif
+-
++
+ return 1;
+ } else if (t->offset < t->size) {
+ fprintf(stderr, "%s.%d: %d, %s\n",
+@@ -781,10 +780,11 @@
pParser = configparserAlloc( malloc );
lasttoken = buffer_init();
token = buffer_init();
while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
buffer_copy_string_buffer(lasttoken, token);
configparser(pParser, token_id, token, context);
-@@ -896,13 +896,12 @@
- static void context_init(server *srv, config_t *context) {
- context->srv = srv;
- context->ok = 1;
-- context->configs_stack = array_init();
-- context->configs_stack->is_weakref = 1;
-+ context->configs_stack = buffer_ptr_init(NULL);
- context->basedir = buffer_init();
- }
-
- static void context_free(config_t *context) {
-- array_free(context->configs_stack);
-+ buffer_ptr_free(context->configs_stack);
- buffer_free(context->basedir);
+-
++
+ token = buffer_init();
+ }
+ buffer_free(token);
+@@ -797,14 +797,14 @@
+ }
+ }
+ configparserFree(pParser, free);
+-
++
+ if (ret == -1) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "configfile parser failed:", lasttoken);
+ } else if (context->ok == 0) {
+- log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
++ log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
+ "source:", t->source,
+- "line:", t->line, "pos:", t->line_pos,
++ "line:", t->line, "pos:", t->line_pos,
+ "parser failed somehow near here:", lasttoken);
+ ret = -1;
+ }
+@@ -821,7 +821,7 @@
+ t->offset = 0;
+ t->line = 1;
+ t->line_pos = 1;
+-
++
+ t->in_key = 1;
+ t->in_brace = 0;
+ t->in_cond = 0;
+@@ -844,7 +844,7 @@
+ }
+
+ if (0 != stream_open(&s, filename)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening configfile ", filename, "failed:", strerror(errno));
+ ret = -1;
+ } else {
+@@ -866,7 +866,7 @@
+ char oldpwd[PATH_MAX];
+
+ if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "cannot get cwd", strerror(errno));
+ return -1;
+ }
+@@ -879,7 +879,7 @@
+ }
+
+ if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening", source, "failed:", strerror(errno));
+ ret = -1;
+ } else {
+@@ -896,13 +896,12 @@
+ static void context_init(server *srv, config_t *context) {
+ context->srv = srv;
+ context->ok = 1;
+- context->configs_stack = array_init();
+- context->configs_stack->is_weakref = 1;
++ context->configs_stack = buffer_ptr_init(NULL);
+ context->basedir = buffer_init();
+ }
+
+ static void context_free(config_t *context) {
+- array_free(context->configs_stack);
++ buffer_ptr_free(context->configs_stack);
+ buffer_free(context->basedir);
}
-@@ -918,13 +917,10 @@
+@@ -918,18 +917,15 @@
context_init(srv, &context);
context.all_configs = srv->config_context;
if (pos) {
buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
fn = pos + 1;
-@@ -1035,6 +1031,7 @@
+ }
+-
++
+ dc = data_config_init();
+ buffer_copy_string(dc->key, "global");
+
+@@ -944,7 +940,7 @@
+ dpid->value = getpid();
+ buffer_copy_string(dpid->key, "var.PID");
+ array_insert_unique(srv->config, (data_unset *)dpid);
+-
++
+ dcwd = data_string_init();
+ buffer_prepare_copy(dcwd->value, 1024);
+ if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
+@@ -968,7 +964,7 @@
+ } else {
+ return -1;
+ }
+-
++
+ if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
+ data_string *ds;
+ data_array *prepends;
+@@ -1026,22 +1022,23 @@
+ buffer_copy_string(modules->key, "server.modules");
+ array_insert_unique(srv->config, (data_unset *)modules);
+ }
+-
++
+
+ if (0 != config_insert(srv)) {
+ return -1;
+ }
+-
++
return 0;
}
int config_set_defaults(server *srv) {
size_t i;
specific_config *s = srv->config_storage[0];
-@@ -1077,10 +1074,11 @@
- }
-
+ struct stat st1, st2;
+-
+- struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
+- {
++
++ struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
++ {
+ /* - poll is most reliable
+ * - select works everywhere
+ * - linux-* are experimental
+@@ -1067,20 +1064,21 @@
+ #endif
+ { FDEVENT_HANDLER_UNSET, NULL }
+ };
+-
+
+- if (buffer_is_empty(s->document_root)) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
+- "a default document-root has to be set");
+-
+- return -1;
+- }
+-
++
++ if (buffer_is_empty(s->document_root)) {
++ log_error_write(srv, __FILE__, __LINE__, "s",
++ "a default document-root has to be set");
++
++ return -1;
++ }
++
if (buffer_is_empty(srv->srvconf.changeroot)) {
-+ pathname_unix2local(s->document_root);
- if (-1 == stat(s->document_root->ptr, &st1)) {
+- if (-1 == stat(s->document_root->ptr, &st1)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
++ pathname_unix2local(s->document_root);
++ if (-1 == stat(s->document_root->ptr, &st1)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbs",
"base-docroot doesn't exist:",
- s->document_root);
return -1;
}
+@@ -1088,18 +1086,18 @@
+ buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
+ buffer_append_string_buffer(srv->tmp_buf, s->document_root);
+
+- if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "base-docroot doesn't exist:",
+- srv->tmp_buf);
++ srv->tmp_buf);
+ return -1;
+ }
+-
++
+ }
+-
+- buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
+
+- buffer_to_lower(srv->tmp_buf);
++ buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
++
++ buffer_to_lower(srv->tmp_buf);
+
+ if (0 == stat(srv->tmp_buf->ptr, &st1)) {
+ int is_lower = 0;
+@@ -1107,68 +1105,68 @@
+ is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
+
+ /* lower-case existed, check upper-case */
+- buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
++ buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
+
+- buffer_to_upper(srv->tmp_buf);
++ buffer_to_upper(srv->tmp_buf);
+
+ /* we have to handle the special case that upper and lower-casing results in the same filename
+ * as in server.document-root = "/" or "/12345/" */
+
+ if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
+- /* lower-casing and upper-casing didn't result in
+- * an other filename, no need to stat(),
++ /* lower-casing and upper-casing didn't result in
++ * an other filename, no need to stat(),
+ * just assume it is case-sensitive. */
+
+ s->force_lowercase_filenames = 0;
+- } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
++ } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
++
++ /* upper case exists too, doesn't the FS handle this ? */
++
++ /* upper and lower have the same inode -> case-insensitve FS */
++
++ if (st1.st_ino == st2.st_ino) {
++ /* upper and lower have the same inode -> case-insensitve FS */
++
++ s->force_lowercase_filenames = 1;
++ }
++ }
++ }
+
+- /* upper case exists too, doesn't the FS handle this ? */
+-
+- /* upper and lower have the same inode -> case-insensitve FS */
+-
+- if (st1.st_ino == st2.st_ino) {
+- /* upper and lower have the same inode -> case-insensitve FS */
+-
+- s->force_lowercase_filenames = 1;
+- }
+- }
+- }
+-
+ if (srv->srvconf.port == 0) {
+ srv->srvconf.port = s->is_ssl ? 443 : 80;
+ }
+-
++
+ if (srv->srvconf.event_handler->used == 0) {
+ /* choose a good default
+- *
+- * the event_handler list is sorted by 'goodness'
++ *
++ * the event_handler list is sorted by 'goodness'
+ * taking the first available should be the best solution
+ */
+ srv->event_handler = event_handlers[0].et;
+-
++
+ if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "sorry, there is no event handler for this system");
+-
++
+ return -1;
+ }
+ } else {
+ /*
+ * User override
+ */
+-
++
+ for (i = 0; event_handlers[i].name; i++) {
+ if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
+ srv->event_handler = event_handlers[i].et;
+ break;
+ }
+ }
+-
++
+ if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "the selected event-handler in unknown or not supported:",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "the selected event-handler in unknown or not supported:",
+ srv->srvconf.event_handler );
+-
++
+ return -1;
+ }
+ }
+@@ -1176,19 +1174,19 @@
+ if (s->is_ssl) {
+ if (buffer_is_empty(s->ssl_pemfile)) {
+ /* PEM file is require */
+-
+- log_error_write(srv, __FILE__, __LINE__, "s",
++
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ssl.pemfile has to be set");
+ return -1;
+ }
+-
++
+ #ifndef USE_OPENSSL
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ssl support is missing, recompile with --with-openssl");
+-
++
+ return -1;
+ #endif
+ }
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configfile.h lighttpd-1.4.12/src/configfile.h
--- lighttpd-1.4.11/src/configfile.h 2005-08-23 17:36:12.000000000 +0300
-+++ lighttpd/src/configfile.h 2006-07-11 21:23:39.995849464 +0300
++++ lighttpd-1.4.12/src/configfile.h 2006-07-11 21:23:39.000000000 +0300
@@ -9,7 +9,7 @@
server *srv;
int ok;
data_config *current; /* current started with { */
buffer *basedir;
} config_t;
---- lighttpd-1.4.11/src/configparser.y 2006-01-26 18:46:25.000000000 +0200
-+++ lighttpd/src/configparser.y 2006-07-11 21:23:40.127857732 +0300
-@@ -21,33 +21,18 @@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configparser.c lighttpd-1.4.12/src/configparser.c
+--- lighttpd-1.4.11/src/configparser.c 2006-02-01 19:51:15.000000000 +0200
++++ lighttpd-1.4.12/src/configparser.c 2006-07-11 21:49:18.000000000 +0300
+@@ -24,52 +24,34 @@
dc->parent = ctx->current;
array_insert_unique(dc->parent->childs, (data_unset *)dc);
}
-
- return NULL;
- } else {
- data_unset *du;
- data_config *dc;
+- data_unset *du;
+- data_config *dc;
++ data_unset *du;
++ data_config *dc;
-@@ -63,11 +48,8 @@
- return du->copy(du);
- }
+ #if 0
+- fprintf(stderr, "get var %s\n", key->ptr);
++ fprintf(stderr, "get var %s\n", key->ptr);
+ #endif
+- for (dc = ctx->current; dc; dc = dc->parent) {
++ for (dc = ctx->current; dc; dc = dc->parent) {
+ #if 0
+- fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
+- array_print(dc->value, 0);
++ fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
++ array_print(dc->value, 0);
+ #endif
+- if (NULL != (du = array_get_element(dc->value, key->ptr))) {
+- return du->copy(du);
+- }
++ if (NULL != (du = array_get_element(dc->value, key->ptr))) {
++ return du->copy(du);
}
- fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
- ctx->ok = 0;
- return NULL;
+- return NULL;
}
--}
++ return NULL;
+ }
/* op1 is to be eat/return by this function, op1->key is not cared
- op2 is left untouch, unreferenced
-@@ -141,6 +123,7 @@
- %type aelement {data_unset *}
- %type condline {data_config *}
- %type condlines {data_config *}
-+%type global {data_config *}
- %type aelements {array *}
- %type array {array *}
- %type key {buffer *}
-@@ -161,7 +144,12 @@
+@@ -124,14 +106,14 @@
+ }
- varline ::= key(A) ASSIGN expression(B). {
- buffer_copy_string_buffer(B->key, A);
-- if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
-+ if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
+
+-#line 128 "configparser.c"
++#line 110 "configparser.c"
+ /* Next is all token values, in a form suitable for use by makeheaders.
+ ** This section will be null unless lemon is run with the -m switch.
+ */
+-/*
++/*
+ ** These constants (all generated automatically by the parser generator)
+ ** specify the various kinds of tokens (terminals) that the parser
+-** understands.
++** understands.
+ **
+ ** Each symbol here is a terminal symbol in the grammar.
+ */
+@@ -148,7 +130,7 @@
+ ** and nonterminals. "int" is used otherwise.
+ ** YYNOCODE is a number of type YYCODETYPE which corresponds
+ ** to no legal terminal or nonterminal number. This
+-** number is used to fill in empty slots of the hash
++** number is used to fill in empty slots of the hash
+ ** table.
+ ** YYFALLBACK If defined, this indicates that one or more tokens
+ ** have fall-back values which should be used if the
+@@ -157,7 +139,7 @@
+ ** and nonterminal numbers. "unsigned char" is
+ ** used if there are fewer than 250 rules and
+ ** states combined. "int" is used otherwise.
+-** configparserTOKENTYPE is the data type used for minor tokens given
++** configparserTOKENTYPE is the data type used for minor tokens given
+ ** directly to the parser from the tokenizer.
+ ** YYMINORTYPE is the data type used for all minor tokens.
+ ** This is typically a union of many types, one of
+@@ -192,8 +174,8 @@
+ #define configparserARG_PDECL ,config_t *ctx
+ #define configparserARG_FETCH config_t *ctx = yypParser->ctx
+ #define configparserARG_STORE yypParser->ctx = ctx
+-#define YYNSTATE 62
+-#define YYNRULE 39
++#define YYNSTATE 63
++#define YYNRULE 40
+ #define YYERRORSYMBOL 26
+ #define YYERRSYMDT yy95
+ #define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
+@@ -203,7 +185,7 @@
+ /* Next are that tables used to determine what action to take based on the
+ ** current state and lookahead token. These tables are used to implement
+ ** functions that take a state number and lookahead value and return an
+-** action integer.
++** action integer.
+ **
+ ** Suppose the action integer is N. Then the action is determined as
+ ** follows
+@@ -228,7 +210,7 @@
+ ** If the index value yy_shift_ofst[S]+X is out of range or if the value
+ ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
+ ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
+-** and that yy_default[S] should be used instead.
++** and that yy_default[S] should be used instead.
+ **
+ ** The formula above is for computing the action when the lookahead is
+ ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
+@@ -248,67 +230,69 @@
+ ** yy_default[] Default action for each state.
+ */
+ static YYACTIONTYPE yy_action[] = {
+- /* 0 */ 2, 3, 4, 5, 13, 14, 62, 15, 7, 44,
+- /* 10 */ 20, 86, 16, 45, 28, 48, 40, 10, 39, 25,
+- /* 20 */ 22, 49, 45, 8, 15, 102, 1, 20, 28, 18,
+- /* 30 */ 57, 59, 19, 25, 22, 39, 19, 61, 98, 45,
+- /* 40 */ 20, 6, 23, 24, 26, 28, 35, 57, 59, 12,
+- /* 50 */ 25, 22, 28, 27, 36, 87, 29, 25, 22, 33,
+- /* 60 */ 15, 30, 31, 20, 28, 38, 9, 17, 37, 25,
+- /* 70 */ 22, 39, 42, 43, 10, 45, 11, 53, 54, 55,
+- /* 80 */ 56, 28, 52, 57, 59, 34, 25, 22, 28, 27,
+- /* 90 */ 32, 88, 41, 25, 22, 33, 28, 48, 46, 28,
+- /* 100 */ 48, 25, 22, 58, 25, 22, 60, 21, 19, 47,
+- /* 110 */ 51, 50, 25, 22, 88, 88, 93,
++ /* 0 */ 2, 3, 4, 5, 13, 14, 63, 15, 7, 45,
++ /* 10 */ 20, 88, 16, 46, 28, 49, 41, 10, 40, 25,
++ /* 20 */ 22, 50, 46, 8, 15, 104, 1, 20, 28, 18,
++ /* 30 */ 58, 60, 6, 25, 22, 40, 47, 62, 11, 46,
++ /* 40 */ 20, 9, 23, 24, 26, 29, 89, 58, 60, 10,
++ /* 50 */ 17, 38, 28, 27, 37, 19, 30, 25, 22, 34,
++ /* 60 */ 15, 100, 20, 20, 23, 24, 26, 12, 19, 31,
++ /* 70 */ 32, 40, 19, 44, 43, 46, 95, 35, 90, 89,
++ /* 80 */ 28, 49, 42, 58, 60, 25, 22, 59, 28, 27,
++ /* 90 */ 33, 48, 52, 25, 22, 34, 28, 49, 51, 28,
++ /* 100 */ 36, 25, 22, 61, 25, 22, 89, 28, 39, 89,
++ /* 110 */ 89, 89, 25, 22, 54, 55, 56, 57, 89, 28,
++ /* 120 */ 53, 21, 89, 89, 25, 22, 25, 22,
+ };
+ static YYCODETYPE yy_lookahead[] = {
+ /* 0 */ 29, 30, 31, 32, 33, 34, 0, 1, 44, 38,
+ /* 10 */ 4, 15, 41, 16, 35, 36, 45, 46, 12, 40,
+ /* 20 */ 41, 42, 16, 15, 1, 27, 28, 4, 35, 36,
+- /* 30 */ 24, 25, 5, 40, 41, 12, 5, 14, 11, 16,
+- /* 40 */ 4, 1, 6, 7, 8, 35, 36, 24, 25, 28,
+- /* 50 */ 40, 41, 35, 36, 37, 15, 39, 40, 41, 42,
+- /* 60 */ 1, 9, 10, 4, 35, 36, 38, 2, 3, 40,
+- /* 70 */ 41, 12, 28, 14, 46, 16, 13, 20, 21, 22,
+- /* 80 */ 23, 35, 36, 24, 25, 11, 40, 41, 35, 36,
+- /* 90 */ 37, 13, 13, 40, 41, 42, 35, 36, 17, 35,
+- /* 100 */ 36, 40, 41, 42, 40, 41, 42, 35, 5, 18,
+- /* 110 */ 43, 19, 40, 41, 47, 47, 13,
++ /* 30 */ 24, 25, 1, 40, 41, 12, 17, 14, 13, 16,
++ /* 40 */ 4, 38, 6, 7, 8, 9, 15, 24, 25, 46,
++ /* 50 */ 2, 3, 35, 36, 37, 5, 39, 40, 41, 42,
++ /* 60 */ 1, 11, 4, 4, 6, 7, 8, 28, 5, 9,
++ /* 70 */ 10, 12, 5, 14, 28, 16, 13, 11, 13, 47,
++ /* 80 */ 35, 36, 13, 24, 25, 40, 41, 42, 35, 36,
++ /* 90 */ 37, 18, 43, 40, 41, 42, 35, 36, 19, 35,
++ /* 100 */ 36, 40, 41, 42, 40, 41, 47, 35, 36, 47,
++ /* 110 */ 47, 47, 40, 41, 20, 21, 22, 23, 47, 35,
++ /* 120 */ 36, 35, 47, 47, 40, 41, 40, 41,
+ };
+ #define YY_SHIFT_USE_DFLT (-5)
+ static signed char yy_shift_ofst[] = {
+- /* 0 */ -5, 6, -5, -5, -5, 40, -4, 8, -3, -5,
+- /* 10 */ 63, -5, 23, -5, -5, -5, 65, 36, 31, 36,
+- /* 20 */ -5, -5, -5, -5, -5, -5, 36, 27, -5, 52,
+- /* 30 */ -5, 36, -5, 74, 36, 31, -5, 36, 31, 78,
+- /* 40 */ 79, -5, 59, -5, -5, 81, 91, 36, 31, 92,
+- /* 50 */ 57, 36, 103, -5, -5, -5, -5, 36, -5, 36,
+- /* 60 */ -5, -5,
++ /* 0 */ -5, 6, -5, -5, -5, 31, -4, 8, -3, -5,
++ /* 10 */ 25, -5, 23, -5, -5, -5, 48, 58, 67, 58,
++ /* 20 */ -5, -5, -5, -5, -5, -5, 36, 50, -5, -5,
++ /* 30 */ 60, -5, 58, -5, 66, 58, 67, -5, 58, 67,
++ /* 40 */ 65, 69, -5, 59, -5, -5, 19, 73, 58, 67,
++ /* 50 */ 79, 94, 58, 63, -5, -5, -5, -5, 58, -5,
++ /* 60 */ 58, -5, -5,
+ };
+ #define YY_REDUCE_USE_DFLT (-37)
+ static signed char yy_reduce_ofst[] = {
+- /* 0 */ -2, -29, -37, -37, -37, -36, -37, -37, 28, -37,
+- /* 10 */ -37, 21, -29, -37, -37, -37, -37, -7, -37, 72,
++ /* 0 */ -2, -29, -37, -37, -37, -36, -37, -37, 3, -37,
++ /* 10 */ -37, 39, -29, -37, -37, -37, -37, -7, -37, 86,
+ /* 20 */ -37, -37, -37, -37, -37, -37, 17, -37, -37, -37,
+- /* 30 */ -37, 53, -37, -37, 10, -37, -37, 29, -37, -37,
+- /* 40 */ -37, 44, -29, -37, -37, -37, -37, -21, -37, -37,
+- /* 50 */ 67, 46, -37, -37, -37, -37, -37, 61, -37, 64,
+- /* 60 */ -37, -37,
++ /* 30 */ -37, -37, 53, -37, -37, 64, -37, -37, 72, -37,
++ /* 40 */ -37, -37, 46, -29, -37, -37, -37, -37, -21, -37,
++ /* 50 */ -37, 49, 84, -37, -37, -37, -37, -37, 45, -37,
++ /* 60 */ 61, -37, -37,
+ };
+ static YYACTIONTYPE yy_default[] = {
+- /* 0 */ 64, 101, 63, 65, 66, 101, 67, 101, 101, 90,
+- /* 10 */ 101, 64, 101, 68, 69, 70, 101, 101, 71, 101,
+- /* 20 */ 73, 74, 76, 77, 78, 79, 101, 84, 75, 101,
+- /* 30 */ 80, 82, 81, 101, 101, 85, 83, 101, 72, 101,
+- /* 40 */ 101, 64, 101, 89, 91, 101, 101, 101, 98, 101,
+- /* 50 */ 101, 101, 101, 94, 95, 96, 97, 101, 99, 101,
+- /* 60 */ 100, 92,
++ /* 0 */ 65, 103, 64, 66, 67, 103, 68, 103, 103, 92,
++ /* 10 */ 103, 65, 103, 69, 70, 71, 103, 103, 72, 103,
++ /* 20 */ 74, 75, 77, 78, 79, 80, 103, 86, 76, 81,
++ /* 30 */ 103, 82, 84, 83, 103, 103, 87, 85, 103, 73,
++ /* 40 */ 103, 103, 65, 103, 91, 93, 103, 103, 103, 100,
++ /* 50 */ 103, 103, 103, 103, 96, 97, 98, 99, 103, 101,
++ /* 60 */ 103, 102, 94,
+ };
+ #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
+
+ /* The next table maps tokens into fallback tokens. If a construct
+ ** like the following:
+-**
++**
+ ** %fallback ID X Y Z.
+ **
+ ** appears in the grammer, then ID becomes a fallback token for X, Y,
+@@ -359,10 +343,10 @@
+ #endif /* NDEBUG */
+
+ #ifndef NDEBUG
+-/*
++/*
+ ** Turn parser tracing on by giving a stream to which to write the trace
+ ** and a prompt to preface each trace message. Tracing is turned off
+-** by making either argument NULL
++** by making either argument NULL
+ **
+ ** Inputs:
+ ** <ul>
+@@ -387,7 +371,7 @@
+ #ifndef NDEBUG
+ /* For tracing shifts, the names of all terminals and nonterminals
+ ** are required. The following table supplies these names */
+-static const char *yyTokenName[] = {
++static const char *yyTokenName[] = {
+ "$", "EOL", "ASSIGN", "APPEND",
+ "LKEY", "PLUS", "STRING", "INTEGER",
+ "LPARAN", "RPARAN", "COMMA", "ARRAY_ASSIGN",
+@@ -425,27 +409,28 @@
+ /* 15 */ "value ::= STRING",
+ /* 16 */ "value ::= INTEGER",
+ /* 17 */ "value ::= array",
+- /* 18 */ "array ::= LPARAN aelements RPARAN",
+- /* 19 */ "aelements ::= aelements COMMA aelement",
+- /* 20 */ "aelements ::= aelements COMMA",
+- /* 21 */ "aelements ::= aelement",
+- /* 22 */ "aelement ::= expression",
+- /* 23 */ "aelement ::= stringop ARRAY_ASSIGN expression",
+- /* 24 */ "eols ::= EOL",
+- /* 25 */ "eols ::=",
+- /* 26 */ "globalstart ::= GLOBAL",
+- /* 27 */ "global ::= globalstart LCURLY metalines RCURLY",
+- /* 28 */ "condlines ::= condlines eols ELSE condline",
+- /* 29 */ "condlines ::= condline",
+- /* 30 */ "condline ::= context LCURLY metalines RCURLY",
+- /* 31 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
+- /* 32 */ "cond ::= EQ",
+- /* 33 */ "cond ::= MATCH",
+- /* 34 */ "cond ::= NE",
+- /* 35 */ "cond ::= NOMATCH",
+- /* 36 */ "stringop ::= expression",
+- /* 37 */ "include ::= INCLUDE stringop",
+- /* 38 */ "include_shell ::= INCLUDE_SHELL stringop",
++ /* 18 */ "array ::= LPARAN RPARAN",
++ /* 19 */ "array ::= LPARAN aelements RPARAN",
++ /* 20 */ "aelements ::= aelements COMMA aelement",
++ /* 21 */ "aelements ::= aelements COMMA",
++ /* 22 */ "aelements ::= aelement",
++ /* 23 */ "aelement ::= expression",
++ /* 24 */ "aelement ::= stringop ARRAY_ASSIGN expression",
++ /* 25 */ "eols ::= EOL",
++ /* 26 */ "eols ::=",
++ /* 27 */ "globalstart ::= GLOBAL",
++ /* 28 */ "global ::= globalstart LCURLY metalines RCURLY",
++ /* 29 */ "condlines ::= condlines eols ELSE condline",
++ /* 30 */ "condlines ::= condline",
++ /* 31 */ "condline ::= context LCURLY metalines RCURLY",
++ /* 32 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
++ /* 33 */ "cond ::= EQ",
++ /* 34 */ "cond ::= MATCH",
++ /* 35 */ "cond ::= NE",
++ /* 36 */ "cond ::= NOMATCH",
++ /* 37 */ "stringop ::= expression",
++ /* 38 */ "include ::= INCLUDE stringop",
++ /* 39 */ "include_shell ::= INCLUDE_SHELL stringop",
+ };
+ #endif /* NDEBUG */
+
+@@ -465,7 +450,7 @@
+ #endif
+ }
+
+-/*
++/*
+ ** This function allocates a new parser.
+ ** The only argument is a pointer to a function which works like
+ ** malloc.
+@@ -496,7 +481,7 @@
+ /* Here is inserted the actions which take place when a
+ ** terminal or non-terminal is destroyed. This can happen
+ ** when the symbol is popped from the stack during a
+- ** reduce or during error processing or when a parser is
++ ** reduce or during error processing or when a parser is
+ ** being destroyed before it is finished parsing.
+ **
+ ** Note: during a reduce, the only symbols destroyed are those
+@@ -528,44 +513,44 @@
+ case 23:
+ case 24:
+ case 25:
+-#line 160 "./configparser.y"
++#line 143 "./configparser.y"
+ { buffer_free((yypminor->yy0)); }
+-#line 533 "configparser.c"
++#line 518 "configparser.c"
+ break;
+ case 35:
+-#line 151 "./configparser.y"
++#line 134 "./configparser.y"
+ { (yypminor->yy41)->free((yypminor->yy41)); }
+-#line 538 "configparser.c"
++#line 523 "configparser.c"
+ break;
+ case 36:
+-#line 152 "./configparser.y"
++#line 135 "./configparser.y"
+ { (yypminor->yy41)->free((yypminor->yy41)); }
+-#line 543 "configparser.c"
++#line 528 "configparser.c"
+ break;
+ case 37:
+-#line 153 "./configparser.y"
++#line 136 "./configparser.y"
+ { (yypminor->yy41)->free((yypminor->yy41)); }
+-#line 548 "configparser.c"
++#line 533 "configparser.c"
+ break;
+ case 39:
+-#line 154 "./configparser.y"
++#line 137 "./configparser.y"
+ { array_free((yypminor->yy40)); }
+-#line 553 "configparser.c"
++#line 538 "configparser.c"
+ break;
+ case 40:
+-#line 155 "./configparser.y"
++#line 138 "./configparser.y"
+ { array_free((yypminor->yy40)); }
+-#line 558 "configparser.c"
++#line 543 "configparser.c"
+ break;
+ case 41:
+-#line 156 "./configparser.y"
++#line 139 "./configparser.y"
+ { buffer_free((yypminor->yy43)); }
+-#line 563 "configparser.c"
++#line 548 "configparser.c"
+ break;
+ case 42:
+-#line 157 "./configparser.y"
++#line 140 "./configparser.y"
+ { buffer_free((yypminor->yy43)); }
+-#line 568 "configparser.c"
++#line 553 "configparser.c"
+ break;
+ default: break; /* If no destructor action specified: do nothing */
+ }
+@@ -597,7 +582,7 @@
+ return yymajor;
+ }
+
+-/*
++/*
+ ** Deallocate and destroy a parser. Destructors are all called for
+ ** all stack elements before shutting the parser down.
+ **
+@@ -633,7 +618,7 @@
+ ){
+ int i;
+ int stateno = pParser->yystack[pParser->yyidx].stateno;
+-
++
+ /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
+ i = yy_shift_ofst[stateno];
+ if( i==YY_SHIFT_USE_DFLT ){
+@@ -677,7 +662,7 @@
+ ){
+ int i;
+ int stateno = pParser->yystack[pParser->yyidx].stateno;
+-
++
+ i = yy_reduce_ofst[stateno];
+ if( i==YY_REDUCE_USE_DFLT ){
+ return yy_default[stateno];
+@@ -759,6 +744,7 @@
+ { 35, 1 },
+ { 35, 1 },
+ { 35, 1 },
++ { 40, 2 },
+ { 40, 3 },
+ { 39, 3 },
+ { 39, 2 },
+@@ -800,7 +786,7 @@
+ configparserARG_FETCH;
+ yymsp = &yypParser->yystack[yypParser->yyidx];
+ #ifndef NDEBUG
+- if( yyTraceFILE && yyruleno>=0
++ if( yyTraceFILE && yyruleno>=0
+ && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
+ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
+ yyRuleName[yyruleno]);
+@@ -832,9 +818,9 @@
+ /* No destructor defined for global */
+ break;
+ case 5:
+-#line 134 "./configparser.y"
++#line 116 "./configparser.y"
+ { yymsp[-1].minor.yy78 = NULL; }
+-#line 837 "configparser.c"
++#line 823 "configparser.c"
+ yy_destructor(1,&yymsp[0].minor);
+ break;
+ case 6:
+@@ -847,10 +833,15 @@
+ yy_destructor(1,&yymsp[0].minor);
+ break;
+ case 9:
+-#line 162 "./configparser.y"
++#line 145 "./configparser.y"
+ {
+ buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
+- if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
++ if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
+ fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
+ ctx->current->context_ndx,
-+ ctx->current->key->ptr, A->ptr);
++ ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
+ ctx->ok = 0;
-+ } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
- array_insert_unique(ctx->current->value, B);
- B = NULL;
++ } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
+ array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
+ yymsp[0].minor.yy41 = NULL;
} else {
-@@ -180,7 +168,12 @@
+@@ -864,16 +855,21 @@
+ buffer_free(yymsp[-2].minor.yy43);
+ yymsp[-2].minor.yy43 = NULL;
+ }
+-#line 867 "configparser.c"
++#line 858 "configparser.c"
+ yy_destructor(2,&yymsp[-1].minor);
+ break;
+ case 10:
+-#line 179 "./configparser.y"
++#line 167 "./configparser.y"
+ {
array *vars = ctx->current->value;
data_unset *du;
-- if (NULL != (du = array_get_element(vars, A->ptr))) {
-+ if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
+- if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
++ if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
+ fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
+ ctx->current->context_ndx,
-+ ctx->current->key->ptr, A->ptr);
++ ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
+ ctx->ok = 0;
-+ } else if (NULL != (du = array_get_element(vars, A->ptr))) {
++ } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
/* exists in current block */
- du = configparser_merge_data(du, B);
+ du = configparser_merge_data(du, yymsp[0].minor.yy41);
if (NULL == du) {
-@@ -190,6 +183,7 @@
- buffer_copy_string_buffer(du->key, A);
+@@ -883,6 +879,7 @@
+ buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
array_replace(vars, du);
}
-+ B->free(B);
- } else if (NULL != (du = configparser_get_variable(ctx, A))) {
- du = configparser_merge_data(du, B);
++ yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
+ } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) {
+ du = configparser_merge_data(du, yymsp[0].minor.yy41);
if (NULL == du) {
-@@ -199,15 +193,13 @@
- buffer_copy_string_buffer(du->key, A);
+@@ -892,22 +889,20 @@
+ buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
array_insert_unique(ctx->current->value, du);
}
-+ B->free(B);
++ yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
} else {
- fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
- ctx->current->context_ndx,
-- ctx->current->key->ptr, A->ptr);
+- ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
- ctx->ok = 0;
-+ buffer_copy_string_buffer(B->key, A);
-+ array_insert_unique(ctx->current->value, B);
++ buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
++ array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
}
- buffer_free(A);
- A = NULL;
-- B->free(B);
- B = NULL;
+ buffer_free(yymsp[-2].minor.yy43);
+ yymsp[-2].minor.yy43 = NULL;
+- yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
+ yymsp[0].minor.yy41 = NULL;
}
-
-@@ -239,7 +231,24 @@
+-#line 906 "configparser.c"
++#line 901 "configparser.c"
+ yy_destructor(3,&yymsp[-1].minor);
+ break;
+ case 11:
+-#line 214 "./configparser.y"
++#line 206 "./configparser.y"
+ {
+ if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) {
+ yygotominor.yy43 = buffer_init_string("var.");
+@@ -919,10 +914,10 @@
+ yymsp[0].minor.yy0 = NULL;
+ }
}
-
- value(A) ::= key(B). {
-- A = configparser_get_variable(ctx, B);
-+ if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
+-#line 922 "configparser.c"
++#line 917 "configparser.c"
+ break;
+ case 12:
+-#line 226 "./configparser.y"
++#line 218 "./configparser.y"
+ {
+ yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41);
+ if (NULL == yygotominor.yy41) {
+@@ -932,21 +927,38 @@
+ yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
+ yymsp[0].minor.yy41 = NULL;
+ }
+-#line 935 "configparser.c"
++#line 930 "configparser.c"
+ yy_destructor(5,&yymsp[-1].minor);
+ break;
+ case 13:
+-#line 236 "./configparser.y"
++#line 228 "./configparser.y"
+ {
+ yygotominor.yy41 = yymsp[0].minor.yy41;
+ yymsp[0].minor.yy41 = NULL;
+ }
+-#line 944 "configparser.c"
++#line 939 "configparser.c"
+ break;
+ case 14:
+-#line 241 "./configparser.y"
++#line 233 "./configparser.y"
+ {
+- yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43);
++ if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
+ char *env;
+
-+ if (NULL != (env = getenv(B->ptr + 4))) {
++ if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) {
+ data_string *ds;
+ ds = data_string_init();
+ buffer_append_string(ds->value, env);
-+ A = (data_unset *)ds;
++ yygotominor.yy41 = (data_unset *)ds;
+ }
+ else {
-+ A = NULL;
-+ fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
++ yygotominor.yy41 = NULL;
++ fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4);
+ ctx->ok = 0;
+ }
-+ } else if (NULL == (A = configparser_get_variable(ctx, B))) {
-+ fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
++ } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) {
++ fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr);
+ ctx->ok = 0;
+ }
- if (!A) {
+ if (!yygotominor.yy41) {
/* make a dummy so it won't crash */
- A = (data_unset *)data_string_init();
-@@ -267,6 +276,9 @@
- ((data_array *)(A))->value = B;
- B = NULL;
+ yygotominor.yy41 = (data_unset *)data_string_init();
+@@ -954,50 +966,59 @@
+ buffer_free(yymsp[0].minor.yy43);
+ yymsp[0].minor.yy43 = NULL;
}
-+array(A) ::= LPARAN RPARAN. {
-+ A = array_init();
+-#line 957 "configparser.c"
++#line 969 "configparser.c"
+ break;
+ case 15:
+-#line 251 "./configparser.y"
++#line 260 "./configparser.y"
+ {
+ yygotominor.yy41 = (data_unset *)data_string_init();
+ buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
+ buffer_free(yymsp[0].minor.yy0);
+ yymsp[0].minor.yy0 = NULL;
+ }
+-#line 967 "configparser.c"
++#line 979 "configparser.c"
+ break;
+ case 16:
+-#line 258 "./configparser.y"
++#line 267 "./configparser.y"
+ {
+ yygotominor.yy41 = (data_unset *)data_integer_init();
+ ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
+ buffer_free(yymsp[0].minor.yy0);
+ yymsp[0].minor.yy0 = NULL;
+ }
+-#line 977 "configparser.c"
++#line 989 "configparser.c"
+ break;
+ case 17:
+-#line 264 "./configparser.y"
++#line 273 "./configparser.y"
+ {
+ yygotominor.yy41 = (data_unset *)data_array_init();
+ array_free(((data_array *)(yygotominor.yy41))->value);
+ ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
+ yymsp[0].minor.yy40 = NULL;
+ }
+-#line 987 "configparser.c"
++#line 999 "configparser.c"
+ break;
+ case 18:
+-#line 270 "./configparser.y"
++#line 279 "./configparser.y"
++{
++ yygotominor.yy40 = array_init();
+}
- array(A) ::= LPARAN aelements(B) RPARAN. {
- A = B;
- B = NULL;
---- lighttpd-1.4.11/src/connections.c 2006-03-05 22:14:53.000000000 +0200
-+++ lighttpd/src/connections.c 2006-07-11 21:23:39.955846959 +0300
-@@ -2,7 +2,6 @@
-
- #include <stdlib.h>
- #include <stdio.h>
--#include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <fcntl.h>
++#line 1006 "configparser.c"
++ yy_destructor(8,&yymsp[-1].minor);
++ yy_destructor(9,&yymsp[0].minor);
++ break;
++ case 19:
++#line 282 "./configparser.y"
+ {
+ yygotominor.yy40 = yymsp[-1].minor.yy40;
+ yymsp[-1].minor.yy40 = NULL;
+ }
+-#line 995 "configparser.c"
++#line 1016 "configparser.c"
+ yy_destructor(8,&yymsp[-2].minor);
+ yy_destructor(9,&yymsp[0].minor);
+ break;
+- case 19:
+-#line 275 "./configparser.y"
++ case 20:
++#line 287 "./configparser.y"
+ {
+ if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
+ NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
+@@ -1014,37 +1035,37 @@
+ yygotominor.yy40 = yymsp[-2].minor.yy40;
+ yymsp[-2].minor.yy40 = NULL;
+ }
+-#line 1017 "configparser.c"
++#line 1038 "configparser.c"
+ yy_destructor(10,&yymsp[-1].minor);
+ break;
+- case 20:
+-#line 292 "./configparser.y"
++ case 21:
++#line 304 "./configparser.y"
+ {
+ yygotominor.yy40 = yymsp[-1].minor.yy40;
+ yymsp[-1].minor.yy40 = NULL;
+ }
+-#line 1026 "configparser.c"
++#line 1047 "configparser.c"
+ yy_destructor(10,&yymsp[0].minor);
+ break;
+- case 21:
+-#line 297 "./configparser.y"
++ case 22:
++#line 309 "./configparser.y"
+ {
+ yygotominor.yy40 = array_init();
+ array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
+ yymsp[0].minor.yy41 = NULL;
+ }
+-#line 1036 "configparser.c"
++#line 1057 "configparser.c"
+ break;
+- case 22:
+-#line 303 "./configparser.y"
++ case 23:
++#line 315 "./configparser.y"
+ {
+ yygotominor.yy41 = yymsp[0].minor.yy41;
+ yymsp[0].minor.yy41 = NULL;
+ }
+-#line 1044 "configparser.c"
++#line 1065 "configparser.c"
+ break;
+- case 23:
+-#line 307 "./configparser.y"
++ case 24:
++#line 319 "./configparser.y"
+ {
+ buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
+ buffer_free(yymsp[-2].minor.yy43);
+@@ -1053,27 +1074,27 @@
+ yygotominor.yy41 = yymsp[0].minor.yy41;
+ yymsp[0].minor.yy41 = NULL;
+ }
+-#line 1056 "configparser.c"
++#line 1077 "configparser.c"
+ yy_destructor(11,&yymsp[-1].minor);
+ break;
+- case 24:
+- yy_destructor(1,&yymsp[0].minor);
+- break;
+ case 25:
++ yy_destructor(1,&yymsp[0].minor);
+ break;
+ case 26:
+-#line 319 "./configparser.y"
++ break;
++ case 27:
++#line 331 "./configparser.y"
+ {
+ data_config *dc;
+ dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
+ assert(dc);
+ configparser_push(ctx, dc, 0);
+ }
+-#line 1072 "configparser.c"
++#line 1093 "configparser.c"
+ yy_destructor(12,&yymsp[0].minor);
+ break;
+- case 27:
+-#line 326 "./configparser.y"
++ case 28:
++#line 338 "./configparser.y"
+ {
+ data_config *cur;
+
+@@ -1082,16 +1103,16 @@
+
+ assert(cur && ctx->current);
+
+- yygotominor.yy0 = cur;
++ yygotominor.yy78 = cur;
+ }
+-#line 1087 "configparser.c"
++#line 1108 "configparser.c"
+ /* No destructor defined for globalstart */
+ yy_destructor(13,&yymsp[-2].minor);
+ /* No destructor defined for metalines */
+ yy_destructor(14,&yymsp[0].minor);
+ break;
+- case 28:
+-#line 337 "./configparser.y"
++ case 29:
++#line 349 "./configparser.y"
+ {
+ assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx);
+ yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
+@@ -1100,20 +1121,20 @@
+ yymsp[-3].minor.yy78 = NULL;
+ yymsp[0].minor.yy78 = NULL;
+ }
+-#line 1103 "configparser.c"
++#line 1124 "configparser.c"
+ /* No destructor defined for eols */
+ yy_destructor(15,&yymsp[-1].minor);
+ break;
+- case 29:
+-#line 346 "./configparser.y"
++ case 30:
++#line 358 "./configparser.y"
+ {
+ yygotominor.yy78 = yymsp[0].minor.yy78;
+ yymsp[0].minor.yy78 = NULL;
+ }
+-#line 1113 "configparser.c"
++#line 1134 "configparser.c"
+ break;
+- case 30:
+-#line 351 "./configparser.y"
++ case 31:
++#line 363 "./configparser.y"
+ {
+ data_config *cur;
+
+@@ -1124,14 +1145,14 @@
+
+ yygotominor.yy78 = cur;
+ }
+-#line 1127 "configparser.c"
++#line 1148 "configparser.c"
+ /* No destructor defined for context */
+ yy_destructor(13,&yymsp[-2].minor);
+ /* No destructor defined for metalines */
+ yy_destructor(14,&yymsp[0].minor);
+ break;
+- case 31:
+-#line 362 "./configparser.y"
++ case 32:
++#line 374 "./configparser.y"
+ {
+ data_config *dc;
+ buffer *b, *rvalue, *op;
+@@ -1266,45 +1287,45 @@
+ yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
+ yymsp[0].minor.yy41 = NULL;
+ }
+-#line 1269 "configparser.c"
++#line 1290 "configparser.c"
+ yy_destructor(16,&yymsp[-6].minor);
+ yy_destructor(18,&yymsp[-4].minor);
+ yy_destructor(19,&yymsp[-2].minor);
+ break;
+- case 32:
+-#line 496 "./configparser.y"
++ case 33:
++#line 508 "./configparser.y"
+ {
+ yygotominor.yy27 = CONFIG_COND_EQ;
+ }
+-#line 1279 "configparser.c"
++#line 1300 "configparser.c"
+ yy_destructor(20,&yymsp[0].minor);
+ break;
+- case 33:
+-#line 499 "./configparser.y"
++ case 34:
++#line 511 "./configparser.y"
+ {
+ yygotominor.yy27 = CONFIG_COND_MATCH;
+ }
+-#line 1287 "configparser.c"
++#line 1308 "configparser.c"
+ yy_destructor(21,&yymsp[0].minor);
+ break;
+- case 34:
+-#line 502 "./configparser.y"
++ case 35:
++#line 514 "./configparser.y"
+ {
+ yygotominor.yy27 = CONFIG_COND_NE;
+ }
+-#line 1295 "configparser.c"
++#line 1316 "configparser.c"
+ yy_destructor(22,&yymsp[0].minor);
+ break;
+- case 35:
+-#line 505 "./configparser.y"
++ case 36:
++#line 517 "./configparser.y"
+ {
+ yygotominor.yy27 = CONFIG_COND_NOMATCH;
+ }
+-#line 1303 "configparser.c"
++#line 1324 "configparser.c"
+ yy_destructor(23,&yymsp[0].minor);
+ break;
+- case 36:
+-#line 509 "./configparser.y"
++ case 37:
++#line 521 "./configparser.y"
+ {
+ yygotominor.yy43 = NULL;
+ if (ctx->ok) {
+@@ -1321,10 +1342,10 @@
+ yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
+ yymsp[0].minor.yy41 = NULL;
+ }
+-#line 1324 "configparser.c"
++#line 1345 "configparser.c"
+ break;
+- case 37:
+-#line 526 "./configparser.y"
++ case 38:
++#line 538 "./configparser.y"
+ {
+ if (ctx->ok) {
+ if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
+@@ -1334,11 +1355,11 @@
+ yymsp[0].minor.yy43 = NULL;
+ }
+ }
+-#line 1337 "configparser.c"
++#line 1358 "configparser.c"
+ yy_destructor(24,&yymsp[-1].minor);
+ break;
+- case 38:
+-#line 536 "./configparser.y"
++ case 39:
++#line 548 "./configparser.y"
+ {
+ if (ctx->ok) {
+ if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
+@@ -1348,7 +1369,7 @@
+ yymsp[0].minor.yy43 = NULL;
+ }
+ }
+-#line 1351 "configparser.c"
++#line 1372 "configparser.c"
+ yy_destructor(25,&yymsp[-1].minor);
+ break;
+ };
+@@ -1378,11 +1399,11 @@
+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+ /* Here code is inserted which will be executed whenever the
+ ** parser fails */
+-#line 125 "./configparser.y"
++#line 107 "./configparser.y"
+
+ ctx->ok = 0;
+
+-#line 1385 "configparser.c"
++#line 1406 "configparser.c"
+ configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
+ }
+
+@@ -1489,7 +1510,7 @@
+ #ifdef YYERRORSYMBOL
+ /* A syntax error has occurred.
+ ** The response to an error depends upon whether or not the
+- ** grammar defines an error token "ERROR".
++ ** grammar defines an error token "ERROR".
+ **
+ ** This is what we do if the grammar does define ERROR:
+ **
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configparser.y lighttpd-1.4.12/src/configparser.y
+--- lighttpd-1.4.11/src/configparser.y 2006-01-26 18:46:25.000000000 +0200
++++ lighttpd-1.4.12/src/configparser.y 2006-07-11 21:23:40.000000000 +0300
+@@ -21,52 +21,34 @@
+ dc->parent = ctx->current;
+ array_insert_unique(dc->parent->childs, (data_unset *)dc);
+ }
+- array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
++ buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
+ ctx->current = dc;
+ }
+
+ static data_config *configparser_pop(config_t *ctx) {
+ data_config *old = ctx->current;
+- ctx->current = (data_config *) array_pop(ctx->configs_stack);
++ ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
+ return old;
+ }
+
+ /* return a copied variable */
+ static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
+- if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
+- char *env;
+-
+- if (NULL != (env = getenv(key->ptr + 4))) {
+- data_string *ds;
+- ds = data_string_init();
+- buffer_append_string(ds->value, env);
+- return (data_unset *)ds;
+- }
+-
+- fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
+- ctx->ok = 0;
+-
+- return NULL;
+- } else {
+- data_unset *du;
+- data_config *dc;
++ data_unset *du;
++ data_config *dc;
+
+ #if 0
+- fprintf(stderr, "get var %s\n", key->ptr);
++ fprintf(stderr, "get var %s\n", key->ptr);
+ #endif
+- for (dc = ctx->current; dc; dc = dc->parent) {
++ for (dc = ctx->current; dc; dc = dc->parent) {
+ #if 0
+- fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
+- array_print(dc->value, 0);
++ fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
++ array_print(dc->value, 0);
+ #endif
+- if (NULL != (du = array_get_element(dc->value, key->ptr))) {
+- return du->copy(du);
+- }
++ if (NULL != (du = array_get_element(dc->value, key->ptr))) {
++ return du->copy(du);
+ }
+- fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
+- ctx->ok = 0;
+- return NULL;
+ }
++ return NULL;
+ }
+
+ /* op1 is to be eat/return by this function, op1->key is not cared
+@@ -141,6 +123,7 @@
+ %type aelement {data_unset *}
+ %type condline {data_config *}
+ %type condlines {data_config *}
++%type global {data_config *}
+ %type aelements {array *}
+ %type array {array *}
+ %type key {buffer *}
+@@ -161,7 +144,12 @@
+
+ varline ::= key(A) ASSIGN expression(B). {
+ buffer_copy_string_buffer(B->key, A);
+- if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
++ if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
++ fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
++ ctx->current->context_ndx,
++ ctx->current->key->ptr, A->ptr);
++ ctx->ok = 0;
++ } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
+ array_insert_unique(ctx->current->value, B);
+ B = NULL;
+ } else {
+@@ -180,7 +168,12 @@
+ array *vars = ctx->current->value;
+ data_unset *du;
+
+- if (NULL != (du = array_get_element(vars, A->ptr))) {
++ if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
++ fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
++ ctx->current->context_ndx,
++ ctx->current->key->ptr, A->ptr);
++ ctx->ok = 0;
++ } else if (NULL != (du = array_get_element(vars, A->ptr))) {
+ /* exists in current block */
+ du = configparser_merge_data(du, B);
+ if (NULL == du) {
+@@ -190,6 +183,7 @@
+ buffer_copy_string_buffer(du->key, A);
+ array_replace(vars, du);
+ }
++ B->free(B);
+ } else if (NULL != (du = configparser_get_variable(ctx, A))) {
+ du = configparser_merge_data(du, B);
+ if (NULL == du) {
+@@ -199,15 +193,13 @@
+ buffer_copy_string_buffer(du->key, A);
+ array_insert_unique(ctx->current->value, du);
+ }
++ B->free(B);
+ } else {
+- fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
+- ctx->current->context_ndx,
+- ctx->current->key->ptr, A->ptr);
+- ctx->ok = 0;
++ buffer_copy_string_buffer(B->key, A);
++ array_insert_unique(ctx->current->value, B);
+ }
+ buffer_free(A);
+ A = NULL;
+- B->free(B);
+ B = NULL;
+ }
+
+@@ -239,7 +231,24 @@
+ }
+
+ value(A) ::= key(B). {
+- A = configparser_get_variable(ctx, B);
++ if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
++ char *env;
++
++ if (NULL != (env = getenv(B->ptr + 4))) {
++ data_string *ds;
++ ds = data_string_init();
++ buffer_append_string(ds->value, env);
++ A = (data_unset *)ds;
++ }
++ else {
++ A = NULL;
++ fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
++ ctx->ok = 0;
++ }
++ } else if (NULL == (A = configparser_get_variable(ctx, B))) {
++ fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
++ ctx->ok = 0;
++ }
+ if (!A) {
+ /* make a dummy so it won't crash */
+ A = (data_unset *)data_string_init();
+@@ -267,6 +276,9 @@
+ ((data_array *)(A))->value = B;
+ B = NULL;
+ }
++array(A) ::= LPARAN RPARAN. {
++ A = array_init();
++}
+ array(A) ::= LPARAN aelements(B) RPARAN. {
+ A = B;
+ B = NULL;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/connections-glue.c lighttpd-1.4.12/src/connections-glue.c
+--- lighttpd-1.4.11/src/connections-glue.c 2005-09-12 10:04:23.000000000 +0300
++++ lighttpd-1.4.12/src/connections-glue.c 2006-07-11 21:23:39.000000000 +0300
+@@ -13,7 +13,7 @@
+ case CON_STATE_REQUEST_END: return "req-end";
+ case CON_STATE_RESPONSE_START: return "resp-start";
+ case CON_STATE_RESPONSE_END: return "resp-end";
+- default: return "(unknown)";
++ default: return "(unknown)";
+ }
+ }
+
+@@ -30,15 +30,15 @@
+ case CON_STATE_REQUEST_END: return "Q";
+ case CON_STATE_RESPONSE_START: return "s";
+ case CON_STATE_RESPONSE_END: return "S";
+- default: return "x";
++ default: return "x";
+ }
+ }
+
+ int connection_set_state(server *srv, connection *con, connection_state_t state) {
+ UNUSED(srv);
+-
++
+ con->state = state;
+-
++
+ return 0;
+ }
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/connections.c lighttpd-1.4.12/src/connections.c
+--- lighttpd-1.4.11/src/connections.c 2006-03-05 22:14:53.000000000 +0200
++++ lighttpd-1.4.12/src/connections.c 2006-07-11 21:23:39.000000000 +0300
+@@ -2,7 +2,6 @@
+
+ #include <stdlib.h>
+ #include <stdio.h>
+-#include <unistd.h>
+ #include <errno.h>
+ #include <string.h>
+ #include <fcntl.h>
+@@ -26,8 +25,8 @@
+ #include "inet_ntop_cache.h"
+
+ #ifdef USE_OPENSSL
+-# include <openssl/ssl.h>
+-# include <openssl/err.h>
++# include <openssl/ssl.h>
++# include <openssl/err.h>
+ #endif
+
+ #ifdef HAVE_SYS_FILIO_H
@@ -35,6 +34,7 @@
#endif
typedef struct {
PLUGIN_DATA;
-@@ -111,9 +111,7 @@
- int connection_close(server *srv, connection *con) {
- #ifdef USE_OPENSSL
- server_socket *srv_sock = con->srv_socket;
--#endif
-
--#ifdef USE_OPENSSL
- if (srv_sock->is_ssl) {
- if (con->ssl) SSL_free(con->ssl);
- con->ssl = NULL;
-@@ -122,7 +120,7 @@
-
- fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
- fdevent_unregister(srv->ev, con->fd);
--#ifdef __WIN32
-+#ifdef _WIN32
- if (closesocket(con->fd)) {
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "(warning) close:", con->fd, strerror(errno));
-@@ -190,150 +188,39 @@
- }
- #endif
+@@ -43,7 +43,7 @@
+ static connection *connections_get_new_connection(server *srv) {
+ connections *conns = srv->conns;
+ size_t i;
+-
++
+ if (conns->size == 0) {
+ conns->size = 128;
+ conns->ptr = NULL;
+@@ -54,21 +54,21 @@
+ } else if (conns->size == conns->used) {
+ conns->size += 128;
+ conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
+-
++
+ for (i = conns->used; i < conns->size; i++) {
+ conns->ptr[i] = connection_init(srv);
+ }
+ }
--static int connection_handle_read(server *srv, connection *con) {
-- int len;
-- buffer *b;
-- int toread;
--#ifdef USE_OPENSSL
-- server_socket *srv_sock = con->srv_socket;
--#endif
+ connection_reset(srv, conns->ptr[conns->used]);
+-#if 0
++#if 0
+ fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
+ for (i = 0; i < conns->used + 1; i++) {
+ fprintf(stderr, "%d ", conns->ptr[i]->fd);
+ }
+ fprintf(stderr, "\n");
+-#endif
+-
++#endif
++
+ conns->ptr[conns->used]->ndx = conns->used;
+ return conns->ptr[conns->used++];
+ }
+@@ -77,26 +77,26 @@
+ size_t i;
+ connections *conns = srv->conns;
+ connection *temp;
+-
++
+ if (con == NULL) return -1;
+-
++
+ if (-1 == con->ndx) return -1;
+-
++
+ i = con->ndx;
+-
++
+ /* not last element */
+-
++
+ if (i != conns->used - 1) {
+ temp = conns->ptr[i];
+ conns->ptr[i] = conns->ptr[conns->used - 1];
+ conns->ptr[conns->used - 1] = temp;
+-
++
+ conns->ptr[i]->ndx = i;
+ conns->ptr[conns->used - 1]->ndx = -1;
+ }
+-
++
+ conns->used--;
+-
++
+ con->ndx = -1;
+ #if 0
+ fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
+@@ -104,25 +104,23 @@
+ fprintf(stderr, "%d ", conns->ptr[i]->fd);
+ }
+ fprintf(stderr, "\n");
+-#endif
++#endif
+ return 0;
+ }
+
+ int connection_close(server *srv, connection *con) {
+ #ifdef USE_OPENSSL
+ server_socket *srv_sock = con->srv_socket;
+-#endif
+-
+-#ifdef USE_OPENSSL
++
+ if (srv_sock->is_ssl) {
+ if (con->ssl) SSL_free(con->ssl);
+ con->ssl = NULL;
+ }
+ #endif
+-
++
+ fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
+ fdevent_unregister(srv->ev, con->fd);
+-#ifdef __WIN32
++#ifdef _WIN32
+ if (closesocket(con->fd)) {
+ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "(warning) close:", con->fd, strerror(errno));
+@@ -133,207 +131,96 @@
+ "(warning) close:", con->fd, strerror(errno));
+ }
+ #endif
+-
++
+ srv->cur_fds--;
+ #if 0
+ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "closed()", con->fd);
+ #endif
+-
++
+ connection_del(srv, con);
+ connection_set_state(srv, con, CON_STATE_CONNECT);
+-
++
+ return 0;
+ }
+
+ #if 0
+ static void dump_packet(const unsigned char *data, size_t len) {
+ size_t i, j;
+-
++
+ if (len == 0) return;
+-
++
+ for (i = 0; i < len; i++) {
+ if (i % 16 == 0) fprintf(stderr, " ");
+-
++
+ fprintf(stderr, "%02x ", data[i]);
+-
++
+ if ((i + 1) % 16 == 0) {
+ fprintf(stderr, " ");
+ for (j = 0; j <= i % 16; j++) {
+ unsigned char c;
+-
++
+ if (i-15+j >= len) break;
+-
++
+ c = data[i-15+j];
+-
++
+ fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
+ }
+-
++
+ fprintf(stderr, "\n");
+ }
+ }
+-
++
+ if (len % 16 != 0) {
+ for (j = i % 16; j < 16; j++) {
+ fprintf(stderr, " ");
+ }
+-
++
+ fprintf(stderr, " ");
+ for (j = i & ~0xf; j < len; j++) {
+ unsigned char c;
+-
++
+ c = data[j];
+ fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+-#endif
-
+-static int connection_handle_read(server *srv, connection *con) {
+- int len;
+- buffer *b;
+- int toread;
+-#ifdef USE_OPENSSL
+- server_socket *srv_sock = con->srv_socket;
+ #endif
+
- b = chunkqueue_get_append_buffer(con->read_queue);
- buffer_prepare_copy(b, 4096);
--
++static network_status_t connection_handle_read(server *srv, connection *con) {
++ off_t oldlen, newlen;
+
-#ifdef USE_OPENSSL
- if (srv_sock->is_ssl) {
- len = SSL_read(con->ssl, b->ptr, b->size - 1);
- return -1;
- }
- buffer_prepare_copy(b, toread);
--
++ oldlen = chunkqueue_length(con->read_queue);
+
- len = read(con->fd, b->ptr, b->size - 1);
- }
-#elif defined(__WIN32)
- log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
- r, ERR_error_string(ssl_err, NULL));
- }
--
++ switch(network_read_chunkqueue(srv, con, con->read_queue)) {
++ case NETWORK_STATUS_SUCCESS:
++ break;
++ case NETWORK_STATUS_WAIT_FOR_EVENT:
++ con->is_readable = 0;
++ return NETWORK_STATUS_WAIT_FOR_EVENT;
++ case NETWORK_STATUS_INTERRUPTED:
++ con->is_readable = 1;
++ return NETWORK_STATUS_WAIT_FOR_EVENT;
++ case NETWORK_STATUS_CONNECTION_CLOSE:
++ /* pipelining */
++ con->is_readable = 0;
++ return NETWORK_STATUS_CONNECTION_CLOSE;
++ case NETWORK_STATUS_FATAL_ERROR:
++ con->is_readable = 0;
++
++ connection_set_state(srv, con, CON_STATE_ERROR);
++ return NETWORK_STATUS_FATAL_ERROR;
++ default:
++ SEGFAULT();
++ break;
++ }
+
- switch(errno) {
- default:
- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
- break;
- case SSL_ERROR_ZERO_RETURN:
- /* clean shutdown on the remote side */
-+static network_status_t connection_handle_read(server *srv, connection *con) {
-+ off_t oldlen, newlen;
-
+-
- if (r == 0) {
- /* FIXME: later */
- }
-+ oldlen = chunkqueue_length(con->read_queue);
-
+-
- /* fall thourgh */
- default:
- while((ssl_err = ERR_get_error())) {
- log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
- r, ERR_error_string(ssl_err, NULL));
- }
-+ switch(network_read_chunkqueue(srv, con, con->read_queue)) {
-+ case NETWORK_STATUS_SUCCESS:
- break;
+- break;
- }
- } else {
- if (errno == EAGAIN) return 0;
-
- return -1;
- } else if (len == 0) {
-+ case NETWORK_STATUS_WAIT_FOR_EVENT:
- con->is_readable = 0;
+- con->is_readable = 0;
- /* the other end close the connection -> KEEP-ALIVE */
-
-+ return NETWORK_STATUS_WAIT_FOR_EVENT;
-+ case NETWORK_STATUS_INTERRUPTED:
-+ con->is_readable = 1;
-+ return NETWORK_STATUS_WAIT_FOR_EVENT;
-+ case NETWORK_STATUS_CONNECTION_CLOSE:
- /* pipelining */
+- /* pipelining */
-
- return -2;
- } else if ((size_t)len < b->size - 1) {
- /* we got less then expected, wait for the next fd-event */
-
- con->is_readable = 0;
-+ return NETWORK_STATUS_CONNECTION_CLOSE;
-+ case NETWORK_STATUS_FATAL_ERROR:
-+ con->is_readable = 0;
-+
-+ connection_set_state(srv, con, CON_STATE_ERROR);
-+ return NETWORK_STATUS_FATAL_ERROR;
-+ default:
-+ SEGFAULT();
-+ break;
- }
-
+- con->is_readable = 0;
+- }
+-
- b->used = len;
- b->ptr[b->used++] = '\0';
-+ newlen = chunkqueue_length(con->read_queue);
-
+-
- con->bytes_read += len;
-#if 0
- dump_packet(b->ptr, len);
-#endif
-+ con->bytes_read += (newlen - oldlen);
-
+-
- return 0;
++ newlen = chunkqueue_length(con->read_queue);
++
++ con->bytes_read += (newlen - oldlen);
++
+ return NETWORK_STATUS_SUCCESS;
}
case HTTP_METHOD_PUT:
case HTTP_METHOD_MKCOL:
case HTTP_METHOD_DELETE:
-@@ -350,6 +238,8 @@
+@@ -350,12 +238,14 @@
case HTTP_METHOD_MOVE:
case HTTP_METHOD_PROPFIND:
case HTTP_METHOD_PROPPATCH:
break;
case HTTP_METHOD_OPTIONS:
/*
-@@ -392,6 +282,8 @@
+ * 400 is coming from the request-parser BEFORE uri.path is set
+- * 403 is from the response handler when noone else catched it
+- *
++ * 403 is from the response handler when noone else catched it
++ *
+ * */
+ if (con->uri.path->used &&
+ con->uri.path->ptr[0] != '*') {
+@@ -381,55 +271,58 @@
+ break;
+ }
+ }
+-
++
+ if (con->http_status == 0) {
+ con->http_status = 403;
+ }
+-
++
+ switch(con->http_status) {
+ case 400: /* class: header + custom body */
+ case 401:
case 403:
case 404:
case 408:
case 411:
case 416:
case 423:
-@@ -399,6 +291,7 @@
+ case 500:
case 501:
case 503:
- case 505:
+- case 505:
++ case 505:
+ case 509:
if (con->mode != DIRECT) break;
-
+-
++
con->file_finished = 0;
-@@ -528,34 +421,37 @@
-
- static int connection_handle_write(server *srv, connection *con) {
- switch(network_write_chunkqueue(srv, con, con->write_queue)) {
-- case 0:
-+ case NETWORK_STATUS_SUCCESS:
- if (con->file_finished) {
- connection_set_state(srv, con, CON_STATE_RESPONSE_END);
- joblist_append(srv, con);
+-
++
+ buffer_reset(con->physical.path);
+-
++
+ /* try to send static errorfile */
+ if (!buffer_is_empty(con->conf.errorfile_prefix)) {
+ stat_cache_entry *sce = NULL;
+-
++
+ buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
+ buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
+-
++
+ if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+ con->file_finished = 1;
+-
++
+ http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
+ }
}
+-
+- if (!con->file_finished) {
++
++ if (!con->file_finished) {
+ buffer *b;
+-
++
+ buffer_reset(con->physical.path);
+-
++
+ con->file_finished = 1;
+ b = chunkqueue_get_append_buffer(con->write_queue);
+-
++
+ /* build default error-page */
+- buffer_copy_string(b,
++ buffer_copy_string(b,
+ "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
+ " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
+@@ -439,7 +332,7 @@
+ buffer_append_long(b, con->http_status);
+ buffer_append_string(b, " - ");
+ buffer_append_string(b, get_http_status_name(con->http_status));
+-
++
+ buffer_append_string(b,
+ "</title>\n"
+ " </head>\n"
+@@ -448,12 +341,12 @@
+ buffer_append_long(b, con->http_status);
+ buffer_append_string(b, " - ");
+ buffer_append_string(b, get_http_status_name(con->http_status));
+-
+- buffer_append_string(b,"</h1>\n"
++
++ buffer_append_string(b,"</h1>\n"
+ " </body>\n"
+ "</html>\n"
+ );
+-
++
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
+ }
+ /* fall through */
+@@ -463,10 +356,10 @@
+ case 301:
+ case 302:
break;
-- case -1: /* error on our side */
-+ case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "connection closed: write failed on fd", con->fd);
- connection_set_state(srv, con, CON_STATE_ERROR);
- joblist_append(srv, con);
- break;
-- case -2: /* remote close */
-+ case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
- connection_set_state(srv, con, CON_STATE_ERROR);
- joblist_append(srv, con);
+-
++
+ case 206: /* write_queue is already prepared */
+ con->file_finished = 1;
+-
++
break;
-- case 1:
-+ case NETWORK_STATUS_WAIT_FOR_EVENT:
- con->is_writable = 0;
-
- /* not finished yet -> WRITE */
+ case 205: /* class: header only */
+ case 304:
+@@ -474,19 +367,19 @@
+ /* disable chunked encoding again as we have no body */
+ con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
+ chunkqueue_reset(con->write_queue);
+-
++
+ con->file_finished = 1;
break;
-+ case NETWORK_STATUS_INTERRUPTED:
-+ con->is_writable = 1;
-+ break;
-+ case NETWORK_STATUS_UNSET:
-+ break;
}
-
- return 0;
- }
+-
++
--
+ if (con->file_finished) {
+- /* we have all the content and chunked encoding is not used, set a content-length */
+-
+- if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
++ /* we have all the content and chunked encoding is not used, set a content-length */
++
++ if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
+ (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
+ buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
+-
++
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
+ }
+ } else {
+@@ -495,74 +388,77 @@
+ ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
+ con->keep_alive = 0;
+ }
+-
++
+ if (0 == (con->parsed_response & HTTP_CONNECTION)) {
+ /* (f)cgi did'nt send Connection: header
+- *
++ *
+ * shall we ?
+ */
+ if (((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) &&
+ (con->parsed_response & HTTP_CONTENT_LENGTH) == 0) {
+ /* without content_length, no keep-alive */
+-
++
+ con->keep_alive = 0;
+ }
+ } else {
+ /* a subrequest disable keep-alive although the client wanted it */
+ if (con->keep_alive && !con->response.keep_alive) {
+ con->keep_alive = 0;
+-
++
+ /* FIXME: we have to drop the Connection: Header from the subrequest */
+ }
+ }
+ }
+-
++
+ if (con->request.http_method == HTTP_METHOD_HEAD) {
+ chunkqueue_reset(con->write_queue);
+ }
+
+ http_response_write_header(srv, con);
+-
++
+ return 0;
+ }
+
+ static int connection_handle_write(server *srv, connection *con) {
+- switch(network_write_chunkqueue(srv, con, con->write_queue)) {
+- case 0:
++ switch(network_write_chunkqueue(srv, con, con->write_queue)) {
++ case NETWORK_STATUS_SUCCESS:
+ if (con->file_finished) {
+ connection_set_state(srv, con, CON_STATE_RESPONSE_END);
+ joblist_append(srv, con);
+ }
+ break;
+- case -1: /* error on our side */
++ case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
+ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connection closed: write failed on fd", con->fd);
+ connection_set_state(srv, con, CON_STATE_ERROR);
+ joblist_append(srv, con);
+ break;
+- case -2: /* remote close */
++ case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
+ connection_set_state(srv, con, CON_STATE_ERROR);
+ joblist_append(srv, con);
+ break;
+- case 1:
++ case NETWORK_STATUS_WAIT_FOR_EVENT:
+ con->is_writable = 0;
+-
++
+ /* not finished yet -> WRITE */
+ break;
++ case NETWORK_STATUS_INTERRUPTED:
++ con->is_writable = 1;
++ break;
++ case NETWORK_STATUS_UNSET:
++ break;
+ }
+-
++
+ return 0;
+ }
+
+-
-
connection *connection_init(server *srv) {
connection *con;
-
-@@ -845,17 +741,20 @@
+-
++
+ UNUSED(srv);
+
+ con = calloc(1, sizeof(*con));
+-
++
+ con->fd = 0;
+ con->ndx = -1;
+ con->fde_ndx = -1;
+@@ -573,32 +469,32 @@
+
+ #define CLEAN(x) \
+ con->x = buffer_init();
+-
++
+ CLEAN(request.uri);
+ CLEAN(request.request_line);
+ CLEAN(request.request);
+ CLEAN(request.pathinfo);
+-
++
+ CLEAN(request.orig_uri);
+-
++
+ CLEAN(uri.scheme);
+ CLEAN(uri.authority);
+ CLEAN(uri.path);
+ CLEAN(uri.path_raw);
+ CLEAN(uri.query);
+-
++
+ CLEAN(physical.doc_root);
+ CLEAN(physical.path);
+ CLEAN(physical.basedir);
+ CLEAN(physical.rel_path);
+ CLEAN(physical.etag);
+ CLEAN(parse_request);
+-
++
+ CLEAN(authed_user);
+ CLEAN(server_name);
+ CLEAN(error_handler);
+ CLEAN(dst_addr_buf);
+-
++
+ #undef CLEAN
+ con->write_queue = chunkqueue_init();
+ con->read_queue = chunkqueue_init();
+@@ -608,26 +504,26 @@
+ con->request.headers = array_init();
+ con->response.headers = array_init();
+ con->environment = array_init();
+-
++
+ /* init plugin specific connection structures */
+-
++
+ con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
+-
++
+ con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
+ config_setup_connection(srv, con);
+-
++
+ return con;
+ }
+
+ void connections_free(server *srv) {
+ connections *conns = srv->conns;
+- size_t i;
+-
++ size_t i;
++
+ for (i = 0; i < conns->size; i++) {
+ connection *con = conns->ptr[i];
+-
++
+ connection_reset(srv, con);
+-
++
+ chunkqueue_free(con->write_queue);
+ chunkqueue_free(con->read_queue);
+ chunkqueue_free(con->request_content_queue);
+@@ -637,27 +533,27 @@
+
+ #define CLEAN(x) \
+ buffer_free(con->x);
+-
++
+ CLEAN(request.uri);
+ CLEAN(request.request_line);
+ CLEAN(request.request);
+ CLEAN(request.pathinfo);
+-
++
+ CLEAN(request.orig_uri);
+-
++
+ CLEAN(uri.scheme);
+ CLEAN(uri.authority);
+ CLEAN(uri.path);
+ CLEAN(uri.path_raw);
+ CLEAN(uri.query);
+-
++
+ CLEAN(physical.doc_root);
+ CLEAN(physical.path);
+ CLEAN(physical.basedir);
+ CLEAN(physical.etag);
+ CLEAN(physical.rel_path);
+ CLEAN(parse_request);
+-
++
+ CLEAN(authed_user);
+ CLEAN(server_name);
+ CLEAN(error_handler);
+@@ -665,97 +561,97 @@
+ #undef CLEAN
+ free(con->plugin_ctx);
+ free(con->cond_cache);
+-
++
+ free(con);
+ }
+-
++
+ free(conns->ptr);
+ }
+
+
+ int connection_reset(server *srv, connection *con) {
+ size_t i;
+-
++
+ plugins_call_connection_reset(srv, con);
+-
++
+ con->is_readable = 1;
+ con->is_writable = 1;
+ con->http_status = 0;
+ con->file_finished = 0;
+ con->file_started = 0;
+ con->got_response = 0;
+-
++
+ con->parsed_response = 0;
+-
++
+ con->bytes_written = 0;
+ con->bytes_written_cur_second = 0;
+ con->bytes_read = 0;
+ con->bytes_header = 0;
+ con->loops_per_request = 0;
+-
++
+ con->request.http_method = HTTP_METHOD_UNSET;
+ con->request.http_version = HTTP_VERSION_UNSET;
+-
++
+ con->request.http_if_modified_since = NULL;
+ con->request.http_if_none_match = NULL;
+-
++
+ con->response.keep_alive = 0;
+ con->response.content_length = -1;
+ con->response.transfer_encoding = 0;
+-
++
+ con->mode = DIRECT;
+-
++
+ #define CLEAN(x) \
+ if (con->x) buffer_reset(con->x);
+-
++
+ CLEAN(request.uri);
+ CLEAN(request.request_line);
+ CLEAN(request.pathinfo);
+ CLEAN(request.request);
+-
++
+ CLEAN(request.orig_uri);
+-
++
+ CLEAN(uri.scheme);
+ CLEAN(uri.authority);
+ CLEAN(uri.path);
+ CLEAN(uri.path_raw);
+ CLEAN(uri.query);
+-
++
+ CLEAN(physical.doc_root);
+ CLEAN(physical.path);
+ CLEAN(physical.basedir);
+ CLEAN(physical.rel_path);
+ CLEAN(physical.etag);
+-
++
+ CLEAN(parse_request);
+-
++
+ CLEAN(authed_user);
+ CLEAN(server_name);
+ CLEAN(error_handler);
+-#undef CLEAN
+-
++#undef CLEAN
++
+ #define CLEAN(x) \
+- if (con->x) con->x->used = 0;
+-
++ if (con->x) con->x->used = 0;
++
+ #undef CLEAN
+-
++
+ #define CLEAN(x) \
+ con->request.x = NULL;
+-
++
+ CLEAN(http_host);
+ CLEAN(http_range);
+ CLEAN(http_content_type);
+ #undef CLEAN
+ con->request.content_length = 0;
+-
++
+ array_reset(con->request.headers);
+ array_reset(con->response.headers);
+ array_reset(con->environment);
+-
++
+ chunkqueue_reset(con->write_queue);
+ chunkqueue_reset(con->request_content_queue);
+
+- /* the plugins should cleanup themself */
++ /* the plugins should cleanup themself */
+ for (i = 0; i < srv->plugins.used; i++) {
+ plugin *p = ((plugin **)(srv->plugins.ptr))[i];
+ plugin_data *pd = p->data;
+@@ -768,7 +664,7 @@
+
+ con->plugin_ctx[pd->id] = NULL;
+ }
+-
++
+ #if COND_RESULT_UNSET
+ for (i = srv->config_context->used - 1; i >= 0; i --) {
+ con->cond_cache[i].result = COND_RESULT_UNSET;
+@@ -777,56 +673,56 @@
+ #else
+ memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
+ #endif
+-
++
+ con->header_len = 0;
+ con->in_error_handler = 0;
+-
++
+ config_setup_connection(srv, con);
+-
++
+ return 0;
+ }
+
+ /**
+- *
+- * search for \r\n\r\n
+- *
++ *
++ * search for \r\n\r\n
++ *
+ * this is a special 32bit version which is using a sliding window for
+- * the comparisions
+- *
++ * the comparisions
++ *
+ * how it works:
+- *
++ *
+ * b: 'abcdefg'
+ * rnrn: 'cdef'
+- *
++ *
+ * cmpbuf: abcd != cdef
+ * cmpbuf: bcde != cdef
+ * cmpbuf: cdef == cdef -> return &c
+- *
+- * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
++ *
++ * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
+ * maintain cmpbuf and rnrn
+- *
++ *
+ */
+
+ char *buffer_search_rnrn(buffer *b) {
+ uint32_t cmpbuf, rnrn;
+ char *cp;
+ size_t i;
+-
++
+ if (b->used < 4) return NULL;
+-
++
+ rnrn = ('\r' << 24) | ('\n' << 16) |
+ ('\r' << 8) | ('\n' << 0);
+-
++
+ cmpbuf = (b->ptr[0] << 24) | (b->ptr[1] << 16) |
+ (b->ptr[2] << 8) | (b->ptr[3] << 0);
+-
++
+ cp = b->ptr + 4;
+ for (i = 0; i < b->used - 4; i++) {
+ if (cmpbuf == rnrn) return cp - 4;
+-
++
+ cmpbuf = (cmpbuf << 8 | *(cp++)) & 0xffffffff;
+ }
+-
++
+ return NULL;
+ }
+ /**
+@@ -840,22 +736,25 @@
+ chunk *c;
+ chunkqueue *cq = con->read_queue;
+ chunkqueue *dst_cq = con->request_content_queue;
+-
++
+ if (con->is_readable) {
con->read_idle_ts = srv->cur_ts;
-
+-
++
switch(connection_handle_read(srv, con)) {
- case -1:
+ case NETWORK_STATUS_FATAL_ERROR:
}
default:
break;
-@@ -925,6 +824,7 @@
-
+@@ -891,14 +790,14 @@
+ /* the last node was empty */
+ if (c->next == NULL) {
+ cq->last = c;
+- }
++ }
+
+ c = c->next;
+ } else {
+ c = c->next;
+ }
+ }
+-
++
+ /* nothing to handle */
+ if (cq->first == NULL) return 0;
+
+@@ -906,25 +805,26 @@
+ case CON_STATE_READ:
+ /* prepare con->request.request */
+ c = cq->first;
+-
++
+ /* check if we need the full package */
+ if (con->request.request->used == 0) {
+ buffer b;
+-
++
+ b.ptr = c->mem->ptr + c->offset;
+ b.used = c->mem->used - c->offset;
+-
++
+ if (NULL != (h_term = buffer_search_rnrn(&b))) {
+ /* \r\n\r\n found
+ * - copy everything incl. the terminator to request.request
+ */
+-
+- buffer_copy_string_len(con->request.request,
+- b.ptr,
++
++ buffer_copy_string_len(con->request.request,
++ b.ptr,
+ h_term - b.ptr + 4);
+-
++
/* the buffer has been read up to the terminator */
c->offset += h_term - b.ptr + 4;
+
} else {
/* not found, copy everything */
buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
-@@ -1177,6 +1077,13 @@
- if (con->state == CON_STATE_READ ||
- con->state == CON_STATE_READ_POST) {
- connection_handle_read_state(srv, con);
-+ /**
-+ * if SSL_read() is not readin in the full packet we won't get
-+ * a fdevent as the low-level has already fetched everything.
-+ *
-+ * we have to call the state-engine to read the rest of the packet
-+ */
-+ if (con->is_readable) joblist_append(srv, con);
- }
-
- if (con->state == CON_STATE_WRITE &&
-@@ -1233,9 +1140,13 @@
- cnt_len = sizeof(cnt_addr);
-
- if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
-+#ifdef _WIN32
+@@ -932,14 +832,14 @@
+ }
+ } else {
+ /* have to take care of overlapping header terminators */
+-
++
+ size_t l = con->request.request->used - 2;
+ char *s = con->request.request->ptr;
+ buffer b;
+-
++
+ b.ptr = c->mem->ptr + c->offset;
+ b.used = c->mem->used - c->offset;
+-
++
+ if (con->request.request->used - 1 > 3 &&
+ c->mem->used > 1 &&
+ s[l-2] == '\r' &&
+@@ -948,7 +848,7 @@
+ c->mem->ptr[0] == '\n') {
+ buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
+ c->offset += 1;
+-
++
+ h_term = con->request.request->ptr;
+ } else if (con->request.request->used - 1 > 2 &&
+ c->mem->used > 2 &&
+@@ -958,7 +858,7 @@
+ c->mem->ptr[1] == '\n') {
+ buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
+ c->offset += 2;
+-
++
+ h_term = con->request.request->ptr;
+ } else if (con->request.request->used - 1 > 1 &&
+ c->mem->used > 3 &&
+@@ -968,17 +868,17 @@
+ c->mem->ptr[2] == '\n') {
+ buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3);
+ c->offset += 3;
+-
++
+ h_term = con->request.request->ptr;
+ } else if (NULL != (h_term = buffer_search_string_len(&b, "\r\n\r\n", 4))) {
+ /* \r\n\r\n found
+ * - copy everything incl. the terminator to request.request
+ */
+-
+- buffer_append_string_len(con->request.request,
+- c->mem->ptr + c->offset,
++
++ buffer_append_string_len(con->request.request,
++ c->mem->ptr + c->offset,
+ c->offset + h_term - b.ptr + 4);
+-
++
+ /* the buffer has been read up to the terminator */
+ c->offset += h_term - b.ptr + 4;
+ } else {
+@@ -999,16 +899,16 @@
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+ }
+ break;
+- case CON_STATE_READ_POST:
++ case CON_STATE_READ_POST:
+ for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
+ off_t weWant, weHave, toRead;
+-
++
+ weWant = con->request.content_length - dst_cq->bytes_in;
+-
++
+ assert(c->mem->used);
+-
++
+ weHave = c->mem->used - c->offset - 1;
+-
++
+ toRead = weHave > weWant ? weWant : weHave;
+
+ /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
+@@ -1017,13 +917,13 @@
+ /* copy everything to max 1Mb sized tempfiles */
+
+ /*
+- * if the last chunk is
++ * if the last chunk is
+ * - smaller than 1Mb (size < 1Mb)
+ * - not read yet (offset == 0)
+ * -> append to it
+ * otherwise
+- * -> create a new chunk
+- *
++ * -> create a new chunk
++ *
+ * */
+
+ if (dst_cq->last &&
+@@ -1056,14 +956,14 @@
+ /* we have a chunk, let's write to it */
+
+ if (dst_c->file.fd == -1) {
+- /* we don't have file to write to,
++ /* we don't have file to write to,
+ * EACCES might be one reason.
+ *
+ * Instead of sending 500 we send 413 and say the request is too large
+ * */
+
+ log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "denying upload as opening to temp-file for upload failed:",
++ "denying upload as opening to temp-file for upload failed:",
+ dst_c->file.name, strerror(errno));
+
+ con->http_status = 413; /* Request-Entity too large */
+@@ -1074,15 +974,15 @@
+ }
+
+ if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
+- /* write failed for some reason ... disk full ? */
++ /* write failed for some reason ... disk full ? */
+ log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "denying upload as writing to file failed:",
++ "denying upload as writing to file failed:",
+ dst_c->file.name, strerror(errno));
+-
++
+ con->http_status = 413; /* Request-Entity too large */
+ con->keep_alive = 0;
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+-
++
+ close(dst_c->file.fd);
+ dst_c->file.fd = -1;
+
+@@ -1090,7 +990,7 @@
+ }
+
+ dst_c->file.length += toRead;
+-
++
+ if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
+ /* we read everything, close the chunk */
+ close(dst_c->file.fd);
+@@ -1102,7 +1002,7 @@
+ b = chunkqueue_get_append_buffer(dst_cq);
+ buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
+ }
+-
++
+ c->offset += toRead;
+ dst_cq->bytes_in += toRead;
+ }
+@@ -1111,7 +1011,7 @@
+ if (dst_cq->bytes_in == (off_t)con->request.content_length) {
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+ }
+-
++
+ break;
+ }
+
+@@ -1123,9 +1023,9 @@
+ handler_t connection_handle_fdevent(void *s, void *context, int revents) {
+ server *srv = (server *)s;
+ connection *con = context;
+-
++
+ joblist_append(srv, con);
+-
++
+ if (revents & FDEVENT_IN) {
+ con->is_readable = 1;
+ #if 0
+@@ -1136,19 +1036,19 @@
+ con->is_writable = 1;
+ /* we don't need the event twice */
+ }
+-
+-
++
++
+ if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
+ /* looks like an error */
+-
++
+ /* FIXME: revents = 0x19 still means that we should read from the queue */
+ if (revents & FDEVENT_HUP) {
+ if (con->state == CON_STATE_CLOSE) {
+ con->close_timeout_ts = 0;
+ } else {
+ /* sigio reports the wrong event here
+- *
+- * there was no HUP at all
++ *
++ * there was no HUP at all
+ */
+ #ifdef USE_LINUX_SIGIO
+ if (srv->ev->in_sigio == 1) {
+@@ -1160,32 +1060,39 @@
+ #else
+ connection_set_state(srv, con, CON_STATE_ERROR);
+ #endif
+-
++
+ }
+ } else if (revents & FDEVENT_ERR) {
+ #ifndef USE_LINUX_SIGIO
+ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connection closed: poll() -> ERR", con->fd);
+-#endif
++#endif
+ connection_set_state(srv, con, CON_STATE_ERROR);
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connection closed: poll() -> ???", revents);
+- }
++ }
+ }
+-
++
+ if (con->state == CON_STATE_READ ||
+ con->state == CON_STATE_READ_POST) {
+ connection_handle_read_state(srv, con);
++ /**
++ * if SSL_read() is not readin in the full packet we won't get
++ * a fdevent as the low-level has already fetched everything.
++ *
++ * we have to call the state-engine to read the rest of the packet
++ */
++ if (con->is_readable) joblist_append(srv, con);
+ }
+-
++
+ if (con->state == CON_STATE_WRITE &&
+ !chunkqueue_is_empty(con->write_queue) &&
+ con->is_writable) {
+-
++
+ if (-1 == connection_handle_write(srv, con)) {
+ connection_set_state(srv, con, CON_STATE_ERROR);
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ds",
+ con->fd,
+ "handle write failed.");
+@@ -1193,30 +1100,30 @@
+ con->write_request_ts = srv->cur_ts;
+ }
+ }
+-
++
+ if (con->state == CON_STATE_CLOSE) {
+ /* flush the read buffers */
+ int b;
+-
++
+ if (ioctl(con->fd, FIONREAD, &b)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "ioctl() failed", strerror(errno));
+ }
+-
++
+ if (b > 0) {
+ char buf[1024];
+ log_error_write(srv, __FILE__, __LINE__, "sdd",
+ "CLOSE-read()", con->fd, b);
+-
++
+ /* */
+ read(con->fd, buf, sizeof(buf));
+ } else {
+ /* nothing to read */
+-
++
+ con->close_timeout_ts = 0;
+ }
+ }
+-
++
+ return HANDLER_FINISHED;
+ }
+
+@@ -1229,63 +1136,68 @@
+ sock_addr cnt_addr;
+ socklen_t cnt_len;
+ /* accept it and register the fd */
+-
++
+ cnt_len = sizeof(cnt_addr);
+
+ if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
++#ifdef _WIN32
+ errno = WSAGetLastError();
+#endif
if ((errno != EAGAIN) &&
}
return NULL;
} else {
-@@ -1251,7 +1162,6 @@
+ connection *con;
+-
++
+ srv->cur_fds++;
+-
++
+ /* ok, we have the connection, register it */
+ #if 0
+ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "appected()", cnt);
+ #endif
srv->con_opened++;
-
+-
++
con = connections_get_new_connection(srv);
-
con->fd = cnt;
con->fde_ndx = -1;
- #if 0
-@@ -1268,6 +1178,7 @@
-
+-#if 0
++#if 0
+ gettimeofday(&(con->start_tv), NULL);
+-#endif
++#endif
+ fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
+-
++
+ connection_set_state(srv, con, CON_STATE_REQUEST_START);
+-
++
+ con->connection_start = srv->cur_ts;
+ con->dst_addr = cnt_addr;
+ buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
+ con->srv_socket = srv_socket;
+-
++
if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
+ connection_close(srv, con);
return NULL;
}
#ifdef USE_OPENSSL
-@@ -1276,7 +1187,7 @@
+ /* connect FD to SSL */
+ if (srv_socket->is_ssl) {
if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
ERR_error_string(ERR_get_error(), NULL));
-
+ connection_close(srv, con);
return NULL;
}
-
-@@ -1286,6 +1197,7 @@
+-
++
+ SSL_set_accept_state(con->ssl);
+ con->conf.is_ssl=1;
+-
++
if (1 != (SSL_set_fd(con->ssl, cnt))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
ERR_error_string(ERR_get_error(), NULL));
+ connection_close(srv, con);
return NULL;
}
}
---- lighttpd-1.4.11/src/crc32.h 2005-09-30 20:18:59.000000000 +0300
-+++ lighttpd/src/crc32.h 2006-07-11 21:23:40.131857983 +0300
-@@ -6,6 +6,7 @@
- #endif
-
- #include <sys/types.h>
-+#include <stdlib.h>
-
- #if defined HAVE_STDINT_H
- #include <stdint.h>
-@@ -13,6 +14,10 @@
- #include <inttypes.h>
+@@ -1300,10 +1212,10 @@
+ #ifdef USE_OPENSSL
+ server_socket *srv_sock = con->srv_socket;
#endif
-
-+#ifdef _WIN32
-+#define uint32_t unsigned __int32
-+#endif
+-
+
- uint32_t generate_crc32c(char *string, size_t length);
-
- #endif
---- lighttpd-1.4.11/src/etag.h 2005-08-11 01:26:40.000000000 +0300
-+++ lighttpd/src/etag.h 2006-07-11 21:23:40.027851469 +0300
-@@ -3,7 +3,6 @@
-
- #include <sys/types.h>
- #include <sys/stat.h>
--#include <unistd.h>
-
- #include "buffer.h"
-
---- lighttpd-1.4.11/src/fdevent.c 2005-11-15 10:51:05.000000000 +0200
-+++ lighttpd/src/fdevent.c 2006-07-11 21:23:40.287867754 +0300
-@@ -2,7 +2,6 @@
-
- #include "settings.h"
-
--#include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
-@@ -12,6 +11,8 @@
- #include "fdevent.h"
- #include "buffer.h"
-
-+#include "sys-socket.h"
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "state at start",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "state at start",
+ con->fd,
+ connection_get_state(con->state));
+ }
+@@ -1311,91 +1223,91 @@
+ while (done == 0) {
+ size_t ostate = con->state;
+ int b;
+-
+
- fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
- fdevents *ev;
-
-@@ -181,6 +182,9 @@
- }
-
- int fdevent_fcntl_set(fdevents *ev, int fd) {
-+#ifdef _WIN32
-+ int i = 1;
-+#endif
- #ifdef FD_CLOEXEC
- /* close fd on exec (cgi) */
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-@@ -188,6 +192,8 @@
- if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
- #ifdef O_NONBLOCK
- return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
-+#elif defined _WIN32
-+ return ioctlsocket(fd, FIONBIO, &i);
- #else
- return 0;
- #endif
---- lighttpd-1.4.11/src/fdevent.h 2005-09-27 11:26:33.000000000 +0300
-+++ lighttpd/src/fdevent.h 2006-07-11 21:23:39.883842449 +0300
-@@ -31,9 +31,11 @@
- # include <signal.h>
- # endif
- #endif
--
-+#ifdef _WIN32
-+# define HAVE_SELECT
-+#endif
- #if defined HAVE_SELECT
--# ifdef __WIN32
-+# ifdef _WIN32
- # include <winsock2.h>
- # endif
- # define USE_SELECT
---- lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c 2005-09-01 10:46:24.000000000 +0300
-+++ lighttpd/src/fdevent_freebsd_kqueue.c 2006-07-11 21:23:39.987848963 +0300
-@@ -1,6 +1,5 @@
- #include <sys/types.h>
+ switch (con->state) {
+ case CON_STATE_REQUEST_START: /* transient */
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "state for fd", con->fd, connection_get_state(con->state));
+ }
+-
++
+ con->request_start = srv->cur_ts;
+ con->read_idle_ts = srv->cur_ts;
+-
++
+ con->request_count++;
+ con->loops_per_request = 0;
+-
++
+ connection_set_state(srv, con, CON_STATE_READ);
+-
++
+ break;
+ case CON_STATE_REQUEST_END: /* transient */
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "state for fd", con->fd, connection_get_state(con->state));
+ }
+-
++
+ if (http_request_parse(srv, con)) {
+ /* we have to read some data from the POST request */
+-
++
+ connection_set_state(srv, con, CON_STATE_READ_POST);
--#include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
---- lighttpd-1.4.11/src/fdevent_linux_rtsig.c 2005-11-21 19:56:11.000000000 +0200
-+++ lighttpd/src/fdevent_linux_rtsig.c 2006-07-11 21:23:40.179860989 +0300
-@@ -1,6 +1,5 @@
- #include <sys/types.h>
-
--#include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-@@ -14,6 +13,7 @@
- #include "fdevent.h"
- #include "settings.h"
- #include "buffer.h"
-+#include "sys-process.h"
-
- #ifdef USE_LINUX_SIGIO
- static void fdevent_linux_rtsig_free(fdevents *ev) {
---- lighttpd-1.4.11/src/fdevent_linux_sysepoll.c 2005-09-30 20:29:27.000000000 +0300
-+++ lighttpd/src/fdevent_linux_sysepoll.c 2006-07-11 21:23:40.223863745 +0300
-@@ -1,6 +1,5 @@
- #include <sys/types.h>
-
--#include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-@@ -12,6 +11,8 @@
- #include "settings.h"
- #include "buffer.h"
-
-+#include "sys-files.h"
+ break;
+ }
+-
+
- #ifdef USE_LINUX_EPOLL
- static void fdevent_linux_sysepoll_free(fdevents *ev) {
- close(ev->epoll_fd);
---- lighttpd-1.4.11/src/fdevent_poll.c 2005-11-18 13:59:16.000000000 +0200
-+++ lighttpd/src/fdevent_poll.c 2006-07-11 21:23:40.207862743 +0300
-@@ -1,6 +1,5 @@
- #include <sys/types.h>
-
--#include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
---- lighttpd-1.4.11/src/fdevent_select.c 2005-08-31 11:12:46.000000000 +0300
-+++ lighttpd/src/fdevent_select.c 2006-07-11 21:23:40.211862994 +0300
-@@ -1,18 +1,19 @@
--#include <sys/time.h>
- #include <sys/types.h>
-
--#include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <assert.h>
-+#include <stdio.h>
-
- #include "fdevent.h"
- #include "settings.h"
- #include "buffer.h"
-
-+#include "sys-socket.h"
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+-
+
- #ifdef USE_SELECT
-
- static int fdevent_select_reset(fdevents *ev) {
-@@ -38,7 +39,9 @@
- UNUSED(fde_ndx);
-
- /* we should be protected by max-fds, but you never know */
-+#ifndef _WIN32
- assert(fd < FD_SETSIZE);
-+#endif
-
- if (events & FDEVENT_IN) {
- FD_SET(fd, &(ev->select_set_read));
---- lighttpd-1.4.11/src/fdevent_solaris_devpoll.c 2005-09-01 10:45:26.000000000 +0300
-+++ lighttpd/src/fdevent_solaris_devpoll.c 2006-07-11 21:23:40.015850717 +0300
-@@ -1,6 +1,5 @@
- #include <sys/types.h>
-
--#include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
---- lighttpd-1.4.11/src/http-header-glue.c 2006-02-08 15:31:36.000000000 +0200
-+++ lighttpd/src/http-header-glue.c 2006-07-11 21:23:40.187861491 +0300
-@@ -261,13 +261,22 @@
- con->http_status = 304;
- return HANDLER_FINISHED;
- } else {
-+#ifdef HAVE_STRPTIME
- char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
--
-- /* convert to timestamp */
-- if (used_len < sizeof(buf)) {
- time_t t_header, t_file;
- struct tm tm;
-
-+ /* check if we can safely copy the string */
-+ if (used_len >= sizeof(buf)) {
-+ log_error_write(srv, __FILE__, __LINE__, "ssdd",
-+ "DEBUG: Last-Modified check failed as the received timestamp was too long:",
-+ con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
+ break;
+ case CON_STATE_HANDLE_REQUEST:
+- /*
++ /*
+ * the request is parsed
+- *
++ *
+ * decided what to do with the request
+- * -
+- *
+- *
++ * -
++ *
++ *
+ */
+-
+
-+ con->http_status = 412;
-+ return HANDLER_FINISHED;
-+ }
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "state for fd", con->fd, connection_get_state(con->state));
+ }
+-
+
+ switch (r = http_response_prepare(srv, con)) {
+ case HANDLER_FINISHED:
+ if (con->http_status == 404 ||
+ con->http_status == 403) {
+ /* 404 error-handler */
+-
+- if (con->in_error_handler == 0 &&
+
- strncpy(buf, con->request.http_if_modified_since, used_len);
- buf[used_len] = '\0';
-
-@@ -277,18 +286,13 @@
- strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
- t_file = mktime(&tm);
-
-- if (t_file > t_header) {
-- con->http_status = 304;
-- return HANDLER_FINISHED;
-- }
-- } else {
-- log_error_write(srv, __FILE__, __LINE__, "ssdd",
-- "DEBUG: Last-Modified check failed as the received timestamp was too long:",
-- con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
-+ if (t_file > t_header) return HANDLER_GO_ON;
-
-- con->http_status = 412;
-+ con->http_status = 304;
- return HANDLER_FINISHED;
-- }
-+#else
-+ return HANDLER_GO_ON;
-+#endif
++ if (con->in_error_handler == 0 &&
+ (!buffer_is_empty(con->conf.error_handler) ||
+ !buffer_is_empty(con->error_handler))) {
+ /* call error-handler */
+-
++
+ con->error_handler_saved_status = con->http_status;
+ con->http_status = 0;
+-
++
+ if (buffer_is_empty(con->error_handler)) {
+ buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
+ } else {
+ buffer_copy_string_buffer(con->request.uri, con->error_handler);
+ }
+ buffer_reset(con->physical.path);
+-
++
+ con->in_error_handler = 1;
+-
++
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+-
++
+ done = -1;
+ break;
+ } else if (con->in_error_handler) {
+ /* error-handler is a 404 */
+-
++
+ /* continue as normal, status is the same */
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "Warning: Either the error-handler returned status 404 or the error-handler itself was not found:", con->request.uri);
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "returning the original status", con->error_handler_saved_status);
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "If this is a rails app: check your production.log");
+ con->http_status = con->error_handler_saved_status;
}
- } else {
- con->http_status = 304;
-@@ -312,6 +316,31 @@
- if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
- con->http_status = 304;
- return HANDLER_FINISHED;
-+ } else {
-+#ifdef HAVE_STRPTIME
-+ char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
-+ time_t t_header, t_file;
-+ struct tm tm;
+@@ -1403,26 +1315,26 @@
+ /* error-handler is back and has generated content */
+ /* if Status: was set, take it otherwise use 200 */
+ }
+-
+
-+ /* convert to timestamp */
-+ if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
+ if (con->http_status == 0) con->http_status = 200;
+-
+
-+ strncpy(buf, con->request.http_if_modified_since, used_len);
-+ buf[used_len] = '\0';
+ /* we have something to send, go on */
+ connection_set_state(srv, con, CON_STATE_RESPONSE_START);
+ break;
+ case HANDLER_WAIT_FOR_FD:
+ srv->want_fds++;
+-
+
-+ strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
-+ t_header = mktime(&tm);
+ fdwaitqueue_append(srv, con);
+-
+
-+ strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
-+ t_file = mktime(&tm);
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+-
+
-+ if (t_file > t_header) return HANDLER_GO_ON;
+ break;
+ case HANDLER_COMEBACK:
+ done = -1;
+ case HANDLER_WAIT_FOR_EVENT:
+ /* come back here */
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+-
+
-+ con->http_status = 304;
-+ return HANDLER_FINISHED;
-+#else
-+ return HANDLER_GO_ON;
-+#endif
- }
- }
-
---- lighttpd-1.4.11/src/http_auth.c 2006-02-01 13:02:52.000000000 +0200
-+++ lighttpd/src/http_auth.c 2006-07-11 21:23:40.115856981 +0300
-@@ -22,7 +22,6 @@
- #include <string.h>
- #include <time.h>
- #include <errno.h>
--#include <unistd.h>
- #include <ctype.h>
-
- #include "server.h"
-@@ -31,23 +30,14 @@
- #include "http_auth_digest.h"
- #include "stream.h"
-
-+#include "sys-strings.h"
+ break;
+ case HANDLER_ERROR:
+ /* something went wrong */
+@@ -1432,44 +1344,44 @@
+ log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
+ break;
+ }
+-
++
+ break;
+ case CON_STATE_RESPONSE_START:
+- /*
++ /*
+ * the decision is done
+ * - create the HTTP-Response-Header
+- *
++ *
+ */
+-
++
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "state for fd", con->fd, connection_get_state(con->state));
+ }
+-
++
+ if (-1 == connection_handle_write_prepare(srv, con)) {
+ connection_set_state(srv, con, CON_STATE_ERROR);
+-
++
+ break;
+ }
+-
++
+ connection_set_state(srv, con, CON_STATE_WRITE);
+ break;
+ case CON_STATE_RESPONSE_END: /* transient */
+ /* log the request */
+-
++
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "state for fd", con->fd, connection_get_state(con->state));
+ }
+-
++
+ plugins_call_handle_request_done(srv, con);
+-
++
+ srv->con_written++;
+-
++
+ if (con->keep_alive) {
+ connection_set_state(srv, con, CON_STATE_REQUEST_START);
+-
+-#if 0
++
++#if 0
+ con->request_start = srv->cur_ts;
+ con->read_idle_ts = srv->cur_ts;
+ #endif
+@@ -1482,7 +1394,7 @@
+ log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
+ break;
+ }
+-
+
#ifdef USE_OPENSSL
- # include <openssl/md5.h>
- #else
- # include "md5.h"
+ if (srv_sock->is_ssl) {
+ switch (SSL_shutdown(con->ssl)) {
+@@ -1490,44 +1402,44 @@
+ /* done */
+ break;
+ case 0:
+- /* wait for fd-event
+- *
++ /* wait for fd-event
++ *
+ * FIXME: wait for fdevent and call SSL_shutdown again
+- *
++ *
+ */
+-
++
+ break;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL));
+ }
+ }
#endif
-
--
--#ifdef USE_PAM
--#include <security/pam_appl.h>
--#include <security/pam_misc.h>
--
--static struct pam_conv conv = {
-- misc_conv,
-- NULL
--};
--#endif
--
- handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
-
- static const char base64_pad = '=';
-@@ -509,33 +499,6 @@
- if (0 == strcmp(password->ptr, pw)) {
- return 0;
- }
-- } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) {
--#ifdef USE_PAM
-- pam_handle_t *pamh=NULL;
-- int retval;
--
-- retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
--
-- if (retval == PAM_SUCCESS)
-- retval = pam_authenticate(pamh, 0); /* is user really user? */
--
-- if (retval == PAM_SUCCESS)
-- retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
--
-- /* This is where we have been authorized or not. */
--
-- if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
-- pamh = NULL;
-- log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
-- }
--
-- if (retval == PAM_SUCCESS) {
-- log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
-- return 0;
-- } else {
-- log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
-- }
--#endif
- } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
- #ifdef USE_LDAP
- LDAP *ldap;
---- lighttpd-1.4.11/src/http_auth.h 2005-08-14 17:12:31.000000000 +0300
-+++ lighttpd/src/http_auth.h 2006-07-11 21:23:40.119857231 +0300
-@@ -9,9 +9,13 @@
- # include <ldap.h>
+ connection_close(srv, con);
+-
++
+ srv->con_closed++;
+ }
+-
++
+ connection_reset(srv, con);
+-
++
+ break;
+ case CON_STATE_CONNECT:
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "state for fd", con->fd, connection_get_state(con->state));
+ }
+-
++
+ chunkqueue_reset(con->read_queue);
+-
++
+ con->request_count = 0;
+-
++
+ break;
+ case CON_STATE_CLOSE:
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "state for fd", con->fd, connection_get_state(con->state));
+ }
+-
++
+ if (con->keep_alive) {
+ if (ioctl(con->fd, FIONREAD, &b)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+@@ -1537,43 +1449,43 @@
+ char buf[1024];
+ log_error_write(srv, __FILE__, __LINE__, "sdd",
+ "CLOSE-read()", con->fd, b);
+-
++
+ /* */
+ read(con->fd, buf, sizeof(buf));
+ } else {
+ /* nothing to read */
+-
++
+ con->close_timeout_ts = 0;
+ }
+ } else {
+ con->close_timeout_ts = 0;
+ }
+-
++
+ if (srv->cur_ts - con->close_timeout_ts > 1) {
+ connection_close(srv, con);
+-
++
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connection closed for fd", con->fd);
+ }
+ }
+-
++
+ break;
+ case CON_STATE_READ_POST:
+ case CON_STATE_READ:
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "state for fd", con->fd, connection_get_state(con->state));
+ }
+-
++
+ connection_handle_read_state(srv, con);
+ break;
+ case CON_STATE_WRITE:
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "state for fd", con->fd, connection_get_state(con->state));
+ }
+-
++
+ /* only try to write if we have something in the queue */
+ if (!chunkqueue_is_empty(con->write_queue)) {
+ #if 0
+@@ -1593,10 +1505,10 @@
+ con->write_request_ts = srv->cur_ts;
+ }
+ }
+-
++
+ break;
+ case CON_STATE_ERROR: /* transient */
+-
++
+ /* even if the connection was drop we still have to write it to the access log */
+ if (con->http_status) {
+ plugins_call_handle_request_done(srv, con);
+@@ -1612,19 +1524,19 @@
+ SSL_shutdown(con->ssl);
+ break;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
+- SSL_get_error(con->ssl, ret),
++ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
++ SSL_get_error(con->ssl, ret),
+ ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+ }
+ }
#endif
+-
++
+ switch(con->mode) {
+ case DIRECT:
+ #if 0
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "emergency exit: direct",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "emergency exit: direct",
+ con->fd);
+ #endif
+ break;
+@@ -1639,35 +1551,35 @@
+ }
+ break;
+ }
+-
++
+ connection_reset(srv, con);
+-
++
+ /* close the connection */
+ if ((con->keep_alive == 1) &&
+ (0 == shutdown(con->fd, SHUT_WR))) {
+ con->close_timeout_ts = srv->cur_ts;
+ connection_set_state(srv, con, CON_STATE_CLOSE);
+-
++
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "shutdown for fd", con->fd);
+ }
+ } else {
+ connection_close(srv, con);
+ }
+-
++
+ con->keep_alive = 0;
+-
++
+ srv->con_closed++;
+-
++
+ break;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "sdd",
++ log_error_write(srv, __FILE__, __LINE__, "sdd",
+ "unknown state:", con->fd, con->state);
+-
++
+ break;
+ }
+-
++
+ if (done == -1) {
+ done = 0;
+ } else if (ostate == con->state) {
+@@ -1676,12 +1588,12 @@
+ }
--typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN,
-- AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD,
-- AUTH_BACKEND_HTDIGEST, AUTH_BACKEND_PAM } auth_backend_t;
-+typedef enum {
-+ AUTH_BACKEND_UNSET,
-+ AUTH_BACKEND_PLAIN,
-+ AUTH_BACKEND_LDAP,
-+ AUTH_BACKEND_HTPASSWD,
-+ AUTH_BACKEND_HTDIGEST
-+} auth_backend_t;
-
- typedef struct {
- /* auth */
---- lighttpd-1.4.11/src/http_chunk.c 2005-08-11 01:26:50.000000000 +0300
-+++ lighttpd/src/http_chunk.c 2006-07-11 21:23:40.251865499 +0300
-@@ -9,7 +9,6 @@
-
- #include <stdlib.h>
- #include <fcntl.h>
--#include <unistd.h>
+ if (srv->srvconf.log_state_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "state at exit:",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "state at exit:",
+ con->fd,
+ connection_get_state(con->state));
+ }
+-
++
+ switch(con->state) {
+ case CON_STATE_READ_POST:
+ case CON_STATE_READ:
+@@ -1689,11 +1601,11 @@
+ fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
+ break;
+ case CON_STATE_WRITE:
+- /* request write-fdevent only if we really need it
++ /* request write-fdevent only if we really need it
+ * - if we have data to write
+- * - if the socket is not writable yet
++ * - if the socket is not writable yet
+ */
+- if (!chunkqueue_is_empty(con->write_queue) &&
++ if (!chunkqueue_is_empty(con->write_queue) &&
+ (con->is_writable == 0) &&
+ (con->traffic_limit_reached == 0)) {
+ fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/crc32.h lighttpd-1.4.12/src/crc32.h
+--- lighttpd-1.4.11/src/crc32.h 2005-09-30 20:18:59.000000000 +0300
++++ lighttpd-1.4.12/src/crc32.h 2006-07-11 21:23:40.000000000 +0300
+@@ -6,6 +6,7 @@
+ #endif
- #include <stdio.h>
- #include <errno.h>
---- lighttpd-1.4.11/src/keyvalue.c 2006-03-02 16:08:06.000000000 +0200
-+++ lighttpd/src/keyvalue.c 2006-07-11 21:23:40.027851469 +0300
-@@ -87,6 +87,7 @@
- { 504, "Gateway Timeout" },
- { 505, "HTTP Version Not Supported" },
- { 507, "Insufficient Storage" }, /* WebDAV */
-+ { 509, "Bandwidth Limit exceeded" },
-
- { -1, NULL }
- };
---- lighttpd-1.4.11/src/log.c 2005-11-07 15:01:35.000000000 +0200
-+++ lighttpd/src/log.c 2006-07-11 21:23:40.275867002 +0300
-@@ -5,7 +5,6 @@
- #include <errno.h>
- #include <fcntl.h>
- #include <time.h>
--#include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
+ #include <sys/types.h>
++#include <stdlib.h>
-@@ -16,6 +15,10 @@
- #include "config.h"
+ #if defined HAVE_STDINT_H
+ #include <stdint.h>
+@@ -13,6 +14,10 @@
+ #include <inttypes.h>
#endif
+#ifdef _WIN32
-+#undef HAVE_SYSLOG_H
++#define uint32_t unsigned __int32
+#endif
+
- #ifdef HAVE_SYSLOG_H
- #include <syslog.h>
- #endif
-@@ -23,6 +26,8 @@
- #include "log.h"
- #include "array.h"
+ uint32_t generate_crc32c(char *string, size_t length);
-+#include "sys-files.h"
-+
- #ifdef HAVE_VALGRIND_VALGRIND_H
- #include <valgrind/valgrind.h>
- #endif
-@@ -246,9 +251,11 @@
- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
- write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
- break;
-+#ifdef HAVE_SYSLOG_H
- case ERRORLOG_SYSLOG:
- syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
- break;
-+#endif
- }
-
- return 0;
---- lighttpd-1.4.11/src/md5.h 2005-11-17 16:20:40.000000000 +0200
-+++ lighttpd/src/md5.h 2006-07-11 21:23:40.155859486 +0300
-@@ -30,9 +30,15 @@
- # include <inttypes.h>
#endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_array.c lighttpd-1.4.12/src/data_array.c
+--- lighttpd-1.4.11/src/data_array.c 2005-08-23 17:36:12.000000000 +0300
++++ lighttpd-1.4.12/src/data_array.c 2006-07-11 21:23:40.000000000 +0300
+@@ -17,16 +17,16 @@
-+#ifdef _WIN32
-+#define UINT4 unsigned __int32
-+#define UINT2 unsigned __int16
-+#define POINTER unsigned char *
-+#else
- #define UINT4 uint32_t
- #define UINT2 uint16_t
- #define POINTER unsigned char *
-+#endif
-
- /* MD5 context. */
- typedef struct {
---- lighttpd-1.4.11/src/mod_access.c 2006-01-14 19:44:54.000000000 +0200
-+++ lighttpd/src/mod_access.c 2006-07-11 21:23:40.219863495 +0300
-@@ -8,6 +8,8 @@
+ static void data_array_free(data_unset *d) {
+ data_array *ds = (data_array *)d;
+-
++
+ buffer_free(ds->key);
+ array_free(ds->value);
+-
++
+ free(d);
+ }
- #include "plugin.h"
+ static void data_array_reset(data_unset *d) {
+ data_array *ds = (data_array *)d;
+-
++
+ /* reused array elements */
+ buffer_reset(ds->key);
+ array_reset(ds->value);
+@@ -36,7 +36,7 @@
+ UNUSED(dst);
-+#include "sys-strings.h"
+ src->free(src);
+-
+
- typedef struct {
- array *access_deny;
- } plugin_config;
-@@ -81,13 +83,11 @@
- return HANDLER_GO_ON;
+ return 0;
}
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
+@@ -48,18 +48,18 @@
-- PATCH(access_deny);
-+ PATCH_OPTION(access_deny);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -102,14 +102,13 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
-- PATCH(access_deny);
-+ PATCH_OPTION(access_deny);
- }
- }
- }
-
- return 0;
+ data_array *data_array_init(void) {
+ data_array *ds;
+-
++
+ ds = calloc(1, sizeof(*ds));
+-
++
+ ds->key = buffer_init();
+ ds->value = array_init();
+-
++
+ ds->copy = data_array_copy;
+ ds->free = data_array_free;
+ ds->reset = data_array_reset;
+ ds->insert_dup = data_array_insert_dup;
+ ds->print = data_array_print;
+ ds->type = TYPE_ARRAY;
+-
++
+ return ds;
}
--#undef PATCH
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_config.c lighttpd-1.4.12/src/data_config.c
+--- lighttpd-1.4.11/src/data_config.c 2005-08-17 12:53:19.000000000 +0300
++++ lighttpd-1.4.12/src/data_config.c 2006-07-11 21:23:39.000000000 +0300
+@@ -17,26 +17,26 @@
- URIHANDLER_FUNC(mod_access_uri_handler) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200
-+++ lighttpd/src/mod_accesslog.c 2006-07-11 21:23:40.219863495 +0300
-@@ -6,8 +6,7 @@
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
--#include <fcntl.h>
--#include <unistd.h>
-+#include <fcntl.h> /* only the defines on windows */
- #include <errno.h>
- #include <time.h>
+ static void data_config_free(data_unset *d) {
+ data_config *ds = (data_config *)d;
+-
++
+ buffer_free(ds->key);
+ buffer_free(ds->op);
+ buffer_free(ds->comp_key);
+-
++
+ array_free(ds->value);
+ array_free(ds->childs);
+-
++
+ if (ds->string) buffer_free(ds->string);
+ #ifdef HAVE_PCRE_H
+ if (ds->regex) pcre_free(ds->regex);
+ if (ds->regex_study) pcre_free(ds->regex_study);
+ #endif
+-
++
+ free(d);
+ }
-@@ -22,6 +21,7 @@
- #include "inet_ntop_cache.h"
+ static void data_config_reset(data_unset *d) {
+ data_config *ds = (data_config *)d;
+-
++
+ /* reused array elements */
+ buffer_reset(ds->key);
+ buffer_reset(ds->comp_key);
+@@ -45,9 +45,9 @@
- #include "sys-socket.h"
-+#include "sys-files.h"
+ static int data_config_insert_dup(data_unset *dst, data_unset *src) {
+ UNUSED(dst);
+-
++
+ src->free(src);
+-
++
+ return 0;
+ }
- #ifdef HAVE_SYSLOG_H
- # include <syslog.h>
-@@ -517,8 +517,9 @@
-
- return HANDLER_ERROR;
- }
-+#ifndef _WIN32
- fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
+@@ -56,7 +56,7 @@
+ array *a = (array *)ds->value;
+ size_t i;
+ size_t maxlen;
-
-+#endif
++
+ if (0 == ds->context_ndx) {
+ fprintf(stderr, "config {\n");
}
-
- return HANDLER_GO_ON;
-@@ -567,20 +568,18 @@
- return HANDLER_GO_ON;
+@@ -117,22 +117,22 @@
+
+ data_config *data_config_init(void) {
+ data_config *ds;
+-
++
+ ds = calloc(1, sizeof(*ds));
+-
++
+ ds->key = buffer_init();
+ ds->op = buffer_init();
+ ds->comp_key = buffer_init();
+ ds->value = array_init();
+ ds->childs = array_init();
+ ds->childs->is_weakref = 1;
+-
++
+ ds->copy = data_config_copy;
+ ds->free = data_config_free;
+ ds->reset = data_config_reset;
+ ds->insert_dup = data_config_insert_dup;
+ ds->print = data_config_print;
+ ds->type = TYPE_CONFIG;
+-
++
+ return ds;
}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_count.c lighttpd-1.4.12/src/data_count.c
+--- lighttpd-1.4.11/src/data_count.c 2005-08-23 17:36:12.000000000 +0300
++++ lighttpd-1.4.12/src/data_count.c 2006-07-11 21:23:40.000000000 +0300
+@@ -16,53 +16,53 @@
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(access_logfile);
-- PATCH(format);
-- PATCH(log_access_fd);
-- PATCH(last_generated_accesslog_ts_ptr);
-- PATCH(access_logbuffer);
-- PATCH(ts_accesslog_str);
-- PATCH(parsed_format);
-- PATCH(use_syslog);
-+ PATCH_OPTION(access_logfile);
-+ PATCH_OPTION(format);
-+ PATCH_OPTION(log_access_fd);
-+ PATCH_OPTION(last_generated_accesslog_ts_ptr);
-+ PATCH_OPTION(access_logbuffer);
-+ PATCH_OPTION(ts_accesslog_str);
-+ PATCH_OPTION(parsed_format);
-+ PATCH_OPTION(use_syslog);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -595,23 +594,22 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
-- PATCH(access_logfile);
-- PATCH(log_access_fd);
-- PATCH(last_generated_accesslog_ts_ptr);
-- PATCH(access_logbuffer);
-- PATCH(ts_accesslog_str);
-+ PATCH_OPTION(access_logfile);
-+ PATCH_OPTION(log_access_fd);
-+ PATCH_OPTION(last_generated_accesslog_ts_ptr);
-+ PATCH_OPTION(access_logbuffer);
-+ PATCH_OPTION(ts_accesslog_str);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
-- PATCH(format);
-- PATCH(parsed_format);
-+ PATCH_OPTION(format);
-+ PATCH_OPTION(parsed_format);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
-- PATCH(use_syslog);
-+ PATCH_OPTION(use_syslog);
- }
- }
- }
-
+ static void data_count_free(data_unset *d) {
+ data_count *ds = (data_count *)d;
+-
++
+ buffer_free(ds->key);
+-
++
+ free(d);
+ }
+
+ static void data_count_reset(data_unset *d) {
+ data_count *ds = (data_count *)d;
+-
++
+ buffer_reset(ds->key);
+-
++
+ ds->count = 0;
+ }
+
+ static int data_count_insert_dup(data_unset *dst, data_unset *src) {
+ data_count *ds_dst = (data_count *)dst;
+ data_count *ds_src = (data_count *)src;
+-
++
+ ds_dst->count += ds_src->count;
+-
++
+ src->free(src);
+-
++
return 0;
}
--#undef PATCH
- REQUESTDONE_FUNC(log_access_write) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_alias.c 2006-03-01 23:18:51.000000000 +0200
-+++ lighttpd/src/mod_alias.c 2006-07-11 21:23:39.979848462 +0300
-@@ -8,6 +8,7 @@
- #include "buffer.h"
+ static void data_count_print(const data_unset *d, int depth) {
+ data_count *ds = (data_count *)d;
+ UNUSED(depth);
+-
++
+ fprintf(stderr, "count(%d)", ds->count);
+ }
- #include "plugin.h"
-+#include "sys-strings.h"
- /* plugin config for all request/connections */
- typedef struct {
-@@ -114,13 +115,11 @@
- return HANDLER_GO_ON;
+ data_count *data_count_init(void) {
+ data_count *ds;
+-
++
+ ds = calloc(1, sizeof(*ds));
+-
++
+ ds->key = buffer_init();
+ ds->count = 1;
+-
++
+ ds->copy = data_count_copy;
+ ds->free = data_count_free;
+ ds->reset = data_count_reset;
+ ds->insert_dup = data_count_insert_dup;
+ ds->print = data_count_print;
+ ds->type = TYPE_COUNT;
+-
++
+ return ds;
}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_fastcgi.c lighttpd-1.4.12/src/data_fastcgi.c
+--- lighttpd-1.4.11/src/data_fastcgi.c 2005-08-23 17:36:12.000000000 +0300
++++ lighttpd-1.4.12/src/data_fastcgi.c 2006-07-11 21:23:40.000000000 +0300
+@@ -17,53 +17,53 @@
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(alias);
-+ PATCH_OPTION(alias);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -135,14 +134,13 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
-- PATCH(alias);
-+ PATCH_OPTION(alias);
- }
- }
- }
-
+ static void data_fastcgi_free(data_unset *d) {
+ data_fastcgi *ds = (data_fastcgi *)d;
+-
++
+ buffer_free(ds->key);
+ buffer_free(ds->host);
+-
++
+ free(d);
+ }
+
+ static void data_fastcgi_reset(data_unset *d) {
+ data_fastcgi *ds = (data_fastcgi *)d;
+-
++
+ buffer_reset(ds->key);
+ buffer_reset(ds->host);
+-
++
+ }
+
+ static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
+ UNUSED(dst);
+
+ src->free(src);
+-
++
return 0;
}
--#undef PATCH
- PHYSICALPATH_FUNC(mod_alias_physical_handler) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_auth.c 2006-02-15 20:01:31.000000000 +0200
-+++ lighttpd/src/mod_auth.c 2006-07-11 21:23:40.171860488 +0300
-@@ -5,13 +5,15 @@
- #include <string.h>
- #include <errno.h>
- #include <fcntl.h>
--#include <unistd.h>
+ static void data_fastcgi_print(const data_unset *d, int depth) {
+ data_fastcgi *ds = (data_fastcgi *)d;
+ UNUSED(depth);
+-
++
+ fprintf(stderr, "fastcgi(%s)", ds->host->ptr);
+ }
- #include "plugin.h"
- #include "http_auth.h"
- #include "log.h"
- #include "response.h"
-+#include "sys-strings.h"
-+#include "sys-files.h"
+ data_fastcgi *data_fastcgi_init(void) {
+ data_fastcgi *ds;
+-
+
- handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
+ ds = calloc(1, sizeof(*ds));
+-
++
+ ds->key = buffer_init();
+ ds->host = buffer_init();
+ ds->port = 0;
+ ds->is_disabled = 0;
+-
++
+ ds->copy = data_fastcgi_copy;
+ ds->free = data_fastcgi_free;
+ ds->reset = data_fastcgi_reset;
+ ds->insert_dup = data_fastcgi_insert_dup;
+ ds->print = data_fastcgi_print;
+ ds->type = TYPE_FASTCGI;
+-
++
+ return ds;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_integer.c lighttpd-1.4.12/src/data_integer.c
+--- lighttpd-1.4.11/src/data_integer.c 2005-08-23 17:36:12.000000000 +0300
++++ lighttpd-1.4.12/src/data_integer.c 2006-07-11 21:23:39.000000000 +0300
+@@ -16,15 +16,15 @@
+
+ static void data_integer_free(data_unset *d) {
+ data_integer *ds = (data_integer *)d;
+-
++
+ buffer_free(ds->key);
+-
++
+ free(d);
+ }
+ static void data_integer_reset(data_unset *d) {
+ data_integer *ds = (data_integer *)d;
+-
++
+ /* reused integer elements */
+ buffer_reset(ds->key);
+ ds->value = 0;
+@@ -32,9 +32,9 @@
-@@ -93,30 +95,28 @@
- return HANDLER_GO_ON;
+ static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
+ UNUSED(dst);
+-
++
+ src->free(src);
+-
++
+ return 0;
}
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
- size_t i, j;
- mod_auth_plugin_config *s = p->config_storage[0];
+@@ -48,18 +48,18 @@
-- PATCH(auth_backend);
-- PATCH(auth_plain_groupfile);
-- PATCH(auth_plain_userfile);
-- PATCH(auth_htdigest_userfile);
-- PATCH(auth_htpasswd_userfile);
-- PATCH(auth_require);
-- PATCH(auth_debug);
-- PATCH(auth_ldap_hostname);
-- PATCH(auth_ldap_basedn);
-- PATCH(auth_ldap_binddn);
-- PATCH(auth_ldap_bindpw);
-- PATCH(auth_ldap_filter);
-- PATCH(auth_ldap_cafile);
-- PATCH(auth_ldap_starttls);
-+ PATCH_OPTION(auth_backend);
-+ PATCH_OPTION(auth_plain_groupfile);
-+ PATCH_OPTION(auth_plain_userfile);
-+ PATCH_OPTION(auth_htdigest_userfile);
-+ PATCH_OPTION(auth_htpasswd_userfile);
-+ PATCH_OPTION(auth_require);
-+ PATCH_OPTION(auth_debug);
-+ PATCH_OPTION(auth_ldap_hostname);
-+ PATCH_OPTION(auth_ldap_basedn);
-+ PATCH_OPTION(auth_ldap_binddn);
-+ PATCH_OPTION(auth_ldap_bindpw);
-+ PATCH_OPTION(auth_ldap_filter);
-+ PATCH_OPTION(auth_ldap_cafile);
-+ PATCH_OPTION(auth_ldap_starttls);
- #ifdef USE_LDAP
-- PATCH(ldap);
-- PATCH(ldap_filter_pre);
-- PATCH(ldap_filter_post);
-+ PATCH_OPTION(ldap);
-+ PATCH_OPTION(ldap_filter_pre);
-+ PATCH_OPTION(ldap_filter_post);
- #endif
-
- /* skip the first, the global context */
-@@ -132,41 +132,40 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
-- PATCH(auth_backend);
-+ PATCH_OPTION(auth_backend);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
-- PATCH(auth_plain_groupfile);
-+ PATCH_OPTION(auth_plain_groupfile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
-- PATCH(auth_plain_userfile);
-+ PATCH_OPTION(auth_plain_userfile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
-- PATCH(auth_htdigest_userfile);
-+ PATCH_OPTION(auth_htdigest_userfile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
-- PATCH(auth_htpasswd_userfile);
-+ PATCH_OPTION(auth_htpasswd_userfile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
-- PATCH(auth_require);
-+ PATCH_OPTION(auth_require);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
-- PATCH(auth_debug);
-+ PATCH_OPTION(auth_debug);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
-- PATCH(auth_ldap_hostname);
-+ PATCH_OPTION(auth_ldap_hostname);
- #ifdef USE_LDAP
-- PATCH(ldap);
-- PATCH(ldap_filter_pre);
-- PATCH(ldap_filter_post);
-+ PATCH_OPTION(ldap);
-+ PATCH_OPTION(ldap_filter_pre);
-+ PATCH_OPTION(ldap_filter_post);
- #endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
-- PATCH(auth_ldap_basedn);
-+ PATCH_OPTION(auth_ldap_basedn);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
-- PATCH(auth_ldap_filter);
-+ PATCH_OPTION(auth_ldap_filter);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
-- PATCH(auth_ldap_cafile);
-+ PATCH_OPTION(auth_ldap_cafile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
-- PATCH(auth_ldap_starttls);
-+ PATCH_OPTION(auth_ldap_starttls);
- }
- }
+ data_integer *data_integer_init(void) {
+ data_integer *ds;
+-
++
+ ds = calloc(1, sizeof(*ds));
+-
++
+ ds->key = buffer_init();
+ ds->value = 0;
+-
++
+ ds->copy = data_integer_copy;
+ ds->free = data_integer_free;
+ ds->reset = data_integer_reset;
+ ds->insert_dup = data_integer_insert_dup;
+ ds->print = data_integer_print;
+ ds->type = TYPE_INTEGER;
+-
++
+ return ds;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_string.c lighttpd-1.4.12/src/data_string.c
+--- lighttpd-1.4.11/src/data_string.c 2005-08-23 17:36:12.000000000 +0300
++++ lighttpd-1.4.12/src/data_string.c 2006-07-11 21:23:40.000000000 +0300
+@@ -17,16 +17,16 @@
+
+ static void data_string_free(data_unset *d) {
+ data_string *ds = (data_string *)d;
+-
++
+ buffer_free(ds->key);
+ buffer_free(ds->value);
+-
++
+ free(d);
+ }
+
+ static void data_string_reset(data_unset *d) {
+ data_string *ds = (data_string *)d;
+-
++
+ /* reused array elements */
+ buffer_reset(ds->key);
+ buffer_reset(ds->value);
+@@ -35,23 +35,23 @@
+ static int data_string_insert_dup(data_unset *dst, data_unset *src) {
+ data_string *ds_dst = (data_string *)dst;
+ data_string *ds_src = (data_string *)src;
+-
++
+ if (ds_dst->value->used) {
+ buffer_append_string(ds_dst->value, ", ");
+ buffer_append_string_buffer(ds_dst->value, ds_src->value);
+ } else {
+ buffer_copy_string_buffer(ds_dst->value, ds_src->value);
}
-
+-
++
+ src->free(src);
+-
++
return 0;
}
--#undef PATCH
- static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
- size_t k;
---- lighttpd-1.4.11/src/mod_cgi.c 2006-02-22 15:15:10.000000000 +0200
-+++ lighttpd/src/mod_cgi.c 2006-07-11 21:23:39.887842700 +0300
-@@ -1,21 +1,8 @@
- #include <sys/types.h>
--#ifdef __WIN32
--#include <winsock2.h>
--#else
--#include <sys/socket.h>
--#include <sys/wait.h>
--#include <sys/mman.h>
--
--#include <netinet/in.h>
--
--#include <arpa/inet.h>
--#endif
+ static int data_response_insert_dup(data_unset *dst, data_unset *src) {
+ data_string *ds_dst = (data_string *)dst;
+ data_string *ds_src = (data_string *)src;
+-
++
+ if (ds_dst->value->used) {
+ buffer_append_string(ds_dst->value, "\r\n");
+ buffer_append_string_buffer(ds_dst->value, ds_dst->key);
+@@ -60,9 +60,9 @@
+ } else {
+ buffer_copy_string_buffer(ds_dst->value, ds_src->value);
+ }
+-
++
+ src->free(src);
+-
++
+ return 0;
+ }
+
+@@ -77,28 +77,28 @@
+
+ data_string *data_string_init(void) {
+ data_string *ds;
+-
++
+ ds = calloc(1, sizeof(*ds));
+ assert(ds);
+-
++
+ ds->key = buffer_init();
+ ds->value = buffer_init();
+-
++
+ ds->copy = data_string_copy;
+ ds->free = data_string_free;
+ ds->reset = data_string_reset;
+ ds->insert_dup = data_string_insert_dup;
+ ds->print = data_string_print;
+ ds->type = TYPE_STRING;
+-
++
+ return ds;
+ }
+
+ data_string *data_response_init(void) {
+ data_string *ds;
+-
++
+ ds = data_string_init();
+ ds->insert_dup = data_response_insert_dup;
+-
++
+ return ds;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/etag.c lighttpd-1.4.12/src/etag.c
+--- lighttpd-1.4.11/src/etag.c 2005-08-11 01:26:40.000000000 +0300
++++ lighttpd-1.4.12/src/etag.c 2006-07-11 21:23:40.000000000 +0300
+@@ -14,19 +14,19 @@
+ buffer_append_off_t(etag, st->st_size);
+ buffer_append_string_len(etag, CONST_STR_LEN("-"));
+ buffer_append_long(etag, st->st_mtime);
+-
++
+ return 0;
+ }
+
+ int etag_mutate(buffer *mut, buffer *etag) {
+ size_t h, i;
+-
++
+ for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
+-
++
+ buffer_reset(mut);
+ buffer_copy_string_len(mut, CONST_STR_LEN("\""));
+ buffer_append_long(mut, h);
+ buffer_append_string_len(mut, CONST_STR_LEN("\""));
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/etag.h lighttpd-1.4.12/src/etag.h
+--- lighttpd-1.4.11/src/etag.h 2005-08-11 01:26:40.000000000 +0300
++++ lighttpd-1.4.12/src/etag.h 2006-07-11 21:23:40.000000000 +0300
+@@ -3,13 +3,12 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
-#include <unistd.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <string.h>
--#include <fdevent.h>
- #include <signal.h>
- #include <ctype.h>
- #include <assert.h>
-@@ -29,9 +16,16 @@
- #include "connections.h"
- #include "joblist.h"
- #include "http_chunk.h"
-+#include "fdevent.h"
- #include "plugin.h"
+ #include "buffer.h"
-+#include "sys-files.h"
-+#include "sys-mmap.h"
-+#include "sys-socket.h"
-+#include "sys-strings.h"
-+#include "sys-process.h"
+ int etag_is_equal(buffer *etag, const char *matches);
+ int etag_create(buffer *etag, struct stat *st);
+ int etag_mutate(buffer *mut, buffer *etag);
+-
+
- #ifdef HAVE_SYS_FILIO_H
- # include <sys/filio.h>
+
#endif
-@@ -45,6 +39,7 @@
- size_t used;
- } char_array;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fastcgi.h lighttpd-1.4.12/src/fastcgi.h
+--- lighttpd-1.4.11/src/fastcgi.h 2005-08-11 01:26:40.000000000 +0300
++++ lighttpd-1.4.12/src/fastcgi.h 2006-07-11 21:23:40.000000000 +0300
+@@ -1,4 +1,4 @@
+-/*
++/*
+ * fastcgi.h --
+ *
+ * Defines for the FastCGI protocol.
+@@ -123,7 +123,7 @@
-+#define pid_t int
- typedef struct {
- pid_t *ptr;
- size_t used;
-@@ -478,7 +473,7 @@
-
- if (con->mode != p->id) return HANDLER_GO_ON;
--#ifndef __WIN32
-+#ifndef _WIN32
-
- /* the connection to the browser went away, but we still have a connection
- * to the CGI script
-@@ -509,6 +504,7 @@
- /* if waitpid hasn't been called by response.c yet, do it here */
- if (pid) {
- /* check if the CGI-script is already gone */
-+#ifndef _WIN32
- switch(waitpid(pid, &status, WNOHANG)) {
- case 0:
- /* not finished yet */
-@@ -558,7 +554,7 @@
-
-
- kill(pid, SIGTERM);
--
-+#endif
- /* cgi-script is still alive, queue the PID for removal */
- cgi_pid_add(srv, p, pid);
- }
-@@ -695,7 +691,7 @@
- int from_cgi_fds[2];
- struct stat st;
-
--#ifndef __WIN32
-+#ifndef _WIN32
-
- if (cgi_handler->used > 1) {
- /* stat the exec file */
-@@ -811,6 +807,9 @@
- cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
- if (!buffer_is_empty(con->uri.query)) {
- cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
-+ } else {
-+ /* set a empty QUERY_STRING */
-+ cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
- }
- if (!buffer_is_empty(con->request.orig_uri)) {
- cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
-@@ -1101,13 +1100,11 @@
- #endif
- }
+ typedef struct {
+- unsigned char type;
++ unsigned char type;
+ unsigned char reserved[7];
+ } FCGI_UnknownTypeBody;
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(cgi);
-+ PATCH_OPTION(cgi);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -1122,14 +1119,13 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
-- PATCH(cgi);
-+ PATCH_OPTION(cgi);
- }
- }
- }
-
- return 0;
- }
--#undef PATCH
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent.c lighttpd-1.4.12/src/fdevent.c
+--- lighttpd-1.4.11/src/fdevent.c 2005-11-15 10:51:05.000000000 +0200
++++ lighttpd-1.4.12/src/fdevent.c 2006-07-11 21:23:40.000000000 +0300
+@@ -2,7 +2,6 @@
- URIHANDLER_FUNC(cgi_is_handled) {
- size_t k, s_len;
-@@ -1168,7 +1164,7 @@
- plugin_data *p = p_d;
- size_t ndx;
- /* the trigger handle only cares about lonely PID which we have to wait for */
--#ifndef __WIN32
-+#ifndef _WIN32
+ #include "settings.h"
- for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
- int status;
-@@ -1218,7 +1214,7 @@
- log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
- #endif
- if (hctx->pid == 0) return HANDLER_FINISHED;
--#ifndef __WIN32
-+#ifndef _WIN32
- switch(waitpid(hctx->pid, &status, WNOHANG)) {
- case 0:
- /* we only have for events here if we don't have the header yet,
---- lighttpd-1.4.11/src/mod_cml.c 2006-01-30 13:51:48.000000000 +0200
-+++ lighttpd/src/mod_cml.c 2006-07-11 21:23:39.931845456 +0300
-@@ -4,7 +4,6 @@
+-#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
--#include <unistd.h>
- #include <stdio.h>
-
+@@ -12,59 +11,61 @@
+ #include "fdevent.h"
#include "buffer.h"
-@@ -135,18 +134,16 @@
- return HANDLER_GO_ON;
- }
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(ext);
-+ PATCH_OPTION(ext);
- #if defined(HAVE_MEMCACHE_H)
-- PATCH(mc);
-+ PATCH_OPTION(mc);
- #endif
-- PATCH(mc_namespace);
-- PATCH(power_magnet);
-+ PATCH_OPTION(mc_namespace);
-+ PATCH_OPTION(power_magnet);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -161,22 +158,21 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
-- PATCH(ext);
-+ PATCH_OPTION(ext);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
- #if defined(HAVE_MEMCACHE_H)
-- PATCH(mc);
-+ PATCH_OPTION(mc);
- #endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
-- PATCH(mc_namespace);
-+ PATCH_OPTION(mc_namespace);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
-- PATCH(power_magnet);
-+ PATCH_OPTION(power_magnet);
- }
++#include "sys-socket.h"
++
+ fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
+ fdevents *ev;
+-
++
+ ev = calloc(1, sizeof(*ev));
+ ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
+ ev->maxfds = maxfds;
+-
++
+ switch(type) {
+ case FDEVENT_HANDLER_POLL:
+ if (0 != fdevent_poll_init(ev)) {
+- fprintf(stderr, "%s.%d: event-handler poll failed\n",
++ fprintf(stderr, "%s.%d: event-handler poll failed\n",
+ __FILE__, __LINE__);
+-
++
+ return NULL;
+ }
+ break;
+ case FDEVENT_HANDLER_SELECT:
+ if (0 != fdevent_select_init(ev)) {
+- fprintf(stderr, "%s.%d: event-handler select failed\n",
++ fprintf(stderr, "%s.%d: event-handler select failed\n",
+ __FILE__, __LINE__);
+ return NULL;
+ }
+ break;
+ case FDEVENT_HANDLER_LINUX_RTSIG:
+ if (0 != fdevent_linux_rtsig_init(ev)) {
+- fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
++ fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__);
+ return NULL;
+ }
+ break;
+ case FDEVENT_HANDLER_LINUX_SYSEPOLL:
+ if (0 != fdevent_linux_sysepoll_init(ev)) {
+- fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
++ fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__);
+ return NULL;
+ }
+ break;
+ case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
+ if (0 != fdevent_solaris_devpoll_init(ev)) {
+- fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
++ fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__);
+ return NULL;
+ }
+ break;
+ case FDEVENT_HANDLER_FREEBSD_KQUEUE:
+ if (0 != fdevent_freebsd_kqueue_init(ev)) {
+- fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
++ fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__);
+ return NULL;
}
+ break;
+ default:
+- fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
++ fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__);
+ return NULL;
}
-
- return 0;
+@@ -75,26 +76,26 @@
+ void fdevent_free(fdevents *ev) {
+ size_t i;
+ if (!ev) return;
+-
++
+ if (ev->free) ev->free(ev);
+-
++
+ for (i = 0; i < ev->maxfds; i++) {
+ if (ev->fdarray[i]) free(ev->fdarray[i]);
+ }
+-
++
+ free(ev->fdarray);
+ free(ev);
}
--#undef PATCH
- int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
- buffer *b;
---- lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200
-+++ lighttpd/src/mod_cml_funcs.c 2006-07-11 21:23:40.083854976 +0300
-@@ -4,8 +4,7 @@
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
--#include <unistd.h>
--#include <dirent.h>
+ int fdevent_reset(fdevents *ev) {
+ if (ev->reset) return ev->reset(ev);
+-
+
- #include <stdio.h>
-
- #include "buffer.h"
-@@ -13,6 +12,7 @@
- #include "log.h"
- #include "plugin.h"
- #include "response.h"
-+#include "sys-files.h"
-
- #include "mod_cml.h"
- #include "mod_cml_funcs.h"
-@@ -92,7 +92,7 @@
-
- return 1;
- }
--
-+#ifndef _WIN32
- int f_dir_files_iter(lua_State *L) {
- DIR *d;
- struct dirent *de;
-@@ -136,7 +136,7 @@
-
- return 1;
+ return 0;
}
--
-+#endif
- int f_file_isreg(lua_State *L) {
- struct stat st;
- int n = lua_gettop(L);
---- lighttpd-1.4.11/src/mod_cml_lua.c 2006-01-30 13:56:40.000000000 +0200
-+++ lighttpd/src/mod_cml_lua.c 2006-07-11 21:23:40.179860989 +0300
-@@ -31,6 +31,7 @@
-
- #include <lua.h>
- #include <lualib.h>
-+#include <lauxlib.h>
- typedef struct {
- stream st;
-@@ -220,13 +221,8 @@
- stream_open(&rm.st, fn);
-
- /* push the lua file to the interpreter and see what happends */
-- L = lua_open();
+ fdnode *fdnode_init() {
+ fdnode *fdn;
-
-- luaopen_base(L);
-- luaopen_table(L);
-- luaopen_string(L);
-- luaopen_math(L);
-- luaopen_io(L);
-+ L = luaL_newstate();
-+ luaL_openlibs(L);
-
- /* register functions */
- lua_register(L, "md5", f_crypto_md5);
---- lighttpd-1.4.11/src/mod_compress.c 2005-11-18 13:49:14.000000000 +0200
-+++ lighttpd/src/mod_compress.c 2006-07-11 21:23:40.139858484 +0300
-@@ -2,7 +2,6 @@
- #include <sys/stat.h>
-
- #include <fcntl.h>
--#include <unistd.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
-@@ -14,6 +13,7 @@
- #include "buffer.h"
- #include "response.h"
- #include "stat_cache.h"
-+#include "http_chunk.h"
-
- #include "plugin.h"
-
-@@ -33,6 +33,7 @@
- #endif
-
- #include "sys-mmap.h"
-+#include "sys-files.h"
-
- /* request: accept-encoding */
- #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
-@@ -102,6 +103,28 @@
- return HANDLER_GO_ON;
- }
++
+ fdn = calloc(1, sizeof(*fdn));
+ fdn->fd = -1;
+ return fdn;
+@@ -106,12 +107,12 @@
-+void mkdir_recursive(const char *dir) {
+ int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
+ fdnode *fdn;
+-
+
-+ char dir_copy[256];
-+ char *p = dir_copy;
+ fdn = fdnode_init();
+ fdn->handler = handler;
+ fdn->fd = fd;
+ fdn->ctx = ctx;
+-
+
-+ if (!dir || !dir[0])
-+ return;
+ ev->fdarray[fd] = fdn;
+
+ return 0;
+@@ -121,31 +122,31 @@
+ fdnode *fdn;
+ if (!ev) return 0;
+ fdn = ev->fdarray[fd];
+-
+
-+ strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
+ fdnode_free(fdn);
+-
+
-+ while ((p = strchr(p + 1, '/')) != NULL) {
+ ev->fdarray[fd] = NULL;
+-
+
-+ *p = '\0';
-+ if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
-+ return;
+ return 0;
+ }
+
+ int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
+ int fde = fde_ndx ? *fde_ndx : -1;
+-
+
-+ *p++ = '/';
-+ }
+ if (ev->event_del) fde = ev->event_del(ev, fde, fd);
+-
+
-+ mkdir(dir, 0700);
-+}
+ if (fde_ndx) *fde_ndx = fde;
+-
+
- SETDEFAULTS_FUNC(mod_compress_setdefaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-@@ -136,13 +159,21 @@
- if (!buffer_is_empty(s->compress_cache_dir)) {
- struct stat st;
- if (0 != stat(s->compress_cache_dir->ptr, &st)) {
-- log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
+ return 0;
+ }
+
+ int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
+ int fde = fde_ndx ? *fde_ndx : -1;
+-
+
-+ log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
-+ s->compress_cache_dir, strerror(errno));
-+ mkdir_recursive(s->compress_cache_dir->ptr);
+ if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
+-
+
-+ if (0 != stat(s->compress_cache_dir->ptr, &st)) {
+ if (fde_ndx) *fde_ndx = fde;
+-
+
-+ log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
- s->compress_cache_dir, strerror(errno));
-
- return HANDLER_ERROR;
- }
- }
- }
-+ }
-
- return HANDLER_GO_ON;
-
-@@ -326,6 +357,9 @@
- void *start;
- const char *filename = fn->ptr;
- ssize_t r;
-+ stat_cache_entry *compressed_sce = NULL;
+ return 0;
+ }
+
+@@ -156,38 +157,43 @@
+
+ int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
+ if (ev->event_get_revent == NULL) SEGFAULT();
+-
+
-+ if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
-
- /* overflow */
- if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
-@@ -339,7 +373,7 @@
-
- buffer_reset(p->ofn);
- buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
-- BUFFER_APPEND_SLASH(p->ofn);
-+ PATHNAME_APPEND_SLASH(p->ofn);
-
- if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
- size_t offset = p->ofn->used - 1;
-@@ -384,26 +418,33 @@
-
- buffer_append_string_buffer(p->ofn, sce->etag);
-
+ return ev->event_get_revent(ev, ndx);
+ }
+
+ int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
+ if (ev->event_get_fd == NULL) SEGFAULT();
+-
+
-+ if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
-+ /* file exists */
+ return ev->event_get_fd(ev, ndx);
+ }
+
+ fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
+ if (ev->fdarray[fd] == NULL) SEGFAULT();
+ if (ev->fdarray[fd]->fd != fd) SEGFAULT();
+-
+
-+ http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
-+ con->file_finished = 1;
+ return ev->fdarray[fd]->handler;
+ }
+
+ void * fdevent_get_context(fdevents *ev, int fd) {
+ if (ev->fdarray[fd] == NULL) SEGFAULT();
+ if (ev->fdarray[fd]->fd != fd) SEGFAULT();
+-
+
-+ return 0;
-+ }
+ return ev->fdarray[fd]->ctx;
+ }
+
+ int fdevent_fcntl_set(fdevents *ev, int fd) {
++#ifdef _WIN32
++ int i = 1;
++#endif
+ #ifdef FD_CLOEXEC
+ /* close fd on exec (cgi) */
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ #endif
+ if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
+-#ifdef O_NONBLOCK
++#ifdef O_NONBLOCK
+ return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
++#elif defined _WIN32
++ return ioctlsocket(fd, FIONBIO, &i);
+ #else
+ return 0;
+ #endif
+@@ -196,7 +202,7 @@
+
+ int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
+ if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
+-
+
- if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
- if (errno == EEXIST) {
- /* cache-entry exists */
--#if 0
-- log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
--#endif
-- buffer_copy_string_buffer(con->physical.path, p->ofn);
-
-- return 0;
- }
-
-- log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
-+ log_error_write(srv, __FILE__, __LINE__, "sbss",
-+ "creating cachefile", p->ofn,
-+ "failed", strerror(errno));
-
+ return -1;
+ }
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent.h lighttpd-1.4.12/src/fdevent.h
+--- lighttpd-1.4.11/src/fdevent.h 2005-09-27 11:26:33.000000000 +0300
++++ lighttpd-1.4.12/src/fdevent.h 2006-07-11 21:23:39.000000000 +0300
+@@ -17,13 +17,13 @@
+ # include <sys/epoll.h>
+ #endif
+
+-/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
++/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
+ * under /usr/include/sys/ */
+ #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
+ # define USE_POLL
+ # ifdef HAVE_POLL_H
+ # include <poll.h>
+-# else
++# else
+ # include <sys/poll.h>
+ # endif
+ # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
+@@ -31,9 +31,11 @@
+ # include <signal.h>
+ # endif
+ #endif
+-
++#ifdef _WIN32
++# define HAVE_SELECT
++#endif
+ #if defined HAVE_SELECT
+-# ifdef __WIN32
++# ifdef _WIN32
+ # include <winsock2.h>
+ # endif
+ # define USE_SELECT
+@@ -67,14 +69,14 @@
+ #define FDEVENT_HUP BV(4)
+ #define FDEVENT_NVAL BV(5)
+
+-typedef enum { FD_EVENT_TYPE_UNSET = -1,
+- FD_EVENT_TYPE_CONNECTION,
+- FD_EVENT_TYPE_FCGI_CONNECTION,
+- FD_EVENT_TYPE_DIRWATCH,
+- FD_EVENT_TYPE_CGI_CONNECTION
++typedef enum { FD_EVENT_TYPE_UNSET = -1,
++ FD_EVENT_TYPE_CONNECTION,
++ FD_EVENT_TYPE_FCGI_CONNECTION,
++ FD_EVENT_TYPE_DIRWATCH,
++ FD_EVENT_TYPE_CGI_CONNECTION
+ } fd_event_t;
+
+-typedef enum { FDEVENT_HANDLER_UNSET,
++typedef enum { FDEVENT_HANDLER_UNSET,
+ FDEVENT_HANDLER_SELECT,
+ FDEVENT_HANDLER_POLL,
+ FDEVENT_HANDLER_LINUX_RTSIG,
+@@ -86,7 +88,7 @@
+
+ /**
+ * a mapping from fd to connection structure
+- *
++ *
+ */
+ typedef struct {
+ int fd; /**< the fd */
+@@ -98,41 +100,41 @@
+
+ typedef struct {
+ fd_conn *ptr;
+-
++
+ size_t size;
+ size_t used;
+ } fd_conn_buffer;
+
+ /**
+ * array of unused fd's
+- *
++ *
+ */
+
+ typedef struct _fdnode {
+ fdevent_handler handler;
+ void *ctx;
+ int fd;
+-
++
+ struct _fdnode *prev, *next;
+ } fdnode;
+
+ typedef struct {
+ int *ptr;
+-
++
+ size_t used;
+ size_t size;
+ } buffer_int;
+
+ /**
+ * fd-event handler for select(), poll() and rt-signals on Linux 2.4
+- *
++ *
+ */
+ typedef struct fdevents {
+ fdevent_handler_t type;
+-
++
+ fdnode **fdarray;
+ size_t maxfds;
+-
++
+ #ifdef USE_LINUX_SIGIO
+ int in_sigio;
+ int signum;
+@@ -146,21 +148,21 @@
+ #endif
+ #ifdef USE_POLL
+ struct pollfd *pollfds;
+-
++
+ size_t size;
+ size_t used;
+-
++
+ buffer_int unused;
+ #endif
+ #ifdef USE_SELECT
+ fd_set select_read;
+ fd_set select_write;
+ fd_set select_error;
+-
++
+ fd_set select_set_read;
+ fd_set select_set_write;
+ fd_set select_set_error;
+-
++
+ int select_max_fd;
+ #endif
+ #ifdef USE_SOLARIS_DEVPOLL
+@@ -177,16 +179,16 @@
+ #endif
+ int (*reset)(struct fdevents *ev);
+ void (*free)(struct fdevents *ev);
+-
++
+ int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events);
+ int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
+ int (*event_get_revent)(struct fdevents *ev, size_t ndx);
+ int (*event_get_fd)(struct fdevents *ev, size_t ndx);
+-
++
+ int (*event_next_fdndx)(struct fdevents *ev, int ndx);
+-
++
+ int (*poll)(struct fdevents *ev, int timeout_ms);
+-
++
+ int (*fcntl_set)(struct fdevents *ev, int fd);
+ } fdevents;
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c
+--- lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c 2005-09-01 10:46:24.000000000 +0300
++++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c 2006-07-11 21:23:39.000000000 +0300
+@@ -1,6 +1,5 @@
+ #include <sys/types.h>
+
+-#include <unistd.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -48,7 +47,7 @@
+
return -1;
}
--#if 0
-- log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
--#endif
+-
+
- if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
-- log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
-+ log_error_write(srv, __FILE__, __LINE__, "sbss",
-+ "opening plain-file", fn,
-+ "failed", strerror(errno));
-
- close(ofd);
-
-@@ -412,7 +453,9 @@
-
-
- if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
-- log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
-+ log_error_write(srv, __FILE__, __LINE__, "sbss",
-+ "mmaping", fn,
-+ "failed", strerror(errno));
-
- close(ofd);
- close(ifd);
-@@ -455,7 +498,8 @@
-
- if (ret != 0) return -1;
-
-- buffer_copy_string_buffer(con->physical.path, p->ofn);
-+ http_chunk_append_file(srv, con, p->ofn, 0, r);
-+ con->file_finished = 1;
-
- return 0;
+ return -1;
}
-@@ -476,18 +520,19 @@
-
- if (sce->st.st_size > 128 * 1024 * 1024) return -1;
-
+
+@@ -65,7 +64,7 @@
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
-
- if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
- log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
-
++
+ ret = kevent(ev->kq_fd,
+ &kev, 1,
+ NULL, 0,
+@@ -77,7 +76,7 @@
+
return -1;
}
-
-+ start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
-
-- if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
-+ close(ifd);
+-
+
-+ if (MAP_FAILED == start) {
- log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
-
-- close(ifd);
- return -1;
+ if (filter == EVFILT_READ) {
+ bitset_set_bit(ev->kq_bevents, fd);
+ } else {
+@@ -124,7 +123,7 @@
+ } else if (e == EVFILT_WRITE) {
+ events |= FDEVENT_OUT;
}
-
-@@ -511,7 +556,6 @@
+-
++
+ e = ev->kq_results[ndx].flags;
+
+ if (e & EV_EOF) {
+@@ -152,10 +151,10 @@
+ if (-1 == (ev->kq_fd = kqueue())) {
+ fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__, strerror(errno));
+-
++
+ return -1;
}
-
- munmap(start, sce->st.st_size);
-- close(ifd);
-
- if (ret != 0) return -1;
-
-@@ -527,16 +571,13 @@
+-
++
return 0;
}
--
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
+@@ -186,7 +185,7 @@
+ if (-1 == (ev->kq_fd = kqueue())) {
+ fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__, strerror(errno));
+-
++
+ return -1;
+ }
-- PATCH(compress_cache_dir);
-- PATCH(compress);
-- PATCH(compress_max_filesize);
-+ PATCH_OPTION(compress_cache_dir);
-+ PATCH_OPTION(compress);
-+ PATCH_OPTION(compress_max_filesize);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -551,18 +592,17 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
-- PATCH(compress_cache_dir);
-+ PATCH_OPTION(compress_cache_dir);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
-- PATCH(compress);
-+ PATCH_OPTION(compress);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
-- PATCH(compress_max_filesize);
-+ PATCH_OPTION(compress_max_filesize);
- }
- }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_linux_rtsig.c lighttpd-1.4.12/src/fdevent_linux_rtsig.c
+--- lighttpd-1.4.11/src/fdevent_linux_rtsig.c 2005-11-21 19:56:11.000000000 +0200
++++ lighttpd-1.4.12/src/fdevent_linux_rtsig.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,6 +1,5 @@
+ #include <sys/types.h>
+
+-#include <unistd.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -14,6 +13,7 @@
+ #include "fdevent.h"
+ #include "settings.h"
+ #include "buffer.h"
++#include "sys-process.h"
+
+ #ifdef USE_LINUX_SIGIO
+ static void fdevent_linux_rtsig_free(fdevents *ev) {
+@@ -26,19 +26,19 @@
+
+ static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) {
+ if (fde_ndx < 0) return -1;
+-
++
+ if ((size_t)fde_ndx >= ev->used) {
+ fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used);
+ SEGFAULT();
}
-
- return 0;
- }
--#undef PATCH
+-
++
+ if (ev->pollfds[fde_ndx].fd == fd) {
+ size_t k = fde_ndx;
+-
++
+ ev->pollfds[k].fd = -1;
- PHYSICALPATH_FUNC(mod_compress_physical) {
- plugin_data *p = p_d;
-@@ -589,6 +629,9 @@
- /* don't compress files that are too large as we need to much time to handle them */
- if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
-
-+ /* compressing the file might lead to larger files instead */
-+ if (sce->st.st_size < 128) return HANDLER_GO_ON;
+ bitset_clear_bit(ev->sigbset, fd);
+-
+
- /* check if mimetype is in compress-config */
- for (m = 0; m < p->conf.compress->used; m++) {
- data_string *compress_ds = (data_string *)p->conf.compress->data[m];
-@@ -638,6 +681,19 @@
-
- const char *compression_name = NULL;
- int compression_type = 0;
-+ buffer *mtime;
-+
-+ mtime = strftime_cache_get(srv, sce->st.st_mtime);
-+ etag_mutate(con->physical.etag, sce->etag);
+ if (ev->unused.size == 0) {
+ ev->unused.size = 16;
+ ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
+@@ -46,29 +46,29 @@
+ ev->unused.size += 16;
+ ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
+ }
+-
+
-+ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
-+ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
+ ev->unused.ptr[ev->unused.used++] = k;
+ } else {
+ fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd);
+-
+
-+ /* perhaps we don't even have to compress the file as the browser still has the
-+ * current version */
-+ if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
-+ return HANDLER_FINISHED;
-+ }
-
- /* select best matching encoding */
- if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
-@@ -651,29 +707,19 @@
- compression_name = dflt_deflate;
- }
-
-- /* deflate it */
-- if (p->conf.compress_cache_dir->used) {
-+ /* deflate it to file (cached) or to memory */
- if (0 == deflate_file_to_file(srv, con, p,
-- con->physical.path, sce, compression_type)) {
-- buffer *mtime;
--
-- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
--
-- mtime = strftime_cache_get(srv, sce->st.st_mtime);
-- response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
--
-- etag_mutate(con->physical.etag, sce->etag);
-- response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
--
-- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
--
-- return HANDLER_GO_ON;
-- }
-- } else if (0 == deflate_file_to_buffer(srv, con, p,
-+ con->physical.path, sce, compression_type) ||
-+ 0 == deflate_file_to_buffer(srv, con, p,
- con->physical.path, sce, compression_type)) {
-
-- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
-- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
-+ response_header_overwrite(srv, con,
-+ CONST_STR_LEN("Content-Encoding"),
-+ compression_name, strlen(compression_name));
+ SEGFAULT();
+ }
+-
+
-+ response_header_overwrite(srv, con,
-+ CONST_STR_LEN("Content-Type"),
-+ CONST_BUF_LEN(sce->content_type));
-
- return HANDLER_FINISHED;
- }
---- lighttpd-1.4.11/src/mod_dirlisting.c 2006-01-13 00:00:45.000000000 +0200
-+++ lighttpd/src/mod_dirlisting.c 2006-07-11 21:23:40.247865249 +0300
-@@ -1,11 +1,9 @@
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
--#include <dirent.h>
- #include <assert.h>
- #include <errno.h>
- #include <stdio.h>
--#include <unistd.h>
- #include <time.h>
+ return -1;
+ }
- #include "base.h"
-@@ -31,6 +29,9 @@
- #include <attr/attributes.h>
+ #if 0
+ static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
+ size_t j;
+-
++
+ if (ev->used == 0) return 0;
+ if (ev->unused.used != 0) return 0;
+-
++
+ for (j = ev->used - 1; j + 1 > 0; j--) {
+ if (ev->pollfds[j].fd == -1) ev->used--;
+ }
+-
+-
++
++
+ return 0;
+ }
#endif
+@@ -78,21 +78,21 @@
+ if (fde_ndx != -1) {
+ if (ev->pollfds[fde_ndx].fd == fd) {
+ ev->pollfds[fde_ndx].events = events;
+-
++
+ return fde_ndx;
+ }
+ fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
+ SEGFAULT();
+ }
+-
++
+ if (ev->unused.used > 0) {
+ int k = ev->unused.ptr[--ev->unused.used];
+-
++
+ ev->pollfds[k].fd = fd;
+ ev->pollfds[k].events = events;
-+#include "sys-files.h"
-+#include "sys-strings.h"
+ bitset_set_bit(ev->sigbset, fd);
+-
+
- /* plugin config for all request/connections */
+ return k;
+ } else {
+ if (ev->size == 0) {
+@@ -102,12 +102,12 @@
+ ev->size += 16;
+ ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
+ }
+-
++
+ ev->pollfds[ev->used].fd = fd;
+ ev->pollfds[ev->used].events = events;
- typedef struct {
-@@ -292,21 +293,19 @@
- return HANDLER_GO_ON;
+ bitset_set_bit(ev->sigbset, fd);
+-
++
+ return ev->used++;
+ }
}
+@@ -115,20 +115,20 @@
+ static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
+ struct timespec ts;
+ int r;
+-
++
+ #if 0
+ fdevent_linux_rtsig_event_compress(ev);
+ #endif
+-
++
+ ev->in_sigio = 1;
+-
++
+ ts.tv_sec = timeout_ms / 1000;
+ ts.tv_nsec = (timeout_ms % 1000) * 1000000;
+ r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
+-
+- if (r == -1) {
++
++ if (r == -1) {
+ if (errno == EAGAIN) return 0;
+- return r;
++ return r;
+ } else if (r == SIGIO) {
+ struct sigaction act;
+
+@@ -140,7 +140,7 @@
+ /* re-enable the signal queue */
+ act.sa_handler = SIG_DFL;
+ sigaction(ev->signum, &act, NULL);
+-
++
+ ev->in_sigio = 0;
+ r = poll(ev->pollfds, ev->used, timeout_ms);
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
+@@ -162,12 +162,12 @@
+ if (ev->siginfo.si_band == POLLERR) {
+ fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno));
+ }
+-# endif
++# endif
+ if (ndx != 0) {
+ fprintf(stderr, "+\n");
+ return 0;
+ }
+-
++
+ return ev->siginfo.si_band & 0x3f;
+ } else {
+ if (ndx >= ev->used) {
+@@ -188,13 +188,13 @@
-- PATCH(dir_listing);
-- PATCH(external_css);
-- PATCH(hide_dot_files);
-- PATCH(encoding);
-- PATCH(show_readme);
-- PATCH(hide_readme_file);
-- PATCH(show_header);
-- PATCH(hide_header_file);
-- PATCH(excludes);
-+ PATCH_OPTION(dir_listing);
-+ PATCH_OPTION(external_css);
-+ PATCH_OPTION(hide_dot_files);
-+ PATCH_OPTION(encoding);
-+ PATCH_OPTION(show_readme);
-+ PATCH_OPTION(hide_readme_file);
-+ PATCH_OPTION(show_header);
-+ PATCH_OPTION(hide_header_file);
-+ PATCH_OPTION(excludes);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -322,30 +321,29 @@
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
- buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
-- PATCH(dir_listing);
-+ PATCH_OPTION(dir_listing);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
-- PATCH(hide_dot_files);
-+ PATCH_OPTION(hide_dot_files);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
-- PATCH(external_css);
-+ PATCH_OPTION(external_css);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
-- PATCH(encoding);
-+ PATCH_OPTION(encoding);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
-- PATCH(show_readme);
-+ PATCH_OPTION(show_readme);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
-- PATCH(hide_readme_file);
-+ PATCH_OPTION(hide_readme_file);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
-- PATCH(show_header);
-+ PATCH_OPTION(show_header);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
-- PATCH(hide_header_file);
-+ PATCH_OPTION(hide_header_file);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
-- PATCH(excludes);
-+ PATCH_OPTION(excludes);
- }
+ static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
+ static pid_t pid = 0;
+-
++
+ if (pid == 0) pid = getpid();
+-
++
+ if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
+-
++
+ if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
+-
++
+ return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
+ }
+
+@@ -205,12 +205,12 @@
+ return -1;
+ } else {
+ size_t i;
+-
++
+ i = (ndx < 0) ? 0 : ndx + 1;
+ for (; i < ev->used; i++) {
+ if (ev->pollfds[i].revents) break;
}
+-
++
+ return i;
}
-
- return 0;
}
--#undef PATCH
-
- typedef struct {
- size_t namelen;
-@@ -494,7 +492,7 @@
- /* if we have a HEADER file, display it in <pre class="header"></pre> */
-
- buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
-- BUFFER_APPEND_SLASH(p->tmp_buf);
-+ PATHNAME_APPEND_SLASH(p->tmp_buf);
- BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
-
- if (-1 != stream_open(&s, p->tmp_buf)) {
-@@ -543,7 +541,7 @@
- /* if we have a README file, display it in <pre class="readme"></pre> */
-
- buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
-- BUFFER_APPEND_SLASH(p->tmp_buf);
-+ PATHNAME_APPEND_SLASH(p->tmp_buf);
- BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
-
- if (-1 != stream_open(&s, p->tmp_buf)) {
-@@ -606,7 +604,7 @@
- name_max = 256; /* stupid default */
- #endif
+@@ -219,34 +219,34 @@
+ ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
+ #define SET(x) \
+ ev->x = fdevent_linux_rtsig_##x;
+-
++
+ SET(free);
+ SET(poll);
+-
++
+ SET(event_del);
+ SET(event_add);
+-
++
+ SET(event_next_fdndx);
+ SET(fcntl_set);
+ SET(event_get_fd);
+ SET(event_get_revent);
+-
++
+ ev->signum = SIGRTMIN + 1;
+-
++
+ sigemptyset(&(ev->sigset));
+ sigaddset(&(ev->sigset), ev->signum);
+ sigaddset(&(ev->sigset), SIGIO);
+ if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) {
+ fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__, strerror(errno));
+-
++
+ return -1;
}
--#elif defined __WIN32
-+#elif defined _WIN32
- name_max = FILENAME_MAX;
+-
++
+ ev->in_sigio = 1;
+
+ ev->sigbset = bitset_init(ev->maxfds);
+-
++
+ return 0;
+ }
#else
- name_max = NAME_MAX;
-@@ -615,6 +613,11 @@
- path = malloc(dir->used + name_max);
- assert(path);
- strcpy(path, dir->ptr);
-+#ifdef _WIN32
-+ /* append \*.* to the path and keep the \ as part of the pathname */
-+ strcat(path, "\\*.*");
-+ i++;
-+#endif
- path_file = path + i;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_linux_sysepoll.c lighttpd-1.4.12/src/fdevent_linux_sysepoll.c
+--- lighttpd-1.4.11/src/fdevent_linux_sysepoll.c 2005-09-30 20:29:27.000000000 +0300
++++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,6 +1,5 @@
+ #include <sys/types.h>
- if (NULL == (dp = opendir(path))) {
-@@ -693,8 +696,10 @@
- if (i > (size_t)name_max) continue;
-
- memcpy(path_file, dent->d_name, i + 1);
-- if (stat(path, &st) != 0)
-+ if (stat(path, &st) != 0) {
-+ fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, path, strerror(errno));
- continue;
-+ }
+-#include <unistd.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -12,6 +11,8 @@
+ #include "settings.h"
+ #include "buffer.h"
- list = &files;
- if (S_ISDIR(st.st_mode))
---- lighttpd-1.4.11/src/mod_evasive.c 2006-01-04 15:24:51.000000000 +0200
-+++ lighttpd/src/mod_evasive.c 2006-07-11 21:23:40.187861491 +0300
-@@ -96,13 +96,11 @@
- return HANDLER_GO_ON;
++#include "sys-files.h"
++
+ #ifdef USE_LINUX_EPOLL
+ static void fdevent_linux_sysepoll_free(fdevents *ev) {
+ close(ev->epoll_fd);
+@@ -20,36 +21,36 @@
+
+ static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
+ struct epoll_event ep;
+-
++
+ if (fde_ndx < 0) return -1;
+-
++
+ memset(&ep, 0, sizeof(ep));
+-
++
+ ep.data.fd = fd;
+ ep.data.ptr = NULL;
+-
++
+ if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
+ fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
+-
++
+ SEGFAULT();
+-
++
+ return 0;
+ }
+-
+-
++
++
+ return -1;
}
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
+ static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
+ struct epoll_event ep;
+ int add = 0;
+-
++
+ if (fde_ndx == -1) add = 1;
+-
++
+ memset(&ep, 0, sizeof(ep));
+-
++
+ ep.events = 0;
+-
++
+ if (events & FDEVENT_IN) ep.events |= EPOLLIN;
+ if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
-- PATCH(max_conns);
-+ PATCH_OPTION(max_conns);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -117,14 +115,13 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
-- PATCH(max_conns);
-+ PATCH_OPTION(max_conns);
- }
- }
+@@ -60,20 +61,20 @@
+ * sent.
+ *
+ */
+-
++
+ ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
+-
++
+ ep.data.ptr = NULL;
+ ep.data.fd = fd;
+-
++
+ if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
+ fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
+-
++
+ SEGFAULT();
+-
++
+ return 0;
}
-
- return 0;
+-
++
+ return fd;
}
--#undef PATCH
- URIHANDLER_FUNC(mod_evasive_uri_handler) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_evhost.c 2005-08-17 10:42:03.000000000 +0300
-+++ lighttpd/src/mod_evhost.c 2006-07-11 21:23:39.991849214 +0300
-@@ -7,6 +7,8 @@
- #include "response.h"
- #include "stat_cache.h"
+@@ -83,14 +84,14 @@
-+#include "sys-files.h"
+ static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
+ int events = 0, e;
+-
+
- typedef struct {
- /* unparsed pieces */
- buffer *path_pieces_raw;
-@@ -221,14 +223,12 @@
- return 0;
+ e = ev->epoll_events[ndx].events;
+ if (e & EPOLLIN) events |= FDEVENT_IN;
+ if (e & EPOLLOUT) events |= FDEVENT_OUT;
+ if (e & EPOLLERR) events |= FDEVENT_ERR;
+ if (e & EPOLLHUP) events |= FDEVENT_HUP;
+ if (e & EPOLLPRI) events |= FDEVENT_PRI;
+-
++
+ return e;
}
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(path_pieces);
-- PATCH(len);
-+ PATCH_OPTION(path_pieces);
-+ PATCH_OPTION(len);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -243,16 +243,14 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
-- PATCH(path_pieces);
-- PATCH(len);
-+ PATCH_OPTION(path_pieces);
-+ PATCH_OPTION(len);
- }
- }
- }
-
- return 0;
+@@ -98,17 +99,17 @@
+ # if 0
+ fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
+ # endif
+-
++
+ return ev->epoll_events[ndx].data.fd;
}
--#undef PATCH
--
- static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
- plugin_data *p = p_d;
-@@ -299,7 +297,7 @@
- }
- }
-
-- BUFFER_APPEND_SLASH(p->tmp_buf);
-+ PATHNAME_APPEND_SLASH(p->tmp_buf);
-
- array_free(parsed_host);
-
---- lighttpd-1.4.11/src/mod_expire.c 2005-11-03 09:52:13.000000000 +0200
-+++ lighttpd/src/mod_expire.c 2006-07-11 21:23:40.103856229 +0300
-@@ -245,13 +245,11 @@
- return HANDLER_GO_ON;
- }
+ static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
+ size_t i;
+-
++
+ UNUSED(ev);
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(expire_url);
-+ PATCH_OPTION(expire_url);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -266,14 +264,13 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
-- PATCH(expire_url);
-+ PATCH_OPTION(expire_url);
- }
- }
- }
-
- return 0;
+ i = (ndx < 0) ? 0 : ndx + 1;
+-
++
+ return i;
}
--#undef PATCH
-
- URIHANDLER_FUNC(mod_expire_path_handler) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_fastcgi.c 2006-03-09 13:18:39.000000000 +0200
-+++ lighttpd/src/mod_fastcgi.c 2006-07-11 21:23:40.207862743 +0300
-@@ -1,5 +1,4 @@
- #include <sys/types.h>
--#include <unistd.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <string.h>
-@@ -24,7 +23,7 @@
- #include "inet_ntop_cache.h"
- #include "stat_cache.h"
--#include <fastcgi.h>
-+#include "fastcgi.h"
- #include <stdio.h>
+@@ -116,17 +117,17 @@
+ ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
+ #define SET(x) \
+ ev->x = fdevent_linux_sysepoll_##x;
+-
++
+ SET(free);
+ SET(poll);
+-
++
+ SET(event_del);
+ SET(event_add);
+-
++
+ SET(event_next_fdndx);
+ SET(event_get_fd);
+ SET(event_get_revent);
+-
++
+ if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
+ fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__, strerror(errno));
+@@ -154,7 +155,7 @@
- #ifdef HAVE_SYS_FILIO_H
-@@ -32,7 +31,11 @@
+ fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__);
+-
++
+ return -1;
+ }
#endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_poll.c lighttpd-1.4.12/src/fdevent_poll.c
+--- lighttpd-1.4.11/src/fdevent_poll.c 2005-11-18 13:59:16.000000000 +0200
++++ lighttpd-1.4.12/src/fdevent_poll.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,6 +1,5 @@
+ #include <sys/types.h>
- #include "sys-socket.h"
-+#include "sys-files.h"
-+#include "sys-strings.h"
-+#include "sys-process.h"
+-#include <unistd.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -20,19 +19,19 @@
-+#include "http_resp.h"
+ static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
+ if (fde_ndx < 0) return -1;
+-
++
+ if ((size_t)fde_ndx >= ev->used) {
+ fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used);
+ SEGFAULT();
+ }
+-
++
+ if (ev->pollfds[fde_ndx].fd == fd) {
+ size_t k = fde_ndx;
+-
++
+ ev->pollfds[k].fd = -1;
+ /* ev->pollfds[k].events = 0; */
+ /* ev->pollfds[k].revents = 0; */
+-
++
+ if (ev->unused.size == 0) {
+ ev->unused.size = 16;
+ ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
+@@ -40,47 +39,47 @@
+ ev->unused.size += 16;
+ ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
+ }
+-
++
+ ev->unused.ptr[ev->unused.used++] = k;
+ } else {
+ SEGFAULT();
+ }
+-
++
+ return -1;
+ }
- #ifndef UNIX_PATH_MAX
- # define UNIX_PATH_MAX 108
-@@ -45,7 +48,6 @@
- #include <sys/wait.h>
+ #if 0
+ static int fdevent_poll_event_compress(fdevents *ev) {
+ size_t j;
+-
++
+ if (ev->used == 0) return 0;
+ if (ev->unused.used != 0) return 0;
+-
++
+ for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
+-
++
+ return 0;
+ }
#endif
--
- /*
- *
- * TODO:
-@@ -310,10 +312,11 @@
- buffer *fcgi_env;
-
- buffer *path;
-- buffer *parse_response;
-
- buffer *statuskey;
-
-+ http_resp *resp;
+ static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
+ /* known index */
+-
+
- plugin_config **config_storage;
-
- plugin_config conf; /* this is only used as long as no handler_ctx is setup */
-@@ -339,11 +342,10 @@
-
- int reconnects; /* number of reconnect attempts */
-
-- chunkqueue *rb; /* read queue */
-+ chunkqueue *rb; /* the raw fcgi read-queue */
-+ chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
- chunkqueue *wb; /* write queue */
-
-- buffer *response_header;
+ if (fde_ndx != -1) {
+ if (ev->pollfds[fde_ndx].fd == fd) {
+ ev->pollfds[fde_ndx].events = events;
+-
++
+ return fde_ndx;
+ }
+ fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
+ SEGFAULT();
+ }
-
- size_t request_id;
- int fd; /* fd to the fastcgi process */
- int fde_ndx; /* index into the fd-event buffer */
-@@ -451,8 +453,6 @@
-
- hctx->fde_ndx = -1;
-
-- hctx->response_header = buffer_init();
++
+ if (ev->unused.used > 0) {
+ int k = ev->unused.ptr[--ev->unused.used];
+-
++
+ ev->pollfds[k].fd = fd;
+ ev->pollfds[k].events = events;
+-
++
+ return k;
+ } else {
+ if (ev->size == 0) {
+@@ -90,10 +89,10 @@
+ ev->size += 16;
+ ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
+ }
+-
++
+ ev->pollfds[ev->used].fd = fd;
+ ev->pollfds[ev->used].events = events;
+-
++
+ return ev->used++;
+ }
+ }
+@@ -109,12 +108,12 @@
+ int r, poll_r;
+ if (ndx >= ev->used) {
+ fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used);
+-
++
+ SEGFAULT();
+-
++
+ return 0;
+ }
-
- hctx->request_id = 0;
- hctx->state = FCGI_STATE_INIT;
- hctx->proc = NULL;
-@@ -463,6 +463,7 @@
- hctx->send_content_body = 1;
++
+ if (ev->pollfds[ndx].revents & POLLNVAL) {
+ /* should never happen */
+ SEGFAULT();
+@@ -131,7 +130,7 @@
+ if (poll_r & POLLHUP) r |= FDEVENT_HUP;
+ if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
+ if (poll_r & POLLPRI) r |= FDEVENT_PRI;
+-
++
+ return ev->pollfds[ndx].revents;
+ }
- hctx->rb = chunkqueue_init();
-+ hctx->http_rb = chunkqueue_init();
- hctx->wb = chunkqueue_init();
-
- return hctx;
-@@ -474,9 +475,8 @@
- hctx->host = NULL;
- }
-
-- buffer_free(hctx->response_header);
--
- chunkqueue_free(hctx->rb);
-+ chunkqueue_free(hctx->http_rb);
- chunkqueue_free(hctx->wb);
+@@ -141,12 +140,12 @@
- free(hctx);
-@@ -639,7 +639,8 @@
- p->fcgi_env = buffer_init();
-
- p->path = buffer_init();
-- p->parse_response = buffer_init();
+ static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
+ size_t i;
+-
+
-+ p->resp = http_response_init();
+ i = (ndx < 0) ? 0 : ndx + 1;
+ for (; i < ev->used; i++) {
+ if (ev->pollfds[i].revents) break;
+ }
+-
++
+ return i;
+ }
- p->statuskey = buffer_init();
-
-@@ -657,9 +658,10 @@
-
- buffer_free(p->fcgi_env);
- buffer_free(p->path);
-- buffer_free(p->parse_response);
- buffer_free(p->statuskey);
-
-+ http_response_free(p->resp);
+@@ -154,17 +153,17 @@
+ ev->type = FDEVENT_HANDLER_POLL;
+ #define SET(x) \
+ ev->x = fdevent_poll_##x;
+-
+
- if (p->config_storage) {
- size_t i, j, n;
- for (i = 0; i < srv->config_context->used; i++) {
-@@ -825,12 +827,8 @@
- fcgi_addr_un.sun_family = AF_UNIX;
- strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
-
--#ifdef SUN_LEN
- servlen = SUN_LEN(&fcgi_addr_un);
--#else
-- /* stevens says: */
-- servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
--#endif
+ SET(free);
+ SET(poll);
+-
+
- socket_type = AF_UNIX;
- fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
+ SET(event_del);
+ SET(event_add);
+-
++
+ SET(event_next_fdndx);
+ SET(event_get_fd);
+ SET(event_get_revent);
+-
++
+ return 0;
+ }
-@@ -933,7 +931,7 @@
- return -1;
- }
-
--#ifdef HAVE_FORK
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_select.c lighttpd-1.4.12/src/fdevent_select.c
+--- lighttpd-1.4.11/src/fdevent_select.c 2005-08-31 11:12:46.000000000 +0300
++++ lighttpd-1.4.12/src/fdevent_select.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,18 +1,19 @@
+-#include <sys/time.h>
+ #include <sys/types.h>
+
+-#include <unistd.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <errno.h>
+ #include <signal.h>
+ #include <fcntl.h>
+ #include <assert.h>
++#include <stdio.h>
+
+ #include "fdevent.h"
+ #include "settings.h"
+ #include "buffer.h"
+
++#include "sys-socket.h"
++
+ #ifdef USE_SELECT
+
+ static int fdevent_select_reset(fdevents *ev) {
+@@ -38,7 +39,9 @@
+ UNUSED(fde_ndx);
+
+ /* we should be protected by max-fds, but you never know */
+#ifndef _WIN32
- switch ((child = fork())) {
- case 0: {
- size_t i = 0;
-@@ -1677,12 +1675,9 @@
- /* use the unix domain socket */
- fcgi_addr_un.sun_family = AF_UNIX;
- strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
--#ifdef SUN_LEN
+ assert(fd < FD_SETSIZE);
++#endif
+
+ if (events & FDEVENT_IN) {
+ FD_SET(fd, &(ev->select_set_read));
+@@ -49,28 +52,28 @@
+ FD_SET(fd, &(ev->select_set_write));
+ }
+ FD_SET(fd, &(ev->select_set_error));
+-
+
- servlen = SUN_LEN(&fcgi_addr_un);
--#else
-- /* stevens says: */
-- servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
--#endif
+ if (fd > ev->select_max_fd) ev->select_max_fd = fd;
+-
+
- fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
-
- if (buffer_is_empty(proc->connection_name)) {
-@@ -1695,6 +1690,7 @@
- #endif
- } else {
- fcgi_addr_in.sin_family = AF_INET;
+ return fd;
+ }
+
+ static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
+ struct timeval tv;
+-
+
- if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "converting IP-adress failed for", host->host,
-@@ -1702,6 +1698,7 @@
-
- return -1;
- }
+ tv.tv_sec = timeout_ms / 1000;
+ tv.tv_usec = (timeout_ms % 1000) * 1000;
+-
+
- fcgi_addr_in.sin_port = htons(proc->port);
- servlen = sizeof(fcgi_addr_in);
-
-@@ -2186,105 +2183,6 @@
- return 0;
+ ev->select_read = ev->select_set_read;
+ ev->select_write = ev->select_set_write;
+ ev->select_error = ev->select_set_error;
+-
++
+ return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
}
--static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
-- char *s, *ns;
+ static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
+ int revents = 0;
-
-- handler_ctx *hctx = con->plugin_ctx[p->id];
-- fcgi_extension_host *host= hctx->host;
++
+ if (FD_ISSET(ndx, &(ev->select_read))) {
+ revents |= FDEVENT_IN;
+ }
+@@ -80,7 +83,7 @@
+ if (FD_ISSET(ndx, &(ev->select_error))) {
+ revents |= FDEVENT_ERR;
+ }
-
-- UNUSED(srv);
--
-- buffer_copy_string_buffer(p->parse_response, in);
++
+ return revents;
+ }
+
+@@ -92,15 +95,15 @@
+
+ static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
+ int i;
-
-- /* search for \n */
-- for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
-- char *key, *value;
-- int key_len;
-- data_string *ds;
--
-- /* a good day. Someone has read the specs and is sending a \r\n to us */
--
-- if (ns > p->parse_response->ptr &&
-- *(ns-1) == '\r') {
-- *(ns-1) = '\0';
-- }
--
-- ns[0] = '\0';
++
+ i = (ndx < 0) ? 0 : ndx + 1;
+-
++
+ for (; i < ev->select_max_fd + 1; i++) {
+ if (FD_ISSET(i, &(ev->select_read))) break;
+ if (FD_ISSET(i, &(ev->select_write))) break;
+ if (FD_ISSET(i, &(ev->select_error))) break;
+ }
+-
++
+ return i;
+ }
+
+@@ -108,17 +111,17 @@
+ ev->type = FDEVENT_HANDLER_SELECT;
+ #define SET(x) \
+ ev->x = fdevent_select_##x;
+-
++
+ SET(reset);
+ SET(poll);
+-
++
+ SET(event_del);
+ SET(event_add);
+-
++
+ SET(event_next_fdndx);
+ SET(event_get_fd);
+ SET(event_get_revent);
+-
++
+ return 0;
+ }
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_solaris_devpoll.c lighttpd-1.4.12/src/fdevent_solaris_devpoll.c
+--- lighttpd-1.4.11/src/fdevent_solaris_devpoll.c 2005-09-01 10:45:26.000000000 +0300
++++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,6 +1,5 @@
+ #include <sys/types.h>
+
+-#include <unistd.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -23,55 +22,55 @@
+
+ static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
+ struct pollfd pfd;
-
-- key = s;
-- if (NULL == (value = strchr(s, ':'))) {
-- /* we expect: "<key>: <value>\n" */
-- continue;
-- }
++
+ if (fde_ndx < 0) return -1;
+-
++
+ pfd.fd = fd;
+ pfd.events = POLLREMOVE;
+ pfd.revents = 0;
+-
++
+ if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
+- fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
+- __FILE__, __LINE__,
++ fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
++ __FILE__, __LINE__,
+ fd, strerror(errno));
-
-- key_len = value - key;
++
+ return -1;
+ }
+-
++
+ return -1;
+ }
+
+ static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
+ struct pollfd pfd;
+ int add = 0;
-
-- value++;
-- /* strip WS */
-- while (*value == ' ' || *value == '\t') value++;
++
+ if (fde_ndx == -1) add = 1;
+-
++
+ pfd.fd = fd;
+ pfd.events = events;
+ pfd.revents = 0;
+-
++
+ if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
+- fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
+- __FILE__, __LINE__,
++ fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
++ __FILE__, __LINE__,
+ fd, strerror(errno));
-
-- if (host->mode != FCGI_AUTHORIZER ||
-- !(con->http_status == 0 ||
-- con->http_status == 200)) {
-- /* authorizers shouldn't affect the response headers sent back to the client */
--
-- /* don't forward Status: */
-- if (0 != strncasecmp(key, "Status", key_len)) {
-- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
-- ds = data_response_init();
-- }
-- buffer_copy_string_len(ds->key, key, key_len);
-- buffer_copy_string(ds->value, value);
--
-- array_insert_unique(con->response.headers, (data_unset *)ds);
-- }
-- }
--
-- switch(key_len) {
-- case 4:
-- if (0 == strncasecmp(key, "Date", key_len)) {
-- con->parsed_response |= HTTP_DATE;
-- }
-- break;
-- case 6:
-- if (0 == strncasecmp(key, "Status", key_len)) {
-- con->http_status = strtol(value, NULL, 10);
-- con->parsed_response |= HTTP_STATUS;
-- }
-- break;
-- case 8:
-- if (0 == strncasecmp(key, "Location", key_len)) {
-- con->parsed_response |= HTTP_LOCATION;
-- }
-- break;
-- case 10:
-- if (0 == strncasecmp(key, "Connection", key_len)) {
-- con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
-- con->parsed_response |= HTTP_CONNECTION;
-- }
-- break;
-- case 14:
-- if (0 == strncasecmp(key, "Content-Length", key_len)) {
-- con->response.content_length = strtol(value, NULL, 10);
-- con->parsed_response |= HTTP_CONTENT_LENGTH;
--
-- if (con->response.content_length < 0) con->response.content_length = 0;
-- }
-- break;
-- default:
-- break;
-- }
-- }
--
-- /* CGI/1.1 rev 03 - 7.2.1.2 */
-- if ((con->parsed_response & HTTP_LOCATION) &&
-- !(con->parsed_response & HTTP_STATUS)) {
-- con->http_status = 302;
-- }
++
+ return -1;
+ }
-
-- return 0;
--}
--
- typedef struct {
- buffer *b;
- size_t len;
-@@ -2386,52 +2284,24 @@
++
+ return fd;
+ }
- static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
- int fin = 0;
-- int toread;
-- ssize_t r;
-
- plugin_data *p = hctx->plugin_data;
- connection *con = hctx->remote_conn;
-- int fcgi_fd = hctx->fd;
- fcgi_extension_host *host= hctx->host;
- fcgi_proc *proc = hctx->proc;
-
-- /*
-- * check how much we have to read
-- */
-- if (ioctl(hctx->fd, FIONREAD, &toread)) {
-- log_error_write(srv, __FILE__, __LINE__, "sd",
-- "unexpected end-of-file (perhaps the fastcgi process died):",
-- fcgi_fd);
-- return -1;
-- }
+ static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
+ struct dvpoll dopoll;
+ int ret;
-
-- /* init read-buffer */
++
+ dopoll.dp_timeout = timeout_ms;
+ dopoll.dp_nfds = ev->maxfds;
+ dopoll.dp_fds = ev->devpollfds;
-
-- if (toread > 0) {
-- buffer *b;
--
-- b = chunkqueue_get_append_buffer(hctx->rb);
-- buffer_prepare_copy(b, toread + 1);
--
-- /* append to read-buffer */
-- if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
-- log_error_write(srv, __FILE__, __LINE__, "sds",
-- "unexpected end-of-file (perhaps the fastcgi process died):",
-- fcgi_fd, strerror(errno));
-- return -1;
-- }
--
-- /* this should be catched by the b > 0 above */
-- assert(r);
--
-- b->used = r + 1; /* one extra for the fake \0 */
-- b->ptr[b->used - 1] = '\0';
-- } else {
-+ switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) {
-+ case NETWORK_STATUS_WAIT_FOR_EVENT:
-+ /* we are only triggered when there is a event */
- log_error_write(srv, __FILE__, __LINE__, "ssdsb",
- "unexpected end-of-file (perhaps the fastcgi process died):",
- "pid:", proc->pid,
- "socket:", proc->connection_name);
--
-+ return -1;
-+ case NETWORK_STATUS_SUCCESS:
-+ break;
-+ default:
-+ log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
- return -1;
- }
++
+ ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
+-
++
+ return ret;
+ }
-@@ -2454,80 +2324,123 @@
+@@ -85,11 +84,11 @@
- /* is the header already finished */
- if (0 == con->file_started) {
-- char *c;
-- size_t blen;
-- data_string *ds;
--
-- /* search for header terminator
-- *
-- * if we start with \r\n check if last packet terminated with \r\n
-- * if we start with \n check if last packet terminated with \n
-- * search for \r\n\r\n
-- * search for \n\n
-- */
--
-- if (hctx->response_header->used == 0) {
-- buffer_copy_string_buffer(hctx->response_header, packet.b);
-- } else {
-- buffer_append_string_buffer(hctx->response_header, packet.b);
-- }
-+ int have_content_length = 0;
-+ int need_more = 0;
-+ size_t i;
+ static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
+ size_t i;
+-
++
+ UNUSED(ev);
-- if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
-- blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
-- hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
-- c += 4; /* point the the start of the response */
-- } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
-- blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
-- hctx->response_header->used = c - hctx->response_header->ptr + 2;
-- c += 2; /* point the the start of the response */
-- } else {
-- /* no luck, no header found */
-+ /* append the current packet to the chunk queue */
-+ chunkqueue_append_buffer(hctx->http_rb, packet.b);
-+ http_response_reset(p->resp);
+ i = (last_ndx < 0) ? 0 : last_ndx + 1;
+-
+
-+ switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
-+ case PARSE_ERROR:
-+ /* parsing the response header failed */
+ return i;
+ }
+
+@@ -117,20 +116,20 @@
+ ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
+ #define SET(x) \
+ ev->x = fdevent_solaris_devpoll_##x;
+-
+
-+ con->http_status = 502; /* Bad Gateway */
+ SET(free);
+ SET(poll);
+ SET(reset);
+-
+
-+ return 1;
-+ case PARSE_NEED_MORE:
-+ need_more = 1;
-+ break; /* leave the loop */
-+ case PARSE_SUCCESS:
- break;
-+ default:
-+ /* should not happen */
-+ SEGFAULT();
- }
+ SET(event_del);
+ SET(event_add);
+-
++
+ SET(event_next_fdndx);
+ SET(event_get_fd);
+ SET(event_get_revent);
+-
++
+ ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
+-
++
+ if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
+ fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__, strerror(errno));
+@@ -152,7 +151,7 @@
-- /* parse the response header */
-- fcgi_response_parse(srv, con, p, hctx->response_header);
-+ if (need_more) break;
+ fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
+ __FILE__, __LINE__);
+-
++
+ return -1;
+ }
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http-header-glue.c lighttpd-1.4.12/src/http-header-glue.c
+--- lighttpd-1.4.11/src/http-header-glue.c 2006-02-08 15:31:36.000000000 +0200
++++ lighttpd-1.4.12/src/http-header-glue.c 2006-07-11 21:23:40.000000000 +0300
+@@ -45,20 +45,20 @@
+ # ifdef HAVE_STRUCT_SOCKADDR_STORAGE
+ static size_t get_sa_len(const struct sockaddr *addr) {
+ switch (addr->sa_family) {
+-
++
+ # ifdef AF_INET
+ case AF_INET:
+ return (sizeof (struct sockaddr_in));
+ # endif
+-
++
+ # ifdef AF_INET6
+ case AF_INET6:
+ return (sizeof (struct sockaddr_in6));
+ # endif
+-
++
+ default:
+ return (sizeof (struct sockaddr));
+-
++
+ }
+ }
+ # define SA_LEN(addr) (get_sa_len(addr))
+@@ -74,7 +74,7 @@
-- con->file_started = 1;
-+ chunkqueue_remove_finished_chunks(hctx->http_rb);
+ int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
+ data_string *ds;
+-
++
+ UNUSED(srv);
-- if (host->mode == FCGI_AUTHORIZER &&
-- (con->http_status == 0 ||
-- con->http_status == 200)) {
-+ con->http_status = p->resp->status;
+ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
+@@ -82,32 +82,32 @@
+ }
+ buffer_copy_string_len(ds->key, key, keylen);
+ buffer_copy_string_len(ds->value, value, vallen);
+-
+
-+ /* handle the header fields */
-+ if (host->mode == FCGI_AUTHORIZER) {
-+ /* auth mode is a bit different */
+ array_insert_unique(con->response.headers, (data_unset *)ds);
+-
+
-+ if (con->http_status == 0 ||
-+ con->http_status == 200) {
- /* a authorizer with approved the static request, ignore the content here */
- hctx->send_content_body = 0;
- }
-+ }
+ return 0;
+ }
-- if (host->allow_xsendfile &&
-- NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
-- stat_cache_entry *sce;
-+ /* copy the http-headers */
-+ for (i = 0; i < p->resp->headers->used; i++) {
-+ const char *ign[] = { "Status", NULL };
-+ size_t j;
-+ data_string *ds;
+ int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
+ data_string *ds;
+-
++
+ UNUSED(srv);
-- if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
-- /* found */
-+ data_string *header = (data_string *)p->resp->headers->data[i];
+ /* if there already is a key by this name overwrite the value */
+ if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
+ buffer_copy_string(ds->value, value);
+-
+
-+ /* ignore all headers in AUTHORIZER mode */
-+ if (host->mode == FCGI_AUTHORIZER) continue;
+ return 0;
+ }
+-
+
-+ /* some headers are ignored by default */
-+ for (j = 0; ign[j]; j++) {
-+ if (0 == strcasecmp(ign[j], header->key->ptr)) break;
-+ }
-+ if (ign[j]) continue;
+ return response_header_insert(srv, con, key, keylen, value, vallen);
+ }
+
+ int http_response_redirect_to_directory(server *srv, connection *con) {
+ buffer *o;
+-
+
-+ if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
-+ /* CGI/1.1 rev 03 - 7.2.1.2 */
-+ con->http_status = 302;
-+ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
-+ have_content_length = 1;
-+ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) ||
-+ 0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
-
-- http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
-+ stat_cache_entry *sce;
-+
-+ if (host->allow_xsendfile &&
-+ HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
-+ http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
- hctx->send_content_body = 0; /* ignore the content */
-+
- joblist_append(srv, con);
- }
-+
-+ continue; /* ignore header */
- }
-
-+ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
-+ ds = data_response_init();
-+ }
-+ buffer_copy_string_buffer(ds->key, header->key);
-+ buffer_copy_string_buffer(ds->value, header->value);
-
-- if (hctx->send_content_body && blen > 1) {
-- /* enable chunked-transfer-encoding */
-+ array_insert_unique(con->response.headers, (data_unset *)ds);
-+ }
+ o = buffer_init();
+-
+
-+ /* header is complete ... go on with the body */
+ if (con->conf.is_ssl) {
+ buffer_copy_string(o, "https://");
+ } else {
+@@ -123,36 +123,36 @@
+ #endif
+ sock_addr our_addr;
+ socklen_t our_addr_len;
+-
+
-+ con->file_started = 1;
+ our_addr_len = sizeof(our_addr);
+-
+
-+ if (hctx->send_content_body) {
-+ chunk *c = hctx->http_rb->first;
+ if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
+ con->http_status = 500;
+-
+
-+ /* if we don't have a content-length enable chunked encoding
-+ * if possible
-+ *
-+ * TODO: move this to a later stage in the filter-queue
-+ * */
- if (con->request.http_version == HTTP_VERSION_1_1 &&
-- !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
-+ !have_content_length) {
- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
- }
-
-- http_chunk_append_mem(srv, con, c, blen);
-+ /* copy the rest of the data */
-+ for (c = hctx->http_rb->first; c; c = c->next) {
-+ if (c->mem->used > 1) {
-+ http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
-+ c->offset = c->mem->used - 1;
-+ }
-+ }
-+ chunkqueue_remove_finished_chunks(hctx->http_rb);
- joblist_append(srv, con);
- }
- } else if (hctx->send_content_body && packet.b->used > 1) {
-- if (con->request.http_version == HTTP_VERSION_1_1 &&
-- !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
-- /* enable chunked-transfer-encoding */
-- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
-- }
--
- http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
- joblist_append(srv, con);
- }
-@@ -2606,7 +2519,7 @@
- if (!proc->is_local) break;
-
- /* the child should not terminate at all */
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "can't get sockname", strerror(errno));
-
-+#ifndef _WIN32
- switch(waitpid(proc->pid, &status, WNOHANG)) {
- case 0:
- /* child is still alive */
-@@ -2633,7 +2546,7 @@
- proc->state = PROC_STATE_DIED;
- break;
- }
--
-+#endif
- /* fall through if we have a dead proc now */
- if (proc->state != PROC_STATE_DIED) break;
-
-@@ -2934,10 +2847,11 @@
- */
- if (hctx->wb->bytes_out == 0 &&
- hctx->reconnects < 5) {
-+#ifndef _WIN32
- usleep(10000); /* take away the load of the webserver
- * to let the php a chance to restart
- */
--
-+#endif
- fcgi_reconnect(srv, hctx);
-
- return HANDLER_WAIT_FOR_FD;
-@@ -2949,7 +2863,7 @@
- *
- */
-
-- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
-+ log_error_write(srv, __FILE__, __LINE__, "ssosd",
- "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
- "write-offset:", hctx->wb->bytes_out,
- "reconnect attempts:", hctx->reconnects);
-@@ -3155,7 +3069,7 @@
- int status;
-
- /* only fetch the zombie if it is not already done */
++
+ buffer_free(o);
+ return 0;
+ }
+-
+-
++
++
+ /* Lookup name: secondly try to get hostname for bind address */
+ switch(our_addr.plain.sa_family) {
+ #ifdef HAVE_IPV6
+ case AF_INET6:
+- if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
+- SA_LEN((const struct sockaddr *)&our_addr.ipv6),
++ if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
++ SA_LEN((const struct sockaddr *)&our_addr.ipv6),
+ hbuf, sizeof(hbuf), NULL, 0, 0)) {
-
-+#ifndef _WIN32
- switch(waitpid(proc->pid, &status, WNOHANG)) {
- case 0:
- /* child is still alive */
-@@ -3195,6 +3109,7 @@
-
- break;
- }
-+#endif
- }
-
- if (con->file_started == 0) {
-@@ -3307,15 +3222,14 @@
-
- return HANDLER_FINISHED;
- }
--#define PATCH(x) \
-- p->conf.x = s->x;
+
- static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(exts);
-- PATCH(debug);
-- PATCH(ext_mapping);
-+ PATCH_OPTION(exts);
-+ PATCH_OPTION(debug);
-+ PATCH_OPTION(ext_mapping);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -3330,19 +3244,17 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
-- PATCH(exts);
-+ PATCH_OPTION(exts);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
-- PATCH(debug);
-+ PATCH_OPTION(debug);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
-- PATCH(ext_mapping);
-+ PATCH_OPTION(ext_mapping);
- }
+ char dst[INET6_ADDRSTRLEN];
+-
++
+ log_error_write(srv, __FILE__, __LINE__,
+ "SSSS", "NOTICE: getnameinfo failed: ",
+ strerror(errno), ", using ip-address instead");
+-
+- buffer_append_string(o,
+- inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
++
++ buffer_append_string(o,
++ inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
+ dst, sizeof(dst)));
+ } else {
+ buffer_append_string(o, hbuf);
+@@ -164,7 +164,7 @@
+ log_error_write(srv, __FILE__, __LINE__,
+ "SdSS", "NOTICE: gethostbyaddr failed: ",
+ h_errno, ", using ip-address instead");
+-
++
+ buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
+ } else {
+ buffer_append_string(o, he->h_name);
+@@ -173,12 +173,12 @@
+ default:
+ log_error_write(srv, __FILE__, __LINE__,
+ "S", "ERROR: unsupported address-type");
+-
++
+ buffer_free(o);
+ return -1;
}
+-
+- if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
++
++ if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
+ (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
+ buffer_append_string(o, ":");
+ buffer_append_long(o, srv->srvconf.port);
+@@ -190,41 +190,41 @@
+ buffer_append_string(o, "?");
+ buffer_append_string_buffer(o, con->uri.query);
}
-
+-
++
+ response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
+-
++
+ con->http_status = 301;
+ con->file_finished = 1;
+-
++
+ buffer_free(o);
+-
++
return 0;
}
--#undef PATCH
--
- static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
- plugin_data *p = p_d;
-@@ -3610,10 +3522,33 @@
- *
- * currently we wait for the TCP timeout which is on Linux 180 seconds
- *
-- *
-- *
+ buffer * strftime_cache_get(server *srv, time_t last_mod) {
+ struct tm *tm;
+ size_t i;
+-
++
+ for (i = 0; i < FILE_CACHE_MAX; i++) {
+ /* found cache-entry */
+ if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;
+-
++
+ /* found empty slot */
+ if (srv->mtime_cache[i].mtime == 0) break;
+ }
+-
++
+ if (i == FILE_CACHE_MAX) {
+ i = 0;
+ }
+-
++
+ srv->mtime_cache[i].mtime = last_mod;
+ buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
+ tm = gmtime(&(srv->mtime_cache[i].mtime));
+- srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
++ srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
+ srv->mtime_cache[i].str->size - 1,
+ "%a, %d %b %Y %H:%M:%S GMT", tm);
+ srv->mtime_cache[i].str->used++;
+-
++
+ return srv->mtime_cache[i].str;
+ }
+
+@@ -239,56 +239,60 @@
+ * request. That is, if no entity tags match, then the server MUST NOT
+ * return a 304 (Not Modified) response.
*/
+-
++
+ /* last-modified handling */
+ if (con->request.http_if_none_match) {
+ if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) {
+- if (con->request.http_method == HTTP_METHOD_GET ||
++ if (con->request.http_method == HTTP_METHOD_GET ||
+ con->request.http_method == HTTP_METHOD_HEAD) {
+-
++
+ /* check if etag + last-modified */
+ if (con->request.http_if_modified_since) {
+ size_t used_len;
+ char *semicolon;
+-
++
+ if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
+ used_len = strlen(con->request.http_if_modified_since);
+ } else {
+ used_len = semicolon - con->request.http_if_modified_since;
+ }
+-
++
+ if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
+ con->http_status = 304;
+ return HANDLER_FINISHED;
+ } else {
++#ifdef HAVE_STRPTIME
+ char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
++ time_t t_header, t_file;
++ struct tm tm;
-+ for (i = 0; i < srv->conns->used; i++) {
-+ connection *con = srv->conns->ptr[i];
-+ handler_ctx *hctx = con->plugin_ctx[p->id];
+- /* convert to timestamp */
+- if (used_len < sizeof(buf)) {
+- time_t t_header, t_file;
+- struct tm tm;
+-
+- strncpy(buf, con->request.http_if_modified_since, used_len);
+- buf[used_len] = '\0';
+-
+- strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
+- t_header = mktime(&tm);
+-
+- strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
+- t_file = mktime(&tm);
+-
+- if (t_file > t_header) {
+- con->http_status = 304;
+- return HANDLER_FINISHED;
+- }
+- } else {
+- log_error_write(srv, __FILE__, __LINE__, "ssdd",
+- "DEBUG: Last-Modified check failed as the received timestamp was too long:",
++ /* check if we can safely copy the string */
++ if (used_len >= sizeof(buf)) {
++ log_error_write(srv, __FILE__, __LINE__, "ssdd",
++ "DEBUG: Last-Modified check failed as the received timestamp was too long:",
+ con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
+-
+
-+ /* if a connection is ours and is in handle-req for more than max-request-time
-+ * kill the connection */
+ con->http_status = 412;
+ return HANDLER_FINISHED;
+ }
+
-+ if (con->mode != p->id) continue;
-+ if (con->state != CON_STATE_HANDLE_REQUEST) continue;
-+ if (srv->cur_ts < con->request_start + 60) continue;
+
-+ /* the request is waiting for a FCGI_STDOUT since 60 seconds */
++ strncpy(buf, con->request.http_if_modified_since, used_len);
++ buf[used_len] = '\0';
+
-+ /* kill the connection */
++ strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
++ t_header = mktime(&tm);
+
-+ log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
++ strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
++ t_file = mktime(&tm);
+
-+ fcgi_connection_close(srv, hctx);
++ if (t_file > t_header) return HANDLER_GO_ON;
+
-+ con->mode = DIRECT;
-+ con->http_status = 500;
++ con->http_status = 304;
++ return HANDLER_FINISHED;
++#else
++ return HANDLER_GO_ON;
++#endif
+ }
+ } else {
+ con->http_status = 304;
+@@ -302,16 +306,41 @@
+ } else if (con->request.http_if_modified_since) {
+ size_t used_len;
+ char *semicolon;
+-
+
-+ joblist_append(srv, con);
-+ }
+ if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
+ used_len = strlen(con->request.http_if_modified_since);
+ } else {
+ used_len = semicolon - con->request.http_if_modified_since;
+ }
+-
+
- /* check all childs if they are still up */
-
- for (i = 0; i < srv->config_context->used; i++) {
-@@ -3737,7 +3672,7 @@
- int status;
-
- if (proc->pid == 0) continue;
--
-+#ifndef _WIN32
- switch (waitpid(proc->pid, &status, WNOHANG)) {
- case 0:
- /* child still running after timeout, good */
-@@ -3781,6 +3716,7 @@
- proc->state = PROC_STATE_UNSET;
- host->max_id--;
- }
+ if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
+ con->http_status = 304;
+ return HANDLER_FINISHED;
++ } else {
++#ifdef HAVE_STRPTIME
++ char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
++ time_t t_header, t_file;
++ struct tm tm;
++
++ /* convert to timestamp */
++ if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
++
++ strncpy(buf, con->request.http_if_modified_since, used_len);
++ buf[used_len] = '\0';
++
++ strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
++ t_header = mktime(&tm);
++
++ strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
++ t_file = mktime(&tm);
++
++ if (t_file > t_header) return HANDLER_GO_ON;
++
++ con->http_status = 304;
++ return HANDLER_FINISHED;
++#else
++ return HANDLER_GO_ON;
+#endif
- }
- }
- }
---- lighttpd-1.4.11/src/mod_flv_streaming.c 2006-03-07 14:06:26.000000000 +0200
-+++ lighttpd/src/mod_flv_streaming.c 2006-07-11 21:23:40.043852471 +0300
-@@ -108,13 +108,11 @@
- return HANDLER_GO_ON;
- }
-
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(extensions);
-+ PATCH_OPTION(extensions);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -129,16 +127,15 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
-- PATCH(extensions);
-+ PATCH_OPTION(extensions);
- }
- }
- }
-
- return 0;
- }
--#undef PATCH
-
--static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
-+static int split_get_params(array *get_params, buffer *qrystr) {
- size_t is_key = 1;
- size_t i;
- char *key = NULL, *val = NULL;
-@@ -167,7 +164,7 @@
- /* terminate the value */
- qrystr->ptr[i] = '\0';
-
-- if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
-+ if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
- ds = data_string_init();
- }
- buffer_copy_string_len(ds->key, key, strlen(key));
-@@ -217,7 +214,7 @@
-
- array_reset(p->get_params);
- buffer_copy_string_buffer(p->query_str, con->uri.query);
-- split_get_params(srv, con, p->get_params, p->query_str);
-+ split_get_params(p->get_params, p->query_str);
-
- if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
- return HANDLER_GO_ON;
---- lighttpd-1.4.11/src/mod_indexfile.c 2005-09-30 01:08:53.000000000 +0300
-+++ lighttpd/src/mod_indexfile.c 2006-07-11 21:23:40.191861741 +0300
-@@ -103,13 +103,11 @@
- return HANDLER_GO_ON;
- }
-
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(indexfiles);
-+ PATCH_OPTION(indexfiles);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -124,16 +122,15 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
-- PATCH(indexfiles);
-+ PATCH_OPTION(indexfiles);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
-- PATCH(indexfiles);
-+ PATCH_OPTION(indexfiles);
- }
}
}
-
- return 0;
- }
--#undef PATCH
- URIHANDLER_FUNC(mod_indexfile_subrequest) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_mysql_vhost.c 2006-01-14 20:35:10.000000000 +0200
-+++ lighttpd/src/mod_mysql_vhost.c 2006-07-11 21:23:40.031851719 +0300
-@@ -1,13 +1,18 @@
--#include <unistd.h>
- #include <stdio.h>
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_auth.c lighttpd-1.4.12/src/http_auth.c
+--- lighttpd-1.4.11/src/http_auth.c 2006-02-01 13:02:52.000000000 +0200
++++ lighttpd-1.4.12/src/http_auth.c 2006-07-11 21:23:40.000000000 +0300
+@@ -22,7 +22,6 @@
+ #include <string.h>
+ #include <time.h>
#include <errno.h>
- #include <fcntl.h>
--#include <strings.h>
-+#include <string.h>
+-#include <unistd.h>
+ #include <ctype.h>
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
+ #include "server.h"
+@@ -31,23 +30,14 @@
+ #include "http_auth_digest.h"
+ #include "stream.h"
-+#ifdef HAVE_MYSQL_H
-+# ifdef HAVE_LIBMYSQL
-+# define HAVE_MYSQL
-+# endif
-+#endif
++#include "sys-strings.h"
+
- #ifdef HAVE_MYSQL
- #include <mysql.h>
+ #ifdef USE_OPENSSL
+ # include <openssl/md5.h>
+ #else
+ # include "md5.h"
#endif
-@@ -16,36 +21,21 @@
- #include "log.h"
- #include "stat_cache.h"
--#ifdef DEBUG_MOD_MYSQL_VHOST
--#define DEBUG
+-
+-#ifdef USE_PAM
+-#include <security/pam_appl.h>
+-#include <security/pam_misc.h>
+-
+-static struct pam_conv conv = {
+- misc_conv,
+- NULL
+-};
-#endif
-+#include "sys-files.h"
-
--/*
-- * Plugin for lighttpd to use MySQL
-- * for domain to directory lookups,
-- * i.e virtual hosts (vhosts).
-- *
-- * Optionally sets fcgi_offset and fcgi_arg
-- * in preparation for fcgi.c to handle
-- * per-user fcgi chroot jails.
-- *
-- * /ada@riksnet.se 2004-12-06
-- */
-+#include "mod_sql_vhost_core.h"
+-
+ handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
- #ifdef HAVE_MYSQL
--typedef struct {
-- MYSQL *mysql;
-
-- buffer *mydb;
-- buffer *myuser;
-- buffer *mypass;
-- buffer *mysock;
-+#define CORE_PLUGIN "mod_sql_vhost_core"
-
-- buffer *hostname;
-- unsigned short port;
-+typedef struct {
-+ MYSQL *mysql;
-
- buffer *mysql_pre;
- buffer *mysql_post;
+ static const char base64_pad = '=';
+@@ -75,25 +65,25 @@
+ unsigned char *result;
+ int ch, j = 0, k;
+ size_t i;
+-
+
-+ mod_sql_vhost_core_plugin_config *core;
- } plugin_config;
-
- /* global plugin data */
-@@ -59,13 +49,7 @@
- plugin_config conf;
- } plugin_data;
-
--/* per connection plugin data */
--typedef struct {
-- buffer *server_name;
-- buffer *document_root;
-- buffer *fcgi_arg;
-- unsigned fcgi_offset;
--} plugin_connection_data;
-+SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost);
-
- /* init the plugin data */
- INIT_FUNC(mod_mysql_vhost_init) {
-@@ -84,10 +68,6 @@
-
- UNUSED(srv);
-
--#ifdef DEBUG
-- log_error_write(srv, __FILE__, __LINE__, "ss",
-- "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
--#endif
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
-@@ -99,10 +79,6 @@
-
- mysql_close(s->mysql);
-
-- buffer_free(s->mydb);
-- buffer_free(s->myuser);
-- buffer_free(s->mypass);
-- buffer_free(s->mysock);
- buffer_free(s->mysql_pre);
- buffer_free(s->mysql_post);
-
-@@ -117,109 +93,50 @@
- return HANDLER_GO_ON;
+ size_t in_len = strlen(in);
+-
++
+ buffer_prepare_copy(out, in_len);
+-
++
+ result = (unsigned char *)out->ptr;
+-
++
+ ch = in[0];
+ /* run through the whole string, converting as we go */
+ for (i = 0; i < in_len; i++) {
+ ch = in[i];
+-
++
+ if (ch == '\0') break;
+-
++
+ if (ch == base64_pad) break;
+-
++
+ ch = base64_reverse_table[ch];
+ if (ch < 0) continue;
+-
++
+ switch(i % 4) {
+ case 0:
+ result[j] = ch << 2;
+@@ -125,168 +115,168 @@
+ }
+ }
+ result[k] = '\0';
+-
++
+ out->used = k;
+-
++
+ return result;
}
--/* handle the plugin per connection data */
--static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
--{
-- plugin_data *p = p_d;
-- plugin_connection_data *c = con->plugin_ctx[p->id];
--
-- UNUSED(srv);
--
--#ifdef DEBUG
-- log_error_write(srv, __FILE__, __LINE__, "ss",
-- "mod_mysql_connection_data", c ? "old" : "NEW");
--#endif
--
-- if (c) return c;
-- c = calloc(1, sizeof(*c));
--
-- c->server_name = buffer_init();
-- c->document_root = buffer_init();
-- c->fcgi_arg = buffer_init();
-- c->fcgi_offset = 0;
--
-- return con->plugin_ctx[p->id] = c;
--}
--
--/* destroy the plugin per connection data */
--CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
-- plugin_data *p = p_d;
-- plugin_connection_data *c = con->plugin_ctx[p->id];
--
-- UNUSED(srv);
--
--#ifdef DEBUG
-- log_error_write(srv, __FILE__, __LINE__, "ss",
-- "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
--#endif
+ static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
+ int ret = -1;
-
-- if (!c) return HANDLER_GO_ON;
--
-- buffer_free(c->server_name);
-- buffer_free(c->document_root);
-- buffer_free(c->fcgi_arg);
-- c->fcgi_offset = 0;
--
-- free(c);
--
-- con->plugin_ctx[p->id] = NULL;
-- return HANDLER_GO_ON;
--}
--
- /* set configuration values */
- SERVER_FUNC(mod_mysql_vhost_set_defaults) {
- plugin_data *p = p_d;
-+ mod_sql_vhost_core_plugin_data *core_config;
-
-- char *qmark;
- size_t i = 0;
-
-- config_values_t cv[] = {
-- { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
-- { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
-- { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
-- { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
-- { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
-- { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
-- { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER },
-- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
-- };
++
+ if (!username->used|| !realm->used) return -1;
-
-+ /* our very own plugin storage, one entry for each conditional
-+ *
-+ * srv->config_context->used is the number of conditionals
-+ * */
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
-+ /* get the config of the core-plugin */
-+ core_config = plugin_get_config(srv, CORE_PLUGIN);
+
+ if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
+ stream f;
+ char * f_line;
+-
+
-+ /* walk through all conditionals and check for assignments */
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
- buffer *sel;
-+ char *qmark;
-
+ if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
-
-+ /* get the config from the core plugin for this conditional-context */
- s = calloc(1, sizeof(plugin_config));
-- s->mydb = buffer_init();
-- s->myuser = buffer_init();
-- s->mypass = buffer_init();
-- s->mysock = buffer_init();
-- s->hostname = buffer_init();
-- s->port = 0; /* default port for mysql */
-- sel = buffer_init();
+
-+ s->core = core_config->config_storage[i];
-+
- s->mysql = NULL;
-
- s->mysql_pre = buffer_init();
- s->mysql_post = buffer_init();
-
-- cv[0].destination = s->mydb;
-- cv[1].destination = s->myuser;
-- cv[2].destination = s->mypass;
-- cv[3].destination = s->mysock;
-- cv[4].destination = sel;
-- cv[5].destination = s->hostname;
-- cv[6].destination = &(s->port);
+ if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno));
+-
++
+ return -1;
+ }
-
- p->config_storage[i] = s;
-
-- if (config_insert_values_global(srv,
-- ((data_config *)srv->config_context->data[i])->value,
-- cv)) return HANDLER_ERROR;
-+ /* check if we are the plugin for this backend */
-+ if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
-
-- s->mysql_pre = buffer_init();
-- s->mysql_post = buffer_init();
-+ /* attach us to the core-plugin */
-+ s->core->backend_data = p;
-+ s->core->get_vhost = mod_mysql_vhost_get_vhost;
+
-+ sel = buffer_init();
-+ buffer_copy_string_buffer(sel, s->core->select_vhost);
-
- if (sel->used && (qmark = index(sel->ptr, '?'))) {
- *qmark = '\0';
-@@ -241,8 +158,8 @@
- */
-
- /* all have to be set */
-- if (!(buffer_is_empty(s->myuser) ||
-- buffer_is_empty(s->mydb))) {
-+ if (!(buffer_is_empty(s->core->user) ||
-+ buffer_is_empty(s->core->db))) {
-
- int fd;
-
-@@ -251,10 +168,10 @@
-
- return HANDLER_ERROR;
+ f_line = f.start;
+-
++
+ while (f_line - f.start != f.size) {
+ char *f_user, *f_pwd, *e, *f_realm;
+ size_t u_len, pwd_len, r_len;
+-
++
+ f_user = f_line;
+-
+- /*
++
++ /*
+ * htdigest format
+- *
+- * user:realm:md5(user:realm:password)
++ *
++ * user:realm:md5(user:realm:password)
+ */
+-
++
+ if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "parsed error in", p->conf.auth_htdigest_userfile,
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
++ "parsed error in", p->conf.auth_htdigest_userfile,
+ "expected 'username:realm:hashed password'");
+-
++
+ stream_close(&f);
+-
++
+ return -1;
}
--#define FOO(x) (s->x->used ? s->x->ptr : NULL)
-+#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
-
-- if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass),
-- FOO(mydb), s->port, FOO(mysock), 0)) {
-+ if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
-+ FOO(db), s->core->port, FOO(sock), 0)) {
- log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
-
- return HANDLER_ERROR;
-@@ -275,17 +192,13 @@
- return HANDLER_GO_ON;
- }
-
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
-- size_t i, j;
-+ size_t i;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(mysql_pre);
-- PATCH(mysql_post);
--#ifdef HAVE_MYSQL
-- PATCH(mysql);
--#endif
-+ PATCH_OPTION(mysql_pre);
-+ PATCH_OPTION(mysql_post);
-+ PATCH_OPTION(mysql);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -295,31 +208,21 @@
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
-- /* merge config */
-- for (j = 0; j < dc->value->used; j++) {
-- data_unset *du = dc->value->data[j];
-
-- if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
-- PATCH(mysql_pre);
-- PATCH(mysql_post);
-- }
-- }
--
- if (s->mysql) {
-- PATCH(mysql);
-+ PATCH_OPTION(mysql);
-+ PATCH_OPTION(mysql_pre);
-+ PATCH_OPTION(mysql_post);
- }
- }
-
- return 0;
- }
--#undef PATCH
-
--
--/* handle document root request */
--CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
-+/**
-+ * get the vhost info from the database
-+ */
-+SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
- plugin_data *p = p_d;
-- plugin_connection_data *c;
-- stat_cache_entry *sce;
-
- unsigned cols;
- MYSQL_ROW row;
-@@ -332,13 +235,6 @@
-
- if (!p->conf.mysql) return HANDLER_GO_ON;
-
-- /* sets up connection data if not done yet */
-- c = mod_mysql_vhost_connection_data(srv, con, p_d);
--
-- /* check if cached this connection */
-- if (c->server_name->used && /* con->uri.authority->used && */
-- buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
--
- /* build and run SQL query */
- buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
- if (p->conf.mysql_post->used) {
-@@ -347,76 +243,42 @@
- }
- if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
- log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
-- goto ERR500;
+
-+ mysql_free_result(result);
-+ return HANDLER_GO_ON;
- }
- result = mysql_store_result(p->conf.mysql);
- cols = mysql_num_fields(result);
- row = mysql_fetch_row(result);
+ if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "parsed error in", p->conf.auth_plain_userfile,
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
++ "parsed error in", p->conf.auth_plain_userfile,
+ "expected 'username:realm:hashed password'");
+-
+
- if (!row || cols < 1) {
- /* no such virtual host */
- mysql_free_result(result);
- return HANDLER_GO_ON;
- }
-
-- /* sanity check that really is a directory */
-- buffer_copy_string(p->tmp_buf, row[0]);
-- BUFFER_APPEND_SLASH(p->tmp_buf);
--
-- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
-- log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
-- goto ERR500;
-- }
-- if (!S_ISDIR(sce->st.st_mode)) {
-- log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
-- goto ERR500;
-- }
--
-- /* cache the data */
-- buffer_copy_string_buffer(c->server_name, con->uri.authority);
-- buffer_copy_string_buffer(c->document_root, p->tmp_buf);
-+ buffer_copy_string(docroot, row[0]);
-
-- /* fcgi_offset and fcgi_arg are optional */
-- if (cols > 1 && row[1]) {
-- c->fcgi_offset = atoi(row[1]);
+ stream_close(&f);
+-
++
+ return -1;
+ }
+-
++
+ /* get pointers to the fields */
+- u_len = f_realm - f_user;
++ u_len = f_realm - f_user;
+ f_realm++;
+ r_len = f_pwd - f_realm;
+ f_pwd++;
+-
++
+ if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
+ pwd_len = e - f_pwd;
+ } else {
+ pwd_len = f.size - (f_pwd - f.start);
+ }
+-
++
+ if (username->used - 1 == u_len &&
+ (realm->used - 1 == r_len) &&
+ (0 == strncmp(username->ptr, f_user, u_len)) &&
+ (0 == strncmp(realm->ptr, f_realm, r_len))) {
+ /* found */
+-
++
+ buffer_copy_string_len(password, f_pwd, pwd_len);
+-
++
+ ret = 0;
+ break;
+ }
+-
++
+ /* EOL */
+ if (!e) break;
+-
++
+ f_line = e + 1;
+ }
-
-- if (cols > 2 && row[2]) {
-- buffer_copy_string(c->fcgi_arg, row[2]);
-- } else {
-- c->fcgi_arg->used = 0;
-- }
-- } else {
-- c->fcgi_offset = c->fcgi_arg->used = 0;
-- }
- mysql_free_result(result);
-
-- /* fix virtual server and docroot */
--GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
-- buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
--
--#ifdef DEBUG
-- log_error_write(srv, __FILE__, __LINE__, "sbbdb",
-- result ? "NOT CACHED" : "cached",
-- con->server_name, con->physical.doc_root,
-- c->fcgi_offset, c->fcgi_arg);
--#endif
- return HANDLER_GO_ON;
--
--ERR500: if (result) mysql_free_result(result);
-- con->http_status = 500; /* Internal Error */
-- return HANDLER_FINISHED;
- }
-
- /* this function is called at dlopen() time and inits the callbacks */
- int mod_mysql_vhost_plugin_init(plugin *p) {
-+ data_string *ds;
-+
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("mysql_vhost");
-
- p->init = mod_mysql_vhost_init;
- p->cleanup = mod_mysql_vhost_cleanup;
-- p->handle_request_done = mod_mysql_vhost_handle_connection_close;
-
- p->set_defaults = mod_mysql_vhost_set_defaults;
-- p->handle_docroot = mod_mysql_vhost_handle_docroot;
-+
-+ ds = data_string_init();
-+ buffer_copy_string(ds->value, CORE_PLUGIN);
-+ array_insert_unique(p->required_plugins, (data_unset *)ds);
-
- return 0;
- }
---- lighttpd-1.4.11/src/mod_proxy.c 2006-01-31 13:01:22.000000000 +0200
-+++ lighttpd/src/mod_proxy.c 2006-07-11 21:23:40.099855979 +0300
-@@ -1,6 +1,5 @@
- #include <sys/types.h>
-
--#include <unistd.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <string.h>
-@@ -23,6 +22,9 @@
-
- #include "inet_ntop_cache.h"
- #include "crc32.h"
-+#include "network.h"
+
-+#include "http_resp.h"
-
- #include <stdio.h>
-
-@@ -31,6 +33,8 @@
- #endif
-
- #include "sys-socket.h"
-+#include "sys-files.h"
-+#include "sys-strings.h"
-
- #define data_proxy data_fastcgi
- #define data_proxy_init data_fastcgi_init
-@@ -66,6 +70,8 @@
- int debug;
-
- proxy_balance_t balance;
+ stream_close(&f);
+ } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
+ p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
+ stream f;
+ char * f_line;
+ buffer *auth_fn;
+-
+
-+ array *last_used_backends; /* "extension" : last_used_backend */
- } plugin_config;
-
- typedef struct {
-@@ -74,6 +80,8 @@
- buffer *parse_response;
- buffer *balance_buf;
-
-+ array *ignore_headers;
+ auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
+-
+
- plugin_config **config_storage;
-
- plugin_config conf;
-@@ -84,7 +92,8 @@
- PROXY_STATE_CONNECT,
- PROXY_STATE_PREPARE_WRITE,
- PROXY_STATE_WRITE,
-- PROXY_STATE_READ,
-+ PROXY_STATE_RESPONSE_HEADER,
-+ PROXY_STATE_RESPONSE_CONTENT,
- PROXY_STATE_ERROR
- } proxy_connection_state_t;
-
-@@ -100,6 +109,7 @@
- buffer *response_header;
-
- chunkqueue *wb;
-+ chunkqueue *rb;
-
- int fd; /* fd to the proxy process */
- int fde_ndx; /* index into the fd-event buffer */
-@@ -127,6 +137,7 @@
- hctx->response_header = buffer_init();
-
- hctx->wb = chunkqueue_init();
-+ hctx->rb = chunkqueue_init();
-
- hctx->fd = -1;
- hctx->fde_ndx = -1;
-@@ -138,17 +149,38 @@
- buffer_free(hctx->response);
- buffer_free(hctx->response_header);
- chunkqueue_free(hctx->wb);
-+ chunkqueue_free(hctx->rb);
-
- free(hctx);
- }
-
- INIT_FUNC(mod_proxy_init) {
- plugin_data *p;
-+ size_t i;
+ if (buffer_is_empty(auth_fn)) return -1;
+-
+
-+ char *hop2hop_headers[] = {
-+ "Connection",
-+ "Keep-Alive",
-+ "Host",
-+ NULL
-+ };
-
- p = calloc(1, sizeof(*p));
-
- p->parse_response = buffer_init();
- p->balance_buf = buffer_init();
-+ p->ignore_headers = array_init();
+ if (0 != stream_open(&f, auth_fn)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening plain-userfile", auth_fn, "failed:", strerror(errno));
+-
+
-+ for (i = 0; hop2hop_headers[i]; i++) {
-+ data_string *ds;
+ return -1;
+ }
+-
+
-+ if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
-+ ds = data_string_init();
-+ }
+ f_line = f.start;
+-
+
-+ buffer_copy_string(ds->value, hop2hop_headers[i]);
-+ array_insert_unique(p->ignore_headers, (data_unset *)ds);
-+ }
-
- return p;
- }
-@@ -168,8 +200,8 @@
- plugin_config *s = p->config_storage[i];
-
- if (s) {
+ while (f_line - f.start != f.size) {
+ char *f_user, *f_pwd, *e;
+ size_t u_len, pwd_len;
-
- array_free(s->extensions);
-+ array_free(s->last_used_backends);
-
- free(s);
++
+ f_user = f_line;
+-
+- /*
++
++ /*
+ * htpasswd format
+- *
++ *
+ * user:crypted passwd
+ */
+-
++
+ if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "parsed error in", auth_fn,
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
++ "parsed error in", auth_fn,
+ "expected 'username:hashed password'");
+-
++
+ stream_close(&f);
+-
++
+ return -1;
}
-@@ -177,6 +209,8 @@
- free(p->config_storage);
- }
-
-+ free(p->ignore_headers);
+-
+
- free(p);
-
- return HANDLER_GO_ON;
-@@ -202,6 +236,7 @@
-
- s = malloc(sizeof(plugin_config));
- s->extensions = array_init();
-+ s->last_used_backends = array_init();
- s->debug = 0;
-
- cv[0].destination = s->extensions;
-@@ -372,14 +407,22 @@
- proxy_addr = (struct sockaddr *) &proxy_addr_in;
-
- if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
-- if (errno == EINPROGRESS || errno == EALREADY) {
-+#ifdef _WIN32
-+ errno = WSAGetLastError();
-+#endif
-+ switch(errno) {
-+#ifdef _WIN32
-+ case WSAEWOULDBLOCK:
-+#endif
-+ case EINPROGRESS:
-+ case EALREADY:
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "connect delayed:", proxy_fd);
+ /* get pointers to the fields */
+- u_len = f_pwd - f_user;
++ u_len = f_pwd - f_user;
+ f_pwd++;
+-
++
+ if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
+ pwd_len = e - f_pwd;
+ } else {
+ pwd_len = f.size - (f_pwd - f.start);
}
-
- return 1;
-- } else {
-+ default:
-
- log_error_write(srv, __FILE__, __LINE__, "sdsd",
- "connect failed:", proxy_fd, strerror(errno), errno);
-@@ -387,6 +430,7 @@
- return -1;
+-
++
+ if (username->used - 1 == u_len &&
+ (0 == strncmp(username->ptr, f_user, u_len))) {
+ /* found */
+-
++
+ buffer_copy_string_len(password, f_pwd, pwd_len);
+-
++
+ ret = 0;
+ break;
+ }
+-
++
+ /* EOL */
+ if (!e) break;
+-
++
+ f_line = e + 1;
}
+-
++
+ stream_close(&f);
+ } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
+ ret = 0;
+ } else {
+ return -1;
}
-+ fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "connect succeeded: ", proxy_fd);
-@@ -424,6 +468,7 @@
- size_t i;
-
- connection *con = hctx->remote_conn;
-+ plugin_data *p = hctx->plugin_data;
- buffer *b;
-
- /* build header */
-@@ -453,7 +498,9 @@
- ds = (data_string *)con->request.headers->data[i];
-
- if (ds->value->used && ds->key->used) {
-- if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
+-
+
-+ /* don't copy hop-to-hop headers */
-+ if (array_get_element(p->ignore_headers, ds->key->ptr)) continue;
-
- buffer_append_string_buffer(b, ds->key);
- BUFFER_APPEND_STRING_CONST(b, ": ");
-@@ -531,199 +578,101 @@
+ return ret;
}
+@@ -296,7 +286,7 @@
+ int username_len;
+ data_string *require;
+ array *req;
+-
++
+ UNUSED(group);
+ UNUSED(host);
--static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
-- char *s, *ns;
-- int http_response_status = -1;
+@@ -304,12 +294,12 @@
+ /* search auth-directives for path */
+ for (i = 0; i < p->conf.auth_require->used; i++) {
+ if (p->conf.auth_require->data[i]->key->used == 0) continue;
+-
++
+ if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
+ break;
+ }
+ }
-
-- UNUSED(srv);
--
-- /* \r\n -> \0\0 */
++
+ if (i == p->conf.auth_require->used) {
+ return -1;
+ }
+@@ -317,72 +307,72 @@
+ req = ((data_array *)(p->conf.auth_require->data[i]))->value;
+
+ require = (data_string *)array_get_element(req, "require");
-
-- buffer_copy_string_buffer(p->parse_response, in);
++
+ /* if we get here, the user we got a authed user */
+ if (0 == strcmp(require->value->ptr, "valid-user")) {
+ return 0;
+ }
-
-- for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
-- char *key, *value;
-- int key_len;
-- data_string *ds;
-- int copy_header;
++
+ /* user=name1|group=name3|host=name4 */
+-
++
+ /* seperate the string by | */
+ #if 0
+ log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
+-#endif
+-
++#endif
++
+ username_len = username ? strlen(username) : 0;
+-
++
+ r = rules = require->value->ptr;
+-
++
+ while (1) {
+ const char *eq;
+ const char *k, *v, *e;
+ int k_len, v_len, r_len;
-
-- ns[0] = '\0';
-- ns[1] = '\0';
--
-- if (-1 == http_response_status) {
-- /* The first line of a Response message is the Status-Line */
--
-- for (key=s; *key && *key != ' '; key++);
-+static void chunkqueue_print(chunkqueue *cq) {
-+ chunk *c;
-
-- if (*key) {
-- http_response_status = (int) strtol(key, NULL, 10);
-- if (http_response_status <= 0) http_response_status = 502;
-- } else {
-- http_response_status = 502;
-+ for (c = cq->first; c; c = c->next) {
-+ fprintf(stderr, "%s", c->mem->ptr + c->offset);
- }
--
-- con->http_status = http_response_status;
-- con->parsed_response |= HTTP_STATUS;
-- continue;
-+ fprintf(stderr, "\r\n");
++
+ e = strchr(r, '|');
+-
++
+ if (e) {
+ r_len = e - r;
+ } else {
+ r_len = strlen(rules) - (r - rules);
}
-
-- if (NULL == (value = strchr(s, ':'))) {
-- /* now we expect: "<key>: <value>\n" */
--
-- continue;
-- }
--
-- key = s;
-- key_len = value - key;
-
-- value++;
-- /* strip WS */
-- while (*value == ' ' || *value == '\t') value++;
++
+ /* from r to r + r_len is a rule */
-
-- copy_header = 1;
-+static int proxy_demux_response(server *srv, handler_ctx *hctx) {
-+ plugin_data *p = hctx->plugin_data;
-+ connection *con = hctx->remote_conn;
-+ int proxy_fd = hctx->fd;
-+ chunkqueue *next_queue = NULL;
-+ chunk *c = NULL;
-
-- switch(key_len) {
-- case 4:
-- if (0 == strncasecmp(key, "Date", key_len)) {
-- con->parsed_response |= HTTP_DATE;
-- }
-- break;
-- case 8:
-- if (0 == strncasecmp(key, "Location", key_len)) {
-- con->parsed_response |= HTTP_LOCATION;
-- }
-- break;
-- case 10:
-- if (0 == strncasecmp(key, "Connection", key_len)) {
-- copy_header = 0;
-- }
-+ switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
-+ case NETWORK_STATUS_SUCCESS:
-+ /* we got content */
- break;
-- case 14:
-- if (0 == strncasecmp(key, "Content-Length", key_len)) {
-- con->response.content_length = strtol(value, NULL, 10);
-- con->parsed_response |= HTTP_CONTENT_LENGTH;
-- }
-- break;
-- default:
-- break;
-- }
-+ case NETWORK_STATUS_CONNECTION_CLOSE:
-+ /* we are done, get out of here */
-+ con->file_finished = 1;
-
-- if (copy_header) {
-- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
-- ds = data_response_init();
-- }
-- buffer_copy_string_len(ds->key, key, key_len);
-- buffer_copy_string(ds->value, value);
-+ /* close the chunk-queue with a empty chunk */
-+ http_chunk_append_mem(srv, con, NULL, 0);
-+ joblist_append(srv, con);
-
-- array_insert_unique(con->response.headers, (data_unset *)ds);
-- }
-+ return 1;
-+ default:
-+ /* oops */
-+ return -1;
++
+ if (0 == strncmp(r, "valid-user", r_len)) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules",
+ require->value);
+ return -1;
+ }
+-
++
+ /* search for = in the rules */
+ if (NULL == (eq = strchr(r, '='))) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "parsing the 'require' section in 'auth.require' failed: a = is missing",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "parsing the 'require' section in 'auth.require' failed: a = is missing",
+ require->value);
+ return -1;
+ }
+-
++
+ /* = out of range */
+ if (eq > r + r_len) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "parsing the 'require' section in 'auth.require' failed: = out of range",
+ require->value);
+-
++
+ return -1;
+ }
+-
++
+ /* the part before the = is user|group|host */
+-
++
+ k = r;
+ k_len = eq - r;
+ v = eq + 1;
+ v_len = r_len - k_len - 1;
+-
++
+ if (k_len == 4) {
+ if (0 == strncmp(k, "user", k_len)) {
+- if (username &&
++ if (username &&
+ username_len == v_len &&
+ 0 == strncmp(username, v, v_len)) {
+ return 0;
+@@ -404,19 +394,19 @@
+ log_error_write(srv, __FILE__, __LINE__, "s", "unknown key");
+ return -1;
+ }
+-
++
+ if (!e) break;
+ r = e + 1;
}
-
-- return 0;
--}
-+ /* looks like we got some content
-+ *
-+ * split off the header from the incoming stream
-+ */
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
+-
++
+ return -1;
+ }
-+ if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
-+ http_resp *resp = http_response_init();
+ /**
+- *
+- *
++ *
++ *
+ * @param password password-string from the auth-backend
+ * @param pw password-string from the client
+ */
+@@ -426,16 +416,16 @@
+ UNUSED(req);
--static int proxy_demux_response(server *srv, handler_ctx *hctx) {
-- int fin = 0;
-- int b;
-- ssize_t r;
-+ /* the response header is not fully received yet,
-+ *
-+ * extract the http-response header from the rb-cq
-+ */
-+ fprintf(stderr, "%s.%d: network-read\r\n", __FILE__, __LINE__);
-+ chunkqueue_print(hctx->rb);
-
-- plugin_data *p = hctx->plugin_data;
-- connection *con = hctx->remote_conn;
-- int proxy_fd = hctx->fd;
-+ switch (http_response_parse_cq(hctx->rb, resp)) {
-+ case PARSE_ERROR:
-+ /* parsing failed */
-
-- /* check how much we have to read */
-- if (ioctl(hctx->fd, FIONREAD, &b)) {
-- log_error_write(srv, __FILE__, __LINE__, "sd",
-- "ioctl failed: ",
-- proxy_fd);
-- return -1;
-- }
-+ con->http_status = 502; /* Bad Gateway */
-+ return 1;
-+ case PARSE_NEED_MORE:
-+ return 0;
-+ case PARSE_SUCCESS:
-+ con->http_status = resp->status;
+ if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
+- /*
++ /*
+ * htdigest format
+- *
+- * user:realm:md5(user:realm:password)
++ *
++ * user:realm:md5(user:realm:password)
+ */
+-
++
+ MD5_CTX Md5Ctx;
+ HASH HA1;
+ char a1[256];
+-
++
+ MD5_Init(&Md5Ctx);
+ MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1);
+ MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
+@@ -443,24 +433,24 @@
+ MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
+ MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
+ MD5_Final(HA1, &Md5Ctx);
+-
++
+ CvtHex(HA1, a1);
+-
++
+ if (0 == strcmp(password->ptr, a1)) {
+ return 0;
+ }
+- } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
+-#ifdef HAVE_CRYPT
++ } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
++#ifdef HAVE_CRYPT
+ char salt[32];
+ char *crypted;
+ size_t salt_len = 0;
+- /*
++ /*
+ * htpasswd format
+- *
++ *
+ * user:crypted password
+ */
-+ fprintf(stderr, "%s.%d: parsing done\r\n", __FILE__, __LINE__);
-+ chunkqueue_print(hctx->rb);
+- /*
++ /*
+ * Algorithm Salt
+ * CRYPT_STD_DES 2-character (Default)
+ * CRYPT_EXT_DES 9-character
+@@ -478,7 +468,7 @@
+ salt_len = 2;
+ } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
+ char *dollar = NULL;
+-
++
+ if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
+ fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
+ return -1;
+@@ -495,7 +485,7 @@
+ strncpy(salt, password->ptr, salt_len);
-- if (p->conf.debug) {
-- log_error_write(srv, __FILE__, __LINE__, "sd",
-- "proxy - have to read:", b);
-- }
-+ con->file_started = 1;
+ salt[salt_len] = '\0';
+-
++
+ crypted = crypt(pw, salt);
-- if (b > 0) {
-- if (hctx->response->used == 0) {
-- /* avoid too small buffer */
-- buffer_prepare_append(hctx->response, b + 1);
-- hctx->response->used = 1;
-- } else {
-- buffer_prepare_append(hctx->response, hctx->response->used + b);
-+ hctx->state = PROXY_STATE_RESPONSE_CONTENT;
-+ break;
+ if (0 == strcmp(password->ptr, crypted)) {
+@@ -503,40 +493,13 @@
+ } else {
+ fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
}
--
-- if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
-- log_error_write(srv, __FILE__, __LINE__, "sds",
-- "unexpected end-of-file (perhaps the proxy process died):",
-- proxy_fd, strerror(errno));
-- return -1;
+-
+-#endif
+- } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
++
++#endif
++ } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
+ if (0 == strcmp(password->ptr, pw)) {
+ return 0;
}
-
-- /* this should be catched by the b > 0 above */
-- assert(r);
-+ /* FIXME: pass the response-header to the other plugins to
-+ * setup the filter-queue
-+ *
-+ * - use next-queue instead of con->write_queue
-+ */
-
-- hctx->response->used += r;
-- hctx->response->ptr[hctx->response->used - 1] = '\0';
-+ next_queue = con->write_queue;
-
--#if 0
-- log_error_write(srv, __FILE__, __LINE__, "sdsbs",
-- "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
--#endif
-+ assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
-
-- if (0 == con->got_response) {
-- con->got_response = 1;
-- buffer_prepare_copy(hctx->response_header, 128);
+- } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) {
+-#ifdef USE_PAM
+- pam_handle_t *pamh=NULL;
+- int retval;
+-
+- retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
+-
+- if (retval == PAM_SUCCESS)
+- retval = pam_authenticate(pamh, 0); /* is user really user? */
+-
+- if (retval == PAM_SUCCESS)
+- retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
+-
+- /* This is where we have been authorized or not. */
+-
+- if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
+- pamh = NULL;
+- log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
- }
--
-- if (0 == con->file_started) {
-- char *c;
--
-- /* search for the \r\n\r\n in the string */
-- if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
-- size_t hlen = c - hctx->response->ptr + 4;
-- size_t blen = hctx->response->used - hlen - 1;
-- /* found */
--
-- buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
--#if 0
-- log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
--#endif
-- /* parse the response header */
-- proxy_response_parse(srv, con, p, hctx->response_header);
-+ /* FIXME: if we have a content-length or chunked-encoding
-+ * handle it.
-+ *
-+ * for now we wait for EOF on the socket */
-
-- /* enable chunked-transfer-encoding */
-- if (con->request.http_version == HTTP_VERSION_1_1 &&
-- !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
-- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
-- }
-+ /* copy the content to the next cq */
-+ for (c = hctx->rb->first; c; c = c->next) {
-+ http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
-
-- con->file_started = 1;
-- if (blen) {
-- http_chunk_append_mem(srv, con, c + 4, blen + 1);
-- joblist_append(srv, con);
-+ c->offset = c->mem->used - 1;
- }
-- hctx->response->used = 0;
-- }
+-
+- if (retval == PAM_SUCCESS) {
+- log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
+- return 0;
- } else {
-- http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
-- joblist_append(srv, con);
-- hctx->response->used = 0;
+- log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
- }
+-#endif
+- } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
++ } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
+ #ifdef USE_LDAP
+ LDAP *ldap;
+ LDAPMessage *lm, *first;
+@@ -544,45 +507,45 @@
+ int ret;
+ char *attrs[] = { LDAP_NO_ATTRS, NULL };
+ size_t i;
-
-- } else {
-- /* reading from upstream done */
-- con->file_finished = 1;
++
+ /* for now we stay synchronous */
-
-- http_chunk_append_mem(srv, con, NULL, 0);
-- joblist_append(srv, con);
-
-- fin = 1;
-- }
-+ chunkqueue_remove_finished_chunks(hctx->rb);
-
-- return fin;
-+ return 0;
- }
-
-
-@@ -803,6 +752,7 @@
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
- }
-+ fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, hctx->fd);
- }
-
- proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
-@@ -818,21 +768,20 @@
-
- chunkqueue_remove_finished_chunks(hctx->wb);
-
-- if (-1 == ret) {
-- if (errno != EAGAIN &&
-- errno != EINTR) {
-+ switch(ret) {
-+ case NETWORK_STATUS_FATAL_ERROR:
- log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
-
- return HANDLER_ERROR;
-- } else {
-+ case NETWORK_STATUS_WAIT_FOR_EVENT:
+- /*
+
- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
-
- return HANDLER_WAIT_FOR_EVENT;
++ /*
+ * 1. connect anonymously (done in plugin init)
+ * 2. get DN for uid = username
+ * 3. auth against ldap server
+ * 4. (optional) check a field
+ * 5. disconnect
+- *
++ *
+ */
+-
++
+ /* check username
+- *
++ *
+ * we have to protect us againt username which modifies out filter in
+ * a unpleasant way
+ */
+-
++
+ for (i = 0; i < username->used - 1; i++) {
+ char c = username->ptr[i];
+-
++
+ if (!isalpha(c) &&
+ !isdigit(c)) {
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbd",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbd",
+ "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
+-
++
+ return -1;
}
-- }
-
- if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
-- proxy_set_state(srv, hctx, PROXY_STATE_READ);
-+ proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
-
- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
-@@ -843,8 +792,9 @@
}
-
- return HANDLER_WAIT_FOR_EVENT;
-- case PROXY_STATE_READ:
-+ case PROXY_STATE_RESPONSE_HEADER:
- /* waiting for a response */
+-
+-
+-
+
- return HANDLER_WAIT_FOR_EVENT;
- default:
- log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
-@@ -854,15 +804,14 @@
- return HANDLER_GO_ON;
- }
++
++
+ /* build filter */
+ buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
+ buffer_append_string_buffer(p->ldap_filter, username);
+ buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post);
+-
+-
++
++
+ /* 2. */
+ if (p->conf.ldap == NULL ||
+ 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))) {
+@@ -590,71 +553,71 @@
+ return -1;
+ 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))) {
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(extensions);
-- PATCH(debug);
-- PATCH(balance);
-+ PATCH_OPTION(extensions);
-+ PATCH_OPTION(debug);
-+ PATCH_OPTION(balance);
-+ PATCH_OPTION(last_used_backends);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -877,18 +826,18 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
-- PATCH(extensions);
-+ PATCH_OPTION(extensions);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
-- PATCH(debug);
-+ PATCH_OPTION(debug);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
-- PATCH(balance);
-+ PATCH_OPTION(balance);
-+ PATCH_OPTION(last_used_backends);
+- log_error_write(srv, __FILE__, __LINE__, "sssb",
++ log_error_write(srv, __FILE__, __LINE__, "sssb",
+ "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
+-
++
+ return -1;
}
}
- }
-
- return 0;
- }
--#undef PATCH
-
- SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
- plugin_data *p = p_d;
-@@ -954,7 +903,8 @@
-
-
- if ((revents & FDEVENT_IN) &&
-- hctx->state == PROXY_STATE_READ) {
-+ (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
-+ hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
-
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
-@@ -1058,6 +1008,11 @@
- buffer *fn;
- data_array *extension = NULL;
- size_t path_info_offset;
-+ data_integer *last_used_backend;
-+ data_proxy *host = NULL;
-+ handler_ctx *hctx = NULL;
+-
+
-+ array *backends = NULL;
-
- /* Possibly, we processed already this request */
- if (con->file_started == 1) return HANDLER_GO_ON;
-@@ -1111,6 +1066,8 @@
- return HANDLER_GO_ON;
- }
-
-+ backends = extension->value;
+ if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
+-
+
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found");
- }
-@@ -1121,33 +1078,33 @@
-
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
-- "proxy - used hash balancing, hosts:", extension->value->used);
-+ "proxy - used hash balancing, hosts:", backends->used);
+ ldap_msgfree(lm);
+-
++
+ return -1;
}
-
-- for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
-- data_proxy *host = (data_proxy *)extension->value->data[k];
-+ for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
- unsigned long cur_max;
-
-- if (host->is_disabled) continue;
-+ data_proxy *cur = (data_proxy *)backends->data[k];
+-
+
-+ if (cur->is_disabled) continue;
-
- cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
-- generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
-+ generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
- generate_crc32c(CONST_BUF_LEN(con->uri.authority));
-
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sbbbd",
- "proxy - election:",
- con->uri.path,
-- host->host,
-+ cur->host,
- con->uri.authority,
- cur_max);
- }
-
-- if ((last_max == ULONG_MAX) || /* first round */
-- (cur_max > last_max)) {
-+ if (host == NULL || (cur_max > last_max)) {
- last_max = cur_max;
-
-- ndx = k;
-+ host = cur;
- }
+ if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
+-
++
+ ldap_msgfree(lm);
+-
++
+ return -1;
}
-
-@@ -1159,15 +1116,16 @@
- "proxy - used fair balancing");
+-
++
+ ldap_msgfree(lm);
+-
+-
++
++
+ /* 3. */
+ if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
+ return -1;
}
-
-- for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
-- data_proxy *host = (data_proxy *)extension->value->data[k];
-+ /* try to find the host with the lowest load */
-+ for (k = 0, max_usage = 0; k < backends->used; k++) {
-+ data_proxy *cur = (data_proxy *)backends->data[k];
-
-- if (host->is_disabled) continue;
-+ if (cur->is_disabled) continue;
-
-- if (host->usage < max_usage) {
-- max_usage = host->usage;
-+ if (NULL == host || cur->usage < max_usage) {
-+ max_usage = cur->usage;
-
-- ndx = k;
-+ host = cur;
- }
+-
++
+ ret = LDAP_VERSION3;
+ if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
+-
++
+ ldap_unbind_s(ldap);
+-
++
+ return -1;
}
+-
++
+ if (p->conf.auth_ldap_starttls == 1) {
+ if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL, NULL))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
+-
++
+ ldap_unbind_s(ldap);
+-
++
+ return -1;
+ }
+ }
-@@ -1180,30 +1138,50 @@
+-
++
+ if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
+-
++
+ ldap_unbind_s(ldap);
+-
++
+ return -1;
}
-
- /* just to be sure */
-- assert(extension->value->used < INT_MAX);
-+ assert(backends->used < INT_MAX);
+-
+
-+ /* send each request to another host:
-+ *
-+ * e.g.:
-+ *
-+ * if we have three hosts it is
-+ *
-+ * 1 .. 2 .. 3 .. 1 .. 2 .. 3
-+ *
-+ **/
+ /* 5. */
+ ldap_unbind_s(ldap);
+-
+
-+ /* walk through the list */
-+ last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
-
-- for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
-- data_proxy *host = (data_proxy *)extension->value->data[k];
-+ if (NULL == last_used_backend) {
-+ last_used_backend = data_integer_init();
-
-- if (host->is_disabled) continue;
-+ buffer_copy_string_buffer(last_used_backend->key, extension->key);
-+ last_used_backend->value = 0;
-
-- /* first usable ndx */
-- if (max_usage == INT_MAX) {
-- max_usage = k;
-+ array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
- }
-
-- /* get next ndx */
-- if ((int)k > host->last_used_ndx) {
-- ndx = k;
-- host->last_used_ndx = k;
-+ /* scan all but the last host to see if they are up
-+ * take the first running host */
-+ for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
-+ data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
+ /* everything worked, good, access granted */
+-
+
-+ if (cur->is_disabled) continue;
+ return 0;
+ #endif
+ }
+@@ -664,65 +627,65 @@
+ int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
+ buffer *username, *password;
+ char *pw;
+-
+
-+ host = cur;
+ data_string *realm;
+-
+
-+ last_used_backend->value = k;
-
- break;
- }
-- }
-
-- /* didn't found a higher id, wrap to the start */
-- if (ndx != -1 && max_usage != INT_MAX) {
-- ndx = max_usage;
-+ if (NULL == host) {
-+ /* we found nothing better, fallback to the last used backend
-+ * and check if it is still up */
-+ host = (data_proxy *)backends->data[last_used_backend->value];
+ realm = (data_string *)array_get_element(req, "realm");
+-
+
-+ if (host->is_disabled) host = NULL;
- }
-
- break;
-@@ -1211,17 +1189,18 @@
- break;
+ username = buffer_init();
+ password = buffer_init();
+-
++
+ base64_decode(username, realm_str);
+-
++
+ /* r2 == user:password */
+ if (NULL == (pw = strchr(username->ptr, ':'))) {
+ buffer_free(username);
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
+-
++
+ return 0;
}
-
-- /* found a server */
-- if (ndx != -1) {
-- data_proxy *host = (data_proxy *)extension->value->data[ndx];
-+ /* we havn't found a host */
-+ if (NULL == host) {
-+ con->http_status = 500;
-
-- /*
-- * if check-local is disabled, use the uri.path handler
-- *
-- */
-+ log_error_write(srv, __FILE__, __LINE__, "sb",
-+ "no proxy-handler found for:",
-+ fn);
+-
+
-+ return HANDLER_FINISHED;
-+ }
-
- /* init handler-context */
-- handler_ctx *hctx;
- hctx = handler_ctx_init();
-
- hctx->path_info_offset = path_info_offset;
-@@ -1233,6 +1212,7 @@
-
- host->usage++;
-
-+ /* we handle this request */
- con->mode = p->id;
-
- if (p->conf.debug) {
-@@ -1242,17 +1222,6 @@
- }
-
- return HANDLER_GO_ON;
-- } else {
-- /* no handler found */
-- con->http_status = 500;
+ *pw++ = '\0';
+-
++
+ username->used = pw - username->ptr;
+-
++
+ /* copy password to r1 */
+ if (http_auth_get_password(srv, p, username, realm->value, password)) {
+ buffer_free(username);
+ buffer_free(password);
-
-- log_error_write(srv, __FILE__, __LINE__, "sb",
-- "no proxy-handler found for:",
-- fn);
++
+ log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed");
-
-- return HANDLER_FINISHED;
-- }
-- return HANDLER_GO_ON;
++
+ return 0;
+ }
+-
++
+ /* password doesn't match */
+ if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
+-
++
+ buffer_free(username);
+ buffer_free(password);
+-
++
+ return 0;
+ }
+-
++
+ /* value is our allow-rules */
+ if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
+ buffer_free(username);
+ buffer_free(password);
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
+-
++
+ return 0;
+ }
+-
++
+ /* remember the username */
+ buffer_copy_string_buffer(p->auth_user, username);
+-
++
+ buffer_free(username);
+ buffer_free(password);
+-
++
+ return 1;
}
- static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
---- lighttpd-1.4.11/src/mod_redirect.c 2006-02-08 15:38:06.000000000 +0200
-+++ lighttpd/src/mod_redirect.c 2006-07-11 21:23:40.111856730 +0300
-@@ -166,7 +166,7 @@
- static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
- #ifdef HAVE_PCRE_H
- plugin_data *p = p_data;
-- size_t i;
-+ int i;
+@@ -735,7 +698,7 @@
+ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
+ char a1[256];
+ char a2[256];
+-
++
+ char *username;
+ char *realm;
+ char *nonce;
+@@ -745,18 +708,18 @@
+ char *cnonce;
+ char *nc;
+ char *respons;
+-
++
+ char *e, *c;
+ const char *m = NULL;
+ int i;
+ buffer *password, *b, *username_buf, *realm_buf;
+-
++
+ MD5_CTX Md5Ctx;
+ HASH HA1;
+ HASH HA2;
+ HASH RespHash;
+ HASHHEX HA2Hex;
+-
++
- /*
- * REWRITE URL
-@@ -178,70 +178,9 @@
- mod_redirect_patch_connection(srv, con, p);
-
- buffer_copy_string_buffer(p->match_buf, con->request.uri);
-+ i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
-
-- for (i = 0; i < p->conf.redirect->used; i++) {
-- pcre *match;
-- pcre_extra *extra;
-- const char *pattern;
-- size_t pattern_len;
-- int n;
-- pcre_keyvalue *kv = p->conf.redirect->kv[i];
--# define N 10
-- int ovec[N * 3];
--
-- match = kv->key;
-- extra = kv->key_extra;
-- pattern = kv->value->ptr;
-- pattern_len = kv->value->used - 1;
+ /* init pointers */
+ #define S(x) \
+@@ -771,11 +734,11 @@
+ { S("cnonce=") },
+ { S("nc=") },
+ { S("response=") },
-
-- if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
-- if (n != PCRE_ERROR_NOMATCH) {
-- log_error_write(srv, __FILE__, __LINE__, "sd",
-- "execution error while matching: ", n);
-- return HANDLER_ERROR;
-- }
-- } else {
-- const char **list;
-- size_t start, end;
-- size_t k;
--
-- /* it matched */
-- pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
--
-- /* search for $[0-9] */
--
-- buffer_reset(p->location);
--
-- start = 0; end = pattern_len;
-- for (k = 0; k < pattern_len; k++) {
-- if ((pattern[k] == '$' || pattern[k] == '%') &&
-- isdigit((unsigned char)pattern[k + 1])) {
-- /* got one */
--
-- size_t num = pattern[k + 1] - '0';
--
-- end = k;
--
-- buffer_append_string_len(p->location, pattern + start, end - start);
--
-- if (pattern[k] == '$') {
-- /* n is always > 0 */
-- if (num < (size_t)n) {
-- buffer_append_string(p->location, list[num]);
-- }
-- } else {
-- config_append_cond_match_buffer(con, p->conf.context, p->location, num);
-- }
++
+ { NULL, 0, NULL }
+ };
+ #undef S
+-
++
+ dkv[0].ptr = &username;
+ dkv[1].ptr = &realm;
+ dkv[2].ptr = &nonce;
+@@ -786,24 +749,24 @@
+ dkv[7].ptr = &nc;
+ dkv[8].ptr = &respons;
+ dkv[9].ptr = NULL;
+-
++
+ UNUSED(req);
+-
++
+ for (i = 0; dkv[i].key; i++) {
+ *(dkv[i].ptr) = NULL;
+ }
+-
+-
++
++
+ if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST &&
+ p->conf.auth_backend != AUTH_BACKEND_PLAIN) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "digest: unsupported backend (only htdigest or plain)");
+-
++
+ return -1;
+ }
+-
++
+ b = buffer_init_string(realm_str);
+-
++
+ /* parse credentials from client */
+ for (c = b->ptr; *c; c++) {
+ /* skip whitespaces */
+@@ -812,18 +775,18 @@
+
+ for (i = 0; dkv[i].key; i++) {
+ if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) {
+- if ((c[dkv[i].key_len] == '"') &&
++ if ((c[dkv[i].key_len] == '"') &&
+ (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) {
+ /* value with "..." */
+ *(dkv[i].ptr) = c + dkv[i].key_len + 1;
+ c = e;
+-
++
+ *e = '\0';
+ } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) {
+ /* value without "...", terminated by ',' */
+ *(dkv[i].ptr) = c + dkv[i].key_len;
+ c = e;
-
-- k++;
-- start = k + 1;
-- }
-- }
--
-- buffer_append_string_len(p->location, pattern + start, pattern_len - start);
--
-- pcre_free(list);
--
-+ if (i >= 0) {
- response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
-
- con->http_status = 301;
-@@ -249,6 +188,9 @@
-
- return HANDLER_FINISHED;
++
+ *e = '\0';
+ } else {
+ /* value without "...", terminated by EOL */
+@@ -833,7 +796,7 @@
+ }
}
-+ else if (i != PCRE_ERROR_NOMATCH) {
+ }
+-
++
+ if (p->conf.auth_debug > 1) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "username", username);
+ log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm);
+@@ -845,22 +808,22 @@
+ log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc);
+ log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons);
+ }
+-
++
+ /* check if everything is transmitted */
+- if (!username ||
++ if (!username ||
+ !realm ||
+ !nonce ||
+ !uri ||
+ (qop && (!nc || !cnonce)) ||
+ !respons ) {
+ /* missing field */
+-
+- log_error_write(srv, __FILE__, __LINE__, "s",
++
+ log_error_write(srv, __FILE__, __LINE__, "s",
-+ "execution error while matching", i);
+ "digest: missing field");
+ return -1;
}
- #undef N
-
---- lighttpd-1.4.11/src/mod_rewrite.c 2005-09-29 20:59:10.000000000 +0300
-+++ lighttpd/src/mod_rewrite.c 2006-07-11 21:23:39.947846458 +0300
-@@ -13,24 +13,8 @@
- #endif
- typedef struct {
--#ifdef HAVE_PCRE_H
-- pcre *key;
--#endif
+- m = get_http_method_name(con->request.http_method);
++ m = get_http_method_name(con->request.http_method);
+
+ /* password-string == HA1 */
+ password = buffer_init();
+@@ -873,10 +836,10 @@
+ buffer_free(realm_buf);
+ return 0;
+ }
-
-- buffer *value;
++
+ buffer_free(username_buf);
+ buffer_free(realm_buf);
-
-- int once;
--} rewrite_rule;
--
--typedef struct {
-- rewrite_rule **ptr;
++
+ if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
+ /* generate password from plain-text */
+ MD5_Init(&Md5Ctx);
+@@ -890,16 +853,16 @@
+ /* HA1 */
+ /* transform the 32-byte-hex-md5 to a 16-byte-md5 */
+ for (i = 0; i < HASHLEN; i++) {
+- HA1[i] = hex2int(password->ptr[i*2]) << 4;
+- HA1[i] |= hex2int(password->ptr[i*2+1]);
++ HA1[i] = hex2int(password->ptr[i*2]) << 4;
++ HA1[i] |= hex2int(password->ptr[i*2+1]);
+ }
+ } else {
+ /* we already check that above */
+ SEGFAULT();
+ }
-
-- size_t used;
-- size_t size;
--} rewrite_rule_buffer;
--
--typedef struct {
-- rewrite_rule_buffer *rewrite;
-+ pcre_keyvalue_buffer *rewrite;
-+ buffer *once;
- data_config *context; /* to which apply me */
- } plugin_config;
-
-@@ -63,80 +47,6 @@
- free(hctx);
- }
-
--rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
-- rewrite_rule_buffer *kvb;
++
+ buffer_free(password);
-
-- kvb = calloc(1, sizeof(*kvb));
++
+ if (algorithm &&
+ strcasecmp(algorithm, "md5-sess") == 0) {
+ MD5_Init(&Md5Ctx);
+@@ -910,9 +873,9 @@
+ MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
+ MD5_Final(HA1, &Md5Ctx);
+ }
-
-- return kvb;
--}
--
--int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
--#ifdef HAVE_PCRE_H
-- size_t i;
-- const char *errptr;
-- int erroff;
++
+ CvtHex(HA1, a1);
-
-- if (!key) return -1;
--
-- if (kvb->size == 0) {
-- kvb->size = 4;
-- kvb->used = 0;
--
-- kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
++
+ /* calculate H(A2) */
+ MD5_Init(&Md5Ctx);
+ MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
+@@ -924,7 +887,7 @@
+ }
+ MD5_Final(HA2, &Md5Ctx);
+ CvtHex(HA2, HA2Hex);
+-
++
+ /* calculate response */
+ MD5_Init(&Md5Ctx);
+ MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN);
+@@ -942,39 +905,39 @@
+ MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN);
+ MD5_Final(RespHash, &Md5Ctx);
+ CvtHex(RespHash, a2);
+-
++
+ if (0 != strcmp(a2, respons)) {
+ /* digest not ok */
-
-- for(i = 0; i < kvb->size; i++) {
-- kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
-- }
-- } else if (kvb->used == kvb->size) {
-- kvb->size += 4;
++
+ if (p->conf.auth_debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sss",
++ log_error_write(srv, __FILE__, __LINE__, "sss",
+ "digest: digest mismatch", a2, respons);
+ }
-
-- kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
+- log_error_write(srv, __FILE__, __LINE__, "sss",
++
++ log_error_write(srv, __FILE__, __LINE__, "sss",
+ "digest: auth failed for", username, "wrong password");
-
-- for(i = kvb->used; i < kvb->size; i++) {
-- kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
-- }
-- }
++
+ buffer_free(b);
+ return 0;
+ }
-
-- if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
-- 0, &errptr, &erroff, NULL))) {
++
+ /* value is our allow-rules */
+ if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
+ buffer_free(b);
-
-- return -1;
-- }
--
-- kvb->ptr[kvb->used]->value = buffer_init();
-- buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
-- kvb->ptr[kvb->used]->once = once;
+- log_error_write(srv, __FILE__, __LINE__, "s",
++
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "digest: rules did match");
+-
++
+ return 0;
+ }
-
-- kvb->used++;
++
+ /* remember the username */
+ buffer_copy_string(p->auth_user, username);
-
-- return 0;
--#else
-- UNUSED(kvb);
-- UNUSED(value);
-- UNUSED(once);
-- UNUSED(key);
--
-- return -1;
--#endif
--}
--
--void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
--#ifdef HAVE_PCRE_H
-- size_t i;
--
-- for (i = 0; i < kvb->size; i++) {
-- if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
-- if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
-- free(kvb->ptr[i]);
-- }
++
+ buffer_free(b);
-
-- if (kvb->ptr) free(kvb->ptr);
--#endif
++
+ if (p->conf.auth_debug) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "digest: auth ok");
+ }
+ return 1;
+@@ -985,23 +948,23 @@
+ HASH h;
+ MD5_CTX Md5Ctx;
+ char hh[32];
-
-- free(kvb);
--}
--
++
+ UNUSED(p);
- INIT_FUNC(mod_rewrite_init) {
- plugin_data *p;
-@@ -160,7 +70,8 @@
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-- rewrite_rule_buffer_free(s->rewrite);
-+ pcre_keyvalue_buffer_free(s->rewrite);
-+ buffer_free(s->once);
-
- free(s);
- }
-@@ -198,10 +109,9 @@
- return HANDLER_ERROR;
- }
-
-- if (0 != rewrite_rule_buffer_append(s->rewrite,
-- ((data_string *)(da->value->data[j]))->key,
-- ((data_string *)(da->value->data[j]))->value,
-- once)) {
-+ if (0 != pcre_keyvalue_buffer_append(s->rewrite,
-+ ((data_string *)(da->value->data[j]))->key->ptr,
-+ ((data_string *)(da->value->data[j]))->value->ptr)) {
- #ifdef HAVE_PCRE_H
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "pcre-compile failed for", da->value->data[j]->key);
-@@ -210,6 +120,12 @@
- "pcre support is missing, please install libpcre and the headers");
+ /* generate shared-secret */
+ MD5_Init(&Md5Ctx);
+ MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
+ MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
+-
++
+ /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
+ ltostr(hh, srv->cur_ts);
+ MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
+ ltostr(hh, rand());
+ MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
+-
++
+ MD5_Final(h, &Md5Ctx);
+-
++
+ CvtHex(h, out);
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_auth.h lighttpd-1.4.12/src/http_auth.h
+--- lighttpd-1.4.11/src/http_auth.h 2005-08-14 17:12:31.000000000 +0300
++++ lighttpd-1.4.12/src/http_auth.h 2006-07-11 21:23:40.000000000 +0300
+@@ -9,22 +9,26 @@
+ # include <ldap.h>
#endif
- }
+
+-typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN,
+- AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD,
+- AUTH_BACKEND_HTDIGEST, AUTH_BACKEND_PAM } auth_backend_t;
++typedef enum {
++ AUTH_BACKEND_UNSET,
++ AUTH_BACKEND_PLAIN,
++ AUTH_BACKEND_LDAP,
++ AUTH_BACKEND_HTPASSWD,
++ AUTH_BACKEND_HTDIGEST
++} auth_backend_t;
+
+ typedef struct {
+ /* auth */
+ array *auth_require;
+-
+
-+ if (once) {
-+ buffer_append_string_len(s->once, CONST_STR_LEN("1"));
-+ } else {
-+ buffer_append_string_len(s->once, CONST_STR_LEN("0"));
-+ }
- }
- }
-
-@@ -245,11 +161,8 @@
- array *ca;
-
- s = calloc(1, sizeof(plugin_config));
-- s->rewrite = rewrite_rule_buffer_init();
--
-- cv[0].destination = s->rewrite;
-- cv[1].destination = s->rewrite;
-- cv[2].destination = s->rewrite;
-+ s->rewrite = pcre_keyvalue_buffer_init();
-+ s->once = buffer_init();
-
- p->config_storage[i] = s;
- ca = ((data_config *)srv->config_context->data[i])->value;
-@@ -271,6 +184,7 @@
- size_t i, j;
- plugin_config *s = p->config_storage[0];
- p->conf.rewrite = s->rewrite;
-+ p->conf.once = s->once;
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -288,15 +202,19 @@
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
- p->conf.rewrite = s->rewrite;
-+ p->conf.once = s->once;
- p->conf.context = dc;
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
- p->conf.rewrite = s->rewrite;
-+ p->conf.once = s->once;
- p->conf.context = dc;
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
- p->conf.rewrite = s->rewrite;
-+ p->conf.once = s->once;
- p->conf.context = dc;
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
- p->conf.rewrite = s->rewrite;
-+ p->conf.once = s->once;
- p->conf.context = dc;
- }
- }
-@@ -321,7 +239,7 @@
- URIHANDLER_FUNC(mod_rewrite_uri_handler) {
- #ifdef HAVE_PCRE_H
- plugin_data *p = p_d;
-- size_t i;
-+ int i;
- handler_ctx *hctx;
-
- /*
-@@ -349,76 +267,21 @@
- if (!p->conf.rewrite) return HANDLER_GO_ON;
-
- buffer_copy_string_buffer(p->match_buf, con->request.uri);
-+ i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
-
-- for (i = 0; i < p->conf.rewrite->used; i++) {
-- pcre *match;
-- const char *pattern;
-- size_t pattern_len;
-- int n;
-- rewrite_rule *rule = p->conf.rewrite->ptr[i];
--# define N 10
-- int ovec[N * 3];
--
-- match = rule->key;
-- pattern = rule->value->ptr;
-- pattern_len = rule->value->used - 1;
--
-- if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
-- if (n != PCRE_ERROR_NOMATCH) {
-- log_error_write(srv, __FILE__, __LINE__, "sd",
-- "execution error while matching: ", n);
-- return HANDLER_ERROR;
-- }
-- } else {
-- const char **list;
-- size_t start, end;
-- size_t k;
--
-- /* it matched */
-- pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
--
-- /* search for $[0-9] */
--
-- buffer_reset(con->request.uri);
--
-- start = 0; end = pattern_len;
-- for (k = 0; k < pattern_len; k++) {
-- if ((pattern[k] == '$' || pattern[k] == '%') &&
-- isdigit((unsigned char)pattern[k + 1])) {
-- /* got one */
--
-- size_t num = pattern[k + 1] - '0';
--
-- end = k;
--
-- buffer_append_string_len(con->request.uri, pattern + start, end - start);
--
-- if (pattern[k] == '$') {
-- /* n is always > 0 */
-- if (num < (size_t)n) {
-- buffer_append_string(con->request.uri, list[num]);
-- }
-- } else {
-- config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
-- }
--
-- k++;
-- start = k + 1;
-- }
-- }
--
-- buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
--
-- pcre_free(list);
--
-+ if (i >= 0) {
- hctx = handler_ctx_init();
-
- con->plugin_ctx[p->id] = hctx;
-
-- if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
-+ if (p->conf.once->ptr[i] == '1')
-+ hctx->state = REWRITE_STATE_FINISHED;
-
- return HANDLER_COMEBACK;
- }
-+ else if (i != PCRE_ERROR_NOMATCH) {
-+ log_error_write(srv, __FILE__, __LINE__, "s",
-+ "execution error while matching", i);
- }
- #undef N
-
---- lighttpd-1.4.11/src/mod_rrdtool.c 2005-08-22 01:52:24.000000000 +0300
-+++ lighttpd/src/mod_rrdtool.c 2006-07-11 21:23:40.059853473 +0300
-@@ -5,7 +5,6 @@
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
--#include <unistd.h>
- #include <errno.h>
- #include <time.h>
+ buffer *auth_plain_groupfile;
+ buffer *auth_plain_userfile;
+-
++
+ buffer *auth_htdigest_userfile;
+ buffer *auth_htpasswd_userfile;
+-
++
+ buffer *auth_backend_conf;
+-
++
+ buffer *auth_ldap_hostname;
+ buffer *auth_ldap_basedn;
+ buffer *auth_ldap_binddn;
+@@ -32,15 +36,15 @@
+ buffer *auth_ldap_filter;
+ buffer *auth_ldap_cafile;
+ unsigned short auth_ldap_starttls;
+-
++
+ unsigned short auth_debug;
+-
++
+ /* generated */
+ auth_backend_t auth_backend;
+-
++
+ #ifdef USE_LDAP
+ LDAP *ldap;
+-
++
+ buffer *ldap_filter_pre;
+ buffer *ldap_filter_post;
+ #endif
+@@ -49,15 +53,15 @@
+ typedef struct {
+ PLUGIN_DATA;
+ buffer *tmp_buf;
+-
++
+ buffer *auth_user;
-@@ -20,6 +19,10 @@
- /* no need for waitpid if we don't have fork */
- #include <sys/wait.h>
+ #ifdef USE_LDAP
+ buffer *ldap_filter;
#endif
+-
+
-+#include "sys-files.h"
-+#include "sys-process.h"
+ mod_auth_plugin_config **config_storage;
+-
+
- typedef struct {
- buffer *path_rrdtool_bin;
- buffer *path_rrd;
-@@ -250,14 +253,12 @@
- return HANDLER_GO_ON;
- }
+ mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
+ } mod_auth_plugin_data;
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(path_rrdtool_bin);
-- PATCH(path_rrd);
-+ PATCH_OPTION(path_rrdtool_bin);
-+ PATCH_OPTION(path_rrd);
-
- p->conf.bytes_written_ptr = &(s->bytes_written);
- p->conf.bytes_read_ptr = &(s->bytes_read);
-@@ -276,7 +277,7 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
-- PATCH(path_rrd);
-+ PATCH_OPTION(path_rrd);
- /* get pointers to double values */
-
- p->conf.bytes_written_ptr = &(s->bytes_written);
-@@ -288,7 +289,6 @@
-
- return 0;
- }
--#undef PATCH
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_auth_digest.h lighttpd-1.4.12/src/http_auth_digest.h
+--- lighttpd-1.4.11/src/http_auth_digest.h 2006-01-05 00:54:01.000000000 +0200
++++ lighttpd-1.4.12/src/http_auth_digest.h 2006-07-11 21:23:40.000000000 +0300
+@@ -12,7 +12,7 @@
+ #ifdef USE_OPENSSL
+ #define IN const
+ #else
+-#define IN
++#define IN
+ #endif
+ #define OUT
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_chunk.c lighttpd-1.4.12/src/http_chunk.c
+--- lighttpd-1.4.11/src/http_chunk.c 2005-08-11 01:26:50.000000000 +0300
++++ lighttpd-1.4.12/src/http_chunk.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,7 +1,7 @@
+ /**
+ * the HTTP chunk-API
+- *
+- *
++ *
++ *
+ */
- SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_scgi.c 2006-03-04 17:15:26.000000000 +0200
-+++ lighttpd/src/mod_scgi.c 2006-07-11 21:23:40.023851218 +0300
-@@ -1,5 +1,4 @@
#include <sys/types.h>
--#include <unistd.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <string.h>
-@@ -30,7 +29,9 @@
- #endif
+@@ -9,7 +9,6 @@
- #include "sys-socket.h"
--
-+#include "sys-files.h"
-+#include "sys-strings.h"
-+#include "sys-process.h"
+ #include <stdlib.h>
+ #include <fcntl.h>
+-#include <unistd.h>
- #ifndef UNIX_PATH_MAX
- # define UNIX_PATH_MAX 108
-@@ -61,7 +62,6 @@
-
- pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
+ #include <stdio.h>
+ #include <errno.h>
+@@ -23,19 +22,19 @@
+ static int http_chunk_append_len(server *srv, connection *con, size_t len) {
+ size_t i, olen = len, j;
+ buffer *b;
+-
++
+ b = srv->tmp_chunk_len;
+-
++
+ if (len == 0) {
+ buffer_copy_string(b, "0");
+ } else {
+ for (i = 0; i < 8 && len; i++) {
+ len >>= 4;
+ }
+-
++
+ /* i is the number of hex digits we have */
+ buffer_prepare_copy(b, i + 1);
+-
++
+ for (j = i-1, len = olen; j+1 > 0; j--) {
+ b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
+ len >>= 4;
+@@ -43,61 +42,61 @@
+ b->used = i;
+ b->ptr[b->used++] = '\0';
+ }
+-
++
+ buffer_append_string(b, "\r\n");
+ chunkqueue_append_buffer(con->write_queue, b);
+-
++
+ return 0;
+ }
--
- size_t load; /* number of requests waiting on this process */
- time_t last_used; /* see idle_timeout */
-@@ -308,7 +308,6 @@
- size_t request_id;
- int fd; /* fd to the scgi process */
- int fde_ndx; /* index into the fd-event buffer */
--
- pid_t pid;
- int got_proc;
-
-@@ -555,7 +554,9 @@
- host = ex->hosts[n];
-
- for (proc = host->first; proc; proc = proc->next) {
-+#ifndef _WIN32
- if (proc->pid != 0) kill(proc->pid, SIGTERM);
-+#endif
-
- if (proc->is_local &&
- !buffer_is_empty(proc->socket)) {
-@@ -564,7 +565,9 @@
- }
-
- for (proc = host->unused_procs; proc; proc = proc->next) {
-+#ifndef _WIN32
- if (proc->pid != 0) kill(proc->pid, SIGTERM);
-+#endif
-
- if (proc->is_local &&
- !buffer_is_empty(proc->socket)) {
-@@ -641,12 +644,8 @@
- scgi_addr_un.sun_family = AF_UNIX;
- strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
-
--#ifdef SUN_LEN
- servlen = SUN_LEN(&scgi_addr_un);
--#else
-- /* stevens says: */
-- servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
--#endif
+ int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
+ chunkqueue *cq;
+-
+
- socket_type = AF_UNIX;
- scgi_addr = (struct sockaddr *) &scgi_addr_un;
- #else
-@@ -1292,12 +1291,9 @@
- /* use the unix domain socket */
- scgi_addr_un.sun_family = AF_UNIX;
- strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
--#ifdef SUN_LEN
-+
- servlen = SUN_LEN(&scgi_addr_un);
--#else
-- /* stevens says: */
-- servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
--#endif
+ if (!con) return -1;
+-
+
- scgi_addr = (struct sockaddr *) &scgi_addr_un;
- #else
- return -1;
-@@ -2058,6 +2054,7 @@
- int status;
-
- if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
-+#ifndef _WIN32
- switch(waitpid(proc->pid, &status, WNOHANG)) {
- case 0:
- /* child is still alive */
-@@ -2084,6 +2081,7 @@
- proc->state = PROC_STATE_DIED;
- break;
- }
-+#endif
- }
-
- /*
-@@ -2271,10 +2269,11 @@
- */
- if (hctx->wb->bytes_out == 0 &&
- hctx->reconnects < 5) {
-+#ifndef _WIN32
- usleep(10000); /* take away the load of the webserver
- * to let the php a chance to restart
- */
--
-+#endif
- scgi_reconnect(srv, hctx);
-
- return HANDLER_WAIT_FOR_FD;
-@@ -2286,7 +2285,7 @@
- *
- */
-
-- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
-+ log_error_write(srv, __FILE__, __LINE__, "ssosd",
- "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
- "write-offset:", hctx->wb->bytes_out,
- "reconnect attempts:", hctx->reconnects);
-@@ -2479,7 +2478,7 @@
- int status;
-
- /* only fetch the zombie if it is not already done */
--
-+#ifndef _WIN32
- switch(waitpid(proc->pid, &status, WNOHANG)) {
- case 0:
- /* child is still alive */
-@@ -2519,6 +2518,7 @@
-
- break;
- }
-+#endif
- }
-
- if (con->file_started == 0) {
-@@ -2536,7 +2536,7 @@
- return HANDLER_WAIT_FOR_FD;
- }
-
-- log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
-+ log_error_write(srv, __FILE__, __LINE__, "sosdsd",
- "response not sent, request sent:", hctx->wb->bytes_out,
- "connection-fd:", con->fd,
- "fcgi-fd:", hctx->fd);
-@@ -2631,14 +2631,13 @@
-
- return HANDLER_FINISHED;
- }
--#define PATCH(x) \
-- p->conf.x = s->x;
+ cq = con->write_queue;
+-
+
- static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(exts);
-- PATCH(debug);
-+ PATCH_OPTION(exts);
-+ PATCH_OPTION(debug);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -2653,17 +2652,15 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
-- PATCH(exts);
-+ PATCH_OPTION(exts);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
-- PATCH(debug);
-+ PATCH_OPTION(debug);
- }
- }
+ if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
+ http_chunk_append_len(srv, con, len);
}
-
+-
++
+ chunkqueue_append_file(cq, fn, offset, len);
+-
++
+ if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
+ chunkqueue_append_mem(cq, "\r\n", 2 + 1);
+ }
+-
++
return 0;
}
--#undef PATCH
--
- static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
- plugin_data *p = p_d;
-@@ -2971,7 +2968,7 @@
- if (proc->load != 0) break;
- if (host->num_procs <= host->min_procs) break;
- if (proc->pid == 0) continue;
--
-+#ifndef _WIN32
- if (srv->cur_ts - proc->last_used > host->idle_timeout) {
- /* a proc is idling for a long time now,
- * terminated it */
-@@ -3009,13 +3006,14 @@
- /* proc is now in unused, let the next second handle the next process */
- break;
- }
-+#endif
- }
-
- for (proc = host->unused_procs; proc; proc = proc->next) {
- int status;
-
- if (proc->pid == 0) continue;
--
-+#ifndef _WIN32
- switch (waitpid(proc->pid, &status, WNOHANG)) {
- case 0:
- /* child still running after timeout, good */
-@@ -3059,6 +3057,7 @@
- proc->state = PROC_STATE_UNSET;
- host->max_id--;
- }
-+#endif
- }
- }
- }
---- lighttpd-1.4.11/src/mod_secure_download.c 2005-12-14 14:37:29.000000000 +0200
-+++ lighttpd/src/mod_secure_download.c 2006-07-11 21:23:39.935845706 +0300
-@@ -156,16 +156,14 @@
- return i == len;
+ int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
+ chunkqueue *cq;
+-
++
+ if (!con) return -1;
+-
++
+ cq = con->write_queue;
+-
++
+ if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
+ http_chunk_append_len(srv, con, mem->used - 1);
+ }
+-
++
+ chunkqueue_append_buffer(cq, mem);
+-
++
+ if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
+ chunkqueue_append_mem(cq, "\r\n", 2 + 1);
+ }
+-
++
+ return 0;
}
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(secret);
-- PATCH(doc_root);
-- PATCH(uri_prefix);
-- PATCH(timeout);
-+ PATCH_OPTION(secret);
-+ PATCH_OPTION(doc_root);
-+ PATCH_OPTION(uri_prefix);
-+ PATCH_OPTION(timeout);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -180,21 +178,19 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
-- PATCH(secret);
-+ PATCH_OPTION(secret);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
-- PATCH(doc_root);
-+ PATCH_OPTION(doc_root);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
-- PATCH(uri_prefix);
-+ PATCH_OPTION(uri_prefix);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
-- PATCH(timeout);
-+ PATCH_OPTION(timeout);
- }
+ int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
+ chunkqueue *cq;
+-
++
+ if (!con) return -1;
+-
++
+ cq = con->write_queue;
+-
++
+ if (len == 0) {
+ if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
+ http_chunk_append_len(srv, con, 0);
+@@ -107,17 +106,17 @@
}
+ return 0;
}
-
+-
++
+ if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
+ http_chunk_append_len(srv, con, len - 1);
+ }
+-
++
+ chunkqueue_append_mem(cq, mem, len);
+-
++
+ if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
+ chunkqueue_append_mem(cq, "\r\n", 2 + 1);
+ }
+-
++
return 0;
}
--#undef PATCH
--
- URIHANDLER_FUNC(mod_secdownload_uri_handler) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_setenv.c 2006-01-14 20:33:12.000000000 +0200
-+++ lighttpd/src/mod_setenv.c 2006-07-11 21:23:40.191861741 +0300
-@@ -120,15 +120,13 @@
- return HANDLER_GO_ON;
+@@ -125,9 +124,9 @@
+ off_t http_chunkqueue_length(server *srv, connection *con) {
+ if (!con) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
+-
++
+ return 0;
+ }
+-
++
+ return chunkqueue_length(con->write_queue);
}
-
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(request_header);
-- PATCH(response_header);
-- PATCH(environment);
-+ PATCH_OPTION(request_header);
-+ PATCH_OPTION(response_header);
-+ PATCH_OPTION(environment);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -143,18 +141,17 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
-- PATCH(request_header);
-+ PATCH_OPTION(request_header);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
-- PATCH(response_header);
-+ PATCH_OPTION(response_header);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_resp.c lighttpd-1.4.12/src/http_resp.c
+--- lighttpd-1.4.11/src/http_resp.c 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/src/http_resp.c 2006-07-11 21:23:40.000000000 +0300
+@@ -0,0 +1,263 @@
++#include <string.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <assert.h>
++
++#include "http_resp.h"
++#include "http_resp_parser.h"
++
++/* declare prototypes for the parser */
++void *http_resp_parserAlloc(void *(*mallocProc)(size_t));
++void http_resp_parserFree(void *p, void (*freeProc)(void*));
++void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt);
++void http_resp_parser(void *, int, buffer *, http_resp_ctx_t *);
++
++typedef struct {
++ chunkqueue *cq;
++
++ chunk *c; /* current chunk in the chunkqueue */
++ size_t offset; /* current offset in current chunk */
++
++ chunk *lookup_c;
++ size_t lookup_offset;
++
++ int is_key;
++ int is_statusline;
++} http_resp_tokenizer_t;
++
++http_resp *http_response_init(void) {
++ http_resp *resp = calloc(1, sizeof(*resp));
++
++ resp->reason = buffer_init();
++ resp->headers = array_init();
++
++ return resp;
++}
++
++void http_response_reset(http_resp *resp) {
++ if (!resp) return;
++
++ buffer_reset(resp->reason);
++ array_reset(resp->headers);
++
++}
++
++void http_response_free(http_resp *resp) {
++ if (!resp) return;
++
++ buffer_free(resp->reason);
++ array_free(resp->headers);
++
++ free(resp);
++}
++
++static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
++ if (t->offset == t->c->mem->used - 1) {
++ /* end of chunk, open next chunk */
++
++ if (!t->c->next) return -1;
++
++ t->c = t->c->next;
++ t->offset = 0;
++ }
++
++ *c = t->c->mem->ptr[t->offset++];
++
++ t->lookup_offset = t->offset;
++ t->lookup_c = t->c;
++
++#if 0
++ fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
++#endif
++
++ return 0;
++}
++
++static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
++ if (t->lookup_offset == t->lookup_c->mem->used - 1) {
++ /* end of chunk, open next chunk */
++
++ if (!t->lookup_c->next) return -1;
++
++ t->lookup_c = t->lookup_c->next;
++ t->lookup_offset = 0;
++ }
++
++ *c = t->lookup_c->mem->ptr[t->lookup_offset++];
++#if 0
++ fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
++#endif
++
++ return 0;
++}
++
++
++static int http_resp_tokenizer(
++ http_resp_tokenizer_t *t,
++ int *token_id,
++ buffer *token
++) {
++ unsigned char c;
++ int tid = 0;
++
++ /* push the token to the parser */
++
++ while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
++ switch (c) {
++ case ':':
++ tid = TK_COLON;
++
++ t->is_key = 0;
++
++ break;
++ case ' ':
++ case '\t':
++ /* ignore WS */
++
++ break;
++ case '\r':
++ if (0 != http_resp_lookup_next_char(t, &c)) return -1;
++
++ if (c == '\n') {
++ tid = TK_CRLF;
++
++ t->c = t->lookup_c;
++ t->offset = t->lookup_offset;
++
++ t->is_statusline = 0;
++ t->is_key = 1;
++ } else {
++ fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__);
++ return -1;
++ }
++ break;
++ case '\n':
++ tid = TK_CRLF;
++
++ t->is_statusline = 0;
++ t->is_key = 1;
++
++ break;
++ default:
++ while (c >= 32 && c != 127 && c != 255) {
++ if (t->is_statusline) {
++ if (c == ':') {t->is_statusline = 0; break; } /* this is not a status line by a real header */
++ if (c == 32) break; /* the space is a splitter in the statusline */
++ } else {
++ if (t->is_key) {
++ if (c == ':') break; /* the : is the splitter between key and value */
++ }
++ }
++ if (0 != http_resp_lookup_next_char(t, &c)) return -1;
++ }
++
++ if (t->c == t->lookup_c &&
++ t->offset == t->lookup_offset + 1) {
++
++ fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__);
++ return -1;
++ }
++
++ tid = TK_STRING;
++
++ /* the lookup points to the first invalid char */
++ t->lookup_offset--;
++
++ /* no overlapping string */
++ if (t->c == t->lookup_c) {
++ buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
++ } else {
++ /* first chunk */
++ buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
++
++ /* chunks in the middle */
++ for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
++ buffer_append_string_buffer(token, t->c->mem);
++ t->offset = t->c->mem->used - 1;
++ }
++
++ /* last chunk */
++ buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
++ }
++
++ t->offset = t->lookup_offset;
++
++ break;
++ }
++ }
++
++ if (tid) {
++ *token_id = tid;
++
++ return 1;
++ }
++
++ return -1;
++}
++
++parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
++ http_resp_tokenizer_t t;
++ void *pParser = NULL;
++ int token_id = 0;
++ buffer *token = NULL;
++ http_resp_ctx_t context;
++ parse_status_t ret = PARSE_UNSET;
++ int last_token_id = 0;
++
++ t.cq = cq;
++ t.c = cq->first;
++ t.offset = t.c->offset;
++ t.is_key = 0;
++ t.is_statusline = 1;
++
++ context.ok = 1;
++ context.errmsg = buffer_init();
++ context.resp = resp;
++
++ pParser = http_resp_parserAlloc( malloc );
++ token = buffer_init();
++ /* http_resp_parserTrace(stderr, "http-response: "); */
++
++ while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) {
++ http_resp_parser(pParser, token_id, token, &context);
++
++ token = buffer_init();
++
++ if (last_token_id == TK_CRLF &&
++ token_id == TK_CRLF) break;
++
++ last_token_id = token_id;
++ }
++
++ /* oops, the parser failed */
++ if (context.ok == 0) {
++ ret = PARSE_ERROR;
++
++ fprintf(stderr, "%s.%d: parsing failed at: ...%20s\r\n",
++ __FILE__, __LINE__, t.c->mem->ptr + t.offset);
++ }
++
++ http_resp_parser(pParser, 0, token, &context);
++ http_resp_parserFree(pParser, free );
++
++ if (context.ok == 0) {
++ /* we are missing the some tokens */
++
++ if (ret == PARSE_UNSET) ret = PARSE_NEED_MORE;
++ } else {
++ chunk *c;
++
++ for (c = cq->first; c != t.c; c = c->next) {
++ c->offset = c->mem->used - 1;
++ }
++
++ c->offset = t.offset;
++
++ ret = PARSE_SUCCESS;
++ }
++
++ buffer_free(token);
++
++ return ret;
++}
++
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_resp.h lighttpd-1.4.12/src/http_resp.h
+--- lighttpd-1.4.11/src/http_resp.h 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/src/http_resp.h 2006-07-11 21:23:40.000000000 +0300
+@@ -0,0 +1,34 @@
++#ifndef _HTTP_RESP_H_
++#define _HTTP_RESP_H_
++
++#include "array.h"
++#include "chunk.h"
++
++typedef enum {
++ PARSE_UNSET,
++ PARSE_SUCCESS,
++ PARSE_ERROR,
++ PARSE_NEED_MORE
++} parse_status_t;
++
++typedef struct {
++ int protocol; /* http/1.0, http/1.1 */
++ int status; /* e.g. 200 */
++ buffer *reason; /* e.g. Ok */
++ array *headers;
++} http_resp;
++
++typedef struct {
++ int ok;
++ buffer *errmsg;
++
++ http_resp *resp;
++} http_resp_ctx_t;
++
++http_resp *http_response_init(void);
++void http_response_free(http_resp *resp);
++void http_response_reset(http_resp *resp);
++
++parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
++
++#endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_resp_parser.c lighttpd-1.4.12/src/http_resp_parser.c
+--- lighttpd-1.4.11/src/http_resp_parser.c 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/src/http_resp_parser.c 2006-07-11 21:49:18.000000000 +0300
+@@ -0,0 +1,894 @@
++/* Driver template for the LEMON parser generator.
++** The author disclaims copyright to this source code.
++*/
++/* First off, code is include which follows the "include" declaration
++** in the input file. */
++#include <stdio.h>
++#line 6 "./http_resp_parser.y"
++
++#include <assert.h>
++#include <string.h>
++#include "http_resp.h"
++#include "keyvalue.h"
++#include "array.h"
++
++#line 16 "http_resp_parser.c"
++/* Next is all token values, in a form suitable for use by makeheaders.
++** This section will be null unless lemon is run with the -m switch.
++*/
++/*
++** These constants (all generated automatically by the parser generator)
++** specify the various kinds of tokens (terminals) that the parser
++** understands.
++**
++** Each symbol here is a terminal symbol in the grammar.
++*/
++/* Make sure the INTERFACE macro is defined.
++*/
++#ifndef INTERFACE
++# define INTERFACE 1
++#endif
++/* The next thing included is series of defines which control
++** various aspects of the generated parser.
++** YYCODETYPE is the data type used for storing terminal
++** and nonterminal numbers. "unsigned char" is
++** used if there are fewer than 250 terminals
++** and nonterminals. "int" is used otherwise.
++** YYNOCODE is a number of type YYCODETYPE which corresponds
++** to no legal terminal or nonterminal number. This
++** number is used to fill in empty slots of the hash
++** table.
++** YYFALLBACK If defined, this indicates that one or more tokens
++** have fall-back values which should be used if the
++** original value of the token will not parse.
++** YYACTIONTYPE is the data type used for storing terminal
++** and nonterminal numbers. "unsigned char" is
++** used if there are fewer than 250 rules and
++** states combined. "int" is used otherwise.
++** http_resp_parserTOKENTYPE is the data type used for minor tokens given
++** directly to the parser from the tokenizer.
++** YYMINORTYPE is the data type used for all minor tokens.
++** This is typically a union of many types, one of
++** which is http_resp_parserTOKENTYPE. The entry in the union
++** for base tokens is called "yy0".
++** YYSTACKDEPTH is the maximum depth of the parser's stack.
++** http_resp_parserARG_SDECL A static variable declaration for the %extra_argument
++** http_resp_parserARG_PDECL A parameter declaration for the %extra_argument
++** http_resp_parserARG_STORE Code to store %extra_argument into yypParser
++** http_resp_parserARG_FETCH Code to extract %extra_argument from yypParser
++** YYNSTATE the combined number of states.
++** YYNRULE the number of rules in the grammar
++** YYERRORSYMBOL is the code number of the error symbol. If not
++** defined, then do no error processing.
++*/
++/* \ 1 */
++#define YYCODETYPE unsigned char
++#define YYNOCODE 12
++#define YYACTIONTYPE unsigned char
++#define http_resp_parserTOKENTYPE buffer *
++typedef union {
++ http_resp_parserTOKENTYPE yy0;
++ http_resp * yy2;
++ data_string * yy9;
++ array * yy12;
++ int yy20;
++ int yy23;
++} YYMINORTYPE;
++#define YYSTACKDEPTH 100
++#define http_resp_parserARG_SDECL http_resp_ctx_t *ctx;
++#define http_resp_parserARG_PDECL ,http_resp_ctx_t *ctx
++#define http_resp_parserARG_FETCH http_resp_ctx_t *ctx = yypParser->ctx
++#define http_resp_parserARG_STORE yypParser->ctx = ctx
++#define YYNSTATE 19
++#define YYNRULE 9
++#define YYERRORSYMBOL 4
++#define YYERRSYMDT yy23
++#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
++#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
++#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
++
++/* Next are that tables used to determine what action to take based on the
++** current state and lookahead token. These tables are used to implement
++** functions that take a state number and lookahead value and return an
++** action integer.
++**
++** Suppose the action integer is N. Then the action is determined as
++** follows
++**
++** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
++** token onto the stack and goto state N.
++**
++** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
++**
++** N == YYNSTATE+YYNRULE A syntax error has occurred.
++**
++** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
++**
++** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
++** slots in the yy_action[] table.
++**
++** The action table is constructed as a single large table named yy_action[].
++** Given state S and lookahead X, the action is computed as
++**
++** yy_action[ yy_shift_ofst[S] + X ]
++**
++** If the index value yy_shift_ofst[S]+X is out of range or if the value
++** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
++** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
++** and that yy_default[S] should be used instead.
++**
++** The formula above is for computing the action when the lookahead is
++** a terminal symbol. If the lookahead is a non-terminal (as occurs after
++** a reduce action) then the yy_reduce_ofst[] array is used in place of
++** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
++** YY_SHIFT_USE_DFLT.
++**
++** The following are the tables generated in this section:
++**
++** yy_action[] A single table containing all actions.
++** yy_lookahead[] A table containing the lookahead for each entry in
++** yy_action. Used to detect hash collisions.
++** yy_shift_ofst[] For each state, the offset into yy_action for
++** shifting terminals.
++** yy_reduce_ofst[] For each state, the offset into yy_action for
++** shifting non-terminals after a reduce.
++** yy_default[] Default action for each state.
++*/
++static YYACTIONTYPE yy_action[] = {
++ /* 0 */ 8, 29, 18, 1, 14, 2, 4, 11, 15, 12,
++ /* 10 */ 14, 13, 4, 21, 5, 19, 3, 5, 6, 7,
++ /* 20 */ 9, 17, 16, 4, 20, 22, 22, 10,
++};
++static YYCODETYPE yy_lookahead[] = {
++ /* 0 */ 5, 6, 2, 8, 9, 1, 2, 1, 2, 8,
++ /* 10 */ 9, 1, 2, 2, 3, 0, 9, 3, 2, 1,
++ /* 20 */ 7, 2, 2, 2, 0, 2, 11, 10,
++};
++#define YY_SHIFT_USE_DFLT (-1)
++static signed char yy_shift_ofst[] = {
++ /* 0 */ 0, 4, 15, -1, 14, 16, 18, -1, 19, 20,
++ /* 10 */ 6, 21, 10, 24, -1, -1, -1, 23, 11,
++};
++#define YY_REDUCE_USE_DFLT (-6)
++static signed char yy_reduce_ofst[] = {
++ /* 0 */ -5, 7, -6, -6, -6, -6, -6, -6, 13, 17,
++ /* 10 */ -6, 1, 7, -6, -6, -6, -6, -6, -6,
++};
++static YYACTIONTYPE yy_default[] = {
++ /* 0 */ 28, 28, 28, 25, 28, 28, 28, 27, 28, 28,
++ /* 10 */ 28, 28, 28, 28, 26, 24, 23, 28, 28,
++};
++#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
++
++/* The next table maps tokens into fallback tokens. If a construct
++** like the following:
++**
++** %fallback ID X Y Z.
++**
++** appears in the grammer, then ID becomes a fallback token for X, Y,
++** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
++** but it does not parse, the type of the token is changed to ID and
++** the parse is retried before an error is thrown.
++*/
++#ifdef YYFALLBACK
++static const YYCODETYPE yyFallback[] = {
++};
++#endif /* YYFALLBACK */
++
++/* The following structure represents a single element of the
++** parser's stack. Information stored includes:
++**
++** + The state number for the parser at this level of the stack.
++**
++** + The value of the token stored at this level of the stack.
++** (In other words, the "major" token.)
++**
++** + The semantic value stored at this level of the stack. This is
++** the information used by the action routines in the grammar.
++** It is sometimes called the "minor" token.
++*/
++struct yyStackEntry {
++ int stateno; /* The state-number */
++ int major; /* The major token value. This is the code
++ ** number for the token at this stack level */
++ YYMINORTYPE minor; /* The user-supplied minor token value. This
++ ** is the value of the token */
++};
++typedef struct yyStackEntry yyStackEntry;
++
++/* The state of the parser is completely contained in an instance of
++** the following structure */
++struct yyParser {
++ int yyidx; /* Index of top element in stack */
++ int yyerrcnt; /* Shifts left before out of the error */
++ http_resp_parserARG_SDECL /* A place to hold %extra_argument */
++ yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
++};
++typedef struct yyParser yyParser;
++
++#ifndef NDEBUG
++#include <stdio.h>
++static FILE *yyTraceFILE = 0;
++static char *yyTracePrompt = 0;
++#endif /* NDEBUG */
++
++#ifndef NDEBUG
++/*
++** Turn parser tracing on by giving a stream to which to write the trace
++** and a prompt to preface each trace message. Tracing is turned off
++** by making either argument NULL
++**
++** Inputs:
++** <ul>
++** <li> A FILE* to which trace output should be written.
++** If NULL, then tracing is turned off.
++** <li> A prefix string written at the beginning of every
++** line of trace output. If NULL, then tracing is
++** turned off.
++** </ul>
++**
++** Outputs:
++** None.
++*/
++void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt){
++ yyTraceFILE = TraceFILE;
++ yyTracePrompt = zTracePrompt;
++ if( yyTraceFILE==0 ) yyTracePrompt = 0;
++ else if( yyTracePrompt==0 ) yyTraceFILE = 0;
++}
++#endif /* NDEBUG */
++
++#ifndef NDEBUG
++/* For tracing shifts, the names of all terminals and nonterminals
++** are required. The following table supplies these names */
++static const char *yyTokenName[] = {
++ "$", "CRLF", "STRING", "COLON",
++ "error", "protocol", "response_hdr", "number",
++ "headers", "header", "reason",
++};
++#endif /* NDEBUG */
++
++#ifndef NDEBUG
++/* For tracing reduce actions, the names of all rules are required.
++*/
++static const char *yyRuleName[] = {
++ /* 0 */ "response_hdr ::= headers CRLF",
++ /* 1 */ "response_hdr ::= protocol number reason CRLF headers CRLF",
++ /* 2 */ "protocol ::= STRING",
++ /* 3 */ "number ::= STRING",
++ /* 4 */ "reason ::= STRING",
++ /* 5 */ "reason ::= reason STRING",
++ /* 6 */ "headers ::= headers header",
++ /* 7 */ "headers ::= header",
++ /* 8 */ "header ::= STRING COLON STRING CRLF",
++};
++#endif /* NDEBUG */
++
++/*
++** This function returns the symbolic name associated with a token
++** value.
++*/
++const char *http_resp_parserTokenName(int tokenType){
++#ifndef NDEBUG
++ if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
++ return yyTokenName[tokenType];
++ }else{
++ return "Unknown";
++ }
++#else
++ return "";
++#endif
++}
++
++/*
++** This function allocates a new parser.
++** The only argument is a pointer to a function which works like
++** malloc.
++**
++** Inputs:
++** A pointer to the function used to allocate memory.
++**
++** Outputs:
++** A pointer to a parser. This pointer is used in subsequent calls
++** to http_resp_parser and http_resp_parserFree.
++*/
++void *http_resp_parserAlloc(void *(*mallocProc)(size_t)){
++ yyParser *pParser;
++ pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
++ if( pParser ){
++ pParser->yyidx = -1;
++ }
++ return pParser;
++}
++
++/* The following function deletes the value associated with a
++** symbol. The symbol can be either a terminal or nonterminal.
++** "yymajor" is the symbol code, and "yypminor" is a pointer to
++** the value.
++*/
++static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
++ switch( yymajor ){
++ /* Here is inserted the actions which take place when a
++ ** terminal or non-terminal is destroyed. This can happen
++ ** when the symbol is popped from the stack during a
++ ** reduce or during error processing or when a parser is
++ ** being destroyed before it is finished parsing.
++ **
++ ** Note: during a reduce, the only symbols destroyed are those
++ ** which appear on the RHS of the rule, but which are not used
++ ** inside the C code.
++ */
++ case 1:
++ case 2:
++ case 3:
++#line 23 "./http_resp_parser.y"
++{ buffer_free((yypminor->yy0)); }
++#line 326 "http_resp_parser.c"
++ break;
++ default: break; /* If no destructor action specified: do nothing */
++ }
++}
++
++/*
++** Pop the parser's stack once.
++**
++** If there is a destructor routine associated with the token which
++** is popped from the stack, then call it.
++**
++** Return the major token number for the symbol popped.
++*/
++static int yy_pop_parser_stack(yyParser *pParser){
++ YYCODETYPE yymajor;
++ yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
++
++ if( pParser->yyidx<0 ) return 0;
++#ifndef NDEBUG
++ if( yyTraceFILE && pParser->yyidx>=0 ){
++ fprintf(yyTraceFILE,"%sPopping %s\n",
++ yyTracePrompt,
++ yyTokenName[yytos->major]);
++ }
++#endif
++ yymajor = yytos->major;
++ yy_destructor( yymajor, &yytos->minor);
++ pParser->yyidx--;
++ return yymajor;
++}
++
++/*
++** Deallocate and destroy a parser. Destructors are all called for
++** all stack elements before shutting the parser down.
++**
++** Inputs:
++** <ul>
++** <li> A pointer to the parser. This should be a pointer
++** obtained from http_resp_parserAlloc.
++** <li> A pointer to a function used to reclaim memory obtained
++** from malloc.
++** </ul>
++*/
++void http_resp_parserFree(
++ void *p, /* The parser to be deleted */
++ void (*freeProc)(void*) /* Function used to reclaim memory */
++){
++ yyParser *pParser = (yyParser*)p;
++ if( pParser==0 ) return;
++ while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
++ (*freeProc)((void*)pParser);
++}
++
++/*
++** Find the appropriate action for a parser given the terminal
++** look-ahead token iLookAhead.
++**
++** If the look-ahead token is YYNOCODE, then check to see if the action is
++** independent of the look-ahead. If it is, return the action, otherwise
++** return YY_NO_ACTION.
++*/
++static int yy_find_shift_action(
++ yyParser *pParser, /* The parser */
++ int iLookAhead /* The look-ahead token */
++){
++ int i;
++ int stateno = pParser->yystack[pParser->yyidx].stateno;
++
++ /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
++ i = yy_shift_ofst[stateno];
++ if( i==YY_SHIFT_USE_DFLT ){
++ return yy_default[stateno];
++ }
++ if( iLookAhead==YYNOCODE ){
++ return YY_NO_ACTION;
++ }
++ i += iLookAhead;
++ if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
++#ifdef YYFALLBACK
++ int iFallback; /* Fallback token */
++ if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
++ && (iFallback = yyFallback[iLookAhead])!=0 ){
++#ifndef NDEBUG
++ if( yyTraceFILE ){
++ fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
++ yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
++ }
++#endif
++ return yy_find_shift_action(pParser, iFallback);
++ }
++#endif
++ return yy_default[stateno];
++ }else{
++ return yy_action[i];
++ }
++}
++
++/*
++** Find the appropriate action for a parser given the non-terminal
++** look-ahead token iLookAhead.
++**
++** If the look-ahead token is YYNOCODE, then check to see if the action is
++** independent of the look-ahead. If it is, return the action, otherwise
++** return YY_NO_ACTION.
++*/
++static int yy_find_reduce_action(
++ yyParser *pParser, /* The parser */
++ int iLookAhead /* The look-ahead token */
++){
++ int i;
++ int stateno = pParser->yystack[pParser->yyidx].stateno;
++
++ i = yy_reduce_ofst[stateno];
++ if( i==YY_REDUCE_USE_DFLT ){
++ return yy_default[stateno];
++ }
++ if( iLookAhead==YYNOCODE ){
++ return YY_NO_ACTION;
++ }
++ i += iLookAhead;
++ if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
++ return yy_default[stateno];
++ }else{
++ return yy_action[i];
++ }
++}
++
++/*
++** Perform a shift action.
++*/
++static void yy_shift(
++ yyParser *yypParser, /* The parser to be shifted */
++ int yyNewState, /* The new state to shift in */
++ int yyMajor, /* The major token to shift in */
++ YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */
++){
++ yyStackEntry *yytos;
++ yypParser->yyidx++;
++ if( yypParser->yyidx>=YYSTACKDEPTH ){
++ http_resp_parserARG_FETCH;
++ yypParser->yyidx--;
++#ifndef NDEBUG
++ if( yyTraceFILE ){
++ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
++ }
++#endif
++ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
++ /* Here code is inserted which will execute if the parser
++ ** stack every overflows */
++ http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument var */
++ return;
++ }
++ yytos = &yypParser->yystack[yypParser->yyidx];
++ yytos->stateno = yyNewState;
++ yytos->major = yyMajor;
++ yytos->minor = *yypMinor;
++#ifndef NDEBUG
++ if( yyTraceFILE && yypParser->yyidx>0 ){
++ int i;
++ fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
++ fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
++ for(i=1; i<=yypParser->yyidx; i++)
++ fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
++ fprintf(yyTraceFILE,"\n");
++ }
++#endif
++}
++
++/* The following table contains information about every rule that
++** is used during the reduce.
++*/
++static struct {
++ YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
++ unsigned char nrhs; /* Number of right-hand side symbols in the rule */
++} yyRuleInfo[] = {
++ { 6, 2 },
++ { 6, 6 },
++ { 5, 1 },
++ { 7, 1 },
++ { 10, 1 },
++ { 10, 2 },
++ { 8, 2 },
++ { 8, 1 },
++ { 9, 4 },
++};
++
++static void yy_accept(yyParser*); /* Forward Declaration */
++
++/*
++** Perform a reduce action and the shift that must immediately
++** follow the reduce.
++*/
++static void yy_reduce(
++ yyParser *yypParser, /* The parser */
++ int yyruleno /* Number of the rule by which to reduce */
++){
++ int yygoto; /* The next state */
++ int yyact; /* The next action */
++ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
++ yyStackEntry *yymsp; /* The top of the parser's stack */
++ int yysize; /* Amount to pop the stack */
++ http_resp_parserARG_FETCH;
++ yymsp = &yypParser->yystack[yypParser->yyidx];
++#ifndef NDEBUG
++ if( yyTraceFILE && yyruleno>=0
++ && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
++ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
++ yyRuleName[yyruleno]);
++ }
++#endif /* NDEBUG */
++
++ switch( yyruleno ){
++ /* Beginning here are the reduction cases. A typical example
++ ** follows:
++ ** case 0:
++ ** #line <lineno> <grammarfile>
++ ** { ... } // User supplied code
++ ** #line <lineno> <thisfile>
++ ** break;
++ */
++ case 0:
++#line 26 "./http_resp_parser.y"
++{
++ http_resp *resp = ctx->resp;
++ data_string *ds;
++
++ resp->protocol = HTTP_VERSION_UNSET;
++
++ buffer_copy_string(resp->reason, ""); /* no reason */
++ array_free(resp->headers);
++ resp->headers = yymsp[-1].minor.yy12;
++
++ if (NULL == (ds = (data_string *)array_get_element(yymsp[-1].minor.yy12, "Status"))) {
++ resp->status = 0;
++ } else {
++ char *err;
++ resp->status = strtol(ds->value->ptr, &err, 10);
++
++ if (*err != '\0') {
++ buffer_copy_string(ctx->errmsg, "expected a number: ");
++ buffer_append_string_buffer(ctx->errmsg, ds->value);
++
++ ctx->ok = 0;
++ }
++
++ }
++
++ yymsp[-1].minor.yy12 = NULL;
++}
++#line 576 "http_resp_parser.c"
++ yy_destructor(1,&yymsp[0].minor);
++ break;
++ case 1:
++#line 54 "./http_resp_parser.y"
++{
++ http_resp *resp = ctx->resp;
++
++ resp->status = yymsp[-4].minor.yy20;
++ resp->protocol = yymsp[-5].minor.yy20;
++ buffer_copy_string_buffer(resp->reason, yymsp[-3].minor.yy0);
++
++ array_free(resp->headers);
++
++ resp->headers = yymsp[-1].minor.yy12;
++
++ yymsp[-1].minor.yy12 = NULL;
++}
++#line 594 "http_resp_parser.c"
++ yy_destructor(1,&yymsp[-2].minor);
++ yy_destructor(1,&yymsp[0].minor);
++ break;
++ case 2:
++#line 68 "./http_resp_parser.y"
++{
++ if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.0"))) {
++ yygotominor.yy20 = HTTP_VERSION_1_0;
++ } else if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.1"))) {
++ yygotominor.yy20 = HTTP_VERSION_1_1;
++ } else {
++ buffer_copy_string(ctx->errmsg, "unknown protocol: ");
++ buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
++
++ ctx->ok = 0;
++ }
++}
++#line 612 "http_resp_parser.c"
++ break;
++ case 3:
++#line 81 "./http_resp_parser.y"
++{
++ char *err;
++ yygotominor.yy20 = strtol(yymsp[0].minor.yy0->ptr, &err, 10);
++
++ if (*err != '\0') {
++ buffer_copy_string(ctx->errmsg, "expected a number: ");
++ buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
++
++ ctx->ok = 0;
++ }
++}
++#line 627 "http_resp_parser.c"
++ break;
++ case 4:
++#line 93 "./http_resp_parser.y"
++{
++ buffer_copy_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
++}
++#line 634 "http_resp_parser.c"
++ break;
++ case 5:
++#line 97 "./http_resp_parser.y"
++{
++ yygotominor.yy0 = yymsp[-1].minor.yy0;
++
++ buffer_append_string(yygotominor.yy0, " ");
++ buffer_append_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
++
++ yymsp[-1].minor.yy0 = NULL;
++}
++#line 646 "http_resp_parser.c"
++ break;
++ case 6:
++#line 106 "./http_resp_parser.y"
++{
++ yygotominor.yy12 = yymsp[-1].minor.yy12;
++
++ array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
++
++ yymsp[-1].minor.yy12 = NULL;
++}
++#line 657 "http_resp_parser.c"
++ break;
++ case 7:
++#line 114 "./http_resp_parser.y"
++{
++ yygotominor.yy12 = array_init();
++
++ array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
++}
++#line 666 "http_resp_parser.c"
++ break;
++ case 8:
++#line 119 "./http_resp_parser.y"
++{
++ yygotominor.yy9 = data_string_init();
++
++ buffer_copy_string_buffer(yygotominor.yy9->key, yymsp[-3].minor.yy0);
++ buffer_copy_string_buffer(yygotominor.yy9->value, yymsp[-1].minor.yy0);
++}
++#line 676 "http_resp_parser.c"
++ yy_destructor(3,&yymsp[-2].minor);
++ yy_destructor(1,&yymsp[0].minor);
++ break;
++ };
++ yygoto = yyRuleInfo[yyruleno].lhs;
++ yysize = yyRuleInfo[yyruleno].nrhs;
++ yypParser->yyidx -= yysize;
++ yyact = yy_find_reduce_action(yypParser,yygoto);
++ if( yyact < YYNSTATE ){
++ yy_shift(yypParser,yyact,yygoto,&yygotominor);
++ }else if( yyact == YYNSTATE + YYNRULE + 1 ){
++ yy_accept(yypParser);
++ }
++}
++
++/*
++** The following code executes when the parse fails
++*/
++static void yy_parse_failed(
++ yyParser *yypParser /* The parser */
++){
++ http_resp_parserARG_FETCH;
++#ifndef NDEBUG
++ if( yyTraceFILE ){
++ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
++ }
++#endif
++ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
++ /* Here code is inserted which will be executed whenever the
++ ** parser fails */
++#line 14 "./http_resp_parser.y"
++
++ ctx->ok = 0;
++
++#line 711 "http_resp_parser.c"
++ http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
++}
++
++/*
++** The following code executes when a syntax error first occurs.
++*/
++static void yy_syntax_error(
++ yyParser *yypParser, /* The parser */
++ int yymajor, /* The major type of the error token */
++ YYMINORTYPE yyminor /* The minor type of the error token */
++){
++ http_resp_parserARG_FETCH;
++#define TOKEN (yyminor.yy0)
++ http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
++}
++
++/*
++** The following is executed when the parser accepts
++*/
++static void yy_accept(
++ yyParser *yypParser /* The parser */
++){
++ http_resp_parserARG_FETCH;
++#ifndef NDEBUG
++ if( yyTraceFILE ){
++ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
++ }
++#endif
++ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
++ /* Here code is inserted which will be executed whenever the
++ ** parser accepts */
++ http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
++}
++
++/* The main parser program.
++** The first argument is a pointer to a structure obtained from
++** "http_resp_parserAlloc" which describes the current state of the parser.
++** The second argument is the major token number. The third is
++** the minor token. The fourth optional argument is whatever the
++** user wants (and specified in the grammar) and is available for
++** use by the action routines.
++**
++** Inputs:
++** <ul>
++** <li> A pointer to the parser (an opaque structure.)
++** <li> The major token number.
++** <li> The minor token number.
++** <li> An option argument of a grammar-specified type.
++** </ul>
++**
++** Outputs:
++** None.
++*/
++void http_resp_parser(
++ void *yyp, /* The parser */
++ int yymajor, /* The major token code number */
++ http_resp_parserTOKENTYPE yyminor /* The value for the token */
++ http_resp_parserARG_PDECL /* Optional %extra_argument parameter */
++){
++ YYMINORTYPE yyminorunion;
++ int yyact; /* The parser action. */
++ int yyendofinput; /* True if we are at the end of input */
++ int yyerrorhit = 0; /* True if yymajor has invoked an error */
++ yyParser *yypParser; /* The parser */
++
++ /* (re)initialize the parser, if necessary */
++ yypParser = (yyParser*)yyp;
++ if( yypParser->yyidx<0 ){
++ if( yymajor==0 ) return;
++ yypParser->yyidx = 0;
++ yypParser->yyerrcnt = -1;
++ yypParser->yystack[0].stateno = 0;
++ yypParser->yystack[0].major = 0;
++ }
++ yyminorunion.yy0 = yyminor;
++ yyendofinput = (yymajor==0);
++ http_resp_parserARG_STORE;
++
++#ifndef NDEBUG
++ if( yyTraceFILE ){
++ fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
++ }
++#endif
++
++ do{
++ yyact = yy_find_shift_action(yypParser,yymajor);
++ if( yyact<YYNSTATE ){
++ yy_shift(yypParser,yyact,yymajor,&yyminorunion);
++ yypParser->yyerrcnt--;
++ if( yyendofinput && yypParser->yyidx>=0 ){
++ yymajor = 0;
++ }else{
++ yymajor = YYNOCODE;
++ }
++ }else if( yyact < YYNSTATE + YYNRULE ){
++ yy_reduce(yypParser,yyact-YYNSTATE);
++ }else if( yyact == YY_ERROR_ACTION ){
++ int yymx;
++#ifndef NDEBUG
++ if( yyTraceFILE ){
++ fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
++ }
++#endif
++#ifdef YYERRORSYMBOL
++ /* A syntax error has occurred.
++ ** The response to an error depends upon whether or not the
++ ** grammar defines an error token "ERROR".
++ **
++ ** This is what we do if the grammar does define ERROR:
++ **
++ ** * Call the %syntax_error function.
++ **
++ ** * Begin popping the stack until we enter a state where
++ ** it is legal to shift the error symbol, then shift
++ ** the error symbol.
++ **
++ ** * Set the error count to three.
++ **
++ ** * Begin accepting and shifting new tokens. No new error
++ ** processing will occur until three tokens have been
++ ** shifted successfully.
++ **
++ */
++ if( yypParser->yyerrcnt<0 ){
++ yy_syntax_error(yypParser,yymajor,yyminorunion);
++ }
++ yymx = yypParser->yystack[yypParser->yyidx].major;
++ if( yymx==YYERRORSYMBOL || yyerrorhit ){
++#ifndef NDEBUG
++ if( yyTraceFILE ){
++ fprintf(yyTraceFILE,"%sDiscard input token %s\n",
++ yyTracePrompt,yyTokenName[yymajor]);
++ }
++#endif
++ yy_destructor(yymajor,&yyminorunion);
++ yymajor = YYNOCODE;
++ }else{
++ while(
++ yypParser->yyidx >= 0 &&
++ yymx != YYERRORSYMBOL &&
++ (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
++ ){
++ yy_pop_parser_stack(yypParser);
++ }
++ if( yypParser->yyidx < 0 || yymajor==0 ){
++ yy_destructor(yymajor,&yyminorunion);
++ yy_parse_failed(yypParser);
++ yymajor = YYNOCODE;
++ }else if( yymx!=YYERRORSYMBOL ){
++ YYMINORTYPE u2;
++ u2.YYERRSYMDT = 0;
++ yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
++ }
++ }
++ yypParser->yyerrcnt = 3;
++ yyerrorhit = 1;
++#else /* YYERRORSYMBOL is not defined */
++ /* This is what we do if the grammar does not define ERROR:
++ **
++ ** * Report an error message, and throw away the input token.
++ **
++ ** * If the input token is $, then fail the parse.
++ **
++ ** As before, subsequent error messages are suppressed until
++ ** three input tokens have been successfully shifted.
++ */
++ if( yypParser->yyerrcnt<=0 ){
++ yy_syntax_error(yypParser,yymajor,yyminorunion);
++ }
++ yypParser->yyerrcnt = 3;
++ yy_destructor(yymajor,&yyminorunion);
++ if( yyendofinput ){
++ yy_parse_failed(yypParser);
++ }
++ yymajor = YYNOCODE;
++#endif
++ }else{
++ yy_accept(yypParser);
++ yymajor = YYNOCODE;
++ }
++ }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
++ return;
++}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/inet_ntop_cache.c lighttpd-1.4.12/src/inet_ntop_cache.c
+--- lighttpd-1.4.11/src/inet_ntop_cache.c 2005-08-11 01:26:38.000000000 +0300
++++ lighttpd-1.4.12/src/inet_ntop_cache.c 2006-07-11 21:23:40.000000000 +0300
+@@ -8,7 +8,7 @@
+ #include "sys-socket.h"
+
+ const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
+-#ifdef HAVE_IPV6
++#ifdef HAVE_IPV6
+ size_t ndx = 0, i;
+ for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
+ if (srv->inet_ntop_cache[i].ts != 0) {
+@@ -20,31 +20,31 @@
+ srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
+ /* IPv4 found in cache */
+ break;
+-
++
+ }
+ }
+ }
+-
++
+ if (i == INET_NTOP_CACHE_MAX) {
+ /* not found in cache */
+-
++
+ i = ndx;
+- inet_ntop(addr->plain.sa_family,
+- addr->plain.sa_family == AF_INET6 ?
++ inet_ntop(addr->plain.sa_family,
++ addr->plain.sa_family == AF_INET6 ?
+ (const void *) &(addr->ipv6.sin6_addr) :
+ (const void *) &(addr->ipv4.sin_addr),
+ srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
+-
++
+ srv->inet_ntop_cache[i].ts = srv->cur_ts;
+ srv->inet_ntop_cache[i].family = addr->plain.sa_family;
+-
++
+ if (srv->inet_ntop_cache[i].family == AF_INET) {
+ srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
+ } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
+ memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
+ }
+ }
+-
++
+ return srv->inet_ntop_cache[i].b2;
+ #else
+ UNUSED(srv);
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/joblist.c lighttpd-1.4.12/src/joblist.c
+--- lighttpd-1.4.11/src/joblist.c 2005-08-11 01:26:41.000000000 +0300
++++ lighttpd-1.4.12/src/joblist.c 2006-07-11 21:23:39.000000000 +0300
+@@ -7,7 +7,7 @@
+
+ int joblist_append(server *srv, connection *con) {
+ if (con->in_joblist) return 0;
+-
++
+ if (srv->joblist->size == 0) {
+ srv->joblist->size = 16;
+ srv->joblist->ptr = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
+@@ -15,15 +15,15 @@
+ srv->joblist->size += 16;
+ srv->joblist->ptr = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
+ }
+-
++
+ srv->joblist->ptr[srv->joblist->used++] = con;
+-
++
+ return 0;
+ }
+
+ void joblist_free(server *srv, connections *joblist) {
+ UNUSED(srv);
+-
++
+ free(joblist->ptr);
+ free(joblist);
+ }
+@@ -31,14 +31,14 @@
+ connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
+ connection *con;
+ UNUSED(srv);
+-
+-
++
++
+ if (fdwaitqueue->used == 0) return NULL;
+-
++
+ con = fdwaitqueue->ptr[0];
+-
++
+ memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
+-
++
+ return con;
+ }
+
+@@ -50,9 +50,9 @@
+ srv->fdwaitqueue->size += 16;
+ srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
+ }
+-
++
+ srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
+-
++
+ return 0;
+ }
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/keyvalue.c lighttpd-1.4.12/src/keyvalue.c
+--- lighttpd-1.4.11/src/keyvalue.c 2006-03-02 16:08:06.000000000 +0200
++++ lighttpd-1.4.12/src/keyvalue.c 2006-07-11 21:23:40.000000000 +0300
+@@ -87,7 +87,8 @@
+ { 504, "Gateway Timeout" },
+ { 505, "HTTP Version Not Supported" },
+ { 507, "Insufficient Storage" }, /* WebDAV */
+-
++ { 509, "Bandwidth Limit exceeded" },
++
+ { -1, NULL }
+ };
+
+@@ -102,12 +103,12 @@
+ { 501, "501.html" },
+ { 503, "503.html" },
+ { 505, "505.html" },
+-
++
+ { -1, NULL }
+ };
+
+
+-const char *keyvalue_get_value(keyvalue *kv, int k) {
++const char *keyvalue_get_value(keyvalue *kv, int k) {
+ int i;
+ for (i = 0; kv[i].value; i++) {
+ if (kv[i].key == k) return kv[i].value;
+@@ -115,7 +116,7 @@
+ return NULL;
+ }
+
+-int keyvalue_get_key(keyvalue *kv, const char *s) {
++int keyvalue_get_key(keyvalue *kv, const char *s) {
+ int i;
+ for (i = 0; kv[i].value; i++) {
+ if (0 == strcmp(kv[i].value, s)) return kv[i].key;
+@@ -125,9 +126,9 @@
+
+ keyvalue_buffer *keyvalue_buffer_init(void) {
+ keyvalue_buffer *kvb;
+-
++
+ kvb = calloc(1, sizeof(*kvb));
+-
++
+ return kvb;
+ }
+
+@@ -135,49 +136,49 @@
+ size_t i;
+ if (kvb->size == 0) {
+ kvb->size = 4;
+-
++
+ kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
+-
++
+ for(i = 0; i < kvb->size; i++) {
+ kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
+ }
+ } else if (kvb->used == kvb->size) {
+ kvb->size += 4;
+-
++
+ kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
+-
++
+ for(i = kvb->used; i < kvb->size; i++) {
+ kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
+ }
+ }
+-
++
+ kvb->kv[kvb->used]->key = key;
+ kvb->kv[kvb->used]->value = strdup(value);
+-
++
+ kvb->used++;
+-
++
+ return 0;
+ }
+
+ void keyvalue_buffer_free(keyvalue_buffer *kvb) {
+ size_t i;
+-
++
+ for (i = 0; i < kvb->size; i++) {
+ if (kvb->kv[i]->value) free(kvb->kv[i]->value);
+ free(kvb->kv[i]);
+ }
+-
++
+ if (kvb->kv) free(kvb->kv);
+-
++
+ free(kvb);
+ }
+
+
+ s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
+ s_keyvalue_buffer *kvb;
+-
++
+ kvb = calloc(1, sizeof(*kvb));
+-
++
+ return kvb;
+ }
+
+@@ -186,50 +187,50 @@
+ if (kvb->size == 0) {
+ kvb->size = 4;
+ kvb->used = 0;
+-
++
+ kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
+-
++
+ for(i = 0; i < kvb->size; i++) {
+ kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
+ }
+ } else if (kvb->used == kvb->size) {
+ kvb->size += 4;
+-
++
+ kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
+-
++
+ for(i = kvb->used; i < kvb->size; i++) {
+ kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
+ }
+ }
+-
++
+ kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
+ kvb->kv[kvb->used]->value = strdup(value);
+-
++
+ kvb->used++;
+-
++
+ return 0;
+ }
+
+ void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
+ size_t i;
+-
++
+ for (i = 0; i < kvb->size; i++) {
+ if (kvb->kv[i]->key) free(kvb->kv[i]->key);
+ if (kvb->kv[i]->value) free(kvb->kv[i]->value);
+ free(kvb->kv[i]);
+ }
+-
++
+ if (kvb->kv) free(kvb->kv);
+-
++
+ free(kvb);
+ }
+
+
+ httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
+ httpauth_keyvalue_buffer *kvb;
+-
++
+ kvb = calloc(1, sizeof(*kvb));
+-
++
+ return kvb;
+ }
+
+@@ -237,42 +238,42 @@
+ size_t i;
+ if (kvb->size == 0) {
+ kvb->size = 4;
+-
++
+ kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
+-
++
+ for(i = 0; i < kvb->size; i++) {
+ kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
+ }
+ } else if (kvb->used == kvb->size) {
+ kvb->size += 4;
+-
++
+ kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
+-
++
+ for(i = kvb->used; i < kvb->size; i++) {
+ kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
+ }
+ }
+-
++
+ kvb->kv[kvb->used]->key = strdup(key);
+ kvb->kv[kvb->used]->realm = strdup(realm);
+ kvb->kv[kvb->used]->type = type;
+-
++
+ kvb->used++;
+-
++
+ return 0;
+ }
+
+ void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
+ size_t i;
+-
++
+ for (i = 0; i < kvb->size; i++) {
+ if (kvb->kv[i]->key) free(kvb->kv[i]->key);
+ if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
+ free(kvb->kv[i]);
+ }
+-
++
+ if (kvb->kv) free(kvb->kv);
+-
++
+ free(kvb);
+ }
+
+@@ -306,9 +307,9 @@
+
+ pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
+ pcre_keyvalue_buffer *kvb;
+-
++
+ kvb = calloc(1, sizeof(*kvb));
+-
++
+ return kvb;
+ }
+
+@@ -319,46 +320,46 @@
+ int erroff;
+ pcre_keyvalue *kv;
+ #endif
+-
++
+ if (!key) return -1;
+
+ #ifdef HAVE_PCRE_H
+ if (kvb->size == 0) {
+ kvb->size = 4;
+ kvb->used = 0;
+-
++
+ kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
+-
++
+ for(i = 0; i < kvb->size; i++) {
+ kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
+ }
+ } else if (kvb->used == kvb->size) {
+ kvb->size += 4;
+-
++
+ kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
+-
++
+ for(i = kvb->used; i < kvb->size; i++) {
+ kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
+ }
+ }
+-
++
+ kv = kvb->kv[kvb->used];
+ if (NULL == (kv->key = pcre_compile(key,
+ 0, &errptr, &erroff, NULL))) {
+-
++
+ fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
+ return -1;
+ }
+
+- if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
++ if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
+ errptr != NULL) {
+ return -1;
+ }
+-
++
+ kv->value = buffer_init_string(value);
+-
++
+ kvb->used++;
+-
++
+ return 0;
+ #else
+ UNUSED(kvb);
+@@ -380,9 +381,9 @@
+ if (kv->value) buffer_free(kv->value);
+ free(kv);
+ }
+-
++
+ if (kvb->kv) free(kvb->kv);
+ #endif
+-
++
+ free(kvb);
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/keyvalue.h lighttpd-1.4.12/src/keyvalue.h
+--- lighttpd-1.4.11/src/keyvalue.h 2006-03-02 16:08:06.000000000 +0200
++++ lighttpd-1.4.12/src/keyvalue.h 2006-07-11 21:23:40.000000000 +0300
+@@ -9,19 +9,19 @@
+ # include <pcre.h>
+ #endif
+
+-typedef enum {
+- HTTP_METHOD_UNSET = -1,
+- HTTP_METHOD_GET,
+- HTTP_METHOD_POST,
+- HTTP_METHOD_HEAD,
+- HTTP_METHOD_OPTIONS,
++typedef enum {
++ HTTP_METHOD_UNSET = -1,
++ HTTP_METHOD_GET,
++ HTTP_METHOD_POST,
++ HTTP_METHOD_HEAD,
++ HTTP_METHOD_OPTIONS,
+ HTTP_METHOD_PROPFIND, /* WebDAV */
+- HTTP_METHOD_MKCOL,
+- HTTP_METHOD_PUT,
+- HTTP_METHOD_DELETE,
+- HTTP_METHOD_COPY,
+- HTTP_METHOD_MOVE,
+- HTTP_METHOD_PROPPATCH,
++ HTTP_METHOD_MKCOL,
++ HTTP_METHOD_PUT,
++ HTTP_METHOD_DELETE,
++ HTTP_METHOD_COPY,
++ HTTP_METHOD_MOVE,
++ HTTP_METHOD_PROPPATCH,
+ HTTP_METHOD_REPORT, /* DeltaV */
+ HTTP_METHOD_CHECKOUT,
+ HTTP_METHOD_CHECKIN,
+@@ -39,13 +39,13 @@
+
+ typedef struct {
+ int key;
+-
++
+ char *value;
+ } keyvalue;
+
+ typedef struct {
+ char *key;
+-
++
+ char *value;
+ } s_keyvalue;
+
+@@ -54,7 +54,7 @@
+ pcre *key;
+ pcre_extra *key_extra;
+ #endif
+-
++
+ buffer *value;
+ } pcre_keyvalue;
+
+@@ -62,7 +62,7 @@
+
+ typedef struct {
+ char *key;
+-
++
+ char *realm;
+ httpauth_type type;
+ } httpauth_keyvalue;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/lemon.c lighttpd-1.4.12/src/lemon.c
+--- lighttpd-1.4.11/src/lemon.c 2005-09-01 00:21:34.000000000 +0300
++++ lighttpd-1.4.12/src/lemon.c 2006-07-11 21:23:40.000000000 +0300
+@@ -579,7 +579,7 @@
+ */
+
+ /* Find a precedence symbol of every rule in the grammar.
+-**
++**
+ ** Those rules which have a precedence symbol coded in the input
+ ** grammar using the "[symbol]" construct will already have the
+ ** rp->precsym field filled. Other rules take as their precedence
+@@ -869,7 +869,7 @@
+ cfp->status = INCOMPLETE;
+ }
+ }
+-
++
+ do{
+ progress = 0;
+ for(i=0; i<lemp->nstate; i++){
+@@ -900,7 +900,7 @@
+ struct symbol *sp;
+ struct rule *rp;
+
+- /* Add all of the reduce actions
++ /* Add all of the reduce actions
+ ** A reduce action is added for each element of the followset of
+ ** a configuration which has its dot at the extreme right.
+ */
+@@ -1017,7 +1017,7 @@
+ apx->type = RD_RESOLVED;
+ }
+ }else{
+- assert(
++ assert(
+ apx->type==SH_RESOLVED ||
+ apx->type==RD_RESOLVED ||
+ apx->type==CONFLICT ||
+@@ -1350,7 +1350,7 @@
+ OptInit(argv,options,stderr);
+ if( version ){
+ printf("Lemon version 1.0\n");
+- exit(0);
++ exit(0);
+ }
+ if( OptNArgs() < 1 ){
+ fprintf(stderr,"Exactly one filename argument is required.\n");
+@@ -2031,7 +2031,7 @@
+ case IN_RHS:
+ if( x[0]=='.' ){
+ struct rule *rp;
+- rp = (struct rule *)malloc( sizeof(struct rule) +
++ rp = (struct rule *)malloc( sizeof(struct rule) +
+ sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
+ if( rp==0 ){
+ ErrorMsg(psp->filename,psp->tokenlineno,
+@@ -2546,7 +2546,7 @@
+ return fp;
+ }
+
+-/* Duplicate the input file without comments and without actions
++/* Duplicate the input file without comments and without actions
+ ** on rules */
+ void Reprint(lemp)
+ struct lemon *lemp;
+@@ -2822,7 +2822,7 @@
+ PRIVATE FILE *tplt_open(lemp)
+ struct lemon *lemp;
+ {
+-
++
+ char buf[1000];
+ FILE *in;
+ char *tpltname;
+@@ -2930,7 +2930,7 @@
+ return ret;
+ }
+
+-/*
++/*
+ ** Generate code which executes when the rule "rp" is reduced. Write
+ ** the code to "out". Make sure lineno stays up-to-date.
+ */
+@@ -3384,7 +3384,7 @@
+
+ /* Output the yy_shift_ofst[] table */
+ fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
+- fprintf(out, "static %s yy_shift_ofst[] = {\n",
++ fprintf(out, "static %s yy_shift_ofst[] = {\n",
+ minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
+ n = lemp->nstate;
+ for(i=j=0; i<n; i++){
+@@ -3405,7 +3405,7 @@
+
+ /* Output the yy_reduce_ofst[] table */
+ fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
+- fprintf(out, "static %s yy_reduce_ofst[] = {\n",
++ fprintf(out, "static %s yy_reduce_ofst[] = {\n",
+ minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
+ n = lemp->nstate;
+ for(i=j=0; i<n; i++){
+@@ -3480,7 +3480,7 @@
+ tplt_xfer(lemp->name,in,out,&lineno);
+
+ /* Generate code which executes every time a symbol is popped from
+- ** the stack while processing errors or while destroying the parser.
++ ** the stack while processing errors or while destroying the parser.
+ ** (In other words, generate the %destructor actions)
+ */
+ if( lemp->tokendest ){
+@@ -3522,7 +3522,7 @@
+ tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
+ tplt_xfer(lemp->name,in,out,&lineno);
+
+- /* Generate the table of rule information
++ /* Generate the table of rule information
+ **
+ ** Note: This code depends on the fact that rules are number
+ ** sequentually beginning with 0.
+@@ -3589,7 +3589,7 @@
+ for(i=1; i<lemp->nterminal; i++){
+ fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
+ }
+- fclose(out);
++ fclose(out);
+ }
+ return;
+ }
+@@ -3630,7 +3630,7 @@
+ rbest = rp;
+ }
+ }
+-
++
+ /* Do not make a default if the number of rules to default
+ ** is not at least 2 */
+ if( nbest<2 ) continue;
+@@ -3781,7 +3781,7 @@
+ if( x1a ){
+ x1a->size = 1024;
+ x1a->count = 0;
+- x1a->tbl = (x1node*)malloc(
++ x1a->tbl = (x1node*)malloc(
+ (sizeof(x1node) + sizeof(x1node*))*1024 );
+ if( x1a->tbl==0 ){
+ free(x1a);
+@@ -3943,7 +3943,7 @@
+ if( x2a ){
+ x2a->size = 128;
+ x2a->count = 0;
+- x2a->tbl = (x2node*)malloc(
++ x2a->tbl = (x2node*)malloc(
+ (sizeof(x2node) + sizeof(x2node*))*128 );
+ if( x2a->tbl==0 ){
+ free(x2a);
+@@ -4149,7 +4149,7 @@
+ if( x3a ){
+ x3a->size = 128;
+ x3a->count = 0;
+- x3a->tbl = (x3node*)malloc(
++ x3a->tbl = (x3node*)malloc(
+ (sizeof(x3node) + sizeof(x3node*))*128 );
+ if( x3a->tbl==0 ){
+ free(x3a);
+@@ -4295,7 +4295,7 @@
+ if( x4a ){
+ x4a->size = 64;
+ x4a->count = 0;
+- x4a->tbl = (x4node*)malloc(
++ x4a->tbl = (x4node*)malloc(
+ (sizeof(x4node) + sizeof(x4node*))*64 );
+ if( x4a->tbl==0 ){
+ free(x4a);
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/lempar.c lighttpd-1.4.12/src/lempar.c
+--- lighttpd-1.4.11/src/lempar.c 2005-08-11 01:26:40.000000000 +0300
++++ lighttpd-1.4.12/src/lempar.c 2006-07-11 21:23:39.000000000 +0300
+@@ -8,10 +8,10 @@
+ /* Next is all token values, in a form suitable for use by makeheaders.
+ ** This section will be null unless lemon is run with the -m switch.
+ */
+-/*
++/*
+ ** These constants (all generated automatically by the parser generator)
+ ** specify the various kinds of tokens (terminals) that the parser
+-** understands.
++** understands.
+ **
+ ** Each symbol here is a terminal symbol in the grammar.
+ */
+@@ -29,7 +29,7 @@
+ ** and nonterminals. "int" is used otherwise.
+ ** YYNOCODE is a number of type YYCODETYPE which corresponds
+ ** to no legal terminal or nonterminal number. This
+-** number is used to fill in empty slots of the hash
++** number is used to fill in empty slots of the hash
+ ** table.
+ ** YYFALLBACK If defined, this indicates that one or more tokens
+ ** have fall-back values which should be used if the
+@@ -38,7 +38,7 @@
+ ** and nonterminal numbers. "unsigned char" is
+ ** used if there are fewer than 250 rules and
+ ** states combined. "int" is used otherwise.
+-** ParseTOKENTYPE is the data type used for minor tokens given
++** ParseTOKENTYPE is the data type used for minor tokens given
+ ** directly to the parser from the tokenizer.
+ ** YYMINORTYPE is the data type used for all minor tokens.
+ ** This is typically a union of many types, one of
+@@ -62,7 +62,7 @@
+ /* Next are that tables used to determine what action to take based on the
+ ** current state and lookahead token. These tables are used to implement
+ ** functions that take a state number and lookahead value and return an
+-** action integer.
++** action integer.
+ **
+ ** Suppose the action integer is N. Then the action is determined as
+ ** follows
+@@ -87,7 +87,7 @@
+ ** If the index value yy_shift_ofst[S]+X is out of range or if the value
+ ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
+ ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
+-** and that yy_default[S] should be used instead.
++** and that yy_default[S] should be used instead.
+ **
+ ** The formula above is for computing the action when the lookahead is
+ ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
+@@ -111,7 +111,7 @@
+
+ /* The next table maps tokens into fallback tokens. If a construct
+ ** like the following:
+-**
++**
+ ** %fallback ID X Y Z.
+ **
+ ** appears in the grammer, then ID becomes a fallback token for X, Y,
+@@ -163,10 +163,10 @@
+ #endif /* NDEBUG */
+
+ #ifndef NDEBUG
+-/*
++/*
+ ** Turn parser tracing on by giving a stream to which to write the trace
+ ** and a prompt to preface each trace message. Tracing is turned off
+-** by making either argument NULL
++** by making either argument NULL
+ **
+ ** Inputs:
+ ** <ul>
+@@ -191,7 +191,7 @@
+ #ifndef NDEBUG
+ /* For tracing shifts, the names of all terminals and nonterminals
+ ** are required. The following table supplies these names */
+-static const char *yyTokenName[] = {
++static const char *yyTokenName[] = {
+ %%
+ };
+ #endif /* NDEBUG */
+@@ -220,7 +220,7 @@
+ #endif
+ }
+
+-/*
++/*
+ ** This function allocates a new parser.
+ ** The only argument is a pointer to a function which works like
+ ** malloc.
+@@ -251,7 +251,7 @@
+ /* Here is inserted the actions which take place when a
+ ** terminal or non-terminal is destroyed. This can happen
+ ** when the symbol is popped from the stack during a
+- ** reduce or during error processing or when a parser is
++ ** reduce or during error processing or when a parser is
+ ** being destroyed before it is finished parsing.
+ **
+ ** Note: during a reduce, the only symbols destroyed are those
+@@ -289,7 +289,7 @@
+ return yymajor;
+ }
+
+-/*
++/*
+ ** Deallocate and destroy a parser. Destructors are all called for
+ ** all stack elements before shutting the parser down.
+ **
+@@ -325,7 +325,7 @@
+ ){
+ int i;
+ int stateno = pParser->yystack[pParser->yyidx].stateno;
+-
++
+ /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
+ i = yy_shift_ofst[stateno];
+ if( i==YY_SHIFT_USE_DFLT ){
+@@ -369,7 +369,7 @@
+ ){
+ int i;
+ int stateno = pParser->yystack[pParser->yyidx].stateno;
+-
++
+ i = yy_reduce_ofst[stateno];
+ if( i==YY_REDUCE_USE_DFLT ){
+ return yy_default[stateno];
+@@ -455,7 +455,7 @@
+ ParseARG_FETCH;
+ yymsp = &yypParser->yystack[yypParser->yyidx];
+ #ifndef NDEBUG
+- if( yyTraceFILE && yyruleno>=0
++ if( yyTraceFILE && yyruleno>=0
+ && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
+ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
+ yyRuleName[yyruleno]);
+@@ -608,7 +608,7 @@
+ #ifdef YYERRORSYMBOL
+ /* A syntax error has occurred.
+ ** The response to an error depends upon whether or not the
+- ** grammar defines an error token "ERROR".
++ ** grammar defines an error token "ERROR".
+ **
+ ** This is what we do if the grammar does define ERROR:
+ **
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/log.c lighttpd-1.4.12/src/log.c
+--- lighttpd-1.4.11/src/log.c 2005-11-07 15:01:35.000000000 +0200
++++ lighttpd-1.4.12/src/log.c 2006-07-11 21:23:40.000000000 +0300
+@@ -5,7 +5,6 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <time.h>
+-#include <unistd.h>
+ #include <string.h>
+ #include <stdlib.h>
+
+@@ -16,6 +15,10 @@
+ #include "config.h"
+ #endif
+
++#ifdef _WIN32
++#undef HAVE_SYSLOG_H
++#endif
++
+ #ifdef HAVE_SYSLOG_H
+ #include <syslog.h>
+ #endif
+@@ -23,6 +26,8 @@
+ #include "log.h"
+ #include "array.h"
+
++#include "sys-files.h"
++
+ #ifdef HAVE_VALGRIND_VALGRIND_H
+ #include <valgrind/valgrind.h>
+ #endif
+@@ -31,38 +36,38 @@
+ # define O_LARGEFILE 0
+ #endif
+
+-/**
++/**
+ * open the errorlog
+- *
++ *
+ * we have 3 possibilities:
+ * - stderr (default)
+- * - syslog
++ * - syslog
+ * - logfile
+- *
++ *
+ * if the open failed, report to the user and die
+- *
++ *
+ */
+
+ int log_error_open(server *srv) {
+ int fd;
+ int close_stderr = 1;
+-
++
+ #ifdef HAVE_SYSLOG_H
+ /* perhaps someone wants to use syslog() */
+ openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
+ #endif
+ srv->errorlog_mode = ERRORLOG_STDERR;
+-
++
+ if (srv->srvconf.errorlog_use_syslog) {
+ srv->errorlog_mode = ERRORLOG_SYSLOG;
+ } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
+ const char *logfile = srv->srvconf.errorlog_file->ptr;
+-
++
+ if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
+- log_error_write(srv, __FILE__, __LINE__, "SSSS",
++ log_error_write(srv, __FILE__, __LINE__, "SSSS",
+ "opening errorlog '", logfile,
+ "' failed: ", strerror(errno));
+-
++
+ return -1;
+ }
+ #ifdef FD_CLOEXEC
+@@ -71,15 +76,15 @@
+ #endif
+ srv->errorlog_mode = ERRORLOG_FILE;
+ }
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "s", "server started");
+-
++
+ #ifdef HAVE_VALGRIND_VALGRIND_H
+ /* don't close stderr for debugging purposes if run in valgrind */
+ if (RUNNING_ON_VALGRIND) close_stderr = 0;
+ #endif
+ if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
+-
++
+ /* move stderr to /dev/null */
+ if (close_stderr &&
+ -1 != (fd = open("/dev/null", O_WRONLY))) {
+@@ -90,33 +95,33 @@
+ return 0;
+ }
+
+-/**
++/**
+ * open the errorlog
+- *
++ *
+ * if the open failed, report to the user and die
+ * if no filename is given, use syslog instead
+- *
++ *
+ */
+
+ int log_error_cycle(server *srv) {
+ /* only cycle if we are not in syslog-mode */
+-
++
+ if (srv->errorlog_mode == ERRORLOG_FILE) {
+ const char *logfile = srv->srvconf.errorlog_file->ptr;
+ /* already check of opening time */
+-
++
+ int new_fd;
+-
++
+ if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
+ /* write to old log */
+- log_error_write(srv, __FILE__, __LINE__, "SSSSS",
++ log_error_write(srv, __FILE__, __LINE__, "SSSSS",
+ "cycling errorlog '", logfile,
+ "' failed: ", strerror(errno),
+ ", falling back to syslog()");
+-
++
+ close(srv->errorlog_fd);
+ srv->errorlog_fd = -1;
+-#ifdef HAVE_SYSLOG_H
++#ifdef HAVE_SYSLOG_H
+ srv->errorlog_mode = ERRORLOG_SYSLOG;
+ #endif
+ } else {
+@@ -125,15 +130,15 @@
+ srv->errorlog_fd = new_fd;
+ }
+ }
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
+-
++
+ return 0;
+ }
+
+ int log_error_close(server *srv) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
+-
++
+ switch(srv->errorlog_mode) {
+ case ERRORLOG_FILE:
+ close(srv->errorlog_fd);
+@@ -146,13 +151,13 @@
+ case ERRORLOG_STDERR:
+ break;
+ }
+-
++
+ return 0;
+ }
+
+ int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
+ va_list ap;
+-
++
+ switch(srv->errorlog_mode) {
+ case ERRORLOG_FILE:
+ case ERRORLOG_STDERR:
+@@ -161,7 +166,7 @@
+ buffer_prepare_copy(srv->ts_debug_str, 255);
+ strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
+ srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
+-
++
+ srv->last_generated_debug_ts = srv->cur_ts;
+ }
+
+@@ -173,19 +178,19 @@
+ BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
+ break;
+ }
+-
++
+ buffer_append_string(srv->errorlog_buf, filename);
+ BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ".");
+ buffer_append_long(srv->errorlog_buf, line);
+ BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") ");
+-
+-
++
++
+ for(va_start(ap, fmt); *fmt; fmt++) {
+ int d;
+ char *s;
+ buffer *b;
+ off_t o;
+-
++
+ switch(*fmt) {
+ case 's': /* string */
+ s = va_arg(ap, char *);
+@@ -227,7 +232,7 @@
+ break;
+ case '(':
+ case ')':
+- case '<':
++ case '<':
+ case '>':
+ case ',':
+ case ' ':
+@@ -236,7 +241,7 @@
+ }
+ }
+ va_end(ap);
+-
++
+ switch(srv->errorlog_mode) {
+ case ERRORLOG_FILE:
+ BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
+@@ -246,11 +251,13 @@
+ BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
+ write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
+ break;
++#ifdef HAVE_SYSLOG_H
+ case ERRORLOG_SYSLOG:
+ syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
+ break;
++#endif
+ }
+-
++
+ return 0;
+ }
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/log.h lighttpd-1.4.12/src/log.h
+--- lighttpd-1.4.11/src/log.h 2005-08-11 01:26:36.000000000 +0300
++++ lighttpd-1.4.12/src/log.h 2006-07-11 21:23:40.000000000 +0300
+@@ -9,5 +9,5 @@
+ int log_error_close(server *srv);
+ int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
+ int log_error_cycle(server *srv);
+-
++
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/md5.h lighttpd-1.4.12/src/md5.h
+--- lighttpd-1.4.11/src/md5.h 2005-11-17 16:20:40.000000000 +0200
++++ lighttpd-1.4.12/src/md5.h 2006-07-11 21:23:40.000000000 +0300
+@@ -30,9 +30,15 @@
+ # include <inttypes.h>
+ #endif
+
++#ifdef _WIN32
++#define UINT4 unsigned __int32
++#define UINT2 unsigned __int16
++#define POINTER unsigned char *
++#else
+ #define UINT4 uint32_t
+ #define UINT2 uint16_t
+ #define POINTER unsigned char *
++#endif
+
+ /* MD5 context. */
+ typedef struct {
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_access.c lighttpd-1.4.12/src/mod_access.c
+--- lighttpd-1.4.11/src/mod_access.c 2006-01-14 19:44:54.000000000 +0200
++++ lighttpd-1.4.12/src/mod_access.c 2006-07-11 21:23:40.000000000 +0300
+@@ -8,126 +8,125 @@
+
+ #include "plugin.h"
+
++#include "sys-strings.h"
++
+ typedef struct {
+ array *access_deny;
+ } plugin_config;
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ INIT_FUNC(mod_access_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ return p;
+ }
+
+ FREE_FUNC(mod_access_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ array_free(s->access_deny);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ SETDEFAULTS_FUNC(mod_access_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "url.access-deny", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->access_deny = array_init();
+-
++
+ cv[0].destination = s->access_deny;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+
+- PATCH(access_deny);
+-
++ PATCH_OPTION(access_deny);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
+- PATCH(access_deny);
++ PATCH_OPTION(access_deny);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_access_uri_handler) {
+ plugin_data *p = p_d;
+ int s_len;
+ size_t k;
+-
++
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_access_patch_connection(srv, con, p);
+-
++
+ s_len = con->uri.path->used - 1;
+-
++
+ for (k = 0; k < p->conf.access_deny->used; k++) {
+ data_string *ds = (data_string *)p->conf.access_deny->data[k];
+ int ct_len = ds->value->used - 1;
+-
++
+ if (ct_len > s_len) continue;
+-
++
+ if (ds->value->used == 0) continue;
+
+ /* if we have a case-insensitive FS we have to lower-case the URI here too */
+@@ -135,18 +134,18 @@
+ if (con->conf.force_lowercase_filenames) {
+ if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
+ con->http_status = 403;
+-
++
+ return HANDLER_FINISHED;
+ }
+ } else {
+ if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
+ con->http_status = 403;
+-
++
+ return HANDLER_FINISHED;
+ }
+ }
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+@@ -155,13 +154,13 @@
+ int mod_access_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("access");
+-
++
+ p->init = mod_access_init;
+ p->set_defaults = mod_access_set_defaults;
+ p->handle_uri_clean = mod_access_uri_handler;
+ p->cleanup = mod_access_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_accesslog.c lighttpd-1.4.12/src/mod_accesslog.c
+--- lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200
++++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-11 21:23:40.000000000 +0300
+@@ -6,8 +6,7 @@
+ #include <ctype.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <fcntl.h>
+-#include <unistd.h>
++#include <fcntl.h> /* only the defines on windows */
+ #include <errno.h>
+ #include <time.h>
+
+@@ -22,6 +21,7 @@
+ #include "inet_ntop_cache.h"
+
+ #include "sys-socket.h"
++#include "sys-files.h"
+
+ #ifdef HAVE_SYSLOG_H
+ # include <syslog.h>
+@@ -29,7 +29,7 @@
+
+ typedef struct {
+ char key;
+- enum {
++ enum {
+ FORMAT_UNSET,
+ FORMAT_UNSUPPORTED,
+ FORMAT_PERCENT,
+@@ -41,7 +41,7 @@
+ FORMAT_STATUS,
+ FORMAT_BYTES_OUT_NO_HEADER,
+ FORMAT_HEADER,
+-
++
+ FORMAT_REMOTE_ADDR,
+ FORMAT_LOCAL_ADDR,
+ FORMAT_COOKIE,
+@@ -59,20 +59,20 @@
+ FORMAT_CONNECTION_STATUS,
+ FORMAT_BYTES_IN,
+ FORMAT_BYTES_OUT,
+-
++
+ FORMAT_RESPONSE_HEADER
+ } type;
+ } format_mapping;
+
+ /**
+- *
+- *
++ *
++ *
+ * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
+- *
++ *
+ */
+
+-const format_mapping fmap[] =
+-{
++const format_mapping fmap[] =
++{
+ { '%', FORMAT_PERCENT },
+ { 'h', FORMAT_REMOTE_HOST },
+ { 'l', FORMAT_REMOTE_IDENT },
+@@ -82,7 +82,7 @@
+ { 's', FORMAT_STATUS },
+ { 'b', FORMAT_BYTES_OUT_NO_HEADER },
+ { 'i', FORMAT_HEADER },
+-
++
+ { 'a', FORMAT_REMOTE_ADDR },
+ { 'A', FORMAT_LOCAL_ADDR },
+ { 'B', FORMAT_BYTES_OUT_NO_HEADER },
+@@ -103,23 +103,23 @@
+ { 'X', FORMAT_CONNECTION_STATUS },
+ { 'I', FORMAT_BYTES_IN },
+ { 'O', FORMAT_BYTES_OUT },
+-
++
+ { 'o', FORMAT_RESPONSE_HEADER },
+-
++
+ { '\0', FORMAT_UNSET }
+ };
+
+
+ typedef struct {
+ enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
+-
++
+ buffer *string;
+ int field;
+ } format_field;
+
+ typedef struct {
+ format_field **ptr;
+-
++
+ size_t used;
+ size_t size;
+ } format_fields;
+@@ -128,39 +128,39 @@
+ buffer *access_logfile;
+ buffer *format;
+ unsigned short use_syslog;
+-
+-
++
++
+ int log_access_fd;
+ time_t last_generated_accesslog_ts;
+ time_t *last_generated_accesslog_ts_ptr;
+-
+-
++
++
+ buffer *access_logbuffer;
+ buffer *ts_accesslog_str;
+-
++
+ format_fields *parsed_format;
+ } plugin_config;
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ plugin_config **config_storage;
+- plugin_config conf;
++ plugin_config conf;
+ } plugin_data;
+
+ INIT_FUNC(mod_accesslog_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ return p;
+ }
+
+ int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
+ size_t i, j, k = 0, start = 0;
+-
++
+ for (i = 0; i < format->used - 1; i++) {
+-
++
+ switch(format->ptr[i]) {
+ case '%':
+ if (start != i) {
+@@ -173,19 +173,19 @@
+ fields->size += 16;
+ fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
+ }
+-
++
+ fields->ptr[fields->used] = malloc(sizeof(format_fields));
+ fields->ptr[fields->used]->type = FIELD_STRING;
+ fields->ptr[fields->used]->string = buffer_init();
+-
++
+ buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
+-
++
+ fields->used++;
+ }
+-
+-
++
++
+ /* we need a new field */
+-
++
+ if (fields->size == 0) {
+ fields->size = 16;
+ fields->used = 0;
+@@ -194,43 +194,43 @@
+ fields->size += 16;
+ fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
+ }
+-
++
+ /* search for the terminating command */
+ switch (format->ptr[i+1]) {
+ case '>':
+ case '<':
+ /* only for s */
+-
++
+ for (j = 0; fmap[j].key != '\0'; j++) {
+ if (fmap[j].key != format->ptr[i+2]) continue;
+-
++
+ /* found key */
+-
++
+ fields->ptr[fields->used] = malloc(sizeof(format_fields));
+ fields->ptr[fields->used]->type = FIELD_FORMAT;
+ fields->ptr[fields->used]->field = fmap[j].type;
+ fields->ptr[fields->used]->string = NULL;
+-
++
+ fields->used++;
+-
++
+ break;
+ }
+-
++
+ if (fmap[j].key == '\0') {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
+ return -1;
+ }
+-
++
+ start = i + 3;
+-
++
+ break;
+ case '{':
+ /* go forward to } */
+-
++
+ for (k = i+2; k < format->used - 1; k++) {
+ if (format->ptr[k] == '}') break;
+ }
+-
++
+ if (k == format->used - 1) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
+ return -1;
+@@ -239,62 +239,62 @@
+ log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
+ return -1;
+ }
+-
++
+ for (j = 0; fmap[j].key != '\0'; j++) {
+ if (fmap[j].key != format->ptr[k+1]) continue;
+-
++
+ /* found key */
+-
++
+ fields->ptr[fields->used] = malloc(sizeof(format_fields));
+ fields->ptr[fields->used]->type = FIELD_FORMAT;
+ fields->ptr[fields->used]->field = fmap[j].type;
+ fields->ptr[fields->used]->string = buffer_init();
+-
++
+ buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
+-
++
+ fields->used++;
+-
++
+ break;
+ }
+-
++
+ if (fmap[j].key == '\0') {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
+ return -1;
+ }
+-
++
+ start = k + 2;
+-
++
+ break;
+ default:
+ for (j = 0; fmap[j].key != '\0'; j++) {
+ if (fmap[j].key != format->ptr[i+1]) continue;
+-
++
+ /* found key */
+-
++
+ fields->ptr[fields->used] = malloc(sizeof(format_fields));
+ fields->ptr[fields->used]->type = FIELD_FORMAT;
+ fields->ptr[fields->used]->field = fmap[j].type;
+ fields->ptr[fields->used]->string = NULL;
+-
++
+ fields->used++;
+-
++
+ break;
+ }
+-
++
+ if (fmap[j].key == '\0') {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
+ return -1;
+ }
+-
++
+ start = i + 2;
+-
++
+ break;
+ }
+-
++
+ break;
+ }
+ }
+-
++
+ if (start < i) {
+ /* copy the string */
+ if (fields->size == 0) {
+@@ -305,32 +305,32 @@
+ fields->size += 16;
+ fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
+ }
+-
++
+ fields->ptr[fields->used] = malloc(sizeof(format_fields));
+ fields->ptr[fields->used]->type = FIELD_STRING;
+ fields->ptr[fields->used]->string = buffer_init();
+-
++
+ buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
+-
++
+ fields->used++;
+ }
+-
++
+ return 0;
+ }
+
+ FREE_FUNC(mod_accesslog_free) {
+ plugin_data *p = p_d;
+ size_t i;
+-
++
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+-
++
+ if (s->access_logbuffer->used) {
+ if (s->use_syslog) {
+ # ifdef HAVE_SYSLOG_H
+@@ -342,14 +342,14 @@
+ write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
+ }
+ }
+-
++
+ if (s->log_access_fd != -1) close(s->log_access_fd);
+-
++
+ buffer_free(s->ts_accesslog_str);
+ buffer_free(s->access_logbuffer);
+ buffer_free(s->format);
+ buffer_free(s->access_logfile);
+-
++
+ if (s->parsed_format) {
+ size_t j;
+ for (j = 0; j < s->parsed_format->used; j++) {
+@@ -359,36 +359,36 @@
+ free(s->parsed_format->ptr);
+ free(s->parsed_format);
+ }
+-
++
+ free(s);
+ }
+-
++
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ SETDEFAULTS_FUNC(log_access_open) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "accesslog.filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { "accesslog.use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
+ { "accesslog.format", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->access_logfile = buffer_init();
+ s->format = buffer_init();
+@@ -397,44 +397,44 @@
+ s->log_access_fd = -1;
+ s->last_generated_accesslog_ts = 0;
+ s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
+-
+-
++
++
+ cv[0].destination = s->access_logfile;
+ cv[1].destination = &(s->use_syslog);
+ cv[2].destination = s->format;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (i == 0 && buffer_is_empty(s->format)) {
+ /* set a default logfile string */
+-
++
+ buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
+ }
+-
++
+ /* parse */
+-
++
+ if (s->format->used) {
+ s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
+-
++
+ if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
+
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "parsing accesslog-definition failed:", s->format);
+
+ return HANDLER_ERROR;
+ }
+ #if 0
+- /* debugging */
++ /* debugging */
+ for (j = 0; j < s->parsed_format->used; j++) {
+ switch (s->parsed_format->ptr[j]->type) {
+ case FIELD_FORMAT:
+- log_error_write(srv, __FILE__, __LINE__, "ssds",
++ log_error_write(srv, __FILE__, __LINE__, "ssds",
+ "config:", "format", s->parsed_format->ptr[j]->field,
+- s->parsed_format->ptr[j]->string ?
++ s->parsed_format->ptr[j]->string ?
+ s->parsed_format->ptr[j]->string->ptr : "" );
+ break;
+ case FIELD_STRING:
+@@ -446,52 +446,52 @@
+ }
+ #endif
+ }
+-
++
+ if (s->use_syslog) {
+ /* ignore the next checks */
+ continue;
+ }
+-
++
+ if (buffer_is_empty(s->access_logfile)) continue;
+-
++
+ if (s->access_logfile->ptr[0] == '|') {
+ #ifdef HAVE_FORK
+ /* create write pipe and spawn process */
+-
++
+ int to_log_fds[2];
+ pid_t pid;
+-
++
+ if (pipe(to_log_fds)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
+ return HANDLER_ERROR;
+ }
+-
++
+ /* fork, execve */
+ switch (pid = fork()) {
+- case 0:
++ case 0:
+ /* child */
+-
++
+ close(STDIN_FILENO);
+ dup2(to_log_fds[0], STDIN_FILENO);
+ close(to_log_fds[0]);
+ /* not needed */
+ close(to_log_fds[1]);
+-
++
+ /* we don't need the client socket */
+ for (i = 3; i < 256; i++) {
+ close(i);
+ }
+-
+- /* exec the log-process (skip the | )
+- *
++
++ /* exec the log-process (skip the | )
++ *
+ */
+-
++
+ execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
+
+- log_error_write(srv, __FILE__, __LINE__, "sss",
+- "spawning log-process failed: ", strerror(errno),
++ log_error_write(srv, __FILE__, __LINE__, "sss",
++ "spawning log-process failed: ", strerror(errno),
+ s->access_logfile->ptr + 1);
+-
++
+ exit(-1);
+ break;
+ case -1:
+@@ -500,27 +500,28 @@
+ break;
+ default:
+ close(to_log_fds[0]);
+-
++
+ s->log_access_fd = to_log_fds[1];
+-
++
+ break;
+ }
+ #else
+ return -1;
+ #endif
+- } else if (-1 == (s->log_access_fd =
++ } else if (-1 == (s->log_access_fd =
+ open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssb",
+- "opening access-log failed:",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssb",
++ "opening access-log failed:",
+ strerror(errno), s->access_logfile);
+-
++
+ return HANDLER_ERROR;
+ }
++#ifndef _WIN32
+ fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
+-
++#endif
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -529,7 +530,7 @@
+ size_t i;
+
+ if (!p->config_storage) return HANDLER_GO_ON;
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+@@ -544,90 +545,87 @@
+ } else if (s->log_access_fd != -1) {
+ write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
+ }
+-
++
+ buffer_reset(s->access_logbuffer);
+ }
+-
++
+ if (s->use_syslog == 0 &&
+ !buffer_is_empty(s->access_logfile) &&
+ s->access_logfile->ptr[0] != '|') {
+-
++
+ close(s->log_access_fd);
+-
+- if (-1 == (s->log_access_fd =
++
++ if (-1 == (s->log_access_fd =
+ open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(access_logfile);
+- PATCH(format);
+- PATCH(log_access_fd);
+- PATCH(last_generated_accesslog_ts_ptr);
+- PATCH(access_logbuffer);
+- PATCH(ts_accesslog_str);
+- PATCH(parsed_format);
+- PATCH(use_syslog);
+-
++
++ PATCH_OPTION(access_logfile);
++ PATCH_OPTION(format);
++ PATCH_OPTION(log_access_fd);
++ PATCH_OPTION(last_generated_accesslog_ts_ptr);
++ PATCH_OPTION(access_logbuffer);
++ PATCH_OPTION(ts_accesslog_str);
++ PATCH_OPTION(parsed_format);
++ PATCH_OPTION(use_syslog);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
+- PATCH(access_logfile);
+- PATCH(log_access_fd);
+- PATCH(last_generated_accesslog_ts_ptr);
+- PATCH(access_logbuffer);
+- PATCH(ts_accesslog_str);
++ PATCH_OPTION(access_logfile);
++ PATCH_OPTION(log_access_fd);
++ PATCH_OPTION(last_generated_accesslog_ts_ptr);
++ PATCH_OPTION(access_logbuffer);
++ PATCH_OPTION(ts_accesslog_str);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
+- PATCH(format);
+- PATCH(parsed_format);
++ PATCH_OPTION(format);
++ PATCH_OPTION(parsed_format);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
+- PATCH(use_syslog);
++ PATCH_OPTION(use_syslog);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ REQUESTDONE_FUNC(log_access_write) {
+ plugin_data *p = p_d;
+ buffer *b;
+ size_t j;
+-
++
+ int newts = 0;
+ data_string *ds;
+-
++
+ mod_accesslog_patch_connection(srv, con, p);
+-
++
+ b = p->conf.access_logbuffer;
+ if (b->used == 0) {
+ buffer_copy_string(b, "");
+ }
+-
++
+ for (j = 0; j < p->conf.parsed_format->used; j++) {
+ switch(p->conf.parsed_format->ptr[j]->type) {
+ case FIELD_STRING:
+@@ -636,14 +634,14 @@
+ case FIELD_FORMAT:
+ switch(p->conf.parsed_format->ptr[j]->field) {
+ case FORMAT_TIMESTAMP:
+-
++
+ /* cache the generated timestamp */
+ if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
+ struct tm tm;
+ #if defined(HAVE_STRUCT_TM_GMTOFF)
+ long scd, hrs, min;
+ #endif
+-
++
+ buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
+ #if defined(HAVE_STRUCT_TM_GMTOFF)
+ # ifdef HAVE_LOCALTIME_R
+@@ -653,17 +651,17 @@
+ 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)));
+ # endif
+ p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
+-
++
+ buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
+-
++
+ scd = abs(tm.tm_gmtoff);
+ hrs = scd / 3600;
+ min = (scd % 3600) / 60;
+-
++
+ /* hours */
+ if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
+ buffer_append_long(p->conf.ts_accesslog_str, hrs);
+-
++
+ if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
+ buffer_append_long(p->conf.ts_accesslog_str, min);
+ BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]");
+@@ -676,20 +674,20 @@
+ #endif
+ p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
+ #endif
+-
++
+ *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
+ newts = 1;
+ }
+-
++
+ buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
+-
++
+ break;
+ case FORMAT_REMOTE_HOST:
+-
++
+ /* handle inet_ntop cache */
+-
++
+ buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
+-
++
+ break;
+ case FORMAT_REMOTE_IDENT:
+ /* ident */
+@@ -710,10 +708,10 @@
+ case FORMAT_STATUS:
+ buffer_append_long(b, con->http_status);
+ break;
+-
++
+ case FORMAT_BYTES_OUT_NO_HEADER:
+ if (con->bytes_written > 0) {
+- buffer_append_off_t(b,
++ buffer_append_off_t(b,
+ con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
+ } else {
+ BUFFER_APPEND_STRING_CONST(b, "-");
+@@ -772,7 +770,7 @@
+ }
+ break;
+ case FORMAT_REQUEST_PROTOCOL:
+- buffer_append_string(b,
++ buffer_append_string(b,
+ con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
+ break;
+ case FORMAT_REQUEST_METHOD:
+@@ -801,7 +799,7 @@
+ { 'D', FORMAT_TIME_USED_MS },
+ { 'e', FORMAT_ENV },
+ */
+-
++
+ break;
+ }
+ break;
+@@ -809,7 +807,7 @@
+ break;
+ }
+ }
+-
++
+ BUFFER_APPEND_STRING_CONST(b, "\n");
+
+ if (p->conf.use_syslog || /* syslog doesn't cache */
+@@ -828,7 +826,7 @@
+ }
+ buffer_reset(b);
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -836,15 +834,15 @@
+ int mod_accesslog_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("accesslog");
+-
++
+ p->init = mod_accesslog_init;
+ p->set_defaults= log_access_open;
+ p->cleanup = mod_accesslog_free;
+-
++
+ p->handle_request_done = log_access_write;
+ p->handle_sighup = log_access_cycle;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_alias.c lighttpd-1.4.12/src/mod_alias.c
+--- lighttpd-1.4.11/src/mod_alias.c 2006-03-01 23:18:51.000000000 +0200
++++ lighttpd-1.4.12/src/mod_alias.c 2006-07-11 21:23:39.000000000 +0300
+@@ -8,6 +8,7 @@
+ #include "buffer.h"
+
+ #include "plugin.h"
++#include "sys-strings.h"
+
+ /* plugin config for all request/connections */
+ typedef struct {
+@@ -16,44 +17,44 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_alias_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
+-
+-
++
++
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_alias_free) {
+ plugin_data *p = p_d;
+-
++
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ array_free(s->alias);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -62,25 +63,25 @@
+ SETDEFAULTS_FUNC(mod_alias_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+- s->alias = array_init();
++ s->alias = array_init();
+ cv[0].destination = s->alias;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+@@ -110,76 +111,73 @@
+ }
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(alias);
+-
++
++ PATCH_OPTION(alias);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
+- PATCH(alias);
++ PATCH_OPTION(alias);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ PHYSICALPATH_FUNC(mod_alias_physical_handler) {
+ plugin_data *p = p_d;
+ int uri_len, basedir_len;
+ char *uri_ptr;
+ size_t k;
+-
++
+ if (con->physical.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_alias_patch_connection(srv, con, p);
+-
++
+ /* not to include the tailing slash */
+ basedir_len = (con->physical.basedir->used - 1) - 1;
+ uri_len = con->physical.path->used - 1 - basedir_len;
+ uri_ptr = con->physical.path->ptr + basedir_len;
+-
++
+ for (k = 0; k < p->conf.alias->used; k++) {
+ data_string *ds = (data_string *)p->conf.alias->data[k];
+ int alias_len = ds->key->used - 1;
+-
++
+ if (alias_len > uri_len) continue;
+ if (ds->key->used == 0) continue;
+-
++
+ if (0 == (con->conf.force_lowercase_filenames ?
+ strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
+ strncmp(uri_ptr, ds->key->ptr, alias_len))) {
+ /* matched */
+-
++
+ buffer_copy_string_buffer(con->physical.basedir, ds->value);
+ buffer_copy_string_buffer(srv->tmp_buf, ds->value);
+ buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
+ buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
+-
++
+ return HANDLER_GO_ON;
+ }
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+@@ -189,13 +187,13 @@
+ int mod_alias_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("alias");
+-
++
+ p->init = mod_alias_init;
+ p->handle_physical= mod_alias_physical_handler;
+ p->set_defaults = mod_alias_set_defaults;
+ p->cleanup = mod_alias_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_auth.c lighttpd-1.4.12/src/mod_auth.c
+--- lighttpd-1.4.11/src/mod_auth.c 2006-02-15 20:01:31.000000000 +0200
++++ lighttpd-1.4.12/src/mod_auth.c 2006-07-11 21:23:40.000000000 +0300
+@@ -5,168 +5,167 @@
+ #include <string.h>
+ #include <errno.h>
+ #include <fcntl.h>
+-#include <unistd.h>
+
+ #include "plugin.h"
+ #include "http_auth.h"
+ #include "log.h"
+ #include "response.h"
+
++#include "sys-strings.h"
++#include "sys-files.h"
++
+ handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
+
+
+ /**
+ * the basic and digest auth framework
+- *
++ *
+ * - config handling
+ * - protocol handling
+- *
+- * http_auth.c
+- * http_auth_digest.c
+- *
++ *
++ * http_auth.c
++ * http_auth_digest.c
++ *
+ * do the real work
+ */
+
+ INIT_FUNC(mod_auth_init) {
+ mod_auth_plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->tmp_buf = buffer_init();
+-
++
+ p->auth_user = buffer_init();
+ #ifdef USE_LDAP
+ p->ldap_filter = buffer_init();
+ #endif
+-
++
+ return p;
+ }
+
+ FREE_FUNC(mod_auth_free) {
+ mod_auth_plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ buffer_free(p->tmp_buf);
+ buffer_free(p->auth_user);
+ #ifdef USE_LDAP
+ buffer_free(p->ldap_filter);
+ #endif
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ mod_auth_plugin_config *s = p->config_storage[i];
+-
++
+ if (!s) continue;
+-
++
+ array_free(s->auth_require);
+ buffer_free(s->auth_plain_groupfile);
+ buffer_free(s->auth_plain_userfile);
+ buffer_free(s->auth_htdigest_userfile);
+ buffer_free(s->auth_htpasswd_userfile);
+ buffer_free(s->auth_backend_conf);
+-
++
+ buffer_free(s->auth_ldap_hostname);
+ buffer_free(s->auth_ldap_basedn);
+ buffer_free(s->auth_ldap_binddn);
+ buffer_free(s->auth_ldap_bindpw);
+ buffer_free(s->auth_ldap_filter);
+ buffer_free(s->auth_ldap_cafile);
+-
++
+ #ifdef USE_LDAP
+ buffer_free(s->ldap_filter_pre);
+ buffer_free(s->ldap_filter_post);
+-
++
+ if (s->ldap) ldap_unbind_s(s->ldap);
+ #endif
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
+ size_t i, j;
+ mod_auth_plugin_config *s = p->config_storage[0];
+
+- PATCH(auth_backend);
+- PATCH(auth_plain_groupfile);
+- PATCH(auth_plain_userfile);
+- PATCH(auth_htdigest_userfile);
+- PATCH(auth_htpasswd_userfile);
+- PATCH(auth_require);
+- PATCH(auth_debug);
+- PATCH(auth_ldap_hostname);
+- PATCH(auth_ldap_basedn);
+- PATCH(auth_ldap_binddn);
+- PATCH(auth_ldap_bindpw);
+- PATCH(auth_ldap_filter);
+- PATCH(auth_ldap_cafile);
+- PATCH(auth_ldap_starttls);
++ PATCH_OPTION(auth_backend);
++ PATCH_OPTION(auth_plain_groupfile);
++ PATCH_OPTION(auth_plain_userfile);
++ PATCH_OPTION(auth_htdigest_userfile);
++ PATCH_OPTION(auth_htpasswd_userfile);
++ PATCH_OPTION(auth_require);
++ PATCH_OPTION(auth_debug);
++ PATCH_OPTION(auth_ldap_hostname);
++ PATCH_OPTION(auth_ldap_basedn);
++ PATCH_OPTION(auth_ldap_binddn);
++ PATCH_OPTION(auth_ldap_bindpw);
++ PATCH_OPTION(auth_ldap_filter);
++ PATCH_OPTION(auth_ldap_cafile);
++ PATCH_OPTION(auth_ldap_starttls);
+ #ifdef USE_LDAP
+- PATCH(ldap);
+- PATCH(ldap_filter_pre);
+- PATCH(ldap_filter_post);
++ PATCH_OPTION(ldap);
++ PATCH_OPTION(ldap_filter_pre);
++ PATCH_OPTION(ldap_filter_post);
+ #endif
+-
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
+- PATCH(auth_backend);
++ PATCH_OPTION(auth_backend);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
+- PATCH(auth_plain_groupfile);
++ PATCH_OPTION(auth_plain_groupfile);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
+- PATCH(auth_plain_userfile);
++ PATCH_OPTION(auth_plain_userfile);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
+- PATCH(auth_htdigest_userfile);
++ PATCH_OPTION(auth_htdigest_userfile);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
+- PATCH(auth_htpasswd_userfile);
++ PATCH_OPTION(auth_htpasswd_userfile);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
+- PATCH(auth_require);
++ PATCH_OPTION(auth_require);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
+- PATCH(auth_debug);
++ PATCH_OPTION(auth_debug);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
+- PATCH(auth_ldap_hostname);
++ PATCH_OPTION(auth_ldap_hostname);
+ #ifdef USE_LDAP
+- PATCH(ldap);
+- PATCH(ldap_filter_pre);
+- PATCH(ldap_filter_post);
++ PATCH_OPTION(ldap);
++ PATCH_OPTION(ldap_filter_pre);
++ PATCH_OPTION(ldap_filter_post);
+ #endif
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
+- PATCH(auth_ldap_basedn);
++ PATCH_OPTION(auth_ldap_basedn);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
+- PATCH(auth_ldap_filter);
++ PATCH_OPTION(auth_ldap_filter);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
+- PATCH(auth_ldap_cafile);
++ PATCH_OPTION(auth_ldap_cafile);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
+- PATCH(auth_ldap_starttls);
++ PATCH_OPTION(auth_ldap_starttls);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
+ size_t k;
+@@ -175,22 +174,22 @@
+ data_string *ds;
+ mod_auth_plugin_data *p = p_d;
+ array *req;
+-
++
+ /* select the right config */
+ mod_auth_patch_connection(srv, con, p);
+-
++
+ if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
+-
++
+ /*
+ * AUTH
+- *
++ *
+ */
+-
++
+ /* do we have to ask for auth ? */
+-
++
+ auth_required = 0;
+ auth_satisfied = 0;
+-
++
+ /* search auth-directives for path */
+ for (k = 0; k < p->conf.auth_require->used; k++) {
+ buffer *req = p->conf.auth_require->data[k]->key;
+@@ -212,31 +211,31 @@
+ }
+ }
+ }
+-
++
+ /* nothing to do for us */
+ if (auth_required == 0) return HANDLER_GO_ON;
+-
++
+ req = ((data_array *)(p->conf.auth_require->data[k]))->value;
+-
++
+ /* try to get Authorization-header */
+-
++
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
+ http_authorization = ds->value->ptr;
+ }
+-
++
+ if (ds && ds->value && ds->value->used) {
+ char *auth_realm;
+ data_string *method;
+-
++
+ method = (data_string *)array_get_element(req, "method");
+-
++
+ /* parse auth-header */
+ if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
+ int auth_type_len = auth_realm - http_authorization;
+-
++
+ if ((auth_type_len == 5) &&
+ (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
+-
++
+ if (0 == strcmp(method->value->ptr, "basic")) {
+ auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
+ }
+@@ -245,43 +244,43 @@
+ if (0 == strcmp(method->value->ptr, "digest")) {
+ if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
+ con->http_status = 400;
+-
++
+ /* a field was missing */
+-
++
+ return HANDLER_FINISHED;
+ }
+ }
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "unknown authentification type:",
+ http_authorization);
+ }
+ }
+ }
+-
++
+ if (!auth_satisfied) {
+ data_string *method, *realm;
+ method = (data_string *)array_get_element(req, "method");
+ realm = (data_string *)array_get_element(req, "realm");
+-
++
+ con->http_status = 401;
+-
++
+ if (0 == strcmp(method->value->ptr, "basic")) {
+ buffer_copy_string(p->tmp_buf, "Basic realm=\"");
+ buffer_append_string_buffer(p->tmp_buf, realm->value);
+ buffer_append_string(p->tmp_buf, "\"");
+-
++
+ response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
+ } else if (0 == strcmp(method->value->ptr, "digest")) {
+ char hh[33];
+ http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
+-
++
+ buffer_copy_string(p->tmp_buf, "Digest realm=\"");
+ buffer_append_string_buffer(p->tmp_buf, realm->value);
+ buffer_append_string(p->tmp_buf, "\", nonce=\"");
+ buffer_append_string(p->tmp_buf, hh);
+ buffer_append_string(p->tmp_buf, "\", qop=\"auth\"");
+-
++
+ response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
+ } else {
+ /* evil */
+@@ -289,18 +288,18 @@
+ return HANDLER_FINISHED;
+ } else {
+ /* the REMOTE_USER header */
+-
++
+ buffer_copy_string_buffer(con->authed_user, p->auth_user);
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ SETDEFAULTS_FUNC(mod_auth_set_defaults) {
+ mod_auth_plugin_data *p = p_d;
+ size_t i;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "auth.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "auth.backend.plain.groupfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { "auth.backend.plain.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+@@ -317,7 +316,7 @@
+ { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+ for (i = 0; i < srv->config_context->used; i++) {
+@@ -325,14 +324,14 @@
+ size_t n;
+ data_array *da;
+ array *ca;
+-
++
+ s = calloc(1, sizeof(mod_auth_plugin_config));
+ s->auth_plain_groupfile = buffer_init();
+ s->auth_plain_userfile = buffer_init();
+ s->auth_htdigest_userfile = buffer_init();
+ s->auth_htpasswd_userfile = buffer_init();
+ s->auth_backend_conf = buffer_init();
+-
++
+ s->auth_ldap_hostname = buffer_init();
+ s->auth_ldap_basedn = buffer_init();
+ s->auth_ldap_binddn = buffer_init();
+@@ -341,15 +340,15 @@
+ s->auth_ldap_cafile = buffer_init();
+ s->auth_ldap_starttls = 0;
+ s->auth_debug = 0;
+-
++
+ s->auth_require = array_init();
+-
++
+ #ifdef USE_LDAP
+ s->ldap_filter_pre = buffer_init();
+ s->ldap_filter_post = buffer_init();
+ s->ldap = NULL;
+ #endif
+-
++
+ cv[0].destination = s->auth_backend_conf;
+ cv[1].destination = s->auth_plain_groupfile;
+ cv[2].destination = s->auth_plain_userfile;
+@@ -364,14 +363,14 @@
+ cv[11].destination = s->auth_htdigest_userfile;
+ cv[12].destination = s->auth_htpasswd_userfile;
+ cv[13].destination = &(s->auth_debug);
+-
++
+ p->config_storage[i] = s;
+ ca = ((data_config *)srv->config_context->data[i])->value;
+-
++
+ if (0 != config_insert_values_global(srv, ca, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (s->auth_backend_conf->used) {
+ if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
+ s->auth_backend = AUTH_BACKEND_HTPASSWD;
+@@ -383,31 +382,31 @@
+ s->auth_backend = AUTH_BACKEND_LDAP;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+
+ /* no auth.require for this section */
+ if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
+-
++
+ if (da->type != TYPE_ARRAY) continue;
+-
++
+ for (n = 0; n < da->value->used; n++) {
+ size_t m;
+ data_array *da_file = (data_array *)da->value->data[n];
+ const char *method, *realm, *require;
+-
++
+ if (da->value->data[n]->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
+- "auth.require should contain an array as in:",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "auth.require should contain an array as in:",
+ "auth.require = ( \"...\" => ( ..., ...) )");
+
+ return HANDLER_ERROR;
+ }
+-
++
+ method = realm = require = NULL;
+-
++
+ for (m = 0; m < da_file->value->used; m++) {
+ if (da_file->value->data[m]->type == TYPE_STRING) {
+ if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
+@@ -417,8 +416,8 @@
+ } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
+ require = ((data_string *)(da_file->value->data[m]))->value->ptr;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "ssbs",
+- "the field is unknown in:",
++ log_error_write(srv, __FILE__, __LINE__, "ssbs",
++ "the field is unknown in:",
+ "auth.require = ( \"...\" => ( ..., -> \"",
+ da_file->value->data[m]->key,
+ "\" <- => \"...\" ) )");
+@@ -426,19 +425,19 @@
+ return HANDLER_ERROR;
+ }
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "ssbs",
+- "a string was expected for:",
++ log_error_write(srv, __FILE__, __LINE__, "ssbs",
++ "a string was expected for:",
+ "auth.require = ( \"...\" => ( ..., -> \"",
+ da_file->value->data[m]->key,
+ "\" <- => \"...\" ) )");
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ if (method == NULL) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
+- "the require field is missing in:",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "the require field is missing in:",
+ "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
+ return HANDLER_ERROR;
+ } else {
+@@ -450,60 +449,60 @@
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ if (realm == NULL) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
+- "the require field is missing in:",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "the require field is missing in:",
+ "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
+ return HANDLER_ERROR;
+ }
+-
++
+ if (require == NULL) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
+- "the require field is missing in:",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "the require field is missing in:",
+ "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
+ return HANDLER_ERROR;
+ }
+-
++
+ if (method && realm && require) {
+ data_string *ds;
+ data_array *a;
+-
++
+ a = data_array_init();
+ buffer_copy_string_buffer(a->key, da_file->key);
+-
++
+ ds = data_string_init();
+-
++
+ buffer_copy_string(ds->key, "method");
+ buffer_copy_string(ds->value, method);
+-
++
+ array_insert_unique(a->value, (data_unset *)ds);
+-
++
+ ds = data_string_init();
+-
++
+ buffer_copy_string(ds->key, "realm");
+ buffer_copy_string(ds->value, realm);
+-
++
+ array_insert_unique(a->value, (data_unset *)ds);
+-
++
+ ds = data_string_init();
+-
++
+ buffer_copy_string(ds->key, "require");
+ buffer_copy_string(ds->value, require);
+-
++
+ array_insert_unique(a->value, (data_unset *)ds);
+-
++
+ array_insert_unique(s->auth_require, (data_unset *)a);
+ }
+ }
+-
++
+ switch(s->auth_backend) {
+ case AUTH_BACKEND_PLAIN:
+ if (s->auth_plain_userfile->used) {
+ int fd;
+ /* try to read */
+ if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening auth.backend.plain.userfile:", s->auth_plain_userfile,
+ "failed:", strerror(errno));
+ return HANDLER_ERROR;
+@@ -516,7 +515,7 @@
+ int fd;
+ /* try to read */
+ if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile,
+ "failed:", strerror(errno));
+ return HANDLER_ERROR;
+@@ -529,7 +528,7 @@
+ int fd;
+ /* try to read */
+ if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile,
+ "failed:", strerror(errno));
+ return HANDLER_ERROR;
+@@ -554,75 +553,75 @@
+ handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
+ #ifdef USE_LDAP
+ int ret;
+-#if 0
++#if 0
+ if (s->auth_ldap_basedn->used == 0) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
+-
++
+ return HANDLER_ERROR;
+ }
+ #endif
+-
++
+ if (s->auth_ldap_filter->used) {
+ char *dollar;
+-
++
+ /* parse filter */
+-
++
+ if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
+ buffer_copy_string(s->ldap_filter_post, dollar+1);
+ }
+-
++
+ if (s->auth_ldap_hostname->used) {
+ if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ ret = LDAP_VERSION3;
+ if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
+-
++
+ return HANDLER_ERROR;
+ }
+
+ if (s->auth_ldap_starttls) {
+- /* if no CA file is given, it is ok, as we will use encryption
++ /* if no CA file is given, it is ok, as we will use encryption
+ * if the server requires a CAfile it will tell us */
+ if (!buffer_is_empty(s->auth_ldap_cafile)) {
+- if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
++ if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
+ s->auth_ldap_cafile->ptr))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "Loading CA certificate failed:", ldap_err2string(ret));
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL, NULL))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+-
+-
++
++
+ /* 1. */
+ if (s->auth_ldap_binddn->used) {
+ if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
+-
++
+ return HANDLER_ERROR;
+ }
+ } else {
+ if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+@@ -641,8 +640,8 @@
+ p->set_defaults = mod_auth_set_defaults;
+ p->handle_uri_clean = mod_auth_uri_handler;
+ p->cleanup = mod_auth_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cgi.c lighttpd-1.4.12/src/mod_cgi.c
+--- lighttpd-1.4.11/src/mod_cgi.c 2006-02-22 15:15:10.000000000 +0200
++++ lighttpd-1.4.12/src/mod_cgi.c 2006-07-11 21:23:39.000000000 +0300
+@@ -1,21 +1,8 @@
+ #include <sys/types.h>
+-#ifdef __WIN32
+-#include <winsock2.h>
+-#else
+-#include <sys/socket.h>
+-#include <sys/wait.h>
+-#include <sys/mman.h>
+-
+-#include <netinet/in.h>
+-
+-#include <arpa/inet.h>
+-#endif
+
+-#include <unistd.h>
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <fdevent.h>
+ #include <signal.h>
+ #include <ctype.h>
+ #include <assert.h>
+@@ -29,9 +16,16 @@
+ #include "connections.h"
+ #include "joblist.h"
+ #include "http_chunk.h"
++#include "fdevent.h"
+
+ #include "plugin.h"
+
++#include "sys-files.h"
++#include "sys-mmap.h"
++#include "sys-socket.h"
++#include "sys-strings.h"
++#include "sys-process.h"
++
+ #ifdef HAVE_SYS_FILIO_H
+ # include <sys/filio.h>
+ #endif
+@@ -40,11 +34,12 @@
+
+ typedef struct {
+ char **ptr;
+-
++
+ size_t size;
+ size_t used;
+ } char_array;
+
++#define pid_t int
+ typedef struct {
+ pid_t *ptr;
+ size_t used;
+@@ -58,23 +53,23 @@
+ typedef struct {
+ PLUGIN_DATA;
+ buffer_pid_t cgi_pid;
+-
++
+ buffer *tmp_buf;
+ buffer *parse_response;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ typedef struct {
+ pid_t pid;
+ int fd;
+ int fde_ndx; /* index into the fd-event buffer */
+-
++
+ connection *remote_conn; /* dumb pointer */
+ plugin_data *plugin_data; /* dumb pointer */
+-
++
+ buffer *response;
+ buffer *response_header;
+ } handler_ctx;
+@@ -83,17 +78,17 @@
+ handler_ctx *hctx = calloc(1, sizeof(*hctx));
+
+ assert(hctx);
+-
++
+ hctx->response = buffer_init();
+ hctx->response_header = buffer_init();
+-
++
+ return hctx;
+ }
+
+ static void cgi_handler_ctx_free(handler_ctx *hctx) {
+ buffer_free(hctx->response);
+ buffer_free(hctx->response_header);
+-
++
+ free(hctx);
+ }
+
+@@ -101,14 +96,14 @@
+
+ INIT_FUNC(mod_cgi_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+
+ assert(p);
+-
++
+ p->tmp_buf = buffer_init();
+ p->parse_response = buffer_init();
+-
++
+ return p;
+ }
+
+@@ -116,62 +111,62 @@
+ FREE_FUNC(mod_cgi_free) {
+ plugin_data *p = p_d;
+ buffer_pid_t *r = &(p->cgi_pid);
+-
++
+ UNUSED(srv);
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ array_free(s->cgi);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+
+ if (r->ptr) free(r->ptr);
+-
++
+ buffer_free(p->tmp_buf);
+ buffer_free(p->parse_response);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
+ };
+
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ assert(s);
+-
++
+ s->cgi = array_init();
+-
++
+ cv[0].destination = s->cgi;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -180,13 +175,13 @@
+ int m = -1;
+ size_t i;
+ buffer_pid_t *r = &(p->cgi_pid);
+-
++
+ UNUSED(srv);
+
+ for (i = 0; i < r->used; i++) {
+ if (r->ptr[i] > m) m = r->ptr[i];
+ }
+-
++
+ if (r->size == 0) {
+ r->size = 16;
+ r->ptr = malloc(sizeof(*r->ptr) * r->size);
+@@ -194,31 +189,31 @@
+ r->size += 16;
+ r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
+ }
+-
++
+ r->ptr[r->used++] = pid;
+-
++
+ return m;
+ }
+
+ static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
+ size_t i;
+ buffer_pid_t *r = &(p->cgi_pid);
+-
++
+ UNUSED(srv);
+
+ for (i = 0; i < r->used; i++) {
+ if (r->ptr[i] == pid) break;
+ }
+-
++
+ if (i != r->used) {
+ /* found */
+-
++
+ if (i != r->used - 1) {
+ r->ptr[i] = r->ptr[r->used - 1];
+ }
+ r->used--;
+ }
+-
++
+ return 0;
+ }
+
+@@ -226,32 +221,32 @@
+ char *ns;
+ const char *s;
+ int line = 0;
+-
++
+ UNUSED(srv);
+-
++
+ buffer_copy_string_buffer(p->parse_response, in);
+-
+- for (s = p->parse_response->ptr;
+- NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
++
++ for (s = p->parse_response->ptr;
++ NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
+ s = ns + (eol == EOL_RN ? 2 : 1), line++) {
+ const char *key, *value;
+ int key_len;
+ data_string *ds;
+-
++
+ ns[0] = '\0';
+-
+- if (line == 0 &&
++
++ if (line == 0 &&
+ 0 == strncmp(s, "HTTP/1.", 7)) {
+ /* non-parsed header ... we parse them anyway */
+-
++
+ if ((s[7] == '1' ||
+ s[7] == '0') &&
+ s[8] == ' ') {
+ int status;
+ /* after the space should be a status code for us */
+-
++
+ status = strtol(s+9, NULL, 10);
+-
++
+ if (con->http_status >= 100 &&
+ con->http_status < 1000) {
+ /* we expected 3 digits and didn't got them */
+@@ -260,27 +255,27 @@
+ }
+ }
+ } else {
+-
++
+ key = s;
+ if (NULL == (value = strchr(s, ':'))) {
+ /* we expect: "<key>: <value>\r\n" */
+ continue;
+ }
+-
++
+ key_len = value - key;
+ value += 1;
+-
++
+ /* skip LWS */
+ while (*value == ' ' || *value == '\t') value++;
+-
++
+ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
+ ds = data_response_init();
+ }
+ buffer_copy_string_len(ds->key, key, key_len);
+ buffer_copy_string(ds->value, value);
+-
++
+ array_insert_unique(con->response.headers, (data_unset *)ds);
+-
++
+ switch(key_len) {
+ case 4:
+ if (0 == strncasecmp(key, "Date", key_len)) {
+@@ -315,13 +310,13 @@
+ }
+ }
+ }
+-
++
+ /* CGI/1.1 rev 03 - 7.2.1.2 */
+ if ((con->parsed_response & HTTP_LOCATION) &&
+ !(con->parsed_response & HTTP_STATUS)) {
+ con->http_status = 302;
+ }
+-
++
+ return 0;
+ }
+
+@@ -329,10 +324,10 @@
+ static int cgi_demux_response(server *srv, handler_ctx *hctx) {
+ plugin_data *p = hctx->plugin_data;
+ connection *con = hctx->remote_conn;
+-
++
+ while(1) {
+ int n;
+-
++
+ buffer_prepare_copy(hctx->response, 1024);
+ if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
+ if (errno == EAGAIN || errno == EINTR) {
+@@ -343,125 +338,125 @@
+ log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
+ return FDEVENT_HANDLED_ERROR;
+ }
+-
++
+ if (n == 0) {
+ /* read finished */
+-
++
+ con->file_finished = 1;
+-
++
+ /* send final chunk */
+ http_chunk_append_mem(srv, con, NULL, 0);
+ joblist_append(srv, con);
+-
++
+ return FDEVENT_HANDLED_FINISHED;
+ }
+-
++
+ hctx->response->ptr[n] = '\0';
+ hctx->response->used = n+1;
+-
++
+ /* split header from body */
+-
++
+ if (con->file_started == 0) {
+ char *c;
+ int in_header = 0;
+ int header_end = 0;
+ int cp, eol = EOL_UNSET;
+ size_t used = 0;
+-
++
+ buffer_append_string_buffer(hctx->response_header, hctx->response);
+-
++
+ /* nph (non-parsed headers) */
+ if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
+-
++
+ /* search for the \r\n\r\n or \n\n in the string */
+ for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
+ if (*c == ':') in_header = 1;
+ else if (*c == '\n') {
+ if (in_header == 0) {
+ /* got a response without a response header */
+-
++
+ c = NULL;
+ header_end = 1;
+ break;
+ }
+-
++
+ if (eol == EOL_UNSET) eol = EOL_N;
+-
++
+ if (*(c+1) == '\n') {
+ header_end = 1;
+ break;
+ }
+-
++
+ } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
+ if (in_header == 0) {
+ /* got a response without a response header */
+-
++
+ c = NULL;
+ header_end = 1;
+ break;
+ }
+-
++
+ if (eol == EOL_UNSET) eol = EOL_RN;
+-
++
+ if (used > 3 &&
+- *(c+2) == '\r' &&
++ *(c+2) == '\r' &&
+ *(c+3) == '\n') {
+ header_end = 1;
+ break;
+ }
+-
++
+ /* skip the \n */
+ c++;
+ cp++;
+ used--;
+ }
+ }
+-
++
+ if (header_end) {
+ if (c == NULL) {
+ /* no header, but a body */
+-
++
+ if (con->request.http_version == HTTP_VERSION_1_1) {
+ con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
+ }
+-
++
+ http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
+ joblist_append(srv, con);
+ } else {
+ size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
+ size_t blen = hctx->response_header->used - hlen - 1;
+-
++
+ /* a small hack: terminate after at the second \r */
+ hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
+ hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
+-
++
+ /* parse the response header */
+ cgi_response_parse(srv, con, p, hctx->response_header, eol);
+-
++
+ /* enable chunked-transfer-encoding */
+ if (con->request.http_version == HTTP_VERSION_1_1 &&
+ !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
+ con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
+ }
+-
++
+ if ((hctx->response->used != hlen) && blen > 0) {
+ http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
+ joblist_append(srv, con);
+ }
+ }
+-
++
+ con->file_started = 1;
+ }
+ } else {
+ http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
+ joblist_append(srv, con);
+ }
+-
+-#if 0
++
++#if 0
+ log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
+ #endif
+ }
+-
++
+ return FDEVENT_HANDLED_NOT_FINISHED;
+ }
+
+@@ -470,45 +465,46 @@
+ pid_t pid;
+ plugin_data *p;
+ connection *con;
+-
++
+ if (NULL == hctx) return HANDLER_GO_ON;
+-
++
+ p = hctx->plugin_data;
+ con = hctx->remote_conn;
+-
++
+ if (con->mode != p->id) return HANDLER_GO_ON;
+
+-#ifndef __WIN32
+-
++#ifndef _WIN32
++
+ /* the connection to the browser went away, but we still have a connection
+- * to the CGI script
++ * to the CGI script
+ *
+ * close cgi-connection
+ */
+-
++
+ if (hctx->fd != -1) {
+ /* close connection to the cgi-script */
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+ fdevent_unregister(srv->ev, hctx->fd);
+-
++
+ if (close(hctx->fd)) {
+ log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
+ }
+-
++
+ hctx->fd = -1;
+ hctx->fde_ndx = -1;
+ }
+-
++
+ pid = hctx->pid;
+-
++
+ con->plugin_ctx[p->id] = NULL;
+-
++
+ /* is this a good idea ? */
+ cgi_handler_ctx_free(hctx);
+-
++
+ /* if waitpid hasn't been called by response.c yet, do it here */
+ if (pid) {
+ /* check if the CGI-script is already gone */
++#ifndef _WIN32
+ switch(waitpid(pid, &status, WNOHANG)) {
+ case 0:
+ /* not finished yet */
+@@ -519,19 +515,19 @@
+ case -1:
+ /* */
+ if (errno == EINTR) break;
+-
+- /*
+- * errno == ECHILD happens if _subrequest catches the process-status before
++
++ /*
++ * errno == ECHILD happens if _subrequest catches the process-status before
+ * we have read the response of the cgi process
+- *
++ *
+ * -> catch status
+ * -> WAIT_FOR_EVENT
+ * -> read response
+ * -> we get here with waitpid == ECHILD
+- *
++ *
+ */
+ if (errno == ECHILD) return HANDLER_GO_ON;
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
+ return HANDLER_ERROR;
+ default:
+@@ -541,13 +537,13 @@
+ con->http_status = 500;
+ con->mode = DIRECT;
+ }
+-
++
+ if (WIFEXITED(status)) {
+ #if 0
+ log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
+ #endif
+ pid = 0;
+-
++
+ return HANDLER_GO_ON;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
+@@ -555,20 +551,20 @@
+ return HANDLER_GO_ON;
+ }
+ }
+-
+-
++
++
+ kill(pid, SIGTERM);
+-
++#endif
+ /* cgi-script is still alive, queue the PID for removal */
+ cgi_pid_add(srv, p, pid);
+ }
+-#endif
++#endif
+ return HANDLER_GO_ON;
+ }
+
+ static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
+ plugin_data *p = p_d;
+-
++
+ return cgi_connection_close(srv, con->plugin_ctx[p->id]);
+ }
+
+@@ -577,43 +573,43 @@
+ server *srv = (server *)s;
+ handler_ctx *hctx = ctx;
+ connection *con = hctx->remote_conn;
+-
++
+ joblist_append(srv, con);
+-
++
+ if (hctx->fd == -1) {
+ log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ if (revents & FDEVENT_IN) {
+ switch (cgi_demux_response(srv, hctx)) {
+ case FDEVENT_HANDLED_NOT_FINISHED:
+ break;
+ case FDEVENT_HANDLED_FINISHED:
+ /* we are done */
+-
++
+ #if 0
+ log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
+ #endif
+ cgi_connection_close(srv, hctx);
+-
+- /* if we get a IN|HUP and have read everything don't exec the close twice */
++
++ /* if we get a IN|HUP and have read everything don't exec the close twice */
+ return HANDLER_FINISHED;
+ case FDEVENT_HANDLED_ERROR:
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+ con->http_status = 500;
+ con->mode = DIRECT;
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
+ break;
+ }
+ }
+-
++
+ if (revents & FDEVENT_OUT) {
+ /* nothing to do */
+ }
+-
++
+ /* perhaps this issue is already handled */
+ if (revents & FDEVENT_HUP) {
+ /* check if we still have a unfinished header package which is a body in reality */
+@@ -623,54 +619,54 @@
+ http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
+ joblist_append(srv, con);
+ }
+-
++
+ if (con->file_finished == 0) {
+ http_chunk_append_mem(srv, con, NULL, 0);
+ joblist_append(srv, con);
+ }
+-
++
+ con->file_finished = 1;
+-
++
+ if (chunkqueue_is_empty(con->write_queue)) {
+ /* there is nothing left to write */
+ connection_set_state(srv, con, CON_STATE_RESPONSE_END);
+ } else {
+ /* used the write-handler to finish the request on demand */
+-
++
+ }
+-
++
+ # if 0
+ log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
+ # endif
+-
++
+ /* rtsigs didn't liked the close */
+ cgi_connection_close(srv, hctx);
+ } else if (revents & FDEVENT_ERR) {
+ con->file_finished = 1;
+-
++
+ /* kill all connections to the cgi process */
+ cgi_connection_close(srv, hctx);
+ #if 1
+ log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
+-#endif
++#endif
+ return HANDLER_ERROR;
+ }
+-
++
+ return HANDLER_FINISHED;
+ }
+
+
+ static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
+ char *dst;
+-
++
+ if (!key || !val) return -1;
+-
++
+ dst = malloc(key_len + val_len + 3);
+ memcpy(dst, key, key_len);
+ dst[key_len] = '=';
+ /* add the \0 from the value */
+ memcpy(dst + key_len + 1, val, val_len + 1);
+-
++
+ if (env->size == 0) {
+ env->size = 16;
+ env->ptr = malloc(env->size * sizeof(*env->ptr));
+@@ -678,45 +674,45 @@
+ env->size += 16;
+ env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
+ }
+-
++
+ env->ptr[env->used++] = dst;
+-
++
+ return 0;
+ }
+
+ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
+ pid_t pid;
+-
++
+ #ifdef HAVE_IPV6
+ char b2[INET6_ADDRSTRLEN + 1];
+ #endif
+-
++
+ int to_cgi_fds[2];
+ int from_cgi_fds[2];
+ struct stat st;
+-
+-#ifndef __WIN32
+-
++
++#ifndef _WIN32
++
+ if (cgi_handler->used > 1) {
+ /* stat the exec file */
+ if (-1 == (stat(cgi_handler->ptr, &st))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "stat for cgi-handler", cgi_handler,
+ "failed:", strerror(errno));
+ return -1;
+ }
+ }
+-
++
+ if (pipe(to_cgi_fds)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
+ return -1;
+ }
+-
++
+ if (pipe(from_cgi_fds)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
+ return -1;
+ }
+-
++
+ /* fork, execve */
+ switch (pid = fork()) {
+ case 0: {
+@@ -730,22 +726,22 @@
+ char *c;
+ const char *s;
+ server_socket *srv_sock = con->srv_socket;
+-
++
+ /* move stdout to from_cgi_fd[1] */
+ close(STDOUT_FILENO);
+ dup2(from_cgi_fds[1], STDOUT_FILENO);
+ close(from_cgi_fds[1]);
+ /* not needed */
+ close(from_cgi_fds[0]);
+-
++
+ /* move the stdin to to_cgi_fd[0] */
+ close(STDIN_FILENO);
+ dup2(to_cgi_fds[0], STDIN_FILENO);
+ close(to_cgi_fds[0]);
+ /* not needed */
+ close(to_cgi_fds[1]);
+-
+- /* HACK:
++
++ /* HACK:
+ * this is not nice, but it works
+ *
+ * we feed the stderr of the CGI to our errorlog, if possible
+@@ -754,20 +750,20 @@
+ close(STDERR_FILENO);
+ dup2(srv->errorlog_fd, STDERR_FILENO);
+ }
+-
++
+ /* create environment */
+ env.ptr = NULL;
+ env.size = 0;
+ env.used = 0;
+-
++
+ cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
+
+ if (!buffer_is_empty(con->server_name)) {
+ cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
+ } else {
+ #ifdef HAVE_IPV6
+- s = inet_ntop(srv_sock->addr.plain.sa_family,
+- srv_sock->addr.plain.sa_family == AF_INET6 ?
++ s = inet_ntop(srv_sock->addr.plain.sa_family,
++ srv_sock->addr.plain.sa_family == AF_INET6 ?
+ (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
+ (const void *) &(srv_sock->addr.ipv4.sin_addr),
+ b2, sizeof(b2)-1);
+@@ -779,10 +775,10 @@
+ cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
+
+ s = get_http_version_name(con->request.http_version);
+-
++
+ cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
+-
+- ltostr(buf,
++
++ ltostr(buf,
+ #ifdef HAVE_IPV6
+ ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
+ #else
+@@ -790,10 +786,10 @@
+ #endif
+ );
+ cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
+-
++
+ #ifdef HAVE_IPV6
+- s = inet_ntop(srv_sock->addr.plain.sa_family,
+- srv_sock->addr.plain.sa_family == AF_INET6 ?
++ s = inet_ntop(srv_sock->addr.plain.sa_family,
++ srv_sock->addr.plain.sa_family == AF_INET6 ?
+ (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
+ (const void *) &(srv_sock->addr.ipv4.sin_addr),
+ b2, sizeof(b2)-1);
+@@ -811,15 +807,18 @@
+ cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
+ if (!buffer_is_empty(con->uri.query)) {
+ cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
++ } else {
++ /* set a empty QUERY_STRING */
++ cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
+ }
+ if (!buffer_is_empty(con->request.orig_uri)) {
+ cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
+ }
+-
+-
++
++
+ #ifdef HAVE_IPV6
+- s = inet_ntop(con->dst_addr.plain.sa_family,
+- con->dst_addr.plain.sa_family == AF_INET6 ?
++ s = inet_ntop(con->dst_addr.plain.sa_family,
++ con->dst_addr.plain.sa_family == AF_INET6 ?
+ (const void *) &(con->dst_addr.ipv6.sin6_addr) :
+ (const void *) &(con->dst_addr.ipv4.sin_addr),
+ b2, sizeof(b2)-1);
+@@ -828,7 +827,7 @@
+ #endif
+ cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
+
+- ltostr(buf,
++ ltostr(buf,
+ #ifdef HAVE_IPV6
+ ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
+ #else
+@@ -836,19 +835,19 @@
+ #endif
+ );
+ cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
+-
++
+ if (!buffer_is_empty(con->authed_user)) {
+ cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
+ CONST_BUF_LEN(con->authed_user));
+ }
+-
++
+ /* request.content_length < SSIZE_MAX, see request.c */
+ ltostr(buf, con->request.content_length);
+ cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
+ cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
+ cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
+ cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
+-
++
+ /* for valgrind */
+ if (NULL != (s = getenv("LD_PRELOAD"))) {
+ cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
+@@ -863,24 +862,24 @@
+ cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
+ }
+ #endif
+-
++
+ for (n = 0; n < con->request.headers->used; n++) {
+ data_string *ds;
+-
++
+ ds = (data_string *)con->request.headers->data[n];
+-
++
+ if (ds->value->used && ds->key->used) {
+ size_t j;
+-
++
+ buffer_reset(p->tmp_buf);
+-
++
+ if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
+ buffer_copy_string(p->tmp_buf, "HTTP_");
+ p->tmp_buf->used--; /* strip \0 after HTTP_ */
+ }
+-
++
+ buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
+-
++
+ for (j = 0; j < ds->key->used - 1; j++) {
+ char cr = '_';
+ if (light_isalpha(ds->key->ptr[j])) {
+@@ -893,46 +892,46 @@
+ p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
+ }
+ p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
+-
++
+ cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
+ }
+ }
+-
++
+ for (n = 0; n < con->environment->used; n++) {
+ data_string *ds;
+-
++
+ ds = (data_string *)con->environment->data[n];
+-
++
+ if (ds->value->used && ds->key->used) {
+ size_t j;
+-
++
+ buffer_reset(p->tmp_buf);
+-
++
+ buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
+-
++
+ for (j = 0; j < ds->key->used - 1; j++) {
+- p->tmp_buf->ptr[p->tmp_buf->used++] =
+- isalpha((unsigned char)ds->key->ptr[j]) ?
++ p->tmp_buf->ptr[p->tmp_buf->used++] =
++ isalpha((unsigned char)ds->key->ptr[j]) ?
+ toupper((unsigned char)ds->key->ptr[j]) : '_';
+ }
+ p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
+-
++
+ cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
+ }
+ }
+-
++
+ if (env.size == env.used) {
+ env.size += 16;
+ env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
+ }
+-
++
+ env.ptr[env.used] = NULL;
+-
++
+ /* set up args */
+ argc = 3;
+ args = malloc(sizeof(*args) * argc);
+ i = 0;
+-
++
+ if (cgi_handler->used > 1) {
+ args[i++] = cgi_handler->ptr;
+ }
+@@ -942,7 +941,7 @@
+ /* search for the last / */
+ if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
+ *c = '\0';
+-
++
+ /* change to the physical directory */
+ if (-1 == chdir(con->physical.path->ptr)) {
+ log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
+@@ -954,12 +953,12 @@
+ for (i = 3; i < 256; i++) {
+ if (i != srv->errorlog_fd) close(i);
+ }
+-
++
+ /* exec the cgi */
+ execve(args[0], args, env.ptr);
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
+-
++
+ /* */
+ SEGFAULT();
+ break;
+@@ -974,11 +973,11 @@
+
+ close(from_cgi_fds[1]);
+ close(to_cgi_fds[0]);
+-
++
+ if (con->request.content_length) {
+ chunkqueue *cq = con->request_content_queue;
+ chunk *c;
+-
++
+ assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
+
+ /* there is content to send */
+@@ -993,16 +992,16 @@
+ if (-1 == c->file.fd && /* open the file if not already open */
+ -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+-
++
+ close(from_cgi_fds[0]);
+ close(to_cgi_fds[1]);
+ return -1;
+ }
+
+ c->file.mmap.length = c->file.length;
+-
++
+ if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
+- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
++ log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
+ strerror(errno), c->file.name, c->file.fd);
+
+ close(from_cgi_fds[0]);
+@@ -1012,7 +1011,7 @@
+
+ close(c->file.fd);
+ c->file.fd = -1;
+-
++
+ /* chunk_reset() or chunk_free() will cleanup for us */
+ }
+
+@@ -1020,7 +1019,7 @@
+ switch(errno) {
+ case ENOSPC:
+ con->http_status = 507;
+-
++
+ break;
+ default:
+ con->http_status = 403;
+@@ -1033,7 +1032,7 @@
+ switch(errno) {
+ case ENOSPC:
+ con->http_status = 507;
+-
++
+ break;
+ default:
+ con->http_status = 403;
+@@ -1056,103 +1055,100 @@
+ }
+
+ close(to_cgi_fds[1]);
+-
++
+ /* register PID and wait for them asyncronously */
+ con->mode = p->id;
+ buffer_reset(con->physical.path);
+-
++
+ hctx = cgi_handler_ctx_init();
+-
++
+ hctx->remote_conn = con;
+ hctx->plugin_data = p;
+ hctx->pid = pid;
+ hctx->fd = from_cgi_fds[0];
+ hctx->fde_ndx = -1;
+-
++
+ con->plugin_ctx[p->id] = hctx;
+-
++
+ fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
+-
++
+ if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
+-
++
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+ fdevent_unregister(srv->ev, hctx->fd);
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
+-
++
+ close(hctx->fd);
+-
++
+ cgi_handler_ctx_free(hctx);
+-
++
+ con->plugin_ctx[p->id] = NULL;
+-
++
+ return -1;
+ }
+-
++
+ break;
+ }
+ }
+-
++
+ return 0;
+ #else
+ return -1;
+ #endif
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(cgi);
+-
++
++ PATCH_OPTION(cgi);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
+- PATCH(cgi);
++ PATCH_OPTION(cgi);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(cgi_is_handled) {
+ size_t k, s_len;
+ plugin_data *p = p_d;
+ buffer *fn = con->physical.path;
+-
++
+ if (fn->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_cgi_patch_connection(srv, con, p);
+-
++
+ s_len = fn->used - 1;
+-
++
+ for (k = 0; k < p->conf.cgi->used; k++) {
+ data_string *ds = (data_string *)p->conf.cgi->data[k];
+ size_t ct_len = ds->key->used - 1;
+-
++
+ if (ds->key->used == 0) continue;
+ if (s_len < ct_len) continue;
+-
++
+ if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
+ if (cgi_create_env(srv, con, p, ds->value)) {
+ con->http_status = 500;
+-
++
+ buffer_reset(con->physical.path);
+ return HANDLER_FINISHED;
+ }
+@@ -1160,7 +1156,7 @@
+ break;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -1168,11 +1164,11 @@
+ plugin_data *p = p_d;
+ size_t ndx;
+ /* the trigger handle only cares about lonely PID which we have to wait for */
+-#ifndef __WIN32
++#ifndef _WIN32
+
+ for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
+ int status;
+-
++
+ switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
+ case 0:
+ /* not finished yet */
+@@ -1182,7 +1178,7 @@
+ break;
+ case -1:
+ log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ default:
+
+@@ -1193,16 +1189,16 @@
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
+ }
+-
++
+ cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
+- /* del modified the buffer structure
++ /* del modified the buffer structure
+ * and copies the last entry to the current one
+ * -> recheck the current index
+ */
+ ndx--;
+ }
+ }
+-#endif
++#endif
+ return HANDLER_GO_ON;
+ }
+
+@@ -1210,15 +1206,15 @@
+ int status;
+ plugin_data *p = p_d;
+ handler_ctx *hctx = con->plugin_ctx[p->id];
+-
++
+ if (con->mode != p->id) return HANDLER_GO_ON;
+ if (NULL == hctx) return HANDLER_GO_ON;
+-
++
+ #if 0
+ log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
+-#endif
++#endif
+ if (hctx->pid == 0) return HANDLER_FINISHED;
+-#ifndef __WIN32
++#ifndef _WIN32
+ switch(waitpid(hctx->pid, &status, WNOHANG)) {
+ case 0:
+ /* we only have for events here if we don't have the header yet,
+@@ -1228,61 +1224,61 @@
+ return HANDLER_WAIT_FOR_EVENT;
+ case -1:
+ if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
+-
++
+ if (errno == ECHILD && con->file_started == 0) {
+ /*
+- * second round but still not response
++ * second round but still not response
+ */
+- return HANDLER_WAIT_FOR_EVENT;
++ return HANDLER_WAIT_FOR_EVENT;
+ }
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
+ con->mode = DIRECT;
+ con->http_status = 500;
+-
++
+ hctx->pid = 0;
+-
++
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+ fdevent_unregister(srv->ev, hctx->fd);
+-
++
+ if (close(hctx->fd)) {
+ log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
+ }
+-
++
+ cgi_handler_ctx_free(hctx);
+-
++
+ con->plugin_ctx[p->id] = NULL;
+-
++
+ return HANDLER_FINISHED;
+ default:
+- /* cgi process exited cleanly
+- *
+- * check if we already got the response
++ /* cgi process exited cleanly
++ *
++ * check if we already got the response
+ */
+-
++
+ if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
+-
++
+ if (WIFEXITED(status)) {
+ /* nothing */
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
+-
++
+ con->mode = DIRECT;
+ con->http_status = 500;
+-
++
+ }
+-
++
+ hctx->pid = 0;
+-
++
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+ fdevent_unregister(srv->ev, hctx->fd);
+-
++
+ if (close(hctx->fd)) {
+ log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
+ }
+-
++
+ cgi_handler_ctx_free(hctx);
+-
++
+ con->plugin_ctx[p->id] = NULL;
+ return HANDLER_FINISHED;
+ }
+@@ -1306,8 +1302,8 @@
+ p->init = mod_cgi_init;
+ p->cleanup = mod_cgi_free;
+ p->set_defaults = mod_fastcgi_set_defaults;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cml.c lighttpd-1.4.12/src/mod_cml.c
+--- lighttpd-1.4.11/src/mod_cml.c 2006-01-30 13:51:48.000000000 +0200
++++ lighttpd-1.4.12/src/mod_cml.c 2006-07-11 21:23:39.000000000 +0300
+@@ -4,7 +4,6 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <errno.h>
+-#include <unistd.h>
+ #include <stdio.h>
+
+ #include "buffer.h"
+@@ -20,50 +19,50 @@
+ /* init the plugin data */
+ INIT_FUNC(mod_cml_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->basedir = buffer_init();
+ p->baseurl = buffer_init();
+ p->trigger_handler = buffer_init();
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_cml_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ buffer_free(s->ext);
+-
++
+ buffer_free(s->mc_namespace);
+ buffer_free(s->power_magnet);
+ array_free(s->mc_hosts);
+-
++
+ #if defined(HAVE_MEMCACHE_H)
+ if (s->mc) mc_free(s->mc);
+ #endif
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->trigger_handler);
+ buffer_free(p->basedir);
+ buffer_free(p->baseurl);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -72,22 +71,22 @@
+ SETDEFAULTS_FUNC(mod_cml_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { "cml.power-magnet", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = malloc(sizeof(plugin_config));
+ s->ext = buffer_init();
+ s->mc_hosts = array_init();
+@@ -96,87 +95,84 @@
+ #if defined(HAVE_MEMCACHE_H)
+ s->mc = NULL;
+ #endif
+-
++
+ cv[0].destination = s->ext;
+ cv[1].destination = s->mc_hosts;
+ cv[2].destination = s->mc_namespace;
+ cv[3].destination = s->power_magnet;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (s->mc_hosts->used) {
+ #if defined(HAVE_MEMCACHE_H)
+ size_t k;
+ s->mc = mc_new();
+-
++
+ for (k = 0; k < s->mc_hosts->used; k++) {
+ data_string *ds = (data_string *)s->mc_hosts->data[k];
+-
++
+ if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "connection to host failed:",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "connection to host failed:",
+ ds->value);
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+ #else
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
+ return HANDLER_ERROR;
+ #endif
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(ext);
++
++ PATCH_OPTION(ext);
+ #if defined(HAVE_MEMCACHE_H)
+- PATCH(mc);
++ PATCH_OPTION(mc);
+ #endif
+- PATCH(mc_namespace);
+- PATCH(power_magnet);
+-
++ PATCH_OPTION(mc_namespace);
++ PATCH_OPTION(power_magnet);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
+- PATCH(ext);
++ PATCH_OPTION(ext);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
+ #if defined(HAVE_MEMCACHE_H)
+- PATCH(mc);
++ PATCH_OPTION(mc);
+ #endif
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
+- PATCH(mc_namespace);
++ PATCH_OPTION(mc_namespace);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
+- PATCH(power_magnet);
++ PATCH_OPTION(power_magnet);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
+ buffer *b;
+@@ -187,57 +183,57 @@
+ b = p->baseurl;
+ buffer_copy_string_buffer(b, con->uri.path);
+ for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
+-
++
+ if (*c == '/') {
+ b->used = c - b->ptr + 2;
+ *(c+1) = '\0';
+ }
+-
++
+ b = p->basedir;
+ buffer_copy_string_buffer(b, con->physical.path);
+ for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
+-
++
+ if (*c == '/') {
+ b->used = c - b->ptr + 2;
+ *(c+1) = '\0';
+ }
+-
++
+
+ /* prepare variables
+ * - cookie-based
+ * - get-param-based
+ */
+-
++
+ return cache_parse_lua(srv, con, p, cml_file);
+-
++
+ }
+
+ URIHANDLER_FUNC(mod_cml_power_magnet) {
+ plugin_data *p = p_d;
+-
++
+ mod_cml_patch_connection(srv, con, p);
+-
++
+ buffer_reset(p->basedir);
+ buffer_reset(p->baseurl);
+ buffer_reset(p->trigger_handler);
+
+ if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
+-
+- /*
++
++ /*
+ * power-magnet:
+ * cml.power-magnet = server.docroot + "/rewrite.cml"
+ *
+ * is called on EACH request, take the original REQUEST_URI and modifies the
+- * request header as neccesary.
++ * request header as neccesary.
+ *
+ * First use:
+ * if file_exists("/maintainance.html") {
+ * output_include = ( "/maintainance.html" )
+- * return CACHE_HIT
++ * return CACHE_HIT
+ * }
+ *
+ * as we only want to rewrite HTML like requests we should cover it in a conditional
+- *
++ *
+ * */
+
+ switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
+@@ -266,20 +262,20 @@
+
+ URIHANDLER_FUNC(mod_cml_is_handled) {
+ plugin_data *p = p_d;
+-
++
+ if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
+-
++
+ mod_cml_patch_connection(srv, con, p);
+-
++
+ buffer_reset(p->basedir);
+ buffer_reset(p->baseurl);
+ buffer_reset(p->trigger_handler);
+
+ if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
+-
++
+ if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
+ return HANDLER_GO_ON;
+- }
++ }
+
+ switch(cache_call_lua(srv, con, p, con->physical.path)) {
+ case -1:
+@@ -311,15 +307,15 @@
+ int mod_cml_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("cache");
+-
++
+ p->init = mod_cml_init;
+ p->cleanup = mod_cml_free;
+ p->set_defaults = mod_cml_set_defaults;
+-
++
+ p->handle_subrequest_start = mod_cml_is_handled;
+ p->handle_physical = mod_cml_power_magnet;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cml.h lighttpd-1.4.12/src/mod_cml.h
+--- lighttpd-1.4.11/src/mod_cml.h 2006-01-30 13:51:35.000000000 +0200
++++ lighttpd-1.4.12/src/mod_cml.h 2006-07-11 21:23:39.000000000 +0300
+@@ -16,10 +16,10 @@
+
+ typedef struct {
+ buffer *ext;
+-
++
+ array *mc_hosts;
+ buffer *mc_namespace;
+-#if defined(HAVE_MEMCACHE_H)
++#if defined(HAVE_MEMCACHE_H)
+ struct memcache *mc;
+ #endif
+ buffer *power_magnet;
+@@ -27,15 +27,15 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *basedir;
+ buffer *baseurl;
+-
++
+ buffer *trigger_handler;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cml_funcs.c lighttpd-1.4.12/src/mod_cml_funcs.c
+--- lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200
++++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-11 21:23:40.000000000 +0300
+@@ -4,8 +4,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <errno.h>
+-#include <unistd.h>
+-#include <dirent.h>
++
+ #include <stdio.h>
+
+ #include "buffer.h"
+@@ -13,6 +12,7 @@
+ #include "log.h"
+ #include "plugin.h"
+ #include "response.h"
++#include "sys-files.h"
+
+ #include "mod_cml.h"
+ #include "mod_cml_funcs.h"
+@@ -30,7 +30,7 @@
+ #ifdef USE_OPENSSL
+ #define IN const
+ #else
+-#define IN
++#define IN
+ #endif
+ #define OUT
+
+@@ -42,29 +42,29 @@
+ buffer b;
+ char hex[33];
+ int n = lua_gettop(L);
+-
++
+ b.ptr = hex;
+ b.used = 0;
+ b.size = sizeof(hex);
+-
++
+ if (n != 1) {
+ lua_pushstring(L, "md5: expected one argument");
+ lua_error(L);
+ }
+-
++
+ if (!lua_isstring(L, 1)) {
+ lua_pushstring(L, "md5: argument has to be a string");
+ lua_error(L);
+ }
+-
++
+ MD5_Init(&Md5Ctx);
+ MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
+ MD5_Final(HA1, &Md5Ctx);
+-
++
+ buffer_copy_string_hex(&b, (char *)HA1, 16);
+-
++
+ lua_pushstring(L, b.ptr);
+-
++
+ return 1;
+ }
+
+@@ -72,37 +72,37 @@
+ int f_file_mtime(lua_State *L) {
+ struct stat st;
+ int n = lua_gettop(L);
+-
++
+ if (n != 1) {
+ lua_pushstring(L, "file_mtime: expected one argument");
+ lua_error(L);
+ }
+-
++
+ if (!lua_isstring(L, 1)) {
+ lua_pushstring(L, "file_mtime: argument has to be a string");
+ lua_error(L);
+ }
+-
++
+ if (-1 == stat(lua_tostring(L, 1), &st)) {
+ lua_pushnil(L);
+ return 1;
+ }
+-
++
+ lua_pushnumber(L, st.st_mtime);
+-
++
+ return 1;
+ }
+-
++#ifndef _WIN32
+ int f_dir_files_iter(lua_State *L) {
+ DIR *d;
+ struct dirent *de;
+-
++
+ d = lua_touserdata(L, lua_upvalueindex(1));
+-
++
+ if (NULL == (de = readdir(d))) {
+ /* EOF */
+ closedir(d);
+-
++
+ return 0;
+ } else {
+ lua_pushstring(L, de->d_name);
+@@ -113,75 +113,75 @@
+ int f_dir_files(lua_State *L) {
+ DIR *d;
+ int n = lua_gettop(L);
+-
++
+ if (n != 1) {
+ lua_pushstring(L, "dir_files: expected one argument");
+ lua_error(L);
+ }
+-
++
+ if (!lua_isstring(L, 1)) {
+ lua_pushstring(L, "dir_files: argument has to be a string");
+ lua_error(L);
+ }
+-
+- /* check if there is a valid DIR handle on the stack */
++
++ /* check if there is a valid DIR handle on the stack */
+ if (NULL == (d = opendir(lua_tostring(L, 1)))) {
+ lua_pushnil(L);
+ return 1;
+ }
+-
++
+ /* push d into registry */
+ lua_pushlightuserdata(L, d);
+ lua_pushcclosure(L, f_dir_files_iter, 1);
+-
++
+ return 1;
+ }
+-
++#endif
+ int f_file_isreg(lua_State *L) {
+ struct stat st;
+ int n = lua_gettop(L);
+-
++
+ if (n != 1) {
+ lua_pushstring(L, "file_isreg: expected one argument");
+ lua_error(L);
+ }
+-
++
+ if (!lua_isstring(L, 1)) {
+ lua_pushstring(L, "file_isreg: argument has to be a string");
+ lua_error(L);
+ }
+-
++
+ if (-1 == stat(lua_tostring(L, 1), &st)) {
+ lua_pushnil(L);
+ return 1;
+ }
+-
++
+ lua_pushnumber(L, S_ISREG(st.st_mode));
+-
++
+ return 1;
+ }
+
+ int f_file_isdir(lua_State *L) {
+ struct stat st;
+ int n = lua_gettop(L);
+-
++
+ if (n != 1) {
+ lua_pushstring(L, "file_isreg: expected one argument");
+ lua_error(L);
+ }
+-
++
+ if (!lua_isstring(L, 1)) {
+ lua_pushstring(L, "file_isreg: argument has to be a string");
+ lua_error(L);
+ }
+-
++
+ if (-1 == stat(lua_tostring(L, 1), &st)) {
+ lua_pushnil(L);
+ return 1;
+ }
+-
++
+ lua_pushnumber(L, S_ISDIR(st.st_mode));
+-
++
+ return 1;
+ }
+
+@@ -192,33 +192,33 @@
+ char *r;
+ int n = lua_gettop(L);
+ struct memcache *mc;
+-
++
+ if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
+ lua_pushstring(L, "where is my userdata ?");
+ lua_error(L);
+ }
+-
++
+ mc = lua_touserdata(L, lua_upvalueindex(1));
+-
++
+ if (n != 1) {
+ lua_pushstring(L, "expected one argument");
+ lua_error(L);
+ }
+-
++
+ if (!lua_isstring(L, 1)) {
+ lua_pushstring(L, "argument has to be a string");
+ lua_error(L);
+ }
+-
+- if (NULL == (r = mc_aget(mc,
++
++ if (NULL == (r = mc_aget(mc,
+ lua_tostring(L, 1), lua_strlen(L, 1)))) {
+-
++
+ lua_pushboolean(L, 0);
+ return 1;
+ }
+-
++
+ free(r);
+-
++
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+@@ -226,74 +226,74 @@
+ int f_memcache_get_string(lua_State *L) {
+ char *r;
+ int n = lua_gettop(L);
+-
++
+ struct memcache *mc;
+-
++
+ if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
+ lua_pushstring(L, "where is my userdata ?");
+ lua_error(L);
+ }
+-
++
+ mc = lua_touserdata(L, lua_upvalueindex(1));
+-
+-
++
++
+ if (n != 1) {
+ lua_pushstring(L, "expected one argument");
+ lua_error(L);
+ }
+-
++
+ if (!lua_isstring(L, 1)) {
+ lua_pushstring(L, "argument has to be a string");
+ lua_error(L);
+ }
+-
+- if (NULL == (r = mc_aget(mc,
++
++ if (NULL == (r = mc_aget(mc,
+ lua_tostring(L, 1), lua_strlen(L, 1)))) {
+ lua_pushnil(L);
+ return 1;
+ }
+-
++
+ lua_pushstring(L, r);
+-
++
+ free(r);
+-
++
+ return 1;
+ }
+
+ int f_memcache_get_long(lua_State *L) {
+ char *r;
+ int n = lua_gettop(L);
+-
++
+ struct memcache *mc;
+-
++
+ if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
+ lua_pushstring(L, "where is my userdata ?");
+ lua_error(L);
+ }
+-
++
+ mc = lua_touserdata(L, lua_upvalueindex(1));
+-
+-
++
++
+ if (n != 1) {
+ lua_pushstring(L, "expected one argument");
+ lua_error(L);
+ }
+-
++
+ if (!lua_isstring(L, 1)) {
+ lua_pushstring(L, "argument has to be a string");
+ lua_error(L);
+ }
+-
+- if (NULL == (r = mc_aget(mc,
++
++ if (NULL == (r = mc_aget(mc,
+ lua_tostring(L, 1), lua_strlen(L, 1)))) {
+ lua_pushnil(L);
+ return 1;
+ }
+-
++
+ lua_pushnumber(L, strtol(r, NULL, 10));
+-
++
+ free(r);
+-
++
+ return 1;
+ }
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cml_lua.c lighttpd-1.4.12/src/mod_cml_lua.c
+--- lighttpd-1.4.11/src/mod_cml_lua.c 2006-01-30 13:56:40.000000000 +0200
++++ lighttpd-1.4.12/src/mod_cml_lua.c 2006-07-11 21:23:40.000000000 +0300
+@@ -23,7 +23,7 @@
+ #ifdef USE_OPENSSL
+ #define IN const
+ #else
+-#define IN
++#define IN
+ #endif
+ #define OUT
+
+@@ -31,6 +31,7 @@
+
+ #include <lua.h>
+ #include <lualib.h>
++#include <lauxlib.h>
+
+ typedef struct {
+ stream st;
+@@ -39,11 +40,11 @@
+
+ static const char * load_file(lua_State *L, void *data, size_t *size) {
+ readme *rm = data;
+-
++
+ UNUSED(L);
+-
++
+ if (rm->done) return 0;
+-
++
+ *size = rm->st.size;
+ rm->done = 1;
+ return rm->st.start;
+@@ -51,47 +52,47 @@
+
+ static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
+ int curelem;
+-
++
+ lua_pushstring(L, varname);
+-
++
+ curelem = lua_gettop(L);
+ lua_gettable(L, LUA_GLOBALSINDEX);
+-
++
+ /* it should be a table */
+ if (!lua_isstring(L, curelem)) {
+ lua_settop(L, curelem - 1);
+-
++
+ return -1;
+ }
+-
++
+ buffer_copy_string(b, lua_tostring(L, curelem));
+-
++
+ lua_pop(L, 1);
+-
++
+ assert(curelem - 1 == lua_gettop(L));
+-
++
+ return 0;
+ }
+
+ static int lua_to_c_is_table(lua_State *L, const char *varname) {
+ int curelem;
+-
++
+ lua_pushstring(L, varname);
+-
++
+ curelem = lua_gettop(L);
+ lua_gettable(L, LUA_GLOBALSINDEX);
+-
++
+ /* it should be a table */
+ if (!lua_istable(L, curelem)) {
+ lua_settop(L, curelem - 1);
+-
++
+ return 0;
+ }
+-
++
+ lua_settop(L, curelem - 1);
+-
++
+ assert(curelem - 1 == lua_gettop(L));
+-
++
+ return 1;
+ }
+
+@@ -99,7 +100,7 @@
+ lua_pushlstring(L, key, key_len);
+ lua_pushlstring(L, val, val_len);
+ lua_settable(L, tbl);
+-
++
+ return 0;
+ }
+
+@@ -108,21 +109,21 @@
+ size_t is_key = 1;
+ size_t i;
+ char *key = NULL, *val = NULL;
+-
++
+ key = qrystr->ptr;
+-
++
+ /* we need the \0 */
+ for (i = 0; i < qrystr->used; i++) {
+ switch(qrystr->ptr[i]) {
+ case '=':
+ if (is_key) {
+ val = qrystr->ptr + i + 1;
+-
++
+ qrystr->ptr[i] = '\0';
+-
++
+ is_key = 0;
+ }
+-
++
+ break;
+ case '&':
+ case '\0': /* fin symbol */
+@@ -131,19 +132,19 @@
+
+ /* terminate the value */
+ qrystr->ptr[i] = '\0';
+-
+- c_to_lua_push(L, tbl,
++
++ c_to_lua_push(L, tbl,
+ key, strlen(key),
+ val, strlen(val));
+ }
+-
++
+ key = qrystr->ptr + i + 1;
+ val = NULL;
+ is_key = 1;
+ break;
+ }
+ }
+-
++
+ return 0;
+ }
+ #if 0
+@@ -151,21 +152,21 @@
+ data_unset *d;
+
+ UNUSED(srv);
+-
++
+ if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
+ data_string *ds = (data_string *)d;
+ size_t key = 0, value = 0;
+ size_t is_key = 1, is_sid = 0;
+ size_t i;
+-
++
+ /* found COOKIE */
+ if (!DATA_IS_STRING(d)) return -1;
+ if (ds->value->used == 0) return -1;
+-
++
+ if (ds->value->ptr[0] == '\0' ||
+ ds->value->ptr[0] == '=' ||
+ ds->value->ptr[0] == ';') return -1;
+-
++
+ buffer_reset(p->session_id);
+ for (i = 0; i < ds->value->used; i++) {
+ switch(ds->value->ptr[i]) {
+@@ -176,16 +177,16 @@
+ is_sid = 1;
+ }
+ value = i + 1;
+-
++
+ is_key = 0;
+ }
+-
++
+ break;
+ case ';':
+ if (is_sid) {
+ buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
+ }
+-
++
+ is_sid = 0;
+ key = i + 1;
+ value = 0;
+@@ -204,48 +205,43 @@
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+ #endif
+
+ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
+- lua_State *L;
++ lua_State *L;
+ readme rm;
+ int ret = -1;
+ buffer *b = buffer_init();
+ int header_tbl = 0;
+-
++
+ rm.done = 0;
+ stream_open(&rm.st, fn);
+-
++
+ /* push the lua file to the interpreter and see what happends */
+- L = lua_open();
+-
+- luaopen_base(L);
+- luaopen_table(L);
+- luaopen_string(L);
+- luaopen_math(L);
+- luaopen_io(L);
+-
++ L = luaL_newstate();
++ luaL_openlibs(L);
++
+ /* register functions */
+ lua_register(L, "md5", f_crypto_md5);
+ lua_register(L, "file_mtime", f_file_mtime);
+ lua_register(L, "file_isreg", f_file_isreg);
+ lua_register(L, "file_isdir", f_file_isreg);
+ lua_register(L, "dir_files", f_dir_files);
+-
++
+ #ifdef HAVE_MEMCACHE_H
+ lua_pushliteral(L, "memcache_get_long");
+ lua_pushlightuserdata(L, p->conf.mc);
+ lua_pushcclosure(L, f_memcache_get_long, 1);
+ lua_settable(L, LUA_GLOBALSINDEX);
+-
++
+ lua_pushliteral(L, "memcache_get_string");
+ lua_pushlightuserdata(L, p->conf.mc);
+ lua_pushcclosure(L, f_memcache_get_string, 1);
+ lua_settable(L, LUA_GLOBALSINDEX);
+-
++
+ lua_pushliteral(L, "memcache_exists");
+ lua_pushlightuserdata(L, p->conf.mc);
+ lua_pushcclosure(L, f_memcache_exists, 1);
+@@ -255,11 +251,11 @@
+ lua_pushliteral(L, "request");
+ lua_newtable(L);
+ lua_settable(L, LUA_GLOBALSINDEX);
+-
++
+ lua_pushliteral(L, "request");
+ header_tbl = lua_gettop(L);
+ lua_gettable(L, LUA_GLOBALSINDEX);
+-
++
+ c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
+ c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
+ c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
+@@ -267,84 +263,84 @@
+ if (!buffer_is_empty(con->request.pathinfo)) {
+ c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
+ }
+-
++
+ c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
+ c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
+-
++
+ /* register GET parameter */
+ lua_pushliteral(L, "get");
+ lua_newtable(L);
+ lua_settable(L, LUA_GLOBALSINDEX);
+-
++
+ lua_pushliteral(L, "get");
+ header_tbl = lua_gettop(L);
+ lua_gettable(L, LUA_GLOBALSINDEX);
+-
++
+ buffer_copy_string_buffer(b, con->uri.query);
+ cache_export_get_params(L, header_tbl, b);
+ buffer_reset(b);
+
+- /* 2 default constants */
++ /* 2 default constants */
+ lua_pushliteral(L, "CACHE_HIT");
+ lua_pushboolean(L, 0);
+ lua_settable(L, LUA_GLOBALSINDEX);
+-
++
+ lua_pushliteral(L, "CACHE_MISS");
+ lua_pushboolean(L, 1);
+ lua_settable(L, LUA_GLOBALSINDEX);
+-
++
+ /* load lua program */
+ if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ lua_tostring(L,-1));
+-
++
+ goto error;
+ }
+-
++
+ /* get return value */
+ ret = (int)lua_tonumber(L, -1);
+ lua_pop(L, 1);
+-
+- /* fetch the data from lua */
++
++ /* fetch the data from lua */
+ lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
+-
++
+ if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
+ }
+-
++
+ if (ret == 0) {
+ /* up to now it is a cache-hit, check if all files exist */
+-
++
+ int curelem;
+ time_t mtime = 0;
+-
++
+ if (!lua_to_c_is_table(L, "output_include")) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "output_include is missing or not a table");
+ ret = -1;
+-
++
+ goto error;
+ }
+-
++
+ lua_pushstring(L, "output_include");
+-
++
+ curelem = lua_gettop(L);
+ lua_gettable(L, LUA_GLOBALSINDEX);
+
+ /* HOW-TO build a etag ?
+- * as we don't just have one file we have to take the stat()
++ * as we don't just have one file we have to take the stat()
+ * from all base files, merge them and build the etag from
+ * it later.
+- *
++ *
+ * The mtime of the content is the mtime of the freshest base file
+- *
++ *
+ * */
+-
++
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, curelem) != 0) {
+ stat_cache_entry *sce = NULL;
+ /* key' is at index -2 and value' at index -1 */
+-
++
+ if (lua_isstring(L, -1)) {
+ const char *s = lua_tostring(L, -1);
+
+@@ -364,18 +360,18 @@
+ /* a file is missing, call the handler to generate it */
+ if (!buffer_is_empty(p->trigger_handler)) {
+ ret = 1; /* cache-miss */
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "a file is missing, calling handler");
+-
++
+ break;
+ } else {
+ /* handler not set -> 500 */
+ ret = -1;
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "a file missing and no handler set");
+-
++
+ break;
+ }
+ break;
+@@ -393,12 +389,12 @@
+ "not a string");
+ break;
+ }
+-
++
+ lua_pop(L, 1); /* removes value'; keeps key' for next iteration */
+ }
+-
++
+ lua_settop(L, curelem - 1);
+-
++
+ if (ret == 0) {
+ data_string *ds;
+ char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
+@@ -410,9 +406,9 @@
+
+ /* no Last-Modified specified */
+ if ((mtime) && (NULL == ds)) {
+-
++
+ strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
+-
++
+ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
+
+
+@@ -428,9 +424,9 @@
+ tbuf.used = 0;
+ tbuf.ptr = NULL;
+ }
+-
++
+ if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
+- /* ok, the client already has our content,
++ /* ok, the client already has our content,
+ * no need to send it again */
+
+ chunkqueue_reset(con->write_queue);
+@@ -440,24 +436,24 @@
+ chunkqueue_reset(con->write_queue);
+ }
+ }
+-
++
+ if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
+ /* cache-miss */
+ buffer_copy_string_buffer(con->uri.path, p->baseurl);
+ buffer_append_string_buffer(con->uri.path, p->trigger_handler);
+-
++
+ buffer_copy_string_buffer(con->physical.path, p->basedir);
+ buffer_append_string_buffer(con->physical.path, p->trigger_handler);
+-
++
+ chunkqueue_reset(con->write_queue);
+ }
+-
++
+ error:
+ lua_close(L);
+-
++
+ stream_close(&rm.st);
+ buffer_free(b);
+-
++
+ return ret /* cache-error */;
+ }
+ #else
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_compress.c lighttpd-1.4.12/src/mod_compress.c
+--- lighttpd-1.4.11/src/mod_compress.c 2005-11-18 13:49:14.000000000 +0200
++++ lighttpd-1.4.12/src/mod_compress.c 2006-07-11 21:23:40.000000000 +0300
+@@ -2,7 +2,6 @@
+ #include <sys/stat.h>
+
+ #include <fcntl.h>
+-#include <unistd.h>
+ #include <ctype.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -14,6 +13,7 @@
+ #include "buffer.h"
+ #include "response.h"
+ #include "stat_cache.h"
++#include "http_chunk.h"
+
+ #include "plugin.h"
+
+@@ -33,6 +33,7 @@
+ #endif
+
+ #include "sys-mmap.h"
++#include "sys-files.h"
+
+ /* request: accept-encoding */
+ #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
+@@ -55,97 +56,127 @@
+ PLUGIN_DATA;
+ buffer *ofn;
+ buffer *b;
+-
++
+ plugin_config **config_storage;
+- plugin_config conf;
++ plugin_config conf;
+ } plugin_data;
+
+ INIT_FUNC(mod_compress_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->ofn = buffer_init();
+ p->b = buffer_init();
+-
++
+ return p;
+ }
+
+ FREE_FUNC(mod_compress_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ buffer_free(p->ofn);
+ buffer_free(p->b);
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+-
++
+ array_free(s->compress);
+ buffer_free(s->compress_cache_dir);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
+-
++
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
++void mkdir_recursive(const char *dir) {
++
++ char dir_copy[256];
++ char *p = dir_copy;
++
++ if (!dir || !dir[0])
++ return;
++
++ strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
++
++ while ((p = strchr(p + 1, '/')) != NULL) {
++
++ *p = '\0';
++ if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
++ return;
++
++ *p++ = '/';
++ }
++
++ mkdir(dir, 0700);
++}
++
+ SETDEFAULTS_FUNC(mod_compress_setdefaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "compress.cache-dir", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { "compress.filetype", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
+ { "compress.max-filesize", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->compress_cache_dir = buffer_init();
+ s->compress = array_init();
+ s->compress_max_filesize = 0;
+-
++
+ cv[0].destination = s->compress_cache_dir;
+ cv[1].destination = s->compress;
+ cv[2].destination = &(s->compress_max_filesize);
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (!buffer_is_empty(s->compress_cache_dir)) {
+ struct stat st;
+ if (0 != stat(s->compress_cache_dir->ptr, &st)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
+ s->compress_cache_dir, strerror(errno));
+-
+- return HANDLER_ERROR;
++ mkdir_recursive(s->compress_cache_dir->ptr);
++
++ if (0 != stat(s->compress_cache_dir->ptr, &st)) {
++
++ log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
++ s->compress_cache_dir, strerror(errno));
++
++ return HANDLER_ERROR;
++ }
+ }
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+-
++
+ }
+
+ #ifdef USE_ZLIB
+@@ -153,32 +184,32 @@
+ unsigned char *c;
+ unsigned long crc;
+ z_stream z;
+-
++
+ UNUSED(srv);
+ UNUSED(con);
+
+ z.zalloc = Z_NULL;
+ z.zfree = Z_NULL;
+ z.opaque = Z_NULL;
+-
+- if (Z_OK != deflateInit2(&z,
++
++ if (Z_OK != deflateInit2(&z,
+ Z_DEFAULT_COMPRESSION,
+- Z_DEFLATED,
++ Z_DEFLATED,
+ -MAX_WBITS, /* supress zlib-header */
+ 8,
+ Z_DEFAULT_STRATEGY)) {
+ return -1;
+ }
+-
++
+ z.next_in = (unsigned char *)start;
+ z.avail_in = st_size;
+ z.total_in = 0;
+-
+-
++
++
+ buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
+-
++
+ /* write gzip header */
+-
++
+ c = (unsigned char *)p->b->ptr;
+ c[0] = 0x1f;
+ c[1] = 0x8b;
+@@ -190,24 +221,24 @@
+ c[7] = (mtime >> 24) & 0xff;
+ c[8] = 0x00; /* extra flags */
+ c[9] = 0x03; /* UNIX */
+-
++
+ p->b->used = 10;
+ z.next_out = (unsigned char *)p->b->ptr + p->b->used;
+ z.avail_out = p->b->size - p->b->used - 8;
+ z.total_out = 0;
+-
++
+ if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
+ deflateEnd(&z);
+ return -1;
+ }
+-
++
+ /* trailer */
+ p->b->used += z.total_out;
+-
++
+ crc = generate_crc32c(start, st_size);
+-
++
+ c = (unsigned char *)p->b->ptr + p->b->used;
+-
++
+ c[0] = (crc >> 0) & 0xff;
+ c[1] = (crc >> 8) & 0xff;
+ c[2] = (crc >> 16) & 0xff;
+@@ -221,51 +252,51 @@
+ if (Z_OK != deflateEnd(&z)) {
+ return -1;
+ }
+-
++
+ return 0;
+ }
+
+ static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
+ z_stream z;
+-
++
+ UNUSED(srv);
+ UNUSED(con);
+
+ z.zalloc = Z_NULL;
+ z.zfree = Z_NULL;
+ z.opaque = Z_NULL;
+-
+- if (Z_OK != deflateInit2(&z,
++
++ if (Z_OK != deflateInit2(&z,
+ Z_DEFAULT_COMPRESSION,
+- Z_DEFLATED,
++ Z_DEFLATED,
+ -MAX_WBITS, /* supress zlib-header */
+ 8,
+ Z_DEFAULT_STRATEGY)) {
+ return -1;
+ }
+-
++
+ z.next_in = start;
+ z.avail_in = st_size;
+ z.total_in = 0;
+-
++
+ buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
+-
++
+ z.next_out = (unsigned char *)p->b->ptr;
+ z.avail_out = p->b->size;
+ z.total_out = 0;
+-
++
+ if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
+ deflateEnd(&z);
+ return -1;
+ }
+-
++
+ /* trailer */
+ p->b->used += z.total_out;
+-
++
+ if (Z_OK != deflateEnd(&z)) {
+ return -1;
+ }
+-
++
+ return 0;
+ }
+
+@@ -274,48 +305,48 @@
+ #ifdef USE_BZ2LIB
+ static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
+ bz_stream bz;
+-
++
+ UNUSED(srv);
+ UNUSED(con);
+
+ bz.bzalloc = NULL;
+ bz.bzfree = NULL;
+ bz.opaque = NULL;
+-
+- if (BZ_OK != BZ2_bzCompressInit(&bz,
++
++ if (BZ_OK != BZ2_bzCompressInit(&bz,
+ 9, /* blocksize = 900k */
+ 0, /* no output */
+ 0)) { /* workFactor: default */
+ return -1;
+ }
+-
++
+ bz.next_in = (char *)start;
+ bz.avail_in = st_size;
+ bz.total_in_lo32 = 0;
+ bz.total_in_hi32 = 0;
+-
++
+ buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
+-
++
+ bz.next_out = p->b->ptr;
+ bz.avail_out = p->b->size;
+ bz.total_out_lo32 = 0;
+ bz.total_out_hi32 = 0;
+-
++
+ if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
+ BZ2_bzCompressEnd(&bz);
+ return -1;
+ }
+-
++
+ /* file is too large for now */
+ if (bz.total_out_hi32) return -1;
+-
++
+ /* trailer */
+ p->b->used = bz.total_out_lo32;
+-
++
+ if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
+ return -1;
+ }
+-
++
+ return 0;
+ }
+ #endif
+@@ -326,47 +357,50 @@
+ void *start;
+ const char *filename = fn->ptr;
+ ssize_t r;
+-
++ stat_cache_entry *compressed_sce = NULL;
++
++ if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
++
+ /* overflow */
+ if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
+-
+- /* don't mmap files > 128Mb
+- *
++
++ /* don't mmap files > 128Mb
++ *
+ * we could use a sliding window, but currently there is no need for it
+ */
+-
++
+ if (sce->st.st_size > 128 * 1024 * 1024) return -1;
+-
++
+ buffer_reset(p->ofn);
+ buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
+- BUFFER_APPEND_SLASH(p->ofn);
+-
++ PATHNAME_APPEND_SLASH(p->ofn);
++
+ if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
+ size_t offset = p->ofn->used - 1;
+ char *dir, *nextdir;
+-
++
+ buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
+-
++
+ buffer_copy_string_buffer(p->b, p->ofn);
+-
++
+ /* mkdir -p ... */
+ for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
+ *nextdir = '\0';
+-
++
+ if (-1 == mkdir(p->b->ptr, 0700)) {
+ if (errno != EEXIST) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
+-
++
+ return -1;
+ }
+ }
+-
++
+ *nextdir = '/';
+ }
+ } else {
+ buffer_append_string_buffer(p->ofn, con->uri.path);
+ }
+-
++
+ switch(type) {
+ case HTTP_ACCEPT_ENCODING_GZIP:
+ buffer_append_string(p->ofn, "-gzip-");
+@@ -381,55 +415,64 @@
+ log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type);
+ return -1;
+ }
+-
++
+ buffer_append_string_buffer(p->ofn, sce->etag);
+-
++
++
++ if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
++ /* file exists */
++
++ http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
++ con->file_finished = 1;
++
++ return 0;
++ }
++
+ if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
+ if (errno == EEXIST) {
+ /* cache-entry exists */
+-#if 0
+- log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
+-#endif
+- buffer_copy_string_buffer(con->physical.path, p->ofn);
+-
+- return 0;
++
+ }
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
+-
++
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
++ "creating cachefile", p->ofn,
++ "failed", strerror(errno));
++
+ return -1;
+ }
+-#if 0
+- log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
+-#endif
++
+ if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
+-
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
++ "opening plain-file", fn,
++ "failed", strerror(errno));
++
+ close(ofd);
+-
++
+ return -1;
+ }
+-
+-
++
++
+ if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
+-
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
++ "mmaping", fn,
++ "failed", strerror(errno));
++
+ close(ofd);
+ close(ifd);
+ return -1;
+ }
+-
++
+ switch(type) {
+ #ifdef USE_ZLIB
+- case HTTP_ACCEPT_ENCODING_GZIP:
++ case HTTP_ACCEPT_ENCODING_GZIP:
+ ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
+ break;
+- case HTTP_ACCEPT_ENCODING_DEFLATE:
++ case HTTP_ACCEPT_ENCODING_DEFLATE:
+ ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
+ break;
+ #endif
+ #ifdef USE_BZ2LIB
+- case HTTP_ACCEPT_ENCODING_BZIP2:
++ case HTTP_ACCEPT_ENCODING_BZIP2:
+ ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
+ break;
+ #endif
+@@ -437,26 +480,27 @@
+ ret = -1;
+ break;
+ }
+-
++
+ if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
+- munmap(start, sce->st.st_size);
++ munmap(start, sce->st.st_size);
+ close(ofd);
+ close(ifd);
+ return -1;
+ }
+-
++
+ if ((size_t)r != p->b->used) {
+-
++
+ }
+-
++
+ munmap(start, sce->st.st_size);
+ close(ofd);
+ close(ifd);
+-
++
+ if (ret != 0) return -1;
+-
+- buffer_copy_string_buffer(con->physical.path, p->ofn);
+-
++
++ http_chunk_append_file(srv, con, p->ofn, 0, r);
++ con->file_finished = 1;
++
+ return 0;
+ }
+
+@@ -465,43 +509,44 @@
+ int ret = -1;
+ void *start;
+ buffer *b;
+-
++
+ /* overflow */
+ if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
+-
++
+ /* don't mmap files > 128M
+- *
++ *
+ * we could use a sliding window, but currently there is no need for it
+ */
+-
++
+ if (sce->st.st_size > 128 * 1024 * 1024) return -1;
+-
+-
++
+ if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
+-
++
+ return -1;
+ }
+-
+-
+- if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
++
++ start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
++
++ close(ifd);
++
++ if (MAP_FAILED == start) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
+-
+- close(ifd);
++
+ return -1;
+ }
+-
++
+ switch(type) {
+ #ifdef USE_ZLIB
+- case HTTP_ACCEPT_ENCODING_GZIP:
++ case HTTP_ACCEPT_ENCODING_GZIP:
+ ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
+ break;
+- case HTTP_ACCEPT_ENCODING_DEFLATE:
++ case HTTP_ACCEPT_ENCODING_DEFLATE:
+ ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
+ break;
+ #endif
+ #ifdef USE_BZ2LIB
+- case HTTP_ACCEPT_ENCODING_BZIP2:
++ case HTTP_ACCEPT_ENCODING_BZIP2:
+ ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
+ break;
+ #endif
+@@ -509,69 +554,64 @@
+ ret = -1;
+ break;
+ }
+-
++
+ munmap(start, sce->st.st_size);
+- close(ifd);
+-
++
+ if (ret != 0) return -1;
+-
++
+ chunkqueue_reset(con->write_queue);
+ b = chunkqueue_get_append_buffer(con->write_queue);
+ buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
+-
++
+ buffer_reset(con->physical.path);
+-
++
+ con->file_finished = 1;
+ con->file_started = 1;
+-
++
+ return 0;
+ }
+
+-
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+
+- PATCH(compress_cache_dir);
+- PATCH(compress);
+- PATCH(compress_max_filesize);
+-
++ PATCH_OPTION(compress_cache_dir);
++ PATCH_OPTION(compress);
++ PATCH_OPTION(compress_max_filesize);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
+- PATCH(compress_cache_dir);
++ PATCH_OPTION(compress_cache_dir);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
+- PATCH(compress);
++ PATCH_OPTION(compress);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
+- PATCH(compress_max_filesize);
++ PATCH_OPTION(compress_max_filesize);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ PHYSICALPATH_FUNC(mod_compress_physical) {
+ plugin_data *p = p_d;
+ size_t m;
+ off_t max_fsize;
+ stat_cache_entry *sce = NULL;
+-
++
+ /* only GET and POST can get compressed */
+- if (con->request.http_method != HTTP_METHOD_GET &&
++ if (con->request.http_method != HTTP_METHOD_GET &&
+ con->request.http_method != HTTP_METHOD_POST) {
+ return HANDLER_GO_ON;
+ }
+@@ -579,46 +619,49 @@
+ if (buffer_is_empty(con->physical.path)) {
+ return HANDLER_GO_ON;
+ }
+-
++
+ mod_compress_patch_connection(srv, con, p);
+-
++
+ max_fsize = p->conf.compress_max_filesize;
+
+ stat_cache_get_entry(srv, con, con->physical.path, &sce);
+
+ /* don't compress files that are too large as we need to much time to handle them */
+ if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
+-
++
++ /* compressing the file might lead to larger files instead */
++ if (sce->st.st_size < 128) return HANDLER_GO_ON;
++
+ /* check if mimetype is in compress-config */
+ for (m = 0; m < p->conf.compress->used; m++) {
+ data_string *compress_ds = (data_string *)p->conf.compress->data[m];
+-
++
+ if (!compress_ds) {
+ log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
+-
++
+ return HANDLER_GO_ON;
+ }
+-
++
+ if (buffer_is_equal(compress_ds->value, sce->content_type)) {
+ /* mimetype found */
+ data_string *ds;
+-
++
+ /* the response might change according to Accept-Encoding */
+ response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
+-
++
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
+ int accept_encoding = 0;
+ char *value = ds->value->ptr;
+ int srv_encodings = 0;
+ int matched_encodings = 0;
+-
++
+ /* get client side support encodings */
+ if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
+ if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
+ if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
+ if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
+ if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
+-
++
+ /* get server side supported ones */
+ #ifdef USE_BZ2LIB
+ srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
+@@ -627,18 +670,31 @@
+ srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
+ srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
+ #endif
+-
++
+ /* find matching entries */
+ matched_encodings = accept_encoding & srv_encodings;
+-
++
+ if (matched_encodings) {
+ const char *dflt_gzip = "gzip";
+ const char *dflt_deflate = "deflate";
+ const char *dflt_bzip2 = "bzip2";
+-
++
+ const char *compression_name = NULL;
+ int compression_type = 0;
+-
++ buffer *mtime;
++
++ mtime = strftime_cache_get(srv, sce->st.st_mtime);
++ etag_mutate(con->physical.etag, sce->etag);
++
++ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
++ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
++
++ /* perhaps we don't even have to compress the file as the browser still has the
++ * current version */
++ if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
++ return HANDLER_FINISHED;
++ }
++
+ /* select best matching encoding */
+ if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
+ compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
+@@ -650,31 +706,21 @@
+ compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
+ compression_name = dflt_deflate;
+ }
+-
+- /* deflate it */
+- if (p->conf.compress_cache_dir->used) {
+- if (0 == deflate_file_to_file(srv, con, p,
+- con->physical.path, sce, compression_type)) {
+- buffer *mtime;
+-
+- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
+-
+- mtime = strftime_cache_get(srv, sce->st.st_mtime);
+- response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
+-
+- etag_mutate(con->physical.etag, sce->etag);
+- response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
+-
+- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
+-
+- return HANDLER_GO_ON;
+- }
+- } else if (0 == deflate_file_to_buffer(srv, con, p,
+- con->physical.path, sce, compression_type)) {
+-
+- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
+- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
+-
++
++ /* deflate it to file (cached) or to memory */
++ if (0 == deflate_file_to_file(srv, con, p,
++ con->physical.path, sce, compression_type) ||
++ 0 == deflate_file_to_buffer(srv, con, p,
++ con->physical.path, sce, compression_type)) {
++
++ response_header_overwrite(srv, con,
++ CONST_STR_LEN("Content-Encoding"),
++ compression_name, strlen(compression_name));
++
++ response_header_overwrite(srv, con,
++ CONST_STR_LEN("Content-Type"),
++ CONST_BUF_LEN(sce->content_type));
++
+ return HANDLER_FINISHED;
+ }
+ break;
+@@ -682,20 +728,20 @@
+ }
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ int mod_compress_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("compress");
+-
++
+ p->init = mod_compress_init;
+ p->set_defaults = mod_compress_setdefaults;
+ p->handle_subrequest_start = mod_compress_physical;
+ p->cleanup = mod_compress_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_dirlisting.c lighttpd-1.4.12/src/mod_dirlisting.c
+--- lighttpd-1.4.11/src/mod_dirlisting.c 2006-01-13 00:00:45.000000000 +0200
++++ lighttpd-1.4.12/src/mod_dirlisting.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,11 +1,9 @@
+ #include <ctype.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <dirent.h>
+ #include <assert.h>
+ #include <errno.h>
+ #include <stdio.h>
+-#include <unistd.h>
+ #include <time.h>
+
+ #include "base.h"
+@@ -31,6 +29,9 @@
+ #include <attr/attributes.h>
+ #endif
+
++#include "sys-files.h"
++#include "sys-strings.h"
++
+ /* plugin config for all request/connections */
+
+ typedef struct {
+@@ -54,7 +55,7 @@
+ unsigned short hide_readme_file;
+ unsigned short show_header;
+ unsigned short hide_header_file;
+-
++
+ excludes_buffer *excludes;
+
+ buffer *external_css;
+@@ -63,13 +64,13 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *tmp_buf;
+ buffer *content_charset;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ excludes_buffer *excludes_buffer_init(void) {
+@@ -146,44 +147,44 @@
+ /* init the plugin data */
+ INIT_FUNC(mod_dirlisting_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+
+ p->tmp_buf = buffer_init();
+ p->content_charset = buffer_init();
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_dirlisting_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ if (!s) continue;
+-
++
+ excludes_buffer_free(s->excludes);
+ buffer_free(s->external_css);
+ buffer_free(s->encoding);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->tmp_buf);
+ buffer_free(p->content_charset);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -215,10 +216,10 @@
+ if (0 != excludes_buffer_append(s->excludes,
+ ((data_string *)(da->value->data[j]))->value)) {
+ #ifdef HAVE_PCRE_H
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
+ #else
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "pcre support is missing, please install libpcre and the headers");
+ #endif
+ }
+@@ -233,8 +234,8 @@
+ SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "dir-listing.exclude", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "dir-listing.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "dir-listing.hide-dotfiles", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+@@ -245,18 +246,18 @@
+ { "dir-listing.show-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
+ { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
+ { "server.dir-listing", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
+-
++
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+ array *ca;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->excludes = excludes_buffer_init();
+ s->dir_listing = 0;
+@@ -267,7 +268,7 @@
+ s->show_header = 0;
+ s->hide_header_file = 0;
+ s->encoding = buffer_init();
+-
++
+ cv[0].destination = s->excludes;
+ cv[1].destination = &(s->dir_listing);
+ cv[2].destination = &(s->hide_dot_files);
+@@ -292,60 +293,57 @@
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+
+- PATCH(dir_listing);
+- PATCH(external_css);
+- PATCH(hide_dot_files);
+- PATCH(encoding);
+- PATCH(show_readme);
+- PATCH(hide_readme_file);
+- PATCH(show_header);
+- PATCH(hide_header_file);
+- PATCH(excludes);
+-
++ PATCH_OPTION(dir_listing);
++ PATCH_OPTION(external_css);
++ PATCH_OPTION(hide_dot_files);
++ PATCH_OPTION(encoding);
++ PATCH_OPTION(show_readme);
++ PATCH_OPTION(hide_readme_file);
++ PATCH_OPTION(show_header);
++ PATCH_OPTION(hide_header_file);
++ PATCH_OPTION(excludes);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
+ buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
+- PATCH(dir_listing);
++ PATCH_OPTION(dir_listing);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
+- PATCH(hide_dot_files);
++ PATCH_OPTION(hide_dot_files);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
+- PATCH(external_css);
++ PATCH_OPTION(external_css);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
+- PATCH(encoding);
++ PATCH_OPTION(encoding);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
+- PATCH(show_readme);
++ PATCH_OPTION(show_readme);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
+- PATCH(hide_readme_file);
++ PATCH_OPTION(hide_readme_file);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
+- PATCH(show_header);
++ PATCH_OPTION(show_header);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
+- PATCH(hide_header_file);
++ PATCH_OPTION(hide_header_file);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
+- PATCH(excludes);
++ PATCH_OPTION(excludes);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ typedef struct {
+ size_t namelen;
+@@ -432,7 +430,7 @@
+
+ static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
+ UNUSED(srv);
+-
++
+ BUFFER_APPEND_STRING_CONST(out,
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
+@@ -492,11 +490,11 @@
+ if (p->conf.show_header) {
+ stream s;
+ /* if we have a HEADER file, display it in <pre class="header"></pre> */
+-
++
+ buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
+- BUFFER_APPEND_SLASH(p->tmp_buf);
++ PATHNAME_APPEND_SLASH(p->tmp_buf);
+ BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
+-
++
+ if (-1 != stream_open(&s, p->tmp_buf)) {
+ BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
+ buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
+@@ -531,21 +529,21 @@
+
+ static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
+ UNUSED(srv);
+-
++
+ BUFFER_APPEND_STRING_CONST(out,
+ "</tbody>\n"
+ "</table>\n"
+ "</div>\n"
+ );
+-
++
+ if (p->conf.show_readme) {
+ stream s;
+ /* if we have a README file, display it in <pre class="readme"></pre> */
+-
++
+ buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
+- BUFFER_APPEND_SLASH(p->tmp_buf);
++ PATHNAME_APPEND_SLASH(p->tmp_buf);
+ BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
+-
++
+ if (-1 != stream_open(&s, p->tmp_buf)) {
+ BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
+ buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
+@@ -553,7 +551,7 @@
+ }
+ stream_close(&s);
+ }
+-
++
+ BUFFER_APPEND_STRING_CONST(out,
+ "<div class=\"foot\">"
+ );
+@@ -595,7 +593,7 @@
+ #endif
+
+ if (dir->used == 0) return -1;
+-
++
+ i = dir->used - 1;
+
+ #ifdef HAVE_PATHCONF
+@@ -606,19 +604,24 @@
+ name_max = 256; /* stupid default */
+ #endif
+ }
+-#elif defined __WIN32
++#elif defined _WIN32
+ name_max = FILENAME_MAX;
+ #else
+ name_max = NAME_MAX;
+ #endif
+-
++
+ path = malloc(dir->used + name_max);
+ assert(path);
+ strcpy(path, dir->ptr);
++#ifdef _WIN32
++ /* append \*.* to the path and keep the \ as part of the pathname */
++ strcat(path, "\\*.*");
++ i++;
++#endif
+ path_file = path + i;
+
+ if (NULL == (dp = opendir(path))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "opendir failed:", dir, strerror(errno));
+
+ free(path);
+@@ -633,7 +636,7 @@
+ assert(files.ent);
+ files.size = DIRLIST_BLOB_SIZE;
+ files.used = 0;
+-
++
+ while ((dent = readdir(dp)) != NULL) {
+ unsigned short exclude_match = 0;
+
+@@ -686,15 +689,17 @@
+ #endif
+
+ i = strlen(dent->d_name);
+-
++
+ /* NOTE: the manual says, d_name is never more than NAME_MAX
+ * so this should actually not be a buffer-overflow-risk
+ */
+ if (i > (size_t)name_max) continue;
+-
++
+ memcpy(path_file, dent->d_name, i + 1);
+- if (stat(path, &st) != 0)
++ if (stat(path, &st) != 0) {
++ fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, path, strerror(errno));
+ continue;
++ }
+
+ list = &files;
+ if (S_ISDIR(st.st_mode))
+@@ -740,7 +745,7 @@
+ #else
+ strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
+ #endif
+-
++
+ BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
+ buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
+ BUFFER_APPEND_STRING_CONST(out, "/\">");
+@@ -758,7 +763,7 @@
+
+ content_type = NULL;
+ #ifdef HAVE_XATTR
+-
++
+ if (con->conf.use_xattr) {
+ memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
+ attrlen = sizeof(attrval) - 1;
+@@ -768,7 +773,7 @@
+ }
+ }
+ #endif
+-
++
+ if (content_type == NULL) {
+ content_type = "application/octet-stream";
+ for (k = 0; k < con->conf.mimetypes->used; k++) {
+@@ -788,7 +793,7 @@
+ }
+ }
+ }
+-
++
+ #ifdef HAVE_LOCALTIME_R
+ localtime_r(&(tmp->mtime), &tm);
+ strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
+@@ -837,36 +842,36 @@
+ URIHANDLER_FUNC(mod_dirlisting_subrequest) {
+ plugin_data *p = p_d;
+ stat_cache_entry *sce = NULL;
+-
++
+ UNUSED(srv);
+-
++
+ if (con->physical.path->used == 0) return HANDLER_GO_ON;
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+ if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
+-
++
+ mod_dirlisting_patch_connection(srv, con, p);
+
+ if (!p->conf.dir_listing) return HANDLER_GO_ON;
+-
++
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Dir-Listing");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
+ }
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+ fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
+ SEGFAULT();
+ }
+-
++
+ if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
+-
++
+ if (http_list_directory(srv, con, p, con->physical.path)) {
+ /* dirlisting failed */
+ con->http_status = 403;
+ }
+-
++
+ buffer_reset(con->physical.path);
+-
++
+ /* not found */
+ return HANDLER_FINISHED;
+ }
+@@ -876,13 +881,13 @@
+ int mod_dirlisting_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("dirlisting");
+-
++
+ p->init = mod_dirlisting_init;
+ p->handle_subrequest_start = mod_dirlisting_subrequest;
+ p->set_defaults = mod_dirlisting_set_defaults;
+ p->cleanup = mod_dirlisting_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_evasive.c lighttpd-1.4.12/src/mod_evasive.c
+--- lighttpd-1.4.11/src/mod_evasive.c 2006-01-04 15:24:51.000000000 +0200
++++ lighttpd-1.4.12/src/mod_evasive.c 2006-07-11 21:23:40.000000000 +0300
+@@ -31,100 +31,97 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ INIT_FUNC(mod_evasive_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ return p;
+ }
+
+ FREE_FUNC(mod_evasive_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "evasive.max-conns-per-ip", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->max_conns = 0;
+-
++
+ cv[0].destination = &(s->max_conns);
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+
+- PATCH(max_conns);
+-
++ PATCH_OPTION(max_conns);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
+- PATCH(max_conns);
++ PATCH_OPTION(max_conns);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_evasive_uri_handler) {
+ plugin_data *p = p_d;
+@@ -132,10 +129,10 @@
+ size_t j;
+
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_evasive_patch_connection(srv, con, p);
+-
+- /* no limit set, nothing to block */
++
++ /* no limit set, nothing to block */
+ if (p->conf.max_conns == 0) return HANDLER_GO_ON;
+
+ for (j = 0; j < srv->conns->used; j++) {
+@@ -147,7 +144,7 @@
+ if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
+ c->state > CON_STATE_REQUEST_END) {
+ conns_by_ip++;
+-
++
+ if (conns_by_ip > p->conf.max_conns) {
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+ inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
+@@ -158,7 +155,7 @@
+ }
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -166,13 +163,13 @@
+ int mod_evasive_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("evasive");
+-
++
+ p->init = mod_evasive_init;
+ p->set_defaults = mod_evasive_set_defaults;
+ p->handle_uri_clean = mod_evasive_uri_handler;
+ p->cleanup = mod_evasive_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_evhost.c lighttpd-1.4.12/src/mod_evhost.c
+--- lighttpd-1.4.11/src/mod_evhost.c 2005-08-17 10:42:03.000000000 +0300
++++ lighttpd-1.4.12/src/mod_evhost.c 2006-07-11 21:23:39.000000000 +0300
+@@ -7,10 +7,12 @@
+ #include "response.h"
+ #include "stat_cache.h"
+
++#include "sys-files.h"
++
+ typedef struct {
+ /* unparsed pieces */
+ buffer *path_pieces_raw;
+-
++
+ /* pieces for path creation */
+ size_t len;
+ buffer **path_pieces;
+@@ -21,14 +23,14 @@
+ buffer *tmp_buf;
+
+ plugin_config **config_storage;
+- plugin_config conf;
++ plugin_config conf;
+ } plugin_data;
+
+ INIT_FUNC(mod_evhost_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->tmp_buf = buffer_init();
+
+ return p;
+@@ -36,34 +38,34 @@
+
+ FREE_FUNC(mod_evhost_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+-
++
+ if(s->path_pieces) {
+ size_t j;
+ for (j = 0; j < s->len; j++) {
+ buffer_free(s->path_pieces[j]);
+ }
+-
++
+ free(s->path_pieces);
+ }
+-
++
+ buffer_free(s->path_pieces_raw);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->tmp_buf);
+
+ free(p);
+@@ -73,30 +75,30 @@
+
+ static void mod_evhost_parse_pattern(plugin_config *s) {
+ char *ptr = s->path_pieces_raw->ptr,*pos;
+-
++
+ s->path_pieces = NULL;
+-
++
+ for(pos=ptr;*ptr;ptr++) {
+ if(*ptr == '%') {
+ s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
+ s->path_pieces[s->len] = buffer_init();
+ s->path_pieces[s->len+1] = buffer_init();
+-
++
+ buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
+ pos = ptr + 2;
+-
++
+ buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
+-
++
+ s->len += 2;
+ }
+ }
+-
++
+ if(*pos != '\0') {
+ s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
+ s->path_pieces[s->len] = buffer_init();
+-
++
+ buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
+-
++
+ s->len += 1;
+ }
+ }
+@@ -104,9 +106,9 @@
+ SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i;
+-
++
+ /**
+- *
++ *
+ * #
+ * # define a pattern for the host url finding
+ * # %% => % sign
+@@ -117,39 +119,39 @@
+ * # %4 => subdomain 2 name
+ * #
+ * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
+- *
++ *
+ */
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "evhost.path-pattern", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->path_pieces_raw = buffer_init();
+ s->path_pieces = NULL;
+ s->len = 0;
+-
++
+ cv[0].destination = s->path_pieces_raw;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (s->path_pieces_raw->used != 0) {
+ mod_evhost_parse_pattern(s);
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -158,7 +160,7 @@
+ * - %0 - full hostname (authority w/o port)
+ * - %1 - tld
+ * - %2 - domain.tld
+- * - %3 -
++ * - %3 -
+ */
+
+ static int mod_evhost_parse_host(connection *con,array *host) {
+@@ -168,7 +170,7 @@
+ int first = 1;
+ data_string *ds;
+ int i;
+-
++
+ /* first, find the domain + tld */
+ for(;ptr > con->uri.authority->ptr;ptr--) {
+ if(*ptr == '.') {
+@@ -179,18 +181,18 @@
+ first = 1;
+ }
+ }
+-
++
+ ds = data_string_init();
+ buffer_copy_string(ds->key,"%0");
+-
++
+ /* if we stopped at a dot, skip the dot */
+ if (*ptr == '.') ptr++;
+ buffer_copy_string_len(ds->value, ptr, colon-ptr);
+-
++
+ array_insert_unique(host,(data_unset *)ds);
+-
++
+ /* if the : is not the start of the authority, go on parsing the hostname */
+-
++
+ if (colon != con->uri.authority->ptr) {
+ for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
+ if(*ptr == '.') {
+@@ -200,59 +202,55 @@
+ buffer_copy_string(ds->key,"%");
+ buffer_append_long(ds->key, i++);
+ buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
+-
++
+ array_insert_unique(host,(data_unset *)ds);
+ }
+ colon = ptr;
+ }
+ }
+-
++
+ /* if the . is not the first charactor of the hostname */
+ if (colon != ptr) {
+ ds = data_string_init();
+ buffer_copy_string(ds->key,"%");
+ buffer_append_long(ds->key, i++);
+ buffer_copy_string_len(ds->value,ptr,colon-ptr);
+-
++
+ array_insert_unique(host,(data_unset *)ds);
+ }
+ }
+-
++
+ return 0;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(path_pieces);
+- PATCH(len);
+-
++
++ PATCH_OPTION(path_pieces);
++ PATCH_OPTION(len);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
+- PATCH(path_pieces);
+- PATCH(len);
++ PATCH_OPTION(path_pieces);
++ PATCH_OPTION(len);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+-
+
+ static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
+ plugin_data *p = p_d;
+@@ -261,29 +259,29 @@
+ register char *ptr;
+ int not_good = 0;
+ stat_cache_entry *sce = NULL;
+-
++
+ /* not authority set */
+ if (con->uri.authority->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_evhost_patch_connection(srv, con, p);
+-
++
+ /* missing even default(global) conf */
+ if (0 == p->conf.len) {
+ return HANDLER_GO_ON;
+ }
+
+ parsed_host = array_init();
+-
++
+ mod_evhost_parse_host(con, parsed_host);
+-
++
+ /* build document-root */
+ buffer_reset(p->tmp_buf);
+-
++
+ for (i = 0; i < p->conf.len; i++) {
+ ptr = p->conf.path_pieces[i]->ptr;
+ if (*ptr == '%') {
+ data_string *ds;
+-
++
+ if (*(ptr+1) == '%') {
+ /* %% */
+ BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
+@@ -298,11 +296,11 @@
+ buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
+ }
+ }
+-
+- BUFFER_APPEND_SLASH(p->tmp_buf);
+-
++
++ PATHNAME_APPEND_SLASH(p->tmp_buf);
++
+ array_free(parsed_host);
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
+ not_good = 1;
+@@ -310,11 +308,11 @@
+ log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
+ not_good = 1;
+ }
+-
++
+ if (!not_good) {
+ buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -325,9 +323,9 @@
+ p->set_defaults = mod_evhost_set_defaults;
+ p->handle_docroot = mod_evhost_uri_handler;
+ p->cleanup = mod_evhost_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_expire.c lighttpd-1.4.12/src/mod_expire.c
+--- lighttpd-1.4.11/src/mod_expire.c 2005-11-03 09:52:13.000000000 +0200
++++ lighttpd-1.4.12/src/mod_expire.c 2006-07-11 21:23:40.000000000 +0300
+@@ -12,8 +12,8 @@
+ #include "stat_cache.h"
+
+ /**
+- * this is a expire module for a lighttpd
+- *
++ * this is a expire module for a lighttpd
++ *
+ * set 'Expires:' HTTP Headers on demand
+ */
+
+@@ -27,51 +27,51 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *expire_tstmp;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_expire_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->expire_tstmp = buffer_init();
+-
++
+ buffer_prepare_copy(p->expire_tstmp, 255);
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_expire_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ buffer_free(p->expire_tstmp);
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ array_free(s->expire_url);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -79,25 +79,25 @@
+ char *ts;
+ int type = -1;
+ int retts = 0;
+-
++
+ UNUSED(p);
+
+- /*
++ /*
+ * parse
+- *
++ *
+ * '(access|modification) [plus] {<num> <type>}*'
+- *
++ *
+ * e.g. 'access 1 years'
+ */
+-
++
+ if (expire->used == 0) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "empty:");
+ return -1;
+ }
+-
++
+ ts = expire->ptr;
+-
++
+ if (0 == strncmp(ts, "access ", 7)) {
+ type = 0;
+ ts += 7;
+@@ -110,39 +110,39 @@
+ "invalid <base>:", ts);
+ return -1;
+ }
+-
++
+ if (0 == strncmp(ts, "plus ", 5)) {
+ /* skip the optional plus */
+ ts += 5;
+ }
+-
++
+ /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
+ while (1) {
+ char *space, *err;
+ int num;
+-
++
+ if (NULL == (space = strchr(ts, ' '))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "missing space after <num>:", ts);
+ return -1;
+ }
+-
++
+ num = strtol(ts, &err, 10);
+ if (*err != ' ') {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "missing <type> after <num>:", ts);
+ return -1;
+ }
+-
++
+ ts = space + 1;
+-
++
+ if (NULL != (space = strchr(ts, ' '))) {
+ int slen;
+ /* */
+-
++
+ slen = space - ts;
+-
+- if (slen == 5 &&
++
++ if (slen == 5 &&
+ 0 == strncmp(ts, "years", slen)) {
+ num *= 60 * 60 * 24 * 30 * 12;
+ } else if (slen == 6 &&
+@@ -161,13 +161,13 @@
+ 0 == strncmp(ts, "seconds", slen)) {
+ num *= 1;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "unknown type:", ts);
+ return -1;
+ }
+-
++
+ retts += num;
+-
++
+ ts = space + 1;
+ } else {
+ if (0 == strcmp(ts, "years")) {
+@@ -183,19 +183,19 @@
+ } else if (0 == strcmp(ts, "seconds")) {
+ num *= 1;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "unknown type:", ts);
+ return -1;
+ }
+-
++
+ retts += num;
+-
++
+ break;
+ }
+ }
+-
++
+ if (offset != NULL) *offset = retts;
+-
++
+ return type;
+ }
+
+@@ -205,102 +205,99 @@
+ SETDEFAULTS_FUNC(mod_expire_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0, k;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "expire.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->expire_url = array_init();
+-
++
+ cv[0].destination = s->expire_url;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ for (k = 0; k < s->expire_url->used; k++) {
+ data_string *ds = (data_string *)s->expire_url->data[k];
+-
++
+ /* parse lines */
+ if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "parsing expire.url failed:", ds->value);
+ return HANDLER_ERROR;
+ }
+ }
+ }
+-
+-
++
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(expire_url);
+-
++
++ PATCH_OPTION(expire_url);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
+- PATCH(expire_url);
++ PATCH_OPTION(expire_url);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_expire_path_handler) {
+ plugin_data *p = p_d;
+ int s_len;
+ size_t k;
+-
++
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_expire_patch_connection(srv, con, p);
+-
++
+ s_len = con->uri.path->used - 1;
+-
++
+ for (k = 0; k < p->conf.expire_url->used; k++) {
+ data_string *ds = (data_string *)p->conf.expire_url->data[k];
+ int ct_len = ds->key->used - 1;
+-
++
+ if (ct_len > s_len) continue;
+ if (ds->key->used == 0) continue;
+-
++
+ if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
+ int ts;
+ time_t t;
+ size_t len;
+ stat_cache_entry *sce = NULL;
+-
++
+ stat_cache_get_entry(srv, con, con->physical.path, &sce);
+-
++
+ switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
+ case 0:
+ /* access */
+@@ -308,38 +305,38 @@
+ break;
+ case 1:
+ /* modification */
+-
++
+ t = (ts + sce->st.st_mtime);
+ break;
+ default:
+ /* -1 is handled at parse-time */
+ break;
+ }
+-
+-
+- if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
++
++
++ if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
+ "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
+ /* could not set expire header, out of mem */
+-
++
+ return HANDLER_GO_ON;
+-
++
+ }
+-
++
+ p->expire_tstmp->used = len + 1;
+-
+- /* HTTP/1.0 */
++
++ /* HTTP/1.0 */
+ response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
+
+- /* HTTP/1.1 */
++ /* HTTP/1.1 */
+ buffer_copy_string(p->expire_tstmp, "max-age=");
+ buffer_append_long(p->expire_tstmp, ts);
+-
++
+ response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
+-
++
+ return HANDLER_GO_ON;
+ }
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+@@ -349,13 +346,13 @@
+ int mod_expire_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("expire");
+-
++
+ p->init = mod_expire_init;
+ p->handle_subrequest_start = mod_expire_path_handler;
+ p->set_defaults = mod_expire_set_defaults;
+ p->cleanup = mod_expire_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_fastcgi.c lighttpd-1.4.12/src/mod_fastcgi.c
+--- lighttpd-1.4.11/src/mod_fastcgi.c 2006-03-09 13:18:39.000000000 +0200
++++ lighttpd-1.4.12/src/mod_fastcgi.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,5 +1,4 @@
+ #include <sys/types.h>
+-#include <unistd.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <string.h>
+@@ -24,7 +23,7 @@
+ #include "inet_ntop_cache.h"
+ #include "stat_cache.h"
+
+-#include <fastcgi.h>
++#include "fastcgi.h"
+ #include <stdio.h>
+
+ #ifdef HAVE_SYS_FILIO_H
+@@ -32,7 +31,11 @@
+ #endif
+
+ #include "sys-socket.h"
++#include "sys-files.h"
++#include "sys-strings.h"
++#include "sys-process.h"
+
++#include "http_resp.h"
+
+ #ifndef UNIX_PATH_MAX
+ # define UNIX_PATH_MAX 108
+@@ -45,14 +48,13 @@
+ #include <sys/wait.h>
+ #endif
+
+-
+ /*
+- *
++ *
+ * TODO:
+- *
++ *
+ * - add timeout for a connect to a non-fastcgi process
+ * (use state_timestamp + state)
+- *
++ *
+ */
+
+ typedef struct fcgi_proc {
+@@ -61,7 +63,7 @@
+ unsigned port; /* config.port + pno */
+
+ buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
+-
++
+ pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
+
+
+@@ -70,20 +72,20 @@
+ time_t last_used; /* see idle_timeout */
+ size_t requests; /* see max_requests */
+ struct fcgi_proc *prev, *next; /* see first */
+-
++
+ time_t disabled_until; /* this proc is disabled until, use something else until than */
+-
++
+ int is_local;
+
+- enum {
++ enum {
+ PROC_STATE_UNSET, /* init-phase */
+ PROC_STATE_RUNNING, /* alive */
+- PROC_STATE_OVERLOADED, /* listen-queue is full,
++ PROC_STATE_OVERLOADED, /* listen-queue is full,
+ don't send something to this proc for the next 2 seconds */
+ PROC_STATE_DIED_WAIT_FOR_PID, /* */
+ PROC_STATE_DIED, /* marked as dead, should be restarted */
+ PROC_STATE_KILLED /* was killed as we don't have the load anymore */
+- } state;
++ } state;
+ } fcgi_proc;
+
+ typedef struct {
+@@ -94,20 +96,20 @@
+ * sorted by lowest load
+ *
+ * whenever a job is done move it up in the list
+- * until it is sorted, move it down as soon as the
++ * until it is sorted, move it down as soon as the
+ * job is started
+ */
+- fcgi_proc *first;
+- fcgi_proc *unused_procs;
++ fcgi_proc *first;
++ fcgi_proc *unused_procs;
+
+- /*
++ /*
+ * spawn at least min_procs, at max_procs.
+ *
+- * as soon as the load of the first entry
++ * as soon as the load of the first entry
+ * is max_load_per_proc we spawn a new one
+- * and add it to the first entry and give it
++ * and add it to the first entry and give it
+ * the load
+- *
++ *
+ */
+
+ unsigned short min_procs;
+@@ -119,44 +121,44 @@
+
+ /*
+ * kick the process from the list if it was not
+- * used for idle_timeout until min_procs is
++ * used for idle_timeout until min_procs is
+ * reached. this helps to get the processlist
+ * small again we had a small peak load.
+ *
+ */
+-
++
+ unsigned short idle_timeout;
+-
++
+ /*
+ * time after a disabled remote connection is tried to be re-enabled
+- *
+- *
++ *
++ *
+ */
+-
++
+ unsigned short disable_time;
+
+ /*
+ * same fastcgi processes get a little bit larger
+- * than wanted. max_requests_per_proc kills a
++ * than wanted. max_requests_per_proc kills a
+ * process after a number of handled requests.
+ *
+ */
+ size_t max_requests_per_proc;
+-
++
+
+ /* config */
+
+- /*
+- * host:port
++ /*
++ * host:port
+ *
+- * if host is one of the local IP adresses the
++ * if host is one of the local IP adresses the
+ * whole connection is local
+ *
+ * if tcp/ip should be used host AND port have
+- * to be specified
+- *
+- */
+- buffer *host;
++ * to be specified
++ *
++ */
++ buffer *host;
+ unsigned short port;
+
+ /*
+@@ -169,7 +171,7 @@
+ */
+ buffer *unixsocket;
+
+- /* if socket is local we can start the fastcgi
++ /* if socket is local we can start the fastcgi
+ * process ourself
+ *
+ * bin-path is the path to the binary
+@@ -177,19 +179,19 @@
+ * check min_procs and max_procs for the number
+ * of process to start-up
+ */
+- buffer *bin_path;
+-
+- /* bin-path is set bin-environment is taken to
++ buffer *bin_path;
++
++ /* bin-path is set bin-environment is taken to
+ * create the environement before starting the
+ * FastCGI process
+- *
++ *
+ */
+ array *bin_env;
+-
++
+ array *bin_env_copy;
+-
++
+ /*
+- * docroot-translation between URL->phys and the
++ * docroot-translation between URL->phys and the
+ * remote host
+ *
+ * reasons:
+@@ -208,7 +210,7 @@
+ unsigned short mode;
+
+ /*
+- * check_local tell you if the phys file is stat()ed
++ * check_local tell you if the phys file is stat()ed
+ * or not. FastCGI doesn't care if the service is
+ * remote. If the web-server side doesn't contain
+ * the fastcgi-files we should not stat() for them
+@@ -218,11 +220,11 @@
+
+ /*
+ * append PATH_INFO to SCRIPT_FILENAME
+- *
++ *
+ * php needs this if cgi.fix_pathinfo is provied
+- *
++ *
+ */
+-
++
+ unsigned short break_scriptfilename_for_php;
+
+ /*
+@@ -231,12 +233,12 @@
+ *
+ */
+ unsigned short allow_xsendfile;
+-
++
+ ssize_t load; /* replace by host->load */
+
+ size_t max_id; /* corresponds most of the time to
+ num_procs.
+-
++
+ only if a process is killed max_id waits for the process itself
+ to die and decrements its afterwards */
+
+@@ -245,17 +247,17 @@
+
+ /*
+ * one extension can have multiple hosts assigned
+- * one host can spawn additional processes on the same
++ * one host can spawn additional processes on the same
+ * socket (if we control it)
+ *
+ * ext -> host -> procs
+ * 1:n 1:n
+ *
+- * if the fastcgi process is remote that whole goes down
++ * if the fastcgi process is remote that whole goes down
+ * to
+ *
+ * ext -> host -> procs
+- * 1:n 1:1
++ * 1:n 1:1
+ *
+ * in case of PHP and FCGI_CHILDREN we have again a procs
+ * but we don't control it directly.
+@@ -268,7 +270,7 @@
+ int note_is_sent;
+
+ fcgi_extension_host **hosts;
+-
++
+ size_t used;
+ size_t size;
+ } fcgi_extension;
+@@ -282,10 +284,10 @@
+
+
+ typedef struct {
+- fcgi_exts *exts;
++ fcgi_exts *exts;
+
+ array *ext_mapping;
+-
++
+ int debug;
+ } plugin_config;
+
+@@ -297,7 +299,7 @@
+
+ typedef struct {
+ char **ptr;
+-
++
+ size_t size;
+ size_t used;
+ } char_array;
+@@ -306,44 +308,44 @@
+ typedef struct {
+ PLUGIN_DATA;
+ buffer_uint fcgi_request_id;
+-
++
+ buffer *fcgi_env;
+-
++
+ buffer *path;
+- buffer *parse_response;
+
+ buffer *statuskey;
+-
++
++ http_resp *resp;
++
+ plugin_config **config_storage;
+-
++
+ plugin_config conf; /* this is only used as long as no handler_ctx is setup */
+ } plugin_data;
+
+ /* connection specific data */
+-typedef enum {
++typedef enum {
+ FCGI_STATE_UNSET,
+- FCGI_STATE_INIT,
+- FCGI_STATE_CONNECT_DELAYED,
+- FCGI_STATE_PREPARE_WRITE,
+- FCGI_STATE_WRITE,
+- FCGI_STATE_READ
++ FCGI_STATE_INIT,
++ FCGI_STATE_CONNECT_DELAYED,
++ FCGI_STATE_PREPARE_WRITE,
++ FCGI_STATE_WRITE,
++ FCGI_STATE_READ
+ } fcgi_connection_state_t;
+
+ typedef struct {
+ fcgi_proc *proc;
+ fcgi_extension_host *host;
+ fcgi_extension *ext;
+-
++
+ fcgi_connection_state_t state;
+ time_t state_timestamp;
+-
++
+ int reconnects; /* number of reconnect attempts */
+-
+- chunkqueue *rb; /* read queue */
++
++ chunkqueue *rb; /* the raw fcgi read-queue */
++ chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
+ chunkqueue *wb; /* write queue */
+-
+- buffer *response_header;
+-
++
+ size_t request_id;
+ int fd; /* fd to the fastcgi process */
+ int fde_ndx; /* index into the fd-event buffer */
+@@ -352,9 +354,9 @@
+ int got_proc;
+
+ int send_content_body;
+-
++
+ plugin_config conf;
+-
++
+ connection *remote_conn; /* dumb pointer */
+ plugin_data *plugin_data; /* dumb pointer */
+ } handler_ctx;
+@@ -380,7 +382,7 @@
+ return di;
+ }
+
+-/* dummies of the statistic framework functions
++/* dummies of the statistic framework functions
+ * they will be moved to a statistics.c later */
+ int status_counter_inc(server *srv, const char *s, size_t len) {
+ data_integer *di = status_counter_get_counter(srv, s, len);
+@@ -429,7 +431,7 @@
+ CLEAN(".connected");
+ CLEAN(".load");
+
+-#undef CLEAN
++#undef CLEAN
+
+ #define CLEAN(x) \
+ fastcgi_status_copy_procname(b, host, NULL); \
+@@ -438,33 +440,32 @@
+
+ CLEAN(".load");
+
+-#undef CLEAN
++#undef CLEAN
+
+ return 0;
+ }
+
+ static handler_ctx * handler_ctx_init() {
+ handler_ctx * hctx;
+-
++
+ hctx = calloc(1, sizeof(*hctx));
+ assert(hctx);
+-
++
+ hctx->fde_ndx = -1;
+-
+- hctx->response_header = buffer_init();
+-
++
+ hctx->request_id = 0;
+ hctx->state = FCGI_STATE_INIT;
+ hctx->proc = NULL;
+-
++
+ hctx->fd = -1;
+-
++
+ hctx->reconnects = 0;
+ hctx->send_content_body = 1;
+
+ hctx->rb = chunkqueue_init();
++ hctx->http_rb = chunkqueue_init();
+ hctx->wb = chunkqueue_init();
+-
++
+ return hctx;
+ }
+
+@@ -473,10 +474,9 @@
+ hctx->host->load--;
+ hctx->host = NULL;
+ }
+-
+- buffer_free(hctx->response_header);
+
+ chunkqueue_free(hctx->rb);
++ chunkqueue_free(hctx->http_rb);
+ chunkqueue_free(hctx->wb);
+
+ free(hctx);
+@@ -488,21 +488,21 @@
+ f = calloc(1, sizeof(*f));
+ f->unixsocket = buffer_init();
+ f->connection_name = buffer_init();
+-
++
+ f->prev = NULL;
+ f->next = NULL;
+-
++
+ return f;
+ }
+
+ void fastcgi_process_free(fcgi_proc *f) {
+ if (!f) return;
+-
++
+ fastcgi_process_free(f->next);
+-
++
+ buffer_free(f->unixsocket);
+ buffer_free(f->connection_name);
+-
++
+ free(f);
+ }
+
+@@ -519,13 +519,13 @@
+ f->bin_env = array_init();
+ f->bin_env_copy = array_init();
+ f->strip_request_uri = buffer_init();
+-
++
+ return f;
+ }
+
+ void fastcgi_host_free(fcgi_extension_host *h) {
+ if (!h) return;
+-
++
+ buffer_free(h->id);
+ buffer_free(h->host);
+ buffer_free(h->unixsocket);
+@@ -534,49 +534,49 @@
+ buffer_free(h->strip_request_uri);
+ array_free(h->bin_env);
+ array_free(h->bin_env_copy);
+-
++
+ fastcgi_process_free(h->first);
+ fastcgi_process_free(h->unused_procs);
+-
++
+ free(h);
+-
++
+ }
+
+ fcgi_exts *fastcgi_extensions_init() {
+ fcgi_exts *f;
+
+ f = calloc(1, sizeof(*f));
+-
++
+ return f;
+ }
+
+ void fastcgi_extensions_free(fcgi_exts *f) {
+ size_t i;
+-
++
+ if (!f) return;
+-
++
+ for (i = 0; i < f->used; i++) {
+ fcgi_extension *fe;
+ size_t j;
+-
++
+ fe = f->exts[i];
+-
++
+ for (j = 0; j < fe->used; j++) {
+ fcgi_extension_host *h;
+-
++
+ h = fe->hosts[j];
+-
++
+ fastcgi_host_free(h);
+ }
+-
++
+ buffer_free(fe->key);
+ free(fe->hosts);
+-
++
+ free(fe);
+ }
+-
++
+ free(f->exts);
+-
++
+ free(f);
+ }
+
+@@ -625,24 +625,25 @@
+ assert(fe->hosts);
+ }
+
+- fe->hosts[fe->used++] = fh;
++ fe->hosts[fe->used++] = fh;
+
+ return 0;
+-
++
+ }
+
+ INIT_FUNC(mod_fastcgi_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->fcgi_env = buffer_init();
+-
++
+ p->path = buffer_init();
+- p->parse_response = buffer_init();
++
++ p->resp = http_response_init();
+
+ p->statuskey = buffer_init();
+-
++
+ return p;
+ }
+
+@@ -650,81 +651,82 @@
+ FREE_FUNC(mod_fastcgi_free) {
+ plugin_data *p = p_d;
+ buffer_uint *r = &(p->fcgi_request_id);
+-
++
+ UNUSED(srv);
+
+ if (r->ptr) free(r->ptr);
+-
++
+ buffer_free(p->fcgi_env);
+ buffer_free(p->path);
+- buffer_free(p->parse_response);
+ buffer_free(p->statuskey);
+-
++
++ http_response_free(p->resp);
++
+ if (p->config_storage) {
+ size_t i, j, n;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+ fcgi_exts *exts;
+-
++
+ if (!s) continue;
+-
++
+ exts = s->exts;
+
+ for (j = 0; j < exts->used; j++) {
+ fcgi_extension *ex;
+-
++
+ ex = exts->exts[j];
+-
++
+ for (n = 0; n < ex->used; n++) {
+ fcgi_proc *proc;
+ fcgi_extension_host *host;
+-
++
+ host = ex->hosts[n];
+-
++
+ for (proc = host->first; proc; proc = proc->next) {
+ if (proc->pid != 0) kill(proc->pid, SIGTERM);
+-
+- if (proc->is_local &&
++
++ if (proc->is_local &&
+ !buffer_is_empty(proc->unixsocket)) {
+ unlink(proc->unixsocket->ptr);
+ }
+ }
+-
++
+ for (proc = host->unused_procs; proc; proc = proc->next) {
+ if (proc->pid != 0) kill(proc->pid, SIGTERM);
+-
+- if (proc->is_local &&
++
++ if (proc->is_local &&
+ !buffer_is_empty(proc->unixsocket)) {
+ unlink(proc->unixsocket->ptr);
+ }
+ }
+ }
+ }
+-
++
+ fastcgi_extensions_free(s->exts);
+ array_free(s->ext_mapping);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
+ char *dst;
+-
++
+ if (!key || !val) return -1;
+-
++
+ dst = malloc(key_len + val_len + 3);
+ memcpy(dst, key, key_len);
+ dst[key_len] = '=';
+ /* add the \0 from the value */
+ memcpy(dst + key_len + 1, val, val_len + 1);
+-
++
+ if (env->size == 0) {
+ env->size = 16;
+ env->ptr = malloc(env->size * sizeof(*env->ptr));
+@@ -732,9 +734,9 @@
+ env->size += 16;
+ env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
+ }
+-
++
+ env->ptr[env->used++] = dst;
+-
++
+ return 0;
+ }
+
+@@ -753,15 +755,15 @@
+ if (env->size == 0) {
+ env->size = 16;
+ env->ptr = malloc(env->size * sizeof(*env->ptr));
+- } else if (env->size == env->used) {
++ } else if (env->size == env->used) {
+ env->size += 16;
+ env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
+ }
+-
++
+ b->ptr[i] = '\0';
+
+ env->ptr[env->used++] = start;
+-
++
+ start = b->ptr + i + 1;
+ break;
+ default:
+@@ -794,7 +796,7 @@
+ return 0;
+ }
+
+-static int fcgi_spawn_connection(server *srv,
++static int fcgi_spawn_connection(server *srv,
+ plugin_data *p,
+ fcgi_extension_host *host,
+ fcgi_proc *proc) {
+@@ -806,31 +808,27 @@
+ #endif
+ struct sockaddr_in fcgi_addr_in;
+ struct sockaddr *fcgi_addr;
+-
++
+ socklen_t servlen;
+-
++
+ #ifndef HAVE_FORK
+ return -1;
+ #endif
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sdb",
+ "new proc, socket:", proc->port, proc->unixsocket);
+ }
+-
++
+ if (!buffer_is_empty(proc->unixsocket)) {
+ memset(&fcgi_addr, 0, sizeof(fcgi_addr));
+-
++
+ #ifdef HAVE_SYS_UN_H
+ fcgi_addr_un.sun_family = AF_UNIX;
+ strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
+-
+-#ifdef SUN_LEN
++
+ servlen = SUN_LEN(&fcgi_addr_un);
+-#else
+- /* stevens says: */
+- servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
+-#endif
++
+ socket_type = AF_UNIX;
+ fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
+
+@@ -844,108 +842,108 @@
+ #endif
+ } else {
+ fcgi_addr_in.sin_family = AF_INET;
+-
++
+ if (buffer_is_empty(host->host)) {
+ fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ struct hostent *he;
+-
++
+ /* set a usefull default */
+ fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+-
+-
++
++
+ if (NULL == (he = gethostbyname(host->host->ptr))) {
+- log_error_write(srv, __FILE__, __LINE__,
+- "sdb", "gethostbyname failed: ",
++ log_error_write(srv, __FILE__, __LINE__,
++ "sdb", "gethostbyname failed: ",
+ h_errno, host->host);
+ return -1;
+ }
+-
++
+ if (he->h_addrtype != AF_INET) {
+ log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
+ return -1;
+ }
+-
++
+ if (he->h_length != sizeof(struct in_addr)) {
+ log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
+ return -1;
+ }
+-
++
+ memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
+-
++
+ }
+ fcgi_addr_in.sin_port = htons(proc->port);
+ servlen = sizeof(fcgi_addr_in);
+-
++
+ socket_type = AF_INET;
+ fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
+-
++
+ buffer_copy_string(proc->connection_name, "tcp:");
+ buffer_append_string_buffer(proc->connection_name, host->host);
+ buffer_append_string(proc->connection_name, ":");
+ buffer_append_long(proc->connection_name, proc->port);
+ }
+-
++
+ if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "failed:", strerror(errno));
+ return -1;
+ }
+-
++
+ if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
+ /* server is not up, spawn in */
+ pid_t child;
+ int val;
+-
+- if (errno != ENOENT &&
++
++ if (errno != ENOENT &&
+ !buffer_is_empty(proc->unixsocket)) {
+ unlink(proc->unixsocket->ptr);
+ }
+-
++
+ close(fcgi_fd);
+-
++
+ /* reopen socket */
+ if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "socket failed:", strerror(errno));
+ return -1;
+ }
+-
++
+ val = 1;
+ if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "socketsockopt failed:", strerror(errno));
+ return -1;
+ }
+-
++
+ /* create socket */
+ if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "bind failed for:",
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
++ "bind failed for:",
+ proc->connection_name,
+ strerror(errno));
+ return -1;
+ }
+-
++
+ if (-1 == listen(fcgi_fd, 1024)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "listen failed:", strerror(errno));
+ return -1;
+ }
+-
+-#ifdef HAVE_FORK
++
++#ifndef _WIN32
+ switch ((child = fork())) {
+ case 0: {
+ size_t i = 0;
+ char *c;
+ char_array env;
+ char_array arg;
+-
++
+ /* create environment */
+ env.ptr = NULL;
+ env.size = 0;
+ env.used = 0;
+-
++
+ arg.ptr = NULL;
+ arg.size = 0;
+ arg.used = 0;
+@@ -955,18 +953,18 @@
+ dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
+ close(fcgi_fd);
+ }
+-
++
+ /* we don't need the client socket */
+ for (i = 3; i < 256; i++) {
+ close(i);
+ }
+-
++
+ /* build clean environment */
+ if (host->bin_env_copy->used) {
+ for (i = 0; i < host->bin_env_copy->used; i++) {
+ data_string *ds = (data_string *)host->bin_env_copy->data[i];
+ char *ge;
+-
++
+ if (NULL != (ge = getenv(ds->value->ptr))) {
+ env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
+ }
+@@ -974,39 +972,39 @@
+ } else {
+ for (i = 0; environ[i]; i++) {
+ char *eq;
+-
++
+ if (NULL != (eq = strchr(environ[i], '='))) {
+ env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
+ }
+ }
+ }
+-
++
+ /* create environment */
+ for (i = 0; i < host->bin_env->used; i++) {
+ data_string *ds = (data_string *)host->bin_env->data[i];
+-
++
+ env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
+ }
+-
++
+ for (i = 0; i < env.used; i++) {
+ /* search for PHP_FCGI_CHILDREN */
+ if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
+ }
+-
++
+ /* not found, add a default */
+ if (i == env.used) {
+ env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
+ }
+-
++
+ env.ptr[env.used] = NULL;
+
+ parse_binpath(&arg, host->bin_path);
+-
++
+ /* chdir into the base of the bin-path,
+ * search for the last / */
+ if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
+ *c = '\0';
+-
++
+ /* change to the physical directory */
+ if (-1 == chdir(arg.ptr[0])) {
+ *c = '/';
+@@ -1018,12 +1016,12 @@
+
+ /* exec the cgi */
+ execve(arg.ptr[0], arg.ptr, env.ptr);
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "execve failed for:", host->bin_path, strerror(errno));
+-
++
+ exit(errno);
+-
++
+ break;
+ }
+ case -1:
+@@ -1031,17 +1029,17 @@
+ break;
+ default:
+ /* father */
+-
++
+ /* wait */
+ select(0, NULL, NULL, NULL, &tv);
+-
++
+ switch (waitpid(child, &status, WNOHANG)) {
+ case 0:
+ /* child still running after timeout, good */
+ break;
+ case -1:
+ /* no PID found ? should never happen */
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "pid not found:", strerror(errno));
+ return -1;
+ default:
+@@ -1049,10 +1047,10 @@
+ "the fastcgi-backend", host->bin_path, "failed to start:");
+ /* the child should not terminate at all */
+ if (WIFEXITED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sdb",
+- "child exited with status",
++ log_error_write(srv, __FILE__, __LINE__, "sdb",
++ "child exited with status",
+ WEXITSTATUS(status), host->bin_path);
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n"
+ "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' "
+ "in the output, NOT (cgi) NOR (cli)\n"
+@@ -1060,8 +1058,8 @@
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "If this is PHP on Gentoo add fastcgi to the USE flags");
+ } else if (WIFSIGNALED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "terminated by signal:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "terminated by signal:",
+ WTERMSIG(status));
+
+ if (WTERMSIG(status) == 11) {
+@@ -1071,8 +1069,8 @@
+ "If this is PHP try to remove the byte-code caches for now and try again.");
+ }
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child died somehow:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child died somehow:",
+ status);
+ }
+ return -1;
+@@ -1082,26 +1080,26 @@
+ proc->pid = child;
+ proc->last_used = srv->cur_ts;
+ proc->is_local = 1;
+-
++
+ break;
+ }
+ #endif
+ } else {
+ proc->is_local = 0;
+ proc->pid = 0;
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "(debug) socket is already used, won't spawn:",
+ proc->connection_name);
+ }
+ }
+-
++
+ proc->state = PROC_STATE_RUNNING;
+ host->active_procs++;
+-
++
+ close(fcgi_fd);
+-
++
+ return 0;
+ }
+
+@@ -1111,93 +1109,93 @@
+ data_unset *du;
+ size_t i = 0;
+ buffer *fcgi_mode = buffer_init();
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "fastcgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "fastcgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "fastcgi.map-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+ array *ca;
+-
++
+ s = malloc(sizeof(plugin_config));
+ s->exts = fastcgi_extensions_init();
+ s->debug = 0;
+ s->ext_mapping = array_init();
+-
++
+ cv[0].destination = s->exts;
+ cv[1].destination = &(s->debug);
+ cv[2].destination = s->ext_mapping;
+-
++
+ p->config_storage[i] = s;
+ ca = ((data_config *)srv->config_context->data[i])->value;
+-
++
+ if (0 != config_insert_values_global(srv, ca, cv)) {
+ return HANDLER_ERROR;
+ }
+-
+- /*
++
++ /*
+ * <key> = ( ... )
+ */
+-
++
+ if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
+ size_t j;
+ data_array *da = (data_array *)du;
+-
++
+ if (du->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "sss",
++ log_error_write(srv, __FILE__, __LINE__, "sss",
+ "unexpected type for key: ", "fastcgi.server", "array of strings");
+-
++
+ return HANDLER_ERROR;
+ }
+-
+-
+- /*
+- * fastcgi.server = ( "<ext>" => ( ... ),
++
++
++ /*
++ * fastcgi.server = ( "<ext>" => ( ... ),
+ * "<ext>" => ( ... ) )
+ */
+-
++
+ for (j = 0; j < da->value->used; j++) {
+ size_t n;
+ data_array *da_ext = (data_array *)da->value->data[j];
+-
++
+ if (da->value->data[j]->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "sssbs",
+- "unexpected type for key: ", "fastcgi.server",
++ log_error_write(srv, __FILE__, __LINE__, "sssbs",
++ "unexpected type for key: ", "fastcgi.server",
+ "[", da->value->data[j]->key, "](string)");
+-
++
+ return HANDLER_ERROR;
+ }
+-
+- /*
+- * da_ext->key == name of the extension
++
++ /*
++ * da_ext->key == name of the extension
+ */
+-
+- /*
+- * fastcgi.server = ( "<ext>" =>
+- * ( "<host>" => ( ... ),
++
++ /*
++ * fastcgi.server = ( "<ext>" =>
++ * ( "<host>" => ( ... ),
+ * "<host>" => ( ... )
+- * ),
++ * ),
+ * "<ext>" => ... )
+ */
+-
++
+ for (n = 0; n < da_ext->value->used; n++) {
+ data_array *da_host = (data_array *)da_ext->value->data[n];
+-
++
+ fcgi_extension_host *host;
+-
+- config_values_t fcv[] = {
++
++ config_values_t fcv[] = {
+ { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "mode", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+ { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
+-
++
+ { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
+ { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
+ { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
+@@ -1205,28 +1203,28 @@
+ { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
+ { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
+ { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
+-
++
+ { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
+ { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
+-
++
+ { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
+ { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
+ { "strip-request-uri", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
+-
++
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (da_host->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "ssSBS",
+- "unexpected type for key:",
+- "fastcgi.server",
++ log_error_write(srv, __FILE__, __LINE__, "ssSBS",
++ "unexpected type for key:",
++ "fastcgi.server",
+ "[", da_host->key, "](string)");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ host = fastcgi_host_init();
+-
++
+ buffer_copy_string_buffer(host->id, da_host->key);
+
+ host->check_local = 1;
+@@ -1238,13 +1236,13 @@
+ host->disable_time = 60;
+ host->break_scriptfilename_for_php = 0;
+ host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
+-
++
+ fcv[0].destination = host->host;
+ fcv[1].destination = host->docroot;
+ fcv[2].destination = fcgi_mode;
+ fcv[3].destination = host->unixsocket;
+ fcv[4].destination = host->bin_path;
+-
++
+ fcv[5].destination = &(host->check_local);
+ fcv[6].destination = &(host->port);
+ fcv[7].destination = &(host->min_procs);
+@@ -1252,35 +1250,35 @@
+ fcv[9].destination = &(host->max_load_per_proc);
+ fcv[10].destination = &(host->idle_timeout);
+ fcv[11].destination = &(host->disable_time);
+-
++
+ fcv[12].destination = host->bin_env;
+ fcv[13].destination = host->bin_env_copy;
+ fcv[14].destination = &(host->break_scriptfilename_for_php);
+ fcv[15].destination = &(host->allow_xsendfile);
+ fcv[16].destination = host->strip_request_uri;
+-
++
+ if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
+ return HANDLER_ERROR;
+ }
+-
+- if ((!buffer_is_empty(host->host) || host->port) &&
++
++ if ((!buffer_is_empty(host->host) || host->port) &&
+ !buffer_is_empty(host->unixsocket)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
++ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
+ "either host/port or socket have to be set in:",
+- da->key, "= (",
++ da->key, "= (",
+ da_ext->key, " => (",
+ da_host->key, " ( ...");
+
+ return HANDLER_ERROR;
+ }
+-
++
+ if (!buffer_is_empty(host->unixsocket)) {
+ /* unix domain socket */
+-
++
+ if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
+- log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
++ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
+ "unixsocket is too long in:",
+- da->key, "= (",
++ da->key, "= (",
+ da_ext->key, " => (",
+ da_host->key, " ( ...");
+
+@@ -1288,37 +1286,37 @@
+ }
+ } else {
+ /* tcp/ip */
+-
+- if (buffer_is_empty(host->host) &&
++
++ if (buffer_is_empty(host->host) &&
+ buffer_is_empty(host->bin_path)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
++ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
+ "host or binpath have to be set in:",
+- da->key, "= (",
++ da->key, "= (",
+ da_ext->key, " => (",
+ da_host->key, " ( ...");
+-
++
+ return HANDLER_ERROR;
+ } else if (host->port == 0) {
+- log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
++ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
+ "port has to be set in:",
+- da->key, "= (",
++ da->key, "= (",
+ da_ext->key, " => (",
+ da_host->key, " ( ...");
+
+ return HANDLER_ERROR;
+ }
+ }
+-
+- if (!buffer_is_empty(host->bin_path)) {
++
++ if (!buffer_is_empty(host->bin_path)) {
+ /* a local socket + self spawning */
+ size_t pno;
+
+ /* HACK: just to make sure the adaptive spawing is disabled */
+ host->min_procs = host->max_procs;
+-
++
+ if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
+ if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
+-
++
+ if (s->debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
+ "--- fastcgi spawning local",
+@@ -1328,7 +1326,7 @@
+ "\n\tmin-procs:", host->min_procs,
+ "\n\tmax-procs:", host->max_procs);
+ }
+-
++
+ for (pno = 0; pno < host->min_procs; pno++) {
+ fcgi_proc *proc;
+
+@@ -1343,7 +1341,7 @@
+ buffer_append_string(proc->unixsocket, "-");
+ buffer_append_long(proc->unixsocket, pno);
+ }
+-
++
+ if (s->debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
+ "--- fastcgi spawning",
+@@ -1351,7 +1349,7 @@
+ "\n\tsocket", host->unixsocket,
+ "\n\tcurrent:", pno, "/", host->min_procs);
+ }
+-
++
+ if (fcgi_spawn_connection(srv, p, host, proc)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "[ERROR]: spawning fcgi failed.");
+@@ -1359,35 +1357,35 @@
+ }
+
+ fastcgi_status_init(srv, p->statuskey, host, proc);
+-
++
+ proc->next = host->first;
+ if (host->first) host->first->prev = proc;
+-
++
+ host->first = proc;
+ }
+ } else {
+ fcgi_proc *proc;
+-
++
+ proc = fastcgi_process_init();
+ proc->id = host->num_procs++;
+ host->max_id++;
+ host->active_procs++;
+ proc->state = PROC_STATE_RUNNING;
+-
++
+ if (buffer_is_empty(host->unixsocket)) {
+ proc->port = host->port;
+ } else {
+ buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
+ }
+-
++
+ fastcgi_status_init(srv, p->statuskey, host, proc);
+
+ host->first = proc;
+-
++
+ host->min_procs = 1;
+ host->max_procs = 1;
+ }
+-
++
+ if (!buffer_is_empty(fcgi_mode)) {
+ if (strcmp(fcgi_mode->ptr, "responder") == 0) {
+ host->mode = FCGI_RESPONDER;
+@@ -1411,16 +1409,16 @@
+ }
+ }
+ }
+-
++
+ buffer_free(fcgi_mode);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) {
+ hctx->state = state;
+ hctx->state_timestamp = srv->cur_ts;
+-
++
+ return 0;
+ }
+
+@@ -1429,13 +1427,13 @@
+ size_t m = 0;
+ size_t i;
+ buffer_uint *r = &(p->fcgi_request_id);
+-
++
+ UNUSED(srv);
+
+ for (i = 0; i < r->used; i++) {
+ if (r->ptr[i] > m) m = r->ptr[i];
+ }
+-
++
+ if (r->size == 0) {
+ r->size = 16;
+ r->ptr = malloc(sizeof(*r->ptr) * r->size);
+@@ -1443,54 +1441,54 @@
+ r->size += 16;
+ r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
+ }
+-
++
+ r->ptr[r->used++] = ++m;
+-
++
+ return m;
+ }
+
+ static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
+ size_t i;
+ buffer_uint *r = &(p->fcgi_request_id);
+-
++
+ UNUSED(srv);
+
+ for (i = 0; i < r->used; i++) {
+ if (r->ptr[i] == request_id) break;
+ }
+-
++
+ if (i != r->used) {
+ /* found */
+-
++
+ if (i != r->used - 1) {
+ r->ptr[i] = r->ptr[r->used - 1];
+ }
+ r->used--;
+ }
+-
++
+ return 0;
+ }
+ void fcgi_connection_close(server *srv, handler_ctx *hctx) {
+ plugin_data *p;
+ connection *con;
+-
++
+ if (NULL == hctx) return;
+-
++
+ p = hctx->plugin_data;
+ con = hctx->remote_conn;
+-
++
+ if (con->mode != p->id) {
+ WP();
+ return;
+ }
+-
++
+ if (hctx->fd != -1) {
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+ fdevent_unregister(srv->ev, hctx->fd);
+ close(hctx->fd);
+ srv->cur_fds--;
+ }
+-
++
+ if (hctx->request_id != 0) {
+ fcgi_requestid_del(srv, p, hctx->request_id);
+ }
+@@ -1499,7 +1497,7 @@
+ if (hctx->got_proc) {
+ /* after the connect the process gets a load */
+ hctx->proc->load--;
+-
++
+ status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
+
+ fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
+@@ -1509,39 +1507,39 @@
+
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
+- "released proc:",
+- "pid:", hctx->proc->pid,
+- "socket:", hctx->proc->connection_name,
++ "released proc:",
++ "pid:", hctx->proc->pid,
++ "socket:", hctx->proc->connection_name,
+ "load:", hctx->proc->load);
+ }
+ }
+ }
+
+-
++
+ handler_ctx_free(hctx);
+- con->plugin_ctx[p->id] = NULL;
++ con->plugin_ctx[p->id] = NULL;
+ }
+
+ static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
+ plugin_data *p = hctx->plugin_data;
+-
+- /* child died
+- *
+- * 1.
+- *
++
++ /* child died
++ *
++ * 1.
++ *
+ * connect was ok, connection was accepted
+ * but the php accept loop checks after the accept if it should die or not.
+- *
+- * if yes we can only detect it at a write()
+- *
++ *
++ * if yes we can only detect it at a write()
++ *
+ * next step is resetting this attemp and setup a connection again
+- *
++ *
+ * if we have more then 5 reconnects for the same request, die
+- *
+- * 2.
+- *
++ *
++ * 2.
++ *
+ * we have a connection but the child died by some other reason
+- *
++ *
+ */
+
+ if (hctx->fd != -1) {
+@@ -1551,59 +1549,59 @@
+ srv->cur_fds--;
+ hctx->fd = -1;
+ }
+-
++
+ fcgi_requestid_del(srv, p, hctx->request_id);
+-
++
+ fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
+-
++
+ hctx->request_id = 0;
+ hctx->reconnects++;
+-
++
+ if (p->conf.debug > 2) {
+ if (hctx->proc) {
+ log_error_write(srv, __FILE__, __LINE__, "sdb",
+- "release proc for reconnect:",
++ "release proc for reconnect:",
+ hctx->proc->pid, hctx->proc->connection_name);
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+- "release proc for reconnect:",
++ "release proc for reconnect:",
+ hctx->host->unixsocket);
+ }
+ }
+
+- if (hctx->proc && hctx->got_proc) {
++ if (hctx->proc && hctx->got_proc) {
+ hctx->proc->load--;
+ }
+
+ /* perhaps another host gives us more luck */
+ hctx->host->load--;
+ hctx->host = NULL;
+-
++
+ return 0;
+ }
+
+
+ static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
+ plugin_data *p = p_d;
+-
++
+ fcgi_connection_close(srv, con->plugin_ctx[p->id]);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+
+ static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
+ size_t len;
+-
++
+ if (!key || !val) return -1;
+-
++
+ len = key_len + val_len;
+-
++
+ len += key_len > 127 ? 4 : 1;
+ len += val_len > 127 ? 4 : 1;
+-
++
+ buffer_prepare_append(env, len);
+-
++
+ if (key_len > 127) {
+ env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
+ env->ptr[env->used++] = (key_len >> 16) & 0xff;
+@@ -1612,7 +1610,7 @@
+ } else {
+ env->ptr[env->used++] = (key_len >> 0) & 0xff;
+ }
+-
++
+ if (val_len > 127) {
+ env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
+ env->ptr[env->used++] = (val_len >> 16) & 0xff;
+@@ -1621,12 +1619,12 @@
+ } else {
+ env->ptr[env->used++] = (val_len >> 0) & 0xff;
+ }
+-
++
+ memcpy(env->ptr + env->used, key, key_len);
+ env->used += key_len;
+ memcpy(env->ptr + env->used, val, val_len);
+ env->used += val_len;
+-
++
+ return 0;
+ }
+
+@@ -1639,11 +1637,11 @@
+ header->contentLengthB1 = (contentLength >> 8) & 0xff;
+ header->paddingLength = paddingLength;
+ header->reserved = 0;
+-
++
+ return 0;
+ }
+ /**
+- *
++ *
+ * returns
+ * -1 error
+ * 0 connected
+@@ -1665,26 +1663,23 @@
+ struct sockaddr_un fcgi_addr_un;
+ #endif
+ socklen_t servlen;
+-
++
+ fcgi_extension_host *host = hctx->host;
+ fcgi_proc *proc = hctx->proc;
+ int fcgi_fd = hctx->fd;
+-
++
+ memset(&fcgi_addr, 0, sizeof(fcgi_addr));
+-
++
+ if (!buffer_is_empty(proc->unixsocket)) {
+ #ifdef HAVE_SYS_UN_H
+ /* use the unix domain socket */
+ fcgi_addr_un.sun_family = AF_UNIX;
+ strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
+-#ifdef SUN_LEN
++
+ servlen = SUN_LEN(&fcgi_addr_un);
+-#else
+- /* stevens says: */
+- servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
+-#endif
++
+ fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
+-
++
+ if (buffer_is_empty(proc->connection_name)) {
+ /* on remote spawing we have to set the connection-name now */
+ buffer_copy_string(proc->connection_name, "unix:");
+@@ -1695,16 +1690,18 @@
+ #endif
+ } else {
+ fcgi_addr_in.sin_family = AF_INET;
++
+ if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "converting IP-adress failed for", host->host,
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
++ "converting IP-adress failed for", host->host,
+ "\nBe sure to specify an IP address here");
+-
++
+ return -1;
+ }
++
+ fcgi_addr_in.sin_port = htons(proc->port);
+ servlen = sizeof(fcgi_addr_in);
+-
++
+ fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
+
+ if (buffer_is_empty(proc->connection_name)) {
+@@ -1715,20 +1712,20 @@
+ buffer_append_long(proc->connection_name, proc->port);
+ }
+ }
+-
++
+ if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
+- if (errno == EINPROGRESS ||
++ if (errno == EINPROGRESS ||
+ errno == EALREADY ||
+ errno == EINTR) {
+ if (hctx->conf.debug > 2) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "connect delayed, will continue later:", proc->connection_name);
+ }
+-
++
+ return CONNECTION_DELAYED;
+ } else if (errno == EAGAIN) {
+ if (hctx->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sbsd",
++ log_error_write(srv, __FILE__, __LINE__, "sbsd",
+ "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
+ "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
+ "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
+@@ -1736,8 +1733,8 @@
+
+ return CONNECTION_OVERLOADED;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sssb",
+- "connect failed:",
++ log_error_write(srv, __FILE__, __LINE__, "sssb",
++ "connect failed:",
+ strerror(errno), "on",
+ proc->connection_name);
+
+@@ -1747,7 +1744,7 @@
+
+ hctx->reconnects = 0;
+ if (hctx->conf.debug > 1) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connect succeeded: ", fcgi_fd);
+ }
+
+@@ -1756,21 +1753,21 @@
+
+ static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
+ size_t i;
+-
++
+ for (i = 0; i < con->request.headers->used; i++) {
+ data_string *ds;
+-
++
+ ds = (data_string *)con->request.headers->data[i];
+-
++
+ if (ds->value->used && ds->key->used) {
+ size_t j;
+ buffer_reset(srv->tmp_buf);
+-
++
+ if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
+ BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
+ srv->tmp_buf->used--;
+ }
+-
++
+ buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
+ for (j = 0; j < ds->key->used - 1; j++) {
+ char c = '_';
+@@ -1784,20 +1781,20 @@
+ srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
+ }
+ srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
+-
++
+ fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
+ }
+ }
+-
++
+ for (i = 0; i < con->environment->used; i++) {
+ data_string *ds;
+-
++
+ ds = (data_string *)con->environment->data[i];
+-
++
+ if (ds->value->used && ds->key->used) {
+ size_t j;
+ buffer_reset(srv->tmp_buf);
+-
++
+ buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
+ for (j = 0; j < ds->key->used - 1; j++) {
+ char c = '_';
+@@ -1811,11 +1808,11 @@
+ srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
+ }
+ srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
+-
++
+ fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
+ }
+ }
+-
++
+ return 0;
+ }
+
+@@ -1824,24 +1821,24 @@
+ FCGI_BeginRequestRecord beginRecord;
+ FCGI_Header header;
+ buffer *b;
+-
++
+ char buf[32];
+ const char *s;
+ #ifdef HAVE_IPV6
+ char b2[INET6_ADDRSTRLEN + 1];
+ #endif
+-
++
+ plugin_data *p = hctx->plugin_data;
+ fcgi_extension_host *host= hctx->host;
+
+ connection *con = hctx->remote_conn;
+ server_socket *srv_sock = con->srv_socket;
+-
++
+ sock_addr our_addr;
+ socklen_t our_addr_len;
+-
++
+ /* send FCGI_BEGIN_REQUEST */
+-
++
+ fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0);
+ beginRecord.body.roleB0 = host->mode;
+ beginRecord.body.roleB1 = 0;
+@@ -1849,21 +1846,21 @@
+ memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
+
+ b = chunkqueue_get_append_buffer(hctx->wb);
+-
++
+ buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
+-
++
+ /* send FCGI_PARAMS */
+ buffer_prepare_copy(p->fcgi_env, 1024);
+
+
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
+-
++
+ if (con->server_name->used) {
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
+ } else {
+ #ifdef HAVE_IPV6
+- s = inet_ntop(srv_sock->addr.plain.sa_family,
+- srv_sock->addr.plain.sa_family == AF_INET6 ?
++ s = inet_ntop(srv_sock->addr.plain.sa_family,
++ srv_sock->addr.plain.sa_family == AF_INET6 ?
+ (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
+ (const void *) &(srv_sock->addr.ipv4.sin_addr),
+ b2, sizeof(b2)-1);
+@@ -1872,50 +1869,50 @@
+ #endif
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
+ }
+-
++
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
+-
+- ltostr(buf,
++
++ ltostr(buf,
+ #ifdef HAVE_IPV6
+ ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
+ #else
+ ntohs(srv_sock->addr.ipv4.sin_port)
+ #endif
+ );
+-
++
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
+-
++
+ /* get the server-side of the connection to the client */
+ our_addr_len = sizeof(our_addr);
+-
++
+ if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
+ s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
+ } else {
+ s = inet_ntop_cache_get_ip(srv, &(our_addr));
+ }
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
+-
+- ltostr(buf,
++
++ ltostr(buf,
+ #ifdef HAVE_IPV6
+ ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
+ #else
+ ntohs(con->dst_addr.ipv4.sin_port)
+ #endif
+ );
+-
++
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
+-
++
+ s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
+-
++
+ if (!buffer_is_empty(con->authed_user)) {
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
+ CONST_BUF_LEN(con->authed_user));
+ }
+-
++
+ if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
+ /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
+-
++
+ /* request.content_length < SSIZE_MAX, see request.c */
+ ltostr(buf, con->request.content_length);
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
+@@ -1930,12 +1927,12 @@
+ */
+
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
+-
++
+ if (!buffer_is_empty(con->request.pathinfo)) {
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
+-
++
+ /* PATH_TRANSLATED is only defined if PATH_INFO is set */
+-
++
+ if (!buffer_is_empty(host->docroot)) {
+ buffer_copy_string_buffer(p->path, host->docroot);
+ } else {
+@@ -1957,27 +1954,27 @@
+ */
+
+ if (!buffer_is_empty(host->docroot)) {
+- /*
+- * rewrite SCRIPT_FILENAME
+- *
++ /*
++ * rewrite SCRIPT_FILENAME
++ *
+ */
+-
++
+ buffer_copy_string_buffer(p->path, host->docroot);
+ buffer_append_string_buffer(p->path, con->uri.path);
+-
++
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
+ } else {
+ buffer_copy_string_buffer(p->path, con->physical.path);
+-
+- /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
+- *
++
++ /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
++ *
+ * see src/sapi/cgi_main.c, init_request_info()
+ */
+ if (host->break_scriptfilename_for_php) {
+ buffer_append_string_buffer(p->path, con->request.pathinfo);
+ }
+-
++
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
+ }
+@@ -1987,7 +1984,7 @@
+ /**
+ * /app1/index/list
+ *
+- * stripping /app1 or /app1/ should lead to
++ * stripping /app1 or /app1/ should lead to
+ *
+ * /index/list
+ *
+@@ -2001,7 +1998,7 @@
+ 0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
+ /* the left is the same */
+
+- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
++ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
+ con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
+ con->request.orig_uri->used - (host->strip_request_uri->used - 2));
+ } else {
+@@ -2018,26 +2015,26 @@
+ } else {
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
+ }
+-
++
+ s = get_http_method_name(con->request.http_method);
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
+ s = get_http_version_name(con->request.http_version);
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
+-
++
+ #ifdef USE_OPENSSL
+ if (srv_sock->is_ssl) {
+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
+ }
+ #endif
+-
+-
++
++
+ fcgi_env_add_request_headers(srv, con, p);
+-
++
+ fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
+ buffer_append_memory(b, (const char *)&header, sizeof(header));
+ buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used);
+-
++
+ fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
+ buffer_append_memory(b, (const char *)&header, sizeof(header));
+
+@@ -2057,7 +2054,7 @@
+
+ /* we announce toWrite octects
+ * now take all the request_content chunk that we need to fill this request
+- * */
++ * */
+
+ b = chunkqueue_get_append_buffer(hctx->wb);
+ fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0);
+@@ -2080,16 +2077,16 @@
+ if (weHave > weWant - written) weHave = weWant - written;
+
+ if (p->conf.debug > 10) {
+- fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
+- __FILE__, __LINE__,
+- weHave,
+- req_c->offset,
+- req_c->file.length,
++ fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
++ __FILE__, __LINE__,
++ weHave,
++ req_c->offset,
++ req_c->file.length,
+ req_c->file.name->ptr);
+ }
+
+ assert(weHave != 0);
+-
++
+ chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
+
+ req_c->offset += weHave;
+@@ -2104,7 +2101,7 @@
+ * - we reference the tempfile from the request-content-queue several times
+ * if the req_c is larger than FCGI_MAX_LENGTH
+ * - we can't simply cleanup the request-content-queue as soon as possible
+- * as it would remove the tempfiles
++ * as it would remove the tempfiles
+ * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
+ * referencing chunk of the fastcgi-write-queue
+ *
+@@ -2141,7 +2138,7 @@
+ req_c->offset += weHave;
+ req_cq->bytes_out += weHave;
+ written += weHave;
+-
++
+ hctx->wb->bytes_in += weHave;
+
+ if (req_c->offset == req_c->mem->used - 1) {
+@@ -2155,12 +2152,12 @@
+ break;
+ }
+ }
+-
++
+ b->used++; /* add virtual \0 */
+ offset += weWant;
+ }
+ }
+-
++
+ b = chunkqueue_get_append_buffer(hctx->wb);
+ /* terminate STDIN */
+ fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0);
+@@ -2175,118 +2172,19 @@
+ if ((i+1) % 16 == 0) {
+ size_t j;
+ for (j = i-15; j <= i; j++) {
+- fprintf(stderr, "%c",
++ fprintf(stderr, "%c",
+ isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+ #endif
+-
+- return 0;
+-}
+-
+-static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
+- char *s, *ns;
+-
+- handler_ctx *hctx = con->plugin_ctx[p->id];
+- fcgi_extension_host *host= hctx->host;
+-
+- UNUSED(srv);
+
+- buffer_copy_string_buffer(p->parse_response, in);
+-
+- /* search for \n */
+- for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
+- char *key, *value;
+- int key_len;
+- data_string *ds;
+-
+- /* a good day. Someone has read the specs and is sending a \r\n to us */
+-
+- if (ns > p->parse_response->ptr &&
+- *(ns-1) == '\r') {
+- *(ns-1) = '\0';
+- }
+-
+- ns[0] = '\0';
+-
+- key = s;
+- if (NULL == (value = strchr(s, ':'))) {
+- /* we expect: "<key>: <value>\n" */
+- continue;
+- }
+-
+- key_len = value - key;
+-
+- value++;
+- /* strip WS */
+- while (*value == ' ' || *value == '\t') value++;
+-
+- if (host->mode != FCGI_AUTHORIZER ||
+- !(con->http_status == 0 ||
+- con->http_status == 200)) {
+- /* authorizers shouldn't affect the response headers sent back to the client */
+-
+- /* don't forward Status: */
+- if (0 != strncasecmp(key, "Status", key_len)) {
+- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
+- ds = data_response_init();
+- }
+- buffer_copy_string_len(ds->key, key, key_len);
+- buffer_copy_string(ds->value, value);
+-
+- array_insert_unique(con->response.headers, (data_unset *)ds);
+- }
+- }
+-
+- switch(key_len) {
+- case 4:
+- if (0 == strncasecmp(key, "Date", key_len)) {
+- con->parsed_response |= HTTP_DATE;
+- }
+- break;
+- case 6:
+- if (0 == strncasecmp(key, "Status", key_len)) {
+- con->http_status = strtol(value, NULL, 10);
+- con->parsed_response |= HTTP_STATUS;
+- }
+- break;
+- case 8:
+- if (0 == strncasecmp(key, "Location", key_len)) {
+- con->parsed_response |= HTTP_LOCATION;
+- }
+- break;
+- case 10:
+- if (0 == strncasecmp(key, "Connection", key_len)) {
+- con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
+- con->parsed_response |= HTTP_CONNECTION;
+- }
+- break;
+- case 14:
+- if (0 == strncasecmp(key, "Content-Length", key_len)) {
+- con->response.content_length = strtol(value, NULL, 10);
+- con->parsed_response |= HTTP_CONTENT_LENGTH;
+-
+- if (con->response.content_length < 0) con->response.content_length = 0;
+- }
+- break;
+- default:
+- break;
+- }
+- }
+-
+- /* CGI/1.1 rev 03 - 7.2.1.2 */
+- if ((con->parsed_response & HTTP_LOCATION) &&
+- !(con->parsed_response & HTTP_STATUS)) {
+- con->http_status = 302;
+- }
+-
+ return 0;
+ }
+
+ typedef struct {
+- buffer *b;
++ buffer *b;
+ size_t len;
+ int type;
+ int padding;
+@@ -2327,9 +2225,9 @@
+ return -1;
+ }
+
+- /* we have at least a header, now check how much me have to fetch */
++ /* we have at least a header, now check how much me have to fetch */
+ header = (FCGI_Header *)(packet->b->ptr);
+-
++
+ packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
+ packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
+ packet->type = header->type;
+@@ -2348,7 +2246,7 @@
+ size_t weHave = c->mem->used - c->offset - offset - 1;
+
+ if (weHave > weWant) weHave = weWant;
+-
++
+ buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
+
+ /* we only skipped the first 8 bytes as they are the fcgi header */
+@@ -2380,65 +2278,37 @@
+ }
+
+ chunkqueue_remove_finished_chunks(hctx->rb);
+-
++
+ return 0;
+ }
+
+ static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
+ int fin = 0;
+- int toread;
+- ssize_t r;
+-
++
+ plugin_data *p = hctx->plugin_data;
+ connection *con = hctx->remote_conn;
+- int fcgi_fd = hctx->fd;
+ fcgi_extension_host *host= hctx->host;
+ fcgi_proc *proc = hctx->proc;
+-
+- /*
+- * check how much we have to read
+- */
+- if (ioctl(hctx->fd, FIONREAD, &toread)) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "unexpected end-of-file (perhaps the fastcgi process died):",
+- fcgi_fd);
+- return -1;
+- }
+-
+- /* init read-buffer */
+-
+- if (toread > 0) {
+- buffer *b;
+-
+- b = chunkqueue_get_append_buffer(hctx->rb);
+- buffer_prepare_copy(b, toread + 1);
+-
+- /* append to read-buffer */
+- if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "unexpected end-of-file (perhaps the fastcgi process died):",
+- fcgi_fd, strerror(errno));
+- return -1;
+- }
+-
+- /* this should be catched by the b > 0 above */
+- assert(r);
+
+- b->used = r + 1; /* one extra for the fake \0 */
+- b->ptr[b->used - 1] = '\0';
+- } else {
+- log_error_write(srv, __FILE__, __LINE__, "ssdsb",
++ switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) {
++ case NETWORK_STATUS_WAIT_FOR_EVENT:
++ /* we are only triggered when there is a event */
++ log_error_write(srv, __FILE__, __LINE__, "ssdsb",
+ "unexpected end-of-file (perhaps the fastcgi process died):",
+ "pid:", proc->pid,
+ "socket:", proc->connection_name);
+-
++ return -1;
++ case NETWORK_STATUS_SUCCESS:
++ break;
++ default:
++ log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
+ return -1;
+ }
+
+ /*
+ * parse the fastcgi packets and forward the content to the write-queue
+ *
+- */
++ */
+ while (fin == 0) {
+ fastcgi_response_packet packet;
+
+@@ -2454,92 +2324,135 @@
+
+ /* is the header already finished */
+ if (0 == con->file_started) {
+- char *c;
+- size_t blen;
+- data_string *ds;
+-
+- /* search for header terminator
+- *
+- * if we start with \r\n check if last packet terminated with \r\n
+- * if we start with \n check if last packet terminated with \n
+- * search for \r\n\r\n
+- * search for \n\n
+- */
+-
+- if (hctx->response_header->used == 0) {
+- buffer_copy_string_buffer(hctx->response_header, packet.b);
+- } else {
+- buffer_append_string_buffer(hctx->response_header, packet.b);
+- }
+-
+- if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
+- blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
+- hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
+- c += 4; /* point the the start of the response */
+- } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
+- blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
+- hctx->response_header->used = c - hctx->response_header->ptr + 2;
+- c += 2; /* point the the start of the response */
+- } else {
+- /* no luck, no header found */
++ int have_content_length = 0;
++ int need_more = 0;
++ size_t i;
++
++ /* append the current packet to the chunk queue */
++ chunkqueue_append_buffer(hctx->http_rb, packet.b);
++ http_response_reset(p->resp);
++
++ switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
++ case PARSE_ERROR:
++ /* parsing the response header failed */
++
++ con->http_status = 502; /* Bad Gateway */
++
++ return 1;
++ case PARSE_NEED_MORE:
++ need_more = 1;
++ break; /* leave the loop */
++ case PARSE_SUCCESS:
+ break;
++ default:
++ /* should not happen */
++ SEGFAULT();
+ }
+
+- /* parse the response header */
+- fcgi_response_parse(srv, con, p, hctx->response_header);
++ if (need_more) break;
+
+- con->file_started = 1;
++ chunkqueue_remove_finished_chunks(hctx->http_rb);
+
+- if (host->mode == FCGI_AUTHORIZER &&
+- (con->http_status == 0 ||
+- con->http_status == 200)) {
+- /* a authorizer with approved the static request, ignore the content here */
+- hctx->send_content_body = 0;
+- }
+-
+- if (host->allow_xsendfile &&
+- NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
+- stat_cache_entry *sce;
+-
+- if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
+- /* found */
+-
+- http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
+- hctx->send_content_body = 0; /* ignore the content */
+- joblist_append(srv, con);
++ con->http_status = p->resp->status;
++
++ /* handle the header fields */
++ if (host->mode == FCGI_AUTHORIZER) {
++ /* auth mode is a bit different */
++
++ if (con->http_status == 0 ||
++ con->http_status == 200) {
++ /* a authorizer with approved the static request, ignore the content here */
++ hctx->send_content_body = 0;
+ }
+ }
+
++ /* copy the http-headers */
++ for (i = 0; i < p->resp->headers->used; i++) {
++ const char *ign[] = { "Status", NULL };
++ size_t j;
++ data_string *ds;
++
++ data_string *header = (data_string *)p->resp->headers->data[i];
++
++ /* ignore all headers in AUTHORIZER mode */
++ if (host->mode == FCGI_AUTHORIZER) continue;
++
++ /* some headers are ignored by default */
++ for (j = 0; ign[j]; j++) {
++ if (0 == strcasecmp(ign[j], header->key->ptr)) break;
++ }
++ if (ign[j]) continue;
++
++ if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
++ /* CGI/1.1 rev 03 - 7.2.1.2 */
++ con->http_status = 302;
++ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
++ have_content_length = 1;
++ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) ||
++ 0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
++
++ stat_cache_entry *sce;
+
+- if (hctx->send_content_body && blen > 1) {
+- /* enable chunked-transfer-encoding */
++ if (host->allow_xsendfile &&
++ HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
++ http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
++ hctx->send_content_body = 0; /* ignore the content */
++
++ joblist_append(srv, con);
++ }
++
++ continue; /* ignore header */
++ }
++
++ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
++ ds = data_response_init();
++ }
++ buffer_copy_string_buffer(ds->key, header->key);
++ buffer_copy_string_buffer(ds->value, header->value);
++
++ array_insert_unique(con->response.headers, (data_unset *)ds);
++ }
++
++ /* header is complete ... go on with the body */
++
++ con->file_started = 1;
++
++ if (hctx->send_content_body) {
++ chunk *c = hctx->http_rb->first;
++
++ /* if we don't have a content-length enable chunked encoding
++ * if possible
++ *
++ * TODO: move this to a later stage in the filter-queue
++ * */
+ if (con->request.http_version == HTTP_VERSION_1_1 &&
+- !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
++ !have_content_length) {
+ con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
+ }
+
+- http_chunk_append_mem(srv, con, c, blen);
++ /* copy the rest of the data */
++ for (c = hctx->http_rb->first; c; c = c->next) {
++ if (c->mem->used > 1) {
++ http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
++ c->offset = c->mem->used - 1;
++ }
++ }
++ chunkqueue_remove_finished_chunks(hctx->http_rb);
+ joblist_append(srv, con);
+ }
+ } else if (hctx->send_content_body && packet.b->used > 1) {
+- if (con->request.http_version == HTTP_VERSION_1_1 &&
+- !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
+- /* enable chunked-transfer-encoding */
+- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
+- }
+-
+ http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
+ joblist_append(srv, con);
+ }
+ break;
+ case FCGI_STDERR:
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "FastCGI-stderr:", packet.b);
+-
++
+ break;
+ case FCGI_END_REQUEST:
+ con->file_finished = 1;
+-
++
+ if (host->mode != FCGI_AUTHORIZER ||
+ !(con->http_status == 0 ||
+ con->http_status == 200)) {
+@@ -2547,39 +2460,39 @@
+ http_chunk_append_mem(srv, con, NULL, 0);
+ joblist_append(srv, con);
+ }
+-
++
+ fin = 1;
+ break;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "FastCGI: header.type not handled: ", packet.type);
+ break;
+ }
+ buffer_free(packet.b);
+ }
+-
++
+ return fin;
+ }
+
+ static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
+ fcgi_proc *proc;
+-
++
+ for (proc = host->first; proc; proc = proc->next) {
+ int status;
+
+ if (p->conf.debug > 2) {
+- log_error_write(srv, __FILE__, __LINE__, "sbdddd",
+- "proc:",
++ log_error_write(srv, __FILE__, __LINE__, "sbdddd",
++ "proc:",
+ proc->connection_name,
+ proc->state,
+ proc->is_local,
+ proc->load,
+ proc->pid);
+ }
+-
+- /*
++
++ /*
+ * if the remote side is overloaded, we check back after <n> seconds
+- *
++ *
+ */
+ switch (proc->state) {
+ case PROC_STATE_KILLED:
+@@ -2592,13 +2505,13 @@
+ break;
+ case PROC_STATE_OVERLOADED:
+ if (srv->cur_ts <= proc->disabled_until) break;
+-
++
+ proc->state = PROC_STATE_RUNNING;
+ host->active_procs++;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbdb",
+- "fcgi-server re-enabled:",
+- host->host, host->port,
++
++ log_error_write(srv, __FILE__, __LINE__, "sbdb",
++ "fcgi-server re-enabled:",
++ host->host, host->port,
+ host->unixsocket);
+ break;
+ case PROC_STATE_DIED_WAIT_FOR_PID:
+@@ -2606,7 +2519,7 @@
+ if (!proc->is_local) break;
+
+ /* the child should not terminate at all */
+-
++#ifndef _WIN32
+ switch(waitpid(proc->pid, &status, WNOHANG)) {
+ case 0:
+ /* child is still alive */
+@@ -2616,45 +2529,45 @@
+ default:
+ if (WIFEXITED(status)) {
+ #if 0
+- log_error_write(srv, __FILE__, __LINE__, "sdsd",
++ log_error_write(srv, __FILE__, __LINE__, "sdsd",
+ "child exited, pid:", proc->pid,
+ "status:", WEXITSTATUS(status));
+ #endif
+ } else if (WIFSIGNALED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child signaled:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child signaled:",
+ WTERMSIG(status));
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child died somehow:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child died somehow:",
+ status);
+ }
+-
++
+ proc->state = PROC_STATE_DIED;
+ break;
+ }
+-
++#endif
+ /* fall through if we have a dead proc now */
+ if (proc->state != PROC_STATE_DIED) break;
+
+ case PROC_STATE_DIED:
+- /* local proc get restarted by us,
++ /* local proc get restarted by us,
+ * remote ones hopefully by the admin */
+-
++
+ if (proc->is_local) {
+ /* we still have connections bound to this proc,
+ * let them terminate first */
+ if (proc->load != 0) break;
+-
++
+ /* restart the child */
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
+ "--- fastcgi spawning",
+ "\n\tsocket", proc->connection_name,
+ "\n\tcurrent:", 1, "/", host->min_procs);
+ }
+-
++
+ if (fcgi_spawn_connection(srv, p, host, proc)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ERROR: spawning fcgi failed.");
+@@ -2662,18 +2575,18 @@
+ }
+ } else {
+ if (srv->cur_ts <= proc->disabled_until) break;
+-
++
+ proc->state = PROC_STATE_RUNNING;
+ host->active_procs++;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "fcgi-server re-enabled:",
++
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "fcgi-server re-enabled:",
+ proc->connection_name);
+ }
+ break;
+ }
+ }
+-
++
+ return 0;
+ }
+
+@@ -2682,19 +2595,19 @@
+ fcgi_extension_host *host= hctx->host;
+ connection *con = hctx->remote_conn;
+ fcgi_proc *proc;
+-
++
+ int ret;
+
+- /* sanity check */
++ /* sanity check */
+ if (!host ||
+ ((!host->host->used || !host->port) && !host->unixsocket->used)) {
+- log_error_write(srv, __FILE__, __LINE__, "sxddd",
++ log_error_write(srv, __FILE__, __LINE__, "sxddd",
+ "write-req: error",
+ host,
+ host->host->used,
+ host->port,
+ host->unixsocket->used);
+-
++
+ hctx->proc->disabled_until = srv->cur_ts + 10;
+ hctx->proc->state = PROC_STATE_DIED;
+
+@@ -2705,12 +2618,12 @@
+ if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
+ int socket_error;
+ socklen_t socket_error_len = sizeof(socket_error);
+-
++
+ /* try to finish the connect() */
+ if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "getsockopt failed:", strerror(errno));
+-
++
+ hctx->proc->disabled_until = srv->cur_ts + 10;
+ hctx->proc->state = PROC_STATE_DIED;
+
+@@ -2719,12 +2632,12 @@
+ if (socket_error != 0) {
+ if (!hctx->proc->is_local || p->conf.debug) {
+ /* local procs get restarted */
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "sssb",
+- "establishing connection failed:", strerror(socket_error),
++ "establishing connection failed:", strerror(socket_error),
+ "socket:", hctx->proc->connection_name);
+ }
+-
++
+ hctx->proc->disabled_until = srv->cur_ts + 5;
+
+ if (hctx->proc->is_local) {
+@@ -2732,17 +2645,17 @@
+ } else {
+ hctx->proc->state = PROC_STATE_DIED;
+ }
+-
++
+ hctx->proc->state = PROC_STATE_DIED;
+-
++
+ fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
+ buffer_append_string(p->statuskey, ".died");
+
+ status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
+-
++
+ return HANDLER_ERROR;
+ }
+- /* go on with preparing the request */
++ /* go on with preparing the request */
+ hctx->state = FCGI_STATE_PREPARE_WRITE;
+ }
+
+@@ -2755,14 +2668,14 @@
+ /* do we have a running process for this host (max-procs) ? */
+ hctx->proc = NULL;
+
+- for (proc = hctx->host->first;
+- proc && proc->state != PROC_STATE_RUNNING;
++ for (proc = hctx->host->first;
++ proc && proc->state != PROC_STATE_RUNNING;
+ proc = proc->next);
+-
++
+ /* all childs are dead */
+ if (proc == NULL) {
+ hctx->fde_ndx = -1;
+-
++
+ return HANDLER_ERROR;
+ }
+
+@@ -2775,50 +2688,50 @@
+ }
+
+ ret = host->unixsocket->used ? AF_UNIX : AF_INET;
+-
++
+ if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
+ if (errno == EMFILE ||
+ errno == EINTR) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "wait for fd at connection:", con->fd);
+-
++
+ return HANDLER_WAIT_FOR_FD;
+ }
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssdd",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssdd",
+ "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
+ return HANDLER_ERROR;
+ }
+ hctx->fde_ndx = -1;
+-
++
+ srv->cur_fds++;
+-
++
+ fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
+-
++
+ if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "fcntl failed:", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ if (hctx->proc->is_local) {
+ hctx->pid = hctx->proc->pid;
+ }
+-
++
+ switch (fcgi_establish_connection(srv, hctx)) {
+ case CONNECTION_DELAYED:
+ /* connection is in progress, wait for an event and call getsockopt() below */
+-
++
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED);
+ return HANDLER_WAIT_FOR_EVENT;
+ case CONNECTION_OVERLOADED:
+ /* cool down the backend, it is overloaded
+ * -> EAGAIN */
+
+- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
++ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
+ "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
+ "reconnects:", hctx->reconnects,
+ "load:", host->load);
+@@ -2831,7 +2744,7 @@
+ buffer_append_string(p->statuskey, ".overloaded");
+
+ status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
+-
++
+ return HANDLER_ERROR;
+ case CONNECTION_DEAD:
+ /* we got a hard error from the backend like
+@@ -2840,19 +2753,19 @@
+ *
+ * for check if the host is back in 5 seconds
+ * */
+-
++
+ hctx->proc->disabled_until = srv->cur_ts + 5;
+ if (hctx->proc->is_local) {
+ hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
+ } else {
+ hctx->proc->state = PROC_STATE_DIED;
+ }
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
+ "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
+ "reconnects:", hctx->reconnects,
+ "load:", host->load);
+-
++
+ fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
+ buffer_append_string(p->statuskey, ".died");
+
+@@ -2863,19 +2776,19 @@
+ /* everything is ok, go on */
+
+ fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
+-
++
+ break;
+ case CONNECTION_UNSET:
+ break;
+ }
+-
++
+ case FCGI_STATE_PREPARE_WRITE:
+ /* ok, we have the connection */
+-
++
+ hctx->proc->load++;
+ hctx->proc->last_used = srv->cur_ts;
+ hctx->got_proc = 1;
+-
++
+ status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
+ status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
+
+@@ -2898,9 +2811,9 @@
+
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
+- "got proc:",
+- "pid:", hctx->proc->pid,
+- "socket:", hctx->proc->connection_name,
++ "got proc:",
++ "pid:", hctx->proc->pid,
++ "socket:", hctx->proc->connection_name,
+ "load:", hctx->proc->load);
+ }
+
+@@ -2908,62 +2821,63 @@
+ if (hctx->request_id == 0) {
+ hctx->request_id = fcgi_requestid_new(srv, p);
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "fcgi-request is already in use:", hctx->request_id);
+ }
+-
++
+ /* fall through */
+ fcgi_create_env(srv, hctx, hctx->request_id);
+-
++
+ fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
+-
++
+ /* fall through */
+ case FCGI_STATE_WRITE:
+- ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
++ ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
+
+ chunkqueue_remove_finished_chunks(hctx->wb);
+-
++
+ if (ret < 0) {
+ switch(errno) {
+ case ENOTCONN:
+- /* the connection got dropped after accept()
+- *
+- * this is most of the time a PHP which dies
++ /* the connection got dropped after accept()
++ *
++ * this is most of the time a PHP which dies
+ * after PHP_FCGI_MAX_REQUESTS
+- *
+- */
++ *
++ */
+ if (hctx->wb->bytes_out == 0 &&
+ hctx->reconnects < 5) {
+- usleep(10000); /* take away the load of the webserver
+- * to let the php a chance to restart
++#ifndef _WIN32
++ usleep(10000); /* take away the load of the webserver
++ * to let the php a chance to restart
+ */
+-
++#endif
+ fcgi_reconnect(srv, hctx);
+-
++
+ return HANDLER_WAIT_FOR_FD;
+ }
+-
++
+ /* not reconnected ... why
+- *
++ *
+ * far@#lighttpd report this for FreeBSD
+- *
++ *
+ */
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssosd",
+ "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
+ "write-offset:", hctx->wb->bytes_out,
+ "reconnect attempts:", hctx->reconnects);
+-
++
+ return HANDLER_ERROR;
+ case EAGAIN:
+ case EINTR:
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
++ log_error_write(srv, __FILE__, __LINE__, "ssd",
+ "write failed:", strerror(errno), errno);
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+@@ -2975,7 +2889,7 @@
+ fcgi_set_state(srv, hctx, FCGI_STATE_READ);
+ } else {
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+ }
+
+@@ -2987,7 +2901,7 @@
+ log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
+ return HANDLER_ERROR;
+ }
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+ }
+
+@@ -2996,18 +2910,18 @@
+ * */
+ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
+ plugin_data *p = p_d;
+-
++
+ handler_ctx *hctx = con->plugin_ctx[p->id];
+ fcgi_proc *proc;
+ fcgi_extension_host *host;
+-
++
+ if (NULL == hctx) return HANDLER_GO_ON;
+-
++
+ /* not my job */
+ if (con->mode != p->id) return HANDLER_GO_ON;
+
+ /* we don't have a host yet, choose one
+- * -> this happens in the first round
++ * -> this happens in the first round
+ * and when the host died and we have to select a new one */
+ if (hctx->host == NULL) {
+ size_t k;
+@@ -3016,23 +2930,23 @@
+ /* get best server */
+ for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
+ host = hctx->ext->hosts[k];
+-
++
+ /* we should have at least one proc that can do something */
+ if (host->active_procs == 0) continue;
+
+ if (used == -1 || host->load < used) {
+ used = host->load;
+-
++
+ ndx = k;
+ }
+ }
+-
++
+ /* found a server */
+ if (ndx == -1) {
+ /* all hosts are down */
+
+ fcgi_connection_close(srv, hctx);
+-
++
+ con->http_status = 500;
+ con->mode = DIRECT;
+
+@@ -3040,16 +2954,16 @@
+ }
+
+ host = hctx->ext->hosts[ndx];
+-
+- /*
+- * if check-local is disabled, use the uri.path handler
+- *
++
++ /*
++ * if check-local is disabled, use the uri.path handler
++ *
+ */
+-
++
+ /* init handler-context */
+ hctx->host = host;
+
+- /* we put a connection on this host, move the other new connections to other hosts
++ /* we put a connection on this host, move the other new connections to other hosts
+ *
+ * as soon as hctx->host is unassigned, decrease the load again */
+ hctx->host->load++;
+@@ -3063,7 +2977,7 @@
+ case HANDLER_ERROR:
+ proc = hctx->proc;
+ host = hctx->host;
+-
++
+ if (hctx->state == FCGI_STATE_INIT ||
+ hctx->state == FCGI_STATE_CONNECT_DELAYED) {
+ if (proc) host->active_procs--;
+@@ -3078,7 +2992,7 @@
+ return HANDLER_WAIT_FOR_FD;
+ } else {
+ fcgi_connection_close(srv, hctx);
+-
++
+ buffer_reset(con->physical.path);
+ con->mode = DIRECT;
+ con->http_status = 500;
+@@ -3088,12 +3002,12 @@
+ }
+ } else {
+ fcgi_connection_close(srv, hctx);
+-
++
+ buffer_reset(con->physical.path);
+ con->mode = DIRECT;
+ con->http_status = 503;
+ joblist_append(srv, con); /* really ? */
+-
++
+ return HANDLER_FINISHED;
+ }
+ case HANDLER_WAIT_FOR_EVENT:
+@@ -3115,7 +3029,7 @@
+ handler_ctx *hctx = ctx;
+ connection *con = hctx->remote_conn;
+ plugin_data *p = hctx->plugin_data;
+-
++
+ fcgi_proc *proc = hctx->proc;
+ fcgi_extension_host *host= hctx->host;
+
+@@ -3125,8 +3039,8 @@
+ case 0:
+ break;
+ case 1:
+-
+- if (host->mode == FCGI_AUTHORIZER &&
++
++ if (host->mode == FCGI_AUTHORIZER &&
+ (con->http_status == 200 ||
+ con->http_status == 0)) {
+ /*
+@@ -3136,26 +3050,26 @@
+ */
+
+ buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
+-
++
+ buffer_copy_string_buffer(con->physical.path, host->docroot);
+ buffer_append_string_buffer(con->physical.path, con->uri.path);
+ fcgi_connection_close(srv, hctx);
+-
++
+ con->mode = DIRECT;
+ con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
+ } else {
+ /* we are done */
+ fcgi_connection_close(srv, hctx);
+ }
+-
++
+ joblist_append(srv, con);
+ return HANDLER_FINISHED;
+ case -1:
+ if (proc->pid && proc->state != PROC_STATE_DIED) {
+ int status;
+-
++
+ /* only fetch the zombie if it is not already done */
+-
++#ifndef _WIN32
+ switch(waitpid(proc->pid, &status, WNOHANG)) {
+ case 0:
+ /* child is still alive */
+@@ -3165,60 +3079,61 @@
+ default:
+ /* the child should not terminate at all */
+ if (WIFEXITED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sdsd",
++ log_error_write(srv, __FILE__, __LINE__, "sdsd",
+ "child exited, pid:", proc->pid,
+ "status:", WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child signaled:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child signaled:",
+ WTERMSIG(status));
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child died somehow:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child died somehow:",
+ status);
+ }
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
+ "--- fastcgi spawning",
+ "\n\tsocket", proc->connection_name,
+ "\n\tcurrent:", 1, "/", host->min_procs);
+ }
+-
++
+ if (fcgi_spawn_connection(srv, p, host, proc)) {
+ /* respawning failed, retry later */
+ proc->state = PROC_STATE_DIED;
+
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "respawning failed, will retry later");
+ }
+-
++
+ break;
+ }
++#endif
+ }
+
+ if (con->file_started == 0) {
+ /* nothing has been send out yet, try to use another child */
+-
++
+ if (hctx->wb->bytes_out == 0 &&
+ hctx->reconnects < 5) {
+ fcgi_reconnect(srv, hctx);
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
+ "response not received, request not sent",
+- "on socket:", proc->connection_name,
++ "on socket:", proc->connection_name,
+ "for", con->uri.path, ", reconnecting");
+-
++
+ return HANDLER_WAIT_FOR_FD;
+ }
+-
+- log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
++
++ log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
+ "response not received, request sent:", hctx->wb->bytes_out,
+- "on socket:", proc->connection_name,
++ "on socket:", proc->connection_name,
+ "for", con->uri.path, ", closing connection");
+-
++
+ fcgi_connection_close(srv, hctx);
+-
++
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+ buffer_reset(con->physical.path);
+ con->http_status = 500;
+@@ -3226,76 +3141,76 @@
+ } else {
+ /* response might have been already started, kill the connection */
+ fcgi_connection_close(srv, hctx);
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
+ "response already sent out, but backend returned error",
+- "on socket:", proc->connection_name,
++ "on socket:", proc->connection_name,
+ "for", con->uri.path, ", terminating connection");
+-
++
+ connection_set_state(srv, con, CON_STATE_ERROR);
+ }
+
+ /* */
+-
+-
++
++
+ joblist_append(srv, con);
+ return HANDLER_FINISHED;
+ }
+ }
+-
++
+ if (revents & FDEVENT_OUT) {
+ if (hctx->state == FCGI_STATE_CONNECT_DELAYED ||
+ hctx->state == FCGI_STATE_WRITE) {
+ /* we are allowed to send something out
+- *
++ *
+ * 1. in a unfinished connect() call
+ * 2. in a unfinished write() call (long POST request)
+ */
+ return mod_fastcgi_handle_subrequest(srv, con, p);
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "got a FDEVENT_OUT and didn't know why:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "got a FDEVENT_OUT and didn't know why:",
+ hctx->state);
+ }
+ }
+-
++
+ /* perhaps this issue is already handled */
+ if (revents & FDEVENT_HUP) {
+ if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
+ /* getoptsock will catch this one (right ?)
+- *
+- * if we are in connect we might get a EINPROGRESS
+- * in the first call and a FDEVENT_HUP in the
++ *
++ * if we are in connect we might get a EINPROGRESS
++ * in the first call and a FDEVENT_HUP in the
+ * second round
+- *
++ *
+ * FIXME: as it is a bit ugly.
+- *
++ *
+ */
+ return mod_fastcgi_handle_subrequest(srv, con, p);
+ } else if (hctx->state == FCGI_STATE_READ &&
+ hctx->proc->port == 0) {
+ /* FIXME:
+- *
++ *
+ * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
+ * even if the FCGI_FIN packet is not received yet
+ */
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
+- "error: unexpected close of fastcgi connection for",
++ log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
++ "error: unexpected close of fastcgi connection for",
+ con->uri.path,
+- "(no fastcgi process on host:",
++ "(no fastcgi process on host:",
+ host->host,
+- ", port: ",
++ ", port: ",
+ host->port,
+ " ?)",
+ hctx->state);
+-
++
+ connection_set_state(srv, con, CON_STATE_ERROR);
+ fcgi_connection_close(srv, hctx);
+ joblist_append(srv, con);
+ }
+ } else if (revents & FDEVENT_ERR) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "fcgi: got a FDEVENT_ERR. Don't know why.");
+ /* kill all connections to the fastcgi process */
+
+@@ -3304,45 +3219,42 @@
+ fcgi_connection_close(srv, hctx);
+ joblist_append(srv, con);
+ }
+-
++
+ return HANDLER_FINISHED;
+ }
+-#define PATCH(x) \
+- p->conf.x = s->x;
++
+ static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(exts);
+- PATCH(debug);
+- PATCH(ext_mapping);
+-
++
++ PATCH_OPTION(exts);
++ PATCH_OPTION(debug);
++ PATCH_OPTION(ext_mapping);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
+- PATCH(exts);
++ PATCH_OPTION(exts);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
+- PATCH(debug);
++ PATCH_OPTION(debug);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
+- PATCH(ext_mapping);
++ PATCH_OPTION(ext_mapping);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+-
+
+ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
+ plugin_data *p = p_d;
+@@ -3351,16 +3263,16 @@
+ buffer *fn;
+ fcgi_extension *extension = NULL;
+ fcgi_extension_host *host = NULL;
+-
++
+ /* Possibly, we processed already this request */
+ if (con->file_started == 1) return HANDLER_GO_ON;
+
+ fn = uri_path_handler ? con->uri.path : con->physical.path;
+
+ if (buffer_is_empty(fn)) return HANDLER_GO_ON;
+-
++
+ s_len = fn->used - 1;
+-
++
+ fcgi_patch_connection(srv, con, p);
+
+ /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
+@@ -3368,24 +3280,24 @@
+ * fastcgi.map-extensions = ( ".php3" => ".php" )
+ *
+ * fastcgi.server = ( ".php" => ... )
+- *
++ *
+ * */
+
+ /* check if extension-mapping matches */
+ for (k = 0; k < p->conf.ext_mapping->used; k++) {
+ data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
+ size_t ct_len; /* length of the config entry */
+-
++
+ if (ds->key->used == 0) continue;
+-
++
+ ct_len = ds->key->used - 1;
+-
++
+ if (s_len < ct_len) continue;
+-
++
+ /* found a mapping */
+ if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
+ /* check if we know the extension */
+-
++
+ /* we can reuse k here */
+ for (k = 0; k < p->conf.exts->used; k++) {
+ extension = p->conf.exts->exts[k];
+@@ -3407,15 +3319,15 @@
+ /* check if extension matches */
+ for (k = 0; k < p->conf.exts->used; k++) {
+ size_t ct_len; /* length of the config entry */
+-
++
+ extension = p->conf.exts->exts[k];
+-
++
+ if (extension->key->used == 0) continue;
+-
++
+ ct_len = extension->key->used - 1;
+-
++
+ if (s_len < ct_len) continue;
+-
++
+ /* check extension in the form "/fcgi_pattern" */
+ if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
+ break;
+@@ -3441,10 +3353,10 @@
+ continue;
+ }
+
+- /* we found one host that is alive */
++ /* we found one host that is alive */
+ break;
+ }
+-
++
+ if (!host) {
+ /* sorry, we don't have a server alive for this ext */
+ buffer_reset(con->physical.path);
+@@ -3459,72 +3371,72 @@
+ "on", extension->key,
+ "are down.");
+ }
+-
++
+ return HANDLER_FINISHED;
+ }
+
+ /* a note about no handler is not sent yey */
+ extension->note_is_sent = 0;
+
+- /*
+- * if check-local is disabled, use the uri.path handler
+- *
++ /*
++ * if check-local is disabled, use the uri.path handler
++ *
+ */
+-
++
+ /* init handler-context */
+ if (uri_path_handler) {
+ if (host->check_local == 0) {
+ handler_ctx *hctx;
+ char *pathinfo;
+-
++
+ hctx = handler_ctx_init();
+-
++
+ hctx->remote_conn = con;
+ hctx->plugin_data = p;
+ hctx->proc = NULL;
+ hctx->ext = extension;
+-
++
+
+ hctx->conf.exts = p->conf.exts;
+ hctx->conf.debug = p->conf.debug;
+-
++
+ con->plugin_ctx[p->id] = hctx;
+-
++
+ con->mode = p->id;
+-
++
+ if (con->conf.log_request_handling) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "handling it in mod_fastcgi");
+ }
+-
+- /* the prefix is the SCRIPT_NAME,
++
++ /* the prefix is the SCRIPT_NAME,
+ * everthing from start to the next slash
+ * this is important for check-local = "disable"
+- *
++ *
+ * if prefix = /admin.fcgi
+- *
++ *
+ * /admin.fcgi/foo/bar
+- *
++ *
+ * SCRIPT_NAME = /admin.fcgi
+ * PATH_INFO = /foo/bar
+- *
++ *
+ * if prefix = /fcgi-bin/
+- *
++ *
+ * /fcgi-bin/foo/bar
+- *
++ *
+ * SCRIPT_NAME = /fcgi-bin/foo
+ * PATH_INFO = /bar
+- *
++ *
+ */
+-
++
+ /* the rewrite is only done for /prefix/? matches */
+ if (extension->key->ptr[0] == '/' &&
+ con->uri.path->used > extension->key->used &&
+ NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
+- /* rewrite uri.path and pathinfo */
+-
++ /* rewrite uri.path and pathinfo */
++
+ buffer_copy_string(con->request.pathinfo, pathinfo);
+-
++
+ con->uri.path->used -= con->request.pathinfo->used - 1;
+ con->uri.path->ptr[con->uri.path->used - 1] = '\0';
+ }
+@@ -3532,19 +3444,19 @@
+ } else {
+ handler_ctx *hctx;
+ hctx = handler_ctx_init();
+-
++
+ hctx->remote_conn = con;
+ hctx->plugin_data = p;
+ hctx->proc = NULL;
+ hctx->ext = extension;
+-
++
+ hctx->conf.exts = p->conf.exts;
+ hctx->conf.debug = p->conf.debug;
+-
++
+ con->plugin_ctx[p->id] = hctx;
+-
++
+ con->mode = p->id;
+-
++
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
+ }
+@@ -3566,19 +3478,19 @@
+ JOBLIST_FUNC(mod_fastcgi_handle_joblist) {
+ plugin_data *p = p_d;
+ handler_ctx *hctx = con->plugin_ctx[p->id];
+-
++
+ if (hctx == NULL) return HANDLER_GO_ON;
+
+ if (hctx->fd != -1) {
+ switch (hctx->state) {
+ case FCGI_STATE_READ:
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
+-
++
+ break;
+ case FCGI_STATE_CONNECT_DELAYED:
+ case FCGI_STATE_WRITE:
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ break;
+ case FCGI_STATE_INIT:
+ /* at reconnect */
+@@ -3595,7 +3507,7 @@
+
+ static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
+ plugin_data *p = p_d;
+-
++
+ fcgi_connection_close(srv, con->plugin_ctx[p->id]);
+
+ return HANDLER_GO_ON;
+@@ -3604,16 +3516,39 @@
+ TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
+ plugin_data *p = p_d;
+ size_t i, j, n;
+-
+-
++
++
+ /* perhaps we should kill a connect attempt after 10-15 seconds
+- *
++ *
+ * currently we wait for the TCP timeout which is on Linux 180 seconds
+- *
+- *
+- *
++ *
+ */
+
++ for (i = 0; i < srv->conns->used; i++) {
++ connection *con = srv->conns->ptr[i];
++ handler_ctx *hctx = con->plugin_ctx[p->id];
++
++ /* if a connection is ours and is in handle-req for more than max-request-time
++ * kill the connection */
++
++ if (con->mode != p->id) continue;
++ if (con->state != CON_STATE_HANDLE_REQUEST) continue;
++ if (srv->cur_ts < con->request_start + 60) continue;
++
++ /* the request is waiting for a FCGI_STDOUT since 60 seconds */
++
++ /* kill the connection */
++
++ log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
++
++ fcgi_connection_close(srv, hctx);
++
++ con->mode = DIRECT;
++ con->http_status = 500;
++
++ joblist_append(srv, con);
++ }
++
+ /* check all childs if they are still up */
+
+ for (i = 0; i < srv->config_context->used; i++) {
+@@ -3628,45 +3563,45 @@
+ fcgi_extension *ex;
+
+ ex = exts->exts[j];
+-
++
+ for (n = 0; n < ex->used; n++) {
+-
++
+ fcgi_proc *proc;
+ unsigned long sum_load = 0;
+ fcgi_extension_host *host;
+-
++
+ host = ex->hosts[n];
+-
++
+ fcgi_restart_dead_procs(srv, p, host);
+-
++
+ for (proc = host->first; proc; proc = proc->next) {
+ sum_load += proc->load;
+ }
+-
++
+ if (host->num_procs &&
+ host->num_procs < host->max_procs &&
+ (sum_load / host->num_procs) > host->max_load_per_proc) {
+ /* overload, spawn new child */
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "overload detected, spawning a new child");
+ }
+-
++
+ for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
+-
++
+ if (proc) {
+ if (proc == host->unused_procs) host->unused_procs = proc->next;
+-
++
+ if (proc->next) proc->next->prev = NULL;
+-
++
+ host->max_id++;
+ } else {
+ proc = fastcgi_process_init();
+ proc->id = host->max_id++;
+ }
+-
++
+ host->num_procs++;
+-
++
+ if (buffer_is_empty(host->unixsocket)) {
+ proc->port = host->port + proc->id;
+ } else {
+@@ -3674,13 +3609,13 @@
+ buffer_append_string(proc->unixsocket, "-");
+ buffer_append_long(proc->unixsocket, proc->id);
+ }
+-
++
+ if (fcgi_spawn_connection(srv, p, host, proc)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ERROR: spawning fcgi failed.");
+ return HANDLER_ERROR;
+ }
+-
++
+ proc->prev = NULL;
+ proc->next = host->first;
+ if (host->first) {
+@@ -3688,56 +3623,56 @@
+ }
+ host->first = proc;
+ }
+-
++
+ for (proc = host->first; proc; proc = proc->next) {
+ if (proc->load != 0) break;
+ if (host->num_procs <= host->min_procs) break;
+ if (proc->pid == 0) continue;
+-
++
+ if (srv->cur_ts - proc->last_used > host->idle_timeout) {
+ /* a proc is idling for a long time now,
+ * terminated it */
+-
++
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "ssbsd",
+- "idle-timeout reached, terminating child:",
+- "socket:", proc->connection_name,
++ log_error_write(srv, __FILE__, __LINE__, "ssbsd",
++ "idle-timeout reached, terminating child:",
++ "socket:", proc->connection_name,
+ "pid", proc->pid);
+ }
+-
+-
++
++
+ if (proc->next) proc->next->prev = proc->prev;
+ if (proc->prev) proc->prev->next = proc->next;
+-
++
+ if (proc->prev == NULL) host->first = proc->next;
+-
++
+ proc->prev = NULL;
+ proc->next = host->unused_procs;
+-
++
+ if (host->unused_procs) host->unused_procs->prev = proc;
+ host->unused_procs = proc;
+-
++
+ kill(proc->pid, SIGTERM);
+-
++
+ proc->state = PROC_STATE_KILLED;
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssbsd",
+- "killed:",
+- "socket:", proc->connection_name,
++
++ log_error_write(srv, __FILE__, __LINE__, "ssbsd",
++ "killed:",
++ "socket:", proc->connection_name,
+ "pid", proc->pid);
+-
++
+ host->num_procs--;
+-
++
+ /* proc is now in unused, let the next second handle the next process */
+ break;
+- }
++ }
+ }
+-
++
+ for (proc = host->unused_procs; proc; proc = proc->next) {
+ int status;
+-
++
+ if (proc->pid == 0) continue;
+-
++#ifndef _WIN32
+ switch (waitpid(proc->pid, &status, WNOHANG)) {
+ case 0:
+ /* child still running after timeout, good */
+@@ -3745,10 +3680,10 @@
+ case -1:
+ if (errno != EINTR) {
+ /* no PID found ? should never happen */
+- log_error_write(srv, __FILE__, __LINE__, "sddss",
++ log_error_write(srv, __FILE__, __LINE__, "sddss",
+ "pid ", proc->pid, proc->state,
+ "not found:", strerror(errno));
+-
++
+ #if 0
+ if (errno == ECHILD) {
+ /* someone else has cleaned up for us */
+@@ -3762,25 +3697,26 @@
+ /* the child should not terminate at all */
+ if (WIFEXITED(status)) {
+ if (proc->state != PROC_STATE_KILLED) {
+- log_error_write(srv, __FILE__, __LINE__, "sdb",
+- "child exited:",
++ log_error_write(srv, __FILE__, __LINE__, "sdb",
++ "child exited:",
+ WEXITSTATUS(status), proc->connection_name);
+ }
+ } else if (WIFSIGNALED(status)) {
+ if (WTERMSIG(status) != SIGTERM) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child signaled:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child signaled:",
+ WTERMSIG(status));
+ }
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child died somehow:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child died somehow:",
+ status);
+ }
+ proc->pid = 0;
+ proc->state = PROC_STATE_UNSET;
+ host->max_id--;
+ }
++#endif
+ }
+ }
+ }
+@@ -3804,8 +3740,8 @@
+ p->handle_subrequest = mod_fastcgi_handle_subrequest;
+ p->handle_joblist = mod_fastcgi_handle_joblist;
+ p->handle_trigger = mod_fastcgi_handle_trigger;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_flv_streaming.c lighttpd-1.4.12/src/mod_flv_streaming.c
+--- lighttpd-1.4.11/src/mod_flv_streaming.c 2006-03-07 14:06:26.000000000 +0200
++++ lighttpd-1.4.12/src/mod_flv_streaming.c 2006-07-11 21:23:40.000000000 +0300
+@@ -23,35 +23,35 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *query_str;
+ array *get_params;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_flv_streaming_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->query_str = buffer_init();
+ p->get_params = array_init();
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_flv_streaming_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+
+@@ -59,19 +59,19 @@
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+-
++
+ array_free(s->extensions);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->query_str);
+ array_free(p->get_params);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -80,83 +80,80 @@
+ SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "flv-streaming.extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->extensions = array_init();
+-
++
+ cv[0].destination = s->extensions;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(extensions);
+-
++
++ PATCH_OPTION(extensions);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
+- PATCH(extensions);
++ PATCH_OPTION(extensions);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+-static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
++static int split_get_params(array *get_params, buffer *qrystr) {
+ size_t is_key = 1;
+ size_t i;
+ char *key = NULL, *val = NULL;
+-
++
+ key = qrystr->ptr;
+-
++
+ /* we need the \0 */
+ for (i = 0; i < qrystr->used; i++) {
+ switch(qrystr->ptr[i]) {
+ case '=':
+ if (is_key) {
+ val = qrystr->ptr + i + 1;
+-
++
+ qrystr->ptr[i] = '\0';
+-
++
+ is_key = 0;
+ }
+-
++
+ break;
+ case '&':
+ case '\0': /* fin symbol */
+@@ -167,7 +164,7 @@
+ /* terminate the value */
+ qrystr->ptr[i] = '\0';
+
+- if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
++ if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
+ ds = data_string_init();
+ }
+ buffer_copy_string_len(ds->key, key, strlen(key));
+@@ -175,14 +172,14 @@
+
+ array_insert_unique(get_params, (data_unset *)ds);
+ }
+-
++
+ key = qrystr->ptr + i + 1;
+ val = NULL;
+ is_key = 1;
+ break;
+ }
+ }
+-
++
+ return 0;
+ }
+
+@@ -190,34 +187,34 @@
+ plugin_data *p = p_d;
+ int s_len;
+ size_t k;
+-
++
+ UNUSED(srv);
+
+ if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
+-
++
+ mod_flv_streaming_patch_connection(srv, con, p);
+
+ s_len = con->physical.path->used - 1;
+-
++
+ for (k = 0; k < p->conf.extensions->used; k++) {
+ data_string *ds = (data_string *)p->conf.extensions->data[k];
+ int ct_len = ds->value->used - 1;
+-
++
+ if (ct_len > s_len) continue;
+ if (ds->value->used == 0) continue;
+-
++
+ if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
+ data_string *get_param;
+ stat_cache_entry *sce = NULL;
+ buffer *b;
+ int start;
+ char *err = NULL;
+- /* if there is a start=[0-9]+ in the header use it as start,
++ /* if there is a start=[0-9]+ in the header use it as start,
+ * otherwise send the full file */
+
+ array_reset(p->get_params);
+ buffer_copy_string_buffer(p->query_str, con->uri.query);
+- split_get_params(srv, con, p->get_params, p->query_str);
++ split_get_params(p->get_params, p->query_str);
+
+ if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
+ return HANDLER_GO_ON;
+@@ -256,7 +253,7 @@
+ return HANDLER_FINISHED;
+ }
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+@@ -266,13 +263,13 @@
+ int mod_flv_streaming_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("flv_streaming");
+-
++
+ p->init = mod_flv_streaming_init;
+ p->handle_physical = mod_flv_streaming_path_handler;
+ p->set_defaults = mod_flv_streaming_set_defaults;
+ p->cleanup = mod_flv_streaming_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_indexfile.c lighttpd-1.4.12/src/mod_indexfile.c
+--- lighttpd-1.4.11/src/mod_indexfile.c 2005-09-30 01:08:53.000000000 +0300
++++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-11 21:23:40.000000000 +0300
+@@ -20,51 +20,51 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *tmp_buf;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_indexfile_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->tmp_buf = buffer_init();
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_indexfile_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+-
++
+ array_free(s->indexfiles);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->tmp_buf);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -73,131 +73,128 @@
+ SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "index-file.names", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "server.indexfiles", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->indexfiles = array_init();
+-
++
+ cv[0].destination = s->indexfiles;
+ cv[1].destination = s->indexfiles; /* old name for [0] */
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(indexfiles);
+-
++
++ PATCH_OPTION(indexfiles);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
+- PATCH(indexfiles);
++ PATCH_OPTION(indexfiles);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
+- PATCH(indexfiles);
++ PATCH_OPTION(indexfiles);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_indexfile_subrequest) {
+ plugin_data *p = p_d;
+ size_t k;
+ stat_cache_entry *sce = NULL;
+-
++
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+ if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
+-
++
+ mod_indexfile_patch_connection(srv, con, p);
+-
++
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Indexfile");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
+ }
+-
++
+ /* indexfile */
+ for (k = 0; k < p->conf.indexfiles->used; k++) {
+ data_string *ds = (data_string *)p->conf.indexfiles->data[k];
+-
++
+ if (ds->value && ds->value->ptr[0] == '/') {
+- /* if the index-file starts with a prefix as use this file as
++ /* if the index-file starts with a prefix as use this file as
+ * index-generator */
+ buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
+ } else {
+ buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
+ }
+ buffer_append_string_buffer(p->tmp_buf, ds->value);
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
+ if (errno == EACCES) {
+ con->http_status = 403;
+ buffer_reset(con->physical.path);
+-
++
+ return HANDLER_FINISHED;
+ }
+-
++
+ if (errno != ENOENT &&
+ errno != ENOTDIR) {
+ /* we have no idea what happend. let's tell the user so. */
+-
++
+ con->http_status = 500;
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ssbsb",
+ "file not found ... or so: ", strerror(errno),
+ con->uri.path,
+ "->", con->physical.path);
+-
++
+ buffer_reset(con->physical.path);
+-
++
+ return HANDLER_FINISHED;
+ }
+ continue;
+ }
+-
++
+ /* rewrite uri.path to the real path (/ -> /index.php) */
+ buffer_append_string_buffer(con->uri.path, ds->value);
+ buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
+-
++
+ /* fce is already set up a few lines above */
+-
++
+ return HANDLER_GO_ON;
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+@@ -207,13 +204,13 @@
+ int mod_indexfile_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("indexfile");
+-
++
+ p->init = mod_indexfile_init;
+ p->handle_subrequest_start = mod_indexfile_subrequest;
+ p->set_defaults = mod_indexfile_set_defaults;
+ p->cleanup = mod_indexfile_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_mysql_vhost.c lighttpd-1.4.12/src/mod_mysql_vhost.c
+--- lighttpd-1.4.11/src/mod_mysql_vhost.c 2006-01-14 20:35:10.000000000 +0200
++++ lighttpd-1.4.12/src/mod_mysql_vhost.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,13 +1,18 @@
+-#include <unistd.h>
+ #include <stdio.h>
+ #include <errno.h>
+ #include <fcntl.h>
+-#include <strings.h>
++#include <string.h>
+
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+
++#ifdef HAVE_MYSQL_H
++# ifdef HAVE_LIBMYSQL
++# define HAVE_MYSQL
++# endif
++#endif
++
+ #ifdef HAVE_MYSQL
+ #include <mysql.h>
+ #endif
+@@ -16,61 +21,40 @@
+ #include "log.h"
+
+ #include "stat_cache.h"
+-#ifdef DEBUG_MOD_MYSQL_VHOST
+-#define DEBUG
+-#endif
++#include "sys-files.h"
+
+-/*
+- * Plugin for lighttpd to use MySQL
+- * for domain to directory lookups,
+- * i.e virtual hosts (vhosts).
+- *
+- * Optionally sets fcgi_offset and fcgi_arg
+- * in preparation for fcgi.c to handle
+- * per-user fcgi chroot jails.
+- *
+- * /ada@riksnet.se 2004-12-06
+- */
++#include "mod_sql_vhost_core.h"
+
+ #ifdef HAVE_MYSQL
++
++#define CORE_PLUGIN "mod_sql_vhost_core"
++
+ typedef struct {
+ MYSQL *mysql;
+-
+- buffer *mydb;
+- buffer *myuser;
+- buffer *mypass;
+- buffer *mysock;
+-
+- buffer *hostname;
+- unsigned short port;
+-
++
+ buffer *mysql_pre;
+ buffer *mysql_post;
++
++ mod_sql_vhost_core_plugin_config *core;
+ } plugin_config;
+
+ /* global plugin data */
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *tmp_buf;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+-/* per connection plugin data */
+-typedef struct {
+- buffer *server_name;
+- buffer *document_root;
+- buffer *fcgi_arg;
+- unsigned fcgi_offset;
+-} plugin_connection_data;
++SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost);
+
+ /* init the plugin data */
+ INIT_FUNC(mod_mysql_vhost_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+
+ p->tmp_buf = buffer_init();
+@@ -83,144 +67,77 @@
+ plugin_data *p = p_d;
+
+ UNUSED(srv);
+-
+-#ifdef DEBUG
+- log_error_write(srv, __FILE__, __LINE__, "ss",
+- "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
+-#endif
++
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+-
++
+ mysql_close(s->mysql);
+-
+- buffer_free(s->mydb);
+- buffer_free(s->myuser);
+- buffer_free(s->mypass);
+- buffer_free(s->mysock);
++
+ buffer_free(s->mysql_pre);
+ buffer_free(s->mysql_post);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+ buffer_free(p->tmp_buf);
+-
+- free(p);
+
+- return HANDLER_GO_ON;
+-}
+-
+-/* handle the plugin per connection data */
+-static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
+-{
+- plugin_data *p = p_d;
+- plugin_connection_data *c = con->plugin_ctx[p->id];
+-
+- UNUSED(srv);
+-
+-#ifdef DEBUG
+- log_error_write(srv, __FILE__, __LINE__, "ss",
+- "mod_mysql_connection_data", c ? "old" : "NEW");
+-#endif
+-
+- if (c) return c;
+- c = calloc(1, sizeof(*c));
+-
+- c->server_name = buffer_init();
+- c->document_root = buffer_init();
+- c->fcgi_arg = buffer_init();
+- c->fcgi_offset = 0;
+-
+- return con->plugin_ctx[p->id] = c;
+-}
+-
+-/* destroy the plugin per connection data */
+-CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
+- plugin_data *p = p_d;
+- plugin_connection_data *c = con->plugin_ctx[p->id];
+-
+- UNUSED(srv);
+-
+-#ifdef DEBUG
+- log_error_write(srv, __FILE__, __LINE__, "ss",
+- "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
+-#endif
+-
+- if (!c) return HANDLER_GO_ON;
+-
+- buffer_free(c->server_name);
+- buffer_free(c->document_root);
+- buffer_free(c->fcgi_arg);
+- c->fcgi_offset = 0;
+-
+- free(c);
++ free(p);
+
+- con->plugin_ctx[p->id] = NULL;
+ return HANDLER_GO_ON;
+ }
+
+ /* set configuration values */
+ SERVER_FUNC(mod_mysql_vhost_set_defaults) {
+ plugin_data *p = p_d;
++ mod_sql_vhost_core_plugin_data *core_config;
+
+- char *qmark;
+ size_t i = 0;
+
+- config_values_t cv[] = {
+- { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
+- { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
+- { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
+- { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
+- { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
+- { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
+- { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER },
+- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+- };
+-
++ /* our very own plugin storage, one entry for each conditional
++ *
++ * srv->config_context->used is the number of conditionals
++ * */
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
++ /* get the config of the core-plugin */
++ core_config = plugin_get_config(srv, CORE_PLUGIN);
++
++
++ /* walk through all conditionals and check for assignments */
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+ buffer *sel;
+-
+-
++ char *qmark;
++
++ /* get the config from the core plugin for this conditional-context */
+ s = calloc(1, sizeof(plugin_config));
+- s->mydb = buffer_init();
+- s->myuser = buffer_init();
+- s->mypass = buffer_init();
+- s->mysock = buffer_init();
+- s->hostname = buffer_init();
+- s->port = 0; /* default port for mysql */
+- sel = buffer_init();
+- s->mysql = NULL;
++
++ s->core = core_config->config_storage[i];
+
++ s->mysql = NULL;
++
+ s->mysql_pre = buffer_init();
+ s->mysql_post = buffer_init();
+-
+- cv[0].destination = s->mydb;
+- cv[1].destination = s->myuser;
+- cv[2].destination = s->mypass;
+- cv[3].destination = s->mysock;
+- cv[4].destination = sel;
+- cv[5].destination = s->hostname;
+- cv[6].destination = &(s->port);
+-
++
+ p->config_storage[i] = s;
+-
+- if (config_insert_values_global(srv,
+- ((data_config *)srv->config_context->data[i])->value,
+- cv)) return HANDLER_ERROR;
+-
+- s->mysql_pre = buffer_init();
+- s->mysql_post = buffer_init();
+-
++
++ /* check if we are the plugin for this backend */
++ if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
++
++ /* attach us to the core-plugin */
++ s->core->backend_data = p;
++ s->core->get_vhost = mod_mysql_vhost_get_vhost;
++
++ sel = buffer_init();
++ buffer_copy_string_buffer(sel, s->core->select_vhost);
++
+ if (sel->used && (qmark = index(sel->ptr, '?'))) {
+ *qmark = '\0';
+ buffer_copy_string(s->mysql_pre, sel->ptr);
+@@ -228,35 +145,35 @@
+ } else {
+ buffer_copy_string_buffer(s->mysql_pre, sel);
+ }
+-
++
+ /* required:
+ * - username
+- * - database
+- *
++ * - database
++ *
+ * optional:
+ * - password, default: empty
+ * - socket, default: mysql default
+ * - hostname, if set overrides socket
+ * - port, default: 3306
+ */
+-
++
+ /* all have to be set */
+- if (!(buffer_is_empty(s->myuser) ||
+- buffer_is_empty(s->mydb))) {
++ if (!(buffer_is_empty(s->core->user) ||
++ buffer_is_empty(s->core->db))) {
+
+ int fd;
+-
++
+ if (NULL == (s->mysql = mysql_init(NULL))) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
+-
++
+ return HANDLER_ERROR;
+ }
+-#define FOO(x) (s->x->used ? s->x->ptr : NULL)
+-
+- if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass),
+- FOO(mydb), s->port, FOO(mysock), 0)) {
++#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
++
++ if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
++ FOO(db), s->core->port, FOO(sock), 0)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
+-
++
+ return HANDLER_ERROR;
+ }
+ #undef FOO
+@@ -265,61 +182,47 @@
+ /* otherwise we cannot be sure that mysql is fd i-1 */
+ if (-1 == (fd = open("/dev/null", 0))) {
+ close(fd);
+- fcntl(fd-1, F_SETFD, FD_CLOEXEC);
++ fcntl(fd-1, F_SETFD, FD_CLOEXEC);
+ }
+ }
+ }
+-
+-
++
++
+
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
+- size_t i, j;
++ size_t i;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(mysql_pre);
+- PATCH(mysql_post);
+-#ifdef HAVE_MYSQL
+- PATCH(mysql);
+-#endif
+-
++
++ PATCH_OPTION(mysql_pre);
++ PATCH_OPTION(mysql_post);
++ PATCH_OPTION(mysql);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
+- /* merge config */
+- for (j = 0; j < dc->value->used; j++) {
+- data_unset *du = dc->value->data[j];
+-
+- if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
+- PATCH(mysql_pre);
+- PATCH(mysql_post);
+- }
+- }
+-
++
+ if (s->mysql) {
+- PATCH(mysql);
++ PATCH_OPTION(mysql);
++ PATCH_OPTION(mysql_pre);
++ PATCH_OPTION(mysql_post);
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+-
+-/* handle document root request */
+-CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
++/**
++ * get the vhost info from the database
++ */
++SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
+ plugin_data *p = p_d;
+- plugin_connection_data *c;
+- stat_cache_entry *sce;
+
+ unsigned cols;
+ MYSQL_ROW row;
+@@ -332,13 +235,6 @@
+
+ if (!p->conf.mysql) return HANDLER_GO_ON;
+
+- /* sets up connection data if not done yet */
+- c = mod_mysql_vhost_connection_data(srv, con, p_d);
+-
+- /* check if cached this connection */
+- if (c->server_name->used && /* con->uri.authority->used && */
+- buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
+-
+ /* build and run SQL query */
+ buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
+ if (p->conf.mysql_post->used) {
+@@ -347,77 +243,43 @@
+ }
+ if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
+- goto ERR500;
++
++ mysql_free_result(result);
++ return HANDLER_GO_ON;
+ }
+ result = mysql_store_result(p->conf.mysql);
+ cols = mysql_num_fields(result);
+ row = mysql_fetch_row(result);
++
+ if (!row || cols < 1) {
+ /* no such virtual host */
+ mysql_free_result(result);
+ return HANDLER_GO_ON;
+ }
+
+- /* sanity check that really is a directory */
+- buffer_copy_string(p->tmp_buf, row[0]);
+- BUFFER_APPEND_SLASH(p->tmp_buf);
+-
+- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
+- log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
+- goto ERR500;
+- }
+- if (!S_ISDIR(sce->st.st_mode)) {
+- log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
+- goto ERR500;
+- }
++ buffer_copy_string(docroot, row[0]);
+
+- /* cache the data */
+- buffer_copy_string_buffer(c->server_name, con->uri.authority);
+- buffer_copy_string_buffer(c->document_root, p->tmp_buf);
+-
+- /* fcgi_offset and fcgi_arg are optional */
+- if (cols > 1 && row[1]) {
+- c->fcgi_offset = atoi(row[1]);
+-
+- if (cols > 2 && row[2]) {
+- buffer_copy_string(c->fcgi_arg, row[2]);
+- } else {
+- c->fcgi_arg->used = 0;
+- }
+- } else {
+- c->fcgi_offset = c->fcgi_arg->used = 0;
+- }
+ mysql_free_result(result);
+
+- /* fix virtual server and docroot */
+-GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
+- buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
+-
+-#ifdef DEBUG
+- log_error_write(srv, __FILE__, __LINE__, "sbbdb",
+- result ? "NOT CACHED" : "cached",
+- con->server_name, con->physical.doc_root,
+- c->fcgi_offset, c->fcgi_arg);
+-#endif
+- return HANDLER_GO_ON;
+-
+-ERR500: if (result) mysql_free_result(result);
+- con->http_status = 500; /* Internal Error */
+- return HANDLER_FINISHED;
++ return HANDLER_GO_ON;
+ }
+
+ /* this function is called at dlopen() time and inits the callbacks */
+ int mod_mysql_vhost_plugin_init(plugin *p) {
++ data_string *ds;
++
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("mysql_vhost");
+
+ p->init = mod_mysql_vhost_init;
+ p->cleanup = mod_mysql_vhost_cleanup;
+- p->handle_request_done = mod_mysql_vhost_handle_connection_close;
+
+ p->set_defaults = mod_mysql_vhost_set_defaults;
+- p->handle_docroot = mod_mysql_vhost_handle_docroot;
+
++ ds = data_string_init();
++ buffer_copy_string(ds->value, CORE_PLUGIN);
++ array_insert_unique(p->required_plugins, (data_unset *)ds);
++
+ return 0;
+ }
+ #else
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_proxy.c lighttpd-1.4.12/src/mod_proxy.c
+--- lighttpd-1.4.11/src/mod_proxy.c 2006-01-31 13:01:22.000000000 +0200
++++ lighttpd-1.4.12/src/mod_proxy.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,6 +1,5 @@
+ #include <sys/types.h>
+
+-#include <unistd.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <string.h>
+@@ -23,6 +22,9 @@
+
+ #include "inet_ntop_cache.h"
+ #include "crc32.h"
++#include "network.h"
++
++#include "http_resp.h"
+
+ #include <stdio.h>
+
+@@ -31,6 +33,8 @@
+ #endif
+
+ #include "sys-socket.h"
++#include "sys-files.h"
++#include "sys-strings.h"
+
+ #define data_proxy data_fastcgi
+ #define data_proxy_init data_fastcgi_init
+@@ -38,16 +42,16 @@
+ #define PROXY_RETRY_TIMEOUT 60
+
+ /**
+- *
+- * the proxy module is based on the fastcgi module
+- *
++ *
++ * the proxy module is based on the fastcgi module
++ *
+ * 28.06.2004 Jan Kneschke The first release
+ * 01.07.2004 Evgeny Rodichev Several bugfixes and cleanups
+ * - co-ordinate up- and downstream flows correctly (proxy_demux_response
+ * and proxy_handle_fdevent)
+ * - correctly transfer upstream http_response_status;
+ * - some unused structures removed.
+- *
++ *
+ * TODO: - delay upstream read if write_queue is too large
+ * (to prevent memory eating, like in apache). Shoud be
+ * configurable).
+@@ -66,26 +70,31 @@
+ int debug;
+
+ proxy_balance_t balance;
++
++ array *last_used_backends; /* "extension" : last_used_backend */
+ } plugin_config;
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *parse_response;
+ buffer *balance_buf;
+-
++
++ array *ignore_headers;
++
+ plugin_config **config_storage;
+-
++
+ plugin_config conf;
+ } plugin_data;
+
+-typedef enum {
+- PROXY_STATE_INIT,
+- PROXY_STATE_CONNECT,
+- PROXY_STATE_PREPARE_WRITE,
+- PROXY_STATE_WRITE,
+- PROXY_STATE_READ,
+- PROXY_STATE_ERROR
++typedef enum {
++ PROXY_STATE_INIT,
++ PROXY_STATE_CONNECT,
++ PROXY_STATE_PREPARE_WRITE,
++ PROXY_STATE_WRITE,
++ PROXY_STATE_RESPONSE_HEADER,
++ PROXY_STATE_RESPONSE_CONTENT,
++ PROXY_STATE_ERROR
+ } proxy_connection_state_t;
+
+ enum { PROXY_STDOUT, PROXY_END_REQUEST };
+@@ -93,19 +102,20 @@
+ typedef struct {
+ proxy_connection_state_t state;
+ time_t state_timestamp;
+-
++
+ data_proxy *host;
+-
++
+ buffer *response;
+ buffer *response_header;
+
+ chunkqueue *wb;
+-
++ chunkqueue *rb;
++
+ int fd; /* fd to the proxy process */
+ int fde_ndx; /* index into the fd-event buffer */
+
+ size_t path_info_offset; /* start of path_info in uri.path */
+-
++
+ connection *remote_conn; /* dump pointer */
+ plugin_data *plugin_data; /* dump pointer */
+ } handler_ctx;
+@@ -116,21 +126,22 @@
+
+ static handler_ctx * handler_ctx_init() {
+ handler_ctx * hctx;
+-
++
+
+ hctx = calloc(1, sizeof(*hctx));
+-
++
+ hctx->state = PROXY_STATE_INIT;
+ hctx->host = NULL;
+-
++
+ hctx->response = buffer_init();
+ hctx->response_header = buffer_init();
+
+ hctx->wb = chunkqueue_init();
++ hctx->rb = chunkqueue_init();
+
+ hctx->fd = -1;
+ hctx->fde_ndx = -1;
+-
++
+ return hctx;
+ }
+
+@@ -138,47 +149,70 @@
+ buffer_free(hctx->response);
+ buffer_free(hctx->response_header);
+ chunkqueue_free(hctx->wb);
+-
++ chunkqueue_free(hctx->rb);
++
+ free(hctx);
+ }
+
+ INIT_FUNC(mod_proxy_init) {
+ plugin_data *p;
+-
++ size_t i;
++
++ char *hop2hop_headers[] = {
++ "Connection",
++ "Keep-Alive",
++ "Host",
++ NULL
++ };
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->parse_response = buffer_init();
+ p->balance_buf = buffer_init();
+-
++ p->ignore_headers = array_init();
++
++ for (i = 0; hop2hop_headers[i]; i++) {
++ data_string *ds;
++
++ if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
++ ds = data_string_init();
++ }
++
++ buffer_copy_string(ds->value, hop2hop_headers[i]);
++ array_insert_unique(p->ignore_headers, (data_unset *)ds);
++ }
++
+ return p;
+ }
+
+
+ FREE_FUNC(mod_proxy_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ buffer_free(p->parse_response);
+ buffer_free(p->balance_buf);
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ if (s) {
+-
+ array_free(s->extensions);
+-
++ array_free(s->last_used_backends);
++
+ free(s);
+ }
+ }
+ free(p->config_storage);
+ }
+-
++
++ free(p->ignore_headers);
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -186,37 +220,38 @@
+ plugin_data *p = p_d;
+ data_unset *du;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "proxy.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "proxy.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "proxy.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+ array *ca;
+-
++
+ s = malloc(sizeof(plugin_config));
+- s->extensions = array_init();
++ s->extensions = array_init();
++ s->last_used_backends = array_init();
+ s->debug = 0;
+-
++
+ cv[0].destination = s->extensions;
+ cv[1].destination = &(s->debug);
+ cv[2].destination = p->balance_buf;
+
+ buffer_reset(p->balance_buf);
+-
++
+ p->config_storage[i] = s;
+ ca = ((data_config *)srv->config_context->data[i])->value;
+-
++
+ if (0 != config_insert_values_global(srv, ca, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (buffer_is_empty(p->balance_buf)) {
+ s->balance = PROXY_BALANCE_FAIR;
+ } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
+@@ -226,7 +261,7 @@
+ } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
+ s->balance = PROXY_BALANCE_HASH;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
+ return HANDLER_ERROR;
+ }
+@@ -234,91 +269,91 @@
+ if (NULL != (du = array_get_element(ca, "proxy.server"))) {
+ size_t j;
+ data_array *da = (data_array *)du;
+-
++
+ if (du->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "sss",
++ log_error_write(srv, __FILE__, __LINE__, "sss",
+ "unexpected type for key: ", "proxy.server", "array of strings");
+-
++
+ return HANDLER_ERROR;
+ }
+-
+- /*
++
++ /*
+ * proxy.server = ( "<ext>" => ...,
+ * "<ext>" => ... )
+ */
+-
++
+ for (j = 0; j < da->value->used; j++) {
+ data_array *da_ext = (data_array *)da->value->data[j];
+ size_t n;
+-
++
+ if (da_ext->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "sssbs",
+- "unexpected type for key: ", "proxy.server",
++ log_error_write(srv, __FILE__, __LINE__, "sssbs",
++ "unexpected type for key: ", "proxy.server",
+ "[", da->value->data[j]->key, "](string)");
+-
++
+ return HANDLER_ERROR;
+ }
+-
+- /*
+- * proxy.server = ( "<ext>" =>
+- * ( "<host>" => ( ... ),
++
++ /*
++ * proxy.server = ( "<ext>" =>
++ * ( "<host>" => ( ... ),
+ * "<host>" => ( ... )
+- * ),
++ * ),
+ * "<ext>" => ... )
+ */
+-
++
+ for (n = 0; n < da_ext->value->used; n++) {
+ data_array *da_host = (data_array *)da_ext->value->data[n];
+-
++
+ data_proxy *df;
+ data_array *dfa;
+-
+- config_values_t pcv[] = {
++
++ config_values_t pcv[] = {
+ { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (da_host->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "ssSBS",
+- "unexpected type for key:",
+- "proxy.server",
++ log_error_write(srv, __FILE__, __LINE__, "ssSBS",
++ "unexpected type for key:",
++ "proxy.server",
+ "[", da_ext->value->data[n]->key, "](string)");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ df = data_proxy_init();
+-
++
+ df->port = 80;
+-
++
+ buffer_copy_string_buffer(df->key, da_host->key);
+-
++
+ pcv[0].destination = df->host;
+ pcv[1].destination = &(df->port);
+-
++
+ if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (buffer_is_empty(df->host)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbbbs",
+- "missing key (string):",
++ log_error_write(srv, __FILE__, __LINE__, "sbbbs",
++ "missing key (string):",
+ da->key,
+ da_ext->key,
+ da_host->key,
+ "host");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ /* if extension already exists, take it */
+-
++
+ if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
+ dfa = data_array_init();
+-
++
+ buffer_copy_string_buffer(dfa->key, da_ext->key);
+-
++
+ array_insert_unique(dfa->value, (data_unset *)df);
+ array_insert_unique(s->extensions, (data_unset *)dfa);
+ } else {
+@@ -328,19 +363,19 @@
+ }
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ void proxy_connection_close(server *srv, handler_ctx *hctx) {
+ plugin_data *p;
+ connection *con;
+-
++
+ if (NULL == hctx) return;
+-
++
+ p = hctx->plugin_data;
+ con = hctx->remote_conn;
+-
++
+ if (hctx->fd != -1) {
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+ fdevent_unregister(srv->ev, hctx->fd);
+@@ -348,47 +383,56 @@
+ close(hctx->fd);
+ srv->cur_fds--;
+ }
+-
++
+ handler_ctx_free(hctx);
+- con->plugin_ctx[p->id] = NULL;
++ con->plugin_ctx[p->id] = NULL;
+ }
+
+ static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
+ struct sockaddr *proxy_addr;
+ struct sockaddr_in proxy_addr_in;
+ socklen_t servlen;
+-
++
+ plugin_data *p = hctx->plugin_data;
+ data_proxy *host= hctx->host;
+ int proxy_fd = hctx->fd;
+-
++
+ memset(&proxy_addr, 0, sizeof(proxy_addr));
+-
++
+ proxy_addr_in.sin_family = AF_INET;
+ proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr);
+ proxy_addr_in.sin_port = htons(host->port);
+ servlen = sizeof(proxy_addr_in);
+-
++
+ proxy_addr = (struct sockaddr *) &proxy_addr_in;
+-
++
+ if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
+- if (errno == EINPROGRESS || errno == EALREADY) {
++#ifdef _WIN32
++ errno = WSAGetLastError();
++#endif
++ switch(errno) {
++#ifdef _WIN32
++ case WSAEWOULDBLOCK:
++#endif
++ case EINPROGRESS:
++ case EALREADY:
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connect delayed:", proxy_fd);
+ }
+-
++
+ return 1;
+- } else {
+-
+- log_error_write(srv, __FILE__, __LINE__, "sdsd",
++ default:
++
++ log_error_write(srv, __FILE__, __LINE__, "sdsd",
+ "connect failed:", proxy_fd, strerror(errno), errno);
+-
++
+ return -1;
+ }
+ }
++ fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connect succeeded: ", proxy_fd);
+ }
+
+@@ -422,25 +466,26 @@
+
+ static int proxy_create_env(server *srv, handler_ctx *hctx) {
+ size_t i;
+-
++
+ connection *con = hctx->remote_conn;
++ plugin_data *p = hctx->plugin_data;
+ buffer *b;
+-
++
+ /* build header */
+
+ b = chunkqueue_get_append_buffer(hctx->wb);
+-
++
+ /* request line */
+ buffer_copy_string(b, get_http_method_name(con->request.http_method));
+ BUFFER_APPEND_STRING_CONST(b, " ");
+-
++
+ buffer_append_string_buffer(b, con->request.uri);
+ BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
+
+ proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
+- /* http_host is NOT is just a pointer to a buffer
++ /* http_host is NOT is just a pointer to a buffer
+ * which is NULL if it is not set */
+- if (con->request.http_host &&
++ if (con->request.http_host &&
+ !buffer_is_empty(con->request.http_host)) {
+ proxy_set_header(con, "X-Host", con->request.http_host->ptr);
+ }
+@@ -449,24 +494,26 @@
+ /* request header */
+ for (i = 0; i < con->request.headers->used; i++) {
+ data_string *ds;
+-
++
+ ds = (data_string *)con->request.headers->data[i];
+-
++
+ if (ds->value->used && ds->key->used) {
+- if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
+-
++
++ /* don't copy hop-to-hop headers */
++ if (array_get_element(p->ignore_headers, ds->key->ptr)) continue;
++
+ buffer_append_string_buffer(b, ds->key);
+ BUFFER_APPEND_STRING_CONST(b, ": ");
+ buffer_append_string_buffer(b, ds->value);
+ BUFFER_APPEND_STRING_CONST(b, "\r\n");
+ }
+ }
+-
++
+ BUFFER_APPEND_STRING_CONST(b, "\r\n");
+-
++
+ hctx->wb->bytes_in += b->used - 1;
+ /* body */
+-
++
+ if (con->request.content_length) {
+ chunkqueue *req_cq = con->request_content_queue;
+ chunk *req_c;
+@@ -479,7 +526,7 @@
+
+ /* we announce toWrite octects
+ * now take all the request_content chunk that we need to fill this request
+- * */
++ * */
+
+ switch (req_c->type) {
+ case FILE_CHUNK:
+@@ -507,223 +554,125 @@
+
+ req_c->offset += weHave;
+ req_cq->bytes_out += weHave;
+-
++
+ hctx->wb->bytes_in += weHave;
+
+ break;
+ default:
+ break;
+ }
+-
++
+ offset += weHave;
+ }
+
+ }
+-
++
+ return 0;
+ }
+
+ static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) {
+ hctx->state = state;
+ hctx->state_timestamp = srv->cur_ts;
+-
++
+ return 0;
+ }
+
+
+-static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
+- char *s, *ns;
+- int http_response_status = -1;
+-
+- UNUSED(srv);
++static void chunkqueue_print(chunkqueue *cq) {
++ chunk *c;
+
+- /* \r\n -> \0\0 */
+-
+- buffer_copy_string_buffer(p->parse_response, in);
+-
+- for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
+- char *key, *value;
+- int key_len;
+- data_string *ds;
+- int copy_header;
+-
+- ns[0] = '\0';
+- ns[1] = '\0';
+-
+- if (-1 == http_response_status) {
+- /* The first line of a Response message is the Status-Line */
+-
+- for (key=s; *key && *key != ' '; key++);
+-
+- if (*key) {
+- http_response_status = (int) strtol(key, NULL, 10);
+- if (http_response_status <= 0) http_response_status = 502;
+- } else {
+- http_response_status = 502;
+- }
+-
+- con->http_status = http_response_status;
+- con->parsed_response |= HTTP_STATUS;
+- continue;
+- }
+-
+- if (NULL == (value = strchr(s, ':'))) {
+- /* now we expect: "<key>: <value>\n" */
+-
+- continue;
+- }
+-
+- key = s;
+- key_len = value - key;
+-
+- value++;
+- /* strip WS */
+- while (*value == ' ' || *value == '\t') value++;
+-
+- copy_header = 1;
+-
+- switch(key_len) {
+- case 4:
+- if (0 == strncasecmp(key, "Date", key_len)) {
+- con->parsed_response |= HTTP_DATE;
+- }
+- break;
+- case 8:
+- if (0 == strncasecmp(key, "Location", key_len)) {
+- con->parsed_response |= HTTP_LOCATION;
+- }
+- break;
+- case 10:
+- if (0 == strncasecmp(key, "Connection", key_len)) {
+- copy_header = 0;
+- }
+- break;
+- case 14:
+- if (0 == strncasecmp(key, "Content-Length", key_len)) {
+- con->response.content_length = strtol(value, NULL, 10);
+- con->parsed_response |= HTTP_CONTENT_LENGTH;
+- }
+- break;
+- default:
+- break;
+- }
+-
+- if (copy_header) {
+- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
+- ds = data_response_init();
+- }
+- buffer_copy_string_len(ds->key, key, key_len);
+- buffer_copy_string(ds->value, value);
+-
+- array_insert_unique(con->response.headers, (data_unset *)ds);
+- }
+- }
+-
+- return 0;
++ for (c = cq->first; c; c = c->next) {
++ fprintf(stderr, "%s", c->mem->ptr + c->offset);
++ }
++ fprintf(stderr, "\r\n");
+ }
+
+-
+ static int proxy_demux_response(server *srv, handler_ctx *hctx) {
+- int fin = 0;
+- int b;
+- ssize_t r;
+-
+ plugin_data *p = hctx->plugin_data;
+ connection *con = hctx->remote_conn;
+ int proxy_fd = hctx->fd;
+-
+- /* check how much we have to read */
+- if (ioctl(hctx->fd, FIONREAD, &b)) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "ioctl failed: ",
+- proxy_fd);
+- return -1;
+- }
+-
++ chunkqueue *next_queue = NULL;
++ chunk *c = NULL;
+
+- if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "proxy - have to read:", b);
+- }
+-
+- if (b > 0) {
+- if (hctx->response->used == 0) {
+- /* avoid too small buffer */
+- buffer_prepare_append(hctx->response, b + 1);
+- hctx->response->used = 1;
+- } else {
+- buffer_prepare_append(hctx->response, hctx->response->used + b);
+- }
+-
+- if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "unexpected end-of-file (perhaps the proxy process died):",
+- proxy_fd, strerror(errno));
+- return -1;
+- }
+-
+- /* this should be catched by the b > 0 above */
+- assert(r);
+-
+- hctx->response->used += r;
+- hctx->response->ptr[hctx->response->used - 1] = '\0';
+-
+-#if 0
+- log_error_write(srv, __FILE__, __LINE__, "sdsbs",
+- "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
+-#endif
+-
+- if (0 == con->got_response) {
+- con->got_response = 1;
+- buffer_prepare_copy(hctx->response_header, 128);
+- }
+-
+- if (0 == con->file_started) {
+- char *c;
+-
+- /* search for the \r\n\r\n in the string */
+- if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
+- size_t hlen = c - hctx->response->ptr + 4;
+- size_t blen = hctx->response->used - hlen - 1;
+- /* found */
+-
+- buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
+-#if 0
+- log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
+-#endif
+- /* parse the response header */
+- proxy_response_parse(srv, con, p, hctx->response_header);
+-
+- /* enable chunked-transfer-encoding */
+- if (con->request.http_version == HTTP_VERSION_1_1 &&
+- !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
+- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
+- }
+-
+- con->file_started = 1;
+- if (blen) {
+- http_chunk_append_mem(srv, con, c + 4, blen + 1);
+- joblist_append(srv, con);
+- }
+- hctx->response->used = 0;
+- }
+- } else {
+- http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
+- joblist_append(srv, con);
+- hctx->response->used = 0;
+- }
+-
+- } else {
+- /* reading from upstream done */
++ switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
++ case NETWORK_STATUS_SUCCESS:
++ /* we got content */
++ break;
++ case NETWORK_STATUS_CONNECTION_CLOSE:
++ /* we are done, get out of here */
+ con->file_finished = 1;
+-
++
++ /* close the chunk-queue with a empty chunk */
+ http_chunk_append_mem(srv, con, NULL, 0);
+ joblist_append(srv, con);
+-
+- fin = 1;
++
++ return 1;
++ default:
++ /* oops */
++ return -1;
++ }
++
++ /* looks like we got some content
++ *
++ * split off the header from the incoming stream
++ */
++
++ if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
++ http_resp *resp = http_response_init();
++
++ /* the response header is not fully received yet,
++ *
++ * extract the http-response header from the rb-cq
++ */
++ fprintf(stderr, "%s.%d: network-read\r\n", __FILE__, __LINE__);
++ chunkqueue_print(hctx->rb);
++
++ switch (http_response_parse_cq(hctx->rb, resp)) {
++ case PARSE_ERROR:
++ /* parsing failed */
++
++ con->http_status = 502; /* Bad Gateway */
++ return 1;
++ case PARSE_NEED_MORE:
++ return 0;
++ case PARSE_SUCCESS:
++ con->http_status = resp->status;
++
++ fprintf(stderr, "%s.%d: parsing done\r\n", __FILE__, __LINE__);
++ chunkqueue_print(hctx->rb);
++
++ con->file_started = 1;
++
++ hctx->state = PROXY_STATE_RESPONSE_CONTENT;
++ break;
++ }
++ }
++
++ /* FIXME: pass the response-header to the other plugins to
++ * setup the filter-queue
++ *
++ * - use next-queue instead of con->write_queue
++ */
++
++ next_queue = con->write_queue;
++
++ assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
++
++ /* FIXME: if we have a content-length or chunked-encoding
++ * handle it.
++ *
++ * for now we wait for EOF on the socket */
++
++ /* copy the content to the next cq */
++ for (c = hctx->rb->first; c; c = c->next) {
++ http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
++
++ c->offset = c->mem->used - 1;
+ }
+-
+- return fin;
++
++ chunkqueue_remove_finished_chunks(hctx->rb);
++
++ return 0;
+ }
+
+
+@@ -731,12 +680,12 @@
+ data_proxy *host= hctx->host;
+ plugin_data *p = hctx->plugin_data;
+ connection *con = hctx->remote_conn;
+-
++
+ int ret;
+-
+- if (!host ||
++
++ if (!host ||
+ (!host->host->used || !host->port)) return -1;
+-
++
+ switch(hctx->state) {
+ case PROXY_STATE_INIT:
+ if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
+@@ -744,19 +693,19 @@
+ return HANDLER_ERROR;
+ }
+ hctx->fde_ndx = -1;
+-
++
+ srv->cur_fds++;
+-
++
+ fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
+-
++
+ if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ /* fall through */
+-
++
+ case PROXY_STATE_CONNECT:
+ /* try to finish the connect() */
+ if (hctx->state == PROXY_STATE_INIT) {
+@@ -764,16 +713,16 @@
+ switch (proxy_establish_connection(srv, hctx)) {
+ case 1:
+ proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
+-
++
+ /* connection is in progress, wait for an event and call getsockopt() below */
+-
++
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+ case -1:
+ /* if ECONNREFUSED choose another connection -> FIXME */
+ hctx->fde_ndx = -1;
+-
++
+ return HANDLER_ERROR;
+ default:
+ /* everything is ok, go on */
+@@ -782,152 +731,152 @@
+ } else {
+ int socket_error;
+ socklen_t socket_error_len = sizeof(socket_error);
+-
+- /* we don't need it anymore */
++
++ /* we don't need it anymore */
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+
+ /* try to finish the connect() */
+ if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "getsockopt failed:", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+ if (socket_error != 0) {
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+- "establishing connection failed:", strerror(socket_error),
++ "establishing connection failed:", strerror(socket_error),
+ "port:", hctx->host->port);
+-
++
+ return HANDLER_ERROR;
+ }
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
++ log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
+ }
++ fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, hctx->fd);
+ }
+-
++
+ proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
+ /* fall through */
+ case PROXY_STATE_PREPARE_WRITE:
+ proxy_create_env(srv, hctx);
+-
++
+ proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
+-
++
+ /* fall through */
+ case PROXY_STATE_WRITE:;
+- ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
++ ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
+
+ chunkqueue_remove_finished_chunks(hctx->wb);
+
+- if (-1 == ret) {
+- if (errno != EAGAIN &&
+- errno != EINTR) {
+- log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
+-
+- return HANDLER_ERROR;
+- } else {
+- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
++ switch(ret) {
++ case NETWORK_STATUS_FATAL_ERROR:
++ log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
+
+- return HANDLER_WAIT_FOR_EVENT;
+- }
++ return HANDLER_ERROR;
++ case NETWORK_STATUS_WAIT_FOR_EVENT:
++
++ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
++
++ return HANDLER_WAIT_FOR_EVENT;
+ }
+
+ if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
+- proxy_set_state(srv, hctx, PROXY_STATE_READ);
++ proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
+
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
+ } else {
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+ }
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+- case PROXY_STATE_READ:
++ case PROXY_STATE_RESPONSE_HEADER:
+ /* waiting for a response */
++
+ return HANDLER_WAIT_FOR_EVENT;
+ default:
+ log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
+ return HANDLER_ERROR;
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(extensions);
+- PATCH(debug);
+- PATCH(balance);
+-
++
++ PATCH_OPTION(extensions);
++ PATCH_OPTION(debug);
++ PATCH_OPTION(balance);
++ PATCH_OPTION(last_used_backends);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
+- PATCH(extensions);
++ PATCH_OPTION(extensions);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
+- PATCH(debug);
++ PATCH_OPTION(debug);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
+- PATCH(balance);
++ PATCH_OPTION(balance);
++ PATCH_OPTION(last_used_backends);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
+ plugin_data *p = p_d;
+-
++
+ handler_ctx *hctx = con->plugin_ctx[p->id];
+ data_proxy *host;
+-
++
+ if (NULL == hctx) return HANDLER_GO_ON;
+
+ mod_proxy_patch_connection(srv, con, p);
+-
++
+ host = hctx->host;
+-
++
+ /* not my job */
+ if (con->mode != p->id) return HANDLER_GO_ON;
+-
++
+ /* ok, create the request */
+ switch(proxy_write_request(srv, hctx)) {
+ case HANDLER_ERROR:
+- log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
++ log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
+ host->host,
+ host->port,
+ hctx->fd);
+-
++
+ /* disable this server */
+ host->is_disabled = 1;
+ host->disable_ts = srv->cur_ts;
+-
++
+ proxy_connection_close(srv, hctx);
+-
+- /* reset the enviroment and restart the sub-request */
++
++ /* reset the enviroment and restart the sub-request */
+ buffer_reset(con->physical.path);
+ con->mode = DIRECT;
+
+ joblist_append(srv, con);
+
+- /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
+- * and hope that the childs will be restarted
+- *
++ /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
++ * and hope that the childs will be restarted
++ *
+ */
+
+ return HANDLER_WAIT_FOR_FD;
+@@ -938,7 +887,7 @@
+ default:
+ break;
+ }
+-
++
+ if (con->file_started == 1) {
+ return HANDLER_FINISHED;
+ } else {
+@@ -951,13 +900,14 @@
+ handler_ctx *hctx = ctx;
+ connection *con = hctx->remote_conn;
+ plugin_data *p = hctx->plugin_data;
+-
+-
++
++
+ if ((revents & FDEVENT_IN) &&
+- hctx->state == PROXY_STATE_READ) {
++ (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
++ hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
+
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "proxy: fdevent-in", hctx->state);
+ }
+
+@@ -966,10 +916,10 @@
+ break;
+ case 1:
+ hctx->host->usage--;
+-
++
+ /* we are done */
+ proxy_connection_close(srv, hctx);
+-
++
+ joblist_append(srv, con);
+ return HANDLER_FINISHED;
+ case -1:
+@@ -982,53 +932,53 @@
+ /* response might have been already started, kill the connection */
+ connection_set_state(srv, con, CON_STATE_ERROR);
+ }
+-
++
+ joblist_append(srv, con);
+ return HANDLER_FINISHED;
+ }
+ }
+-
++
+ if (revents & FDEVENT_OUT) {
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "proxy: fdevent-out", hctx->state);
+ }
+
+ if (hctx->state == PROXY_STATE_CONNECT ||
+ hctx->state == PROXY_STATE_WRITE) {
+ /* we are allowed to send something out
+- *
++ *
+ * 1. in a unfinished connect() call
+ * 2. in a unfinished write() call (long POST request)
+ */
+ return mod_proxy_handle_subrequest(srv, con, p);
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "proxy: out", hctx->state);
+ }
+ }
+-
++
+ /* perhaps this issue is already handled */
+ if (revents & FDEVENT_HUP) {
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "proxy: fdevent-hup", hctx->state);
+ }
+-
++
+ if (hctx->state == PROXY_STATE_CONNECT) {
+ /* connect() -> EINPROGRESS -> HUP */
+-
++
+ /**
+- * what is proxy is doing if it can't reach the next hop ?
+- *
++ * what is proxy is doing if it can't reach the next hop ?
++ *
+ */
+-
++
+ proxy_connection_close(srv, hctx);
+ joblist_append(srv, con);
+-
++
+ con->http_status = 503;
+ con->mode = DIRECT;
+-
++
+ return HANDLER_FINISHED;
+ }
+
+@@ -1038,13 +988,13 @@
+ joblist_append(srv, con);
+ } else if (revents & FDEVENT_ERR) {
+ /* kill all connections to the proxy process */
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
+
+ joblist_append(srv, con);
+ proxy_connection_close(srv, hctx);
+ }
+-
++
+ return HANDLER_FINISHED;
+ }
+
+@@ -1058,44 +1008,49 @@
+ buffer *fn;
+ data_array *extension = NULL;
+ size_t path_info_offset;
+-
++ data_integer *last_used_backend;
++ data_proxy *host = NULL;
++ handler_ctx *hctx = NULL;
++
++ array *backends = NULL;
++
+ /* Possibly, we processed already this request */
+ if (con->file_started == 1) return HANDLER_GO_ON;
+-
++
+ mod_proxy_patch_connection(srv, con, p);
+-
++
+ fn = con->uri.path;
+
+ if (fn->used == 0) {
+ return HANDLER_ERROR;
+ }
+-
++
+ s_len = fn->used - 1;
+-
+-
++
++
+ path_info_offset = 0;
+
+- if (p->conf.debug) {
++ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "proxy - start");
+ }
+
+ /* check if extension matches */
+ for (k = 0; k < p->conf.extensions->used; k++) {
+ size_t ct_len;
+-
++
+ extension = (data_array *)p->conf.extensions->data[k];
+-
++
+ if (extension->key->used == 0) continue;
+-
++
+ ct_len = extension->key->used - 1;
+-
++
+ if (s_len < ct_len) continue;
+-
++
+ /* check extension in the form "/proxy_pattern" */
+ if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
+ if (s_len > ct_len + 1) {
+ char *pi_offset;
+-
++
+ if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
+ path_info_offset = pi_offset - fn->ptr;
+ }
+@@ -1106,12 +1061,14 @@
+ break;
+ }
+ }
+-
++
+ if (k == p->conf.extensions->used) {
+ return HANDLER_GO_ON;
+ }
+
+- if (p->conf.debug) {
++ backends = extension->value;
++
++ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found");
+ }
+
+@@ -1120,34 +1077,34 @@
+ /* hash balancing */
+
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "proxy - used hash balancing, hosts:", extension->value->used);
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "proxy - used hash balancing, hosts:", backends->used);
+ }
+
+- for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
+- data_proxy *host = (data_proxy *)extension->value->data[k];
++ for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
+ unsigned long cur_max;
+
+- if (host->is_disabled) continue;
+-
++ data_proxy *cur = (data_proxy *)backends->data[k];
++
++ if (cur->is_disabled) continue;
++
+ cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
+- generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
++ generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
+ generate_crc32c(CONST_BUF_LEN(con->uri.authority));
+-
++
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sbbbd",
++ log_error_write(srv, __FILE__, __LINE__, "sbbbd",
+ "proxy - election:",
+ con->uri.path,
+- host->host,
++ cur->host,
+ con->uri.authority,
+ cur_max);
+ }
+
+- if ((last_max == ULONG_MAX) || /* first round */
+- (cur_max > last_max)) {
++ if (host == NULL || (cur_max > last_max)) {
+ last_max = cur_max;
+
+- ndx = k;
++ host = cur;
+ }
+ }
+
+@@ -1155,19 +1112,20 @@
+ case PROXY_BALANCE_FAIR:
+ /* fair balancing */
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "proxy - used fair balancing");
+ }
+
+- for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
+- data_proxy *host = (data_proxy *)extension->value->data[k];
+-
+- if (host->is_disabled) continue;
+-
+- if (host->usage < max_usage) {
+- max_usage = host->usage;
+-
+- ndx = k;
++ /* try to find the host with the lowest load */
++ for (k = 0, max_usage = 0; k < backends->used; k++) {
++ data_proxy *cur = (data_proxy *)backends->data[k];
++
++ if (cur->is_disabled) continue;
++
++ if (NULL == host || cur->usage < max_usage) {
++ max_usage = cur->usage;
++
++ host = cur;
+ }
+ }
+
+@@ -1175,89 +1133,100 @@
+ case PROXY_BALANCE_RR:
+ /* round robin */
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "proxy - used round-robin balancing");
+ }
+
+ /* just to be sure */
+- assert(extension->value->used < INT_MAX);
+-
+- for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
+- data_proxy *host = (data_proxy *)extension->value->data[k];
+-
+- if (host->is_disabled) continue;
+-
+- /* first usable ndx */
+- if (max_usage == INT_MAX) {
+- max_usage = k;
+- }
++ assert(backends->used < INT_MAX);
+
+- /* get next ndx */
+- if ((int)k > host->last_used_ndx) {
+- ndx = k;
+- host->last_used_ndx = k;
++ /* send each request to another host:
++ *
++ * e.g.:
++ *
++ * if we have three hosts it is
++ *
++ * 1 .. 2 .. 3 .. 1 .. 2 .. 3
++ *
++ **/
+
+- break;
+- }
++ /* walk through the list */
++ last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
++
++ if (NULL == last_used_backend) {
++ last_used_backend = data_integer_init();
++
++ buffer_copy_string_buffer(last_used_backend->key, extension->key);
++ last_used_backend->value = 0;
++
++ array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
++ }
++
++ /* scan all but the last host to see if they are up
++ * take the first running host */
++ for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
++ data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
++
++ if (cur->is_disabled) continue;
++
++ host = cur;
++
++ last_used_backend->value = k;
++
++ break;
+ }
+-
+- /* didn't found a higher id, wrap to the start */
+- if (ndx != -1 && max_usage != INT_MAX) {
+- ndx = max_usage;
++
++ if (NULL == host) {
++ /* we found nothing better, fallback to the last used backend
++ * and check if it is still up */
++ host = (data_proxy *)backends->data[last_used_backend->value];
++
++ if (host->is_disabled) host = NULL;
+ }
+
+ break;
+ default:
+ break;
+ }
+-
+- /* found a server */
+- if (ndx != -1) {
+- data_proxy *host = (data_proxy *)extension->value->data[ndx];
+-
+- /*
+- * if check-local is disabled, use the uri.path handler
+- *
+- */
+-
+- /* init handler-context */
+- handler_ctx *hctx;
+- hctx = handler_ctx_init();
+-
+- hctx->path_info_offset = path_info_offset;
+- hctx->remote_conn = con;
+- hctx->plugin_data = p;
+- hctx->host = host;
+-
+- con->plugin_ctx[p->id] = hctx;
+-
+- host->usage++;
+-
+- con->mode = p->id;
+-
+- if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sbd",
+- "proxy - found a host",
+- host->host, host->port);
+- }
+
+- return HANDLER_GO_ON;
+- } else {
+- /* no handler found */
++ /* we havn't found a host */
++ if (NULL == host) {
+ con->http_status = 500;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "no proxy-handler found for:",
++
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "no proxy-handler found for:",
+ fn);
+-
++
+ return HANDLER_FINISHED;
+ }
++
++ /* init handler-context */
++ hctx = handler_ctx_init();
++
++ hctx->path_info_offset = path_info_offset;
++ hctx->remote_conn = con;
++ hctx->plugin_data = p;
++ hctx->host = host;
++
++ con->plugin_ctx[p->id] = hctx;
++
++ host->usage++;
++
++ /* we handle this request */
++ con->mode = p->id;
++
++ if (p->conf.debug) {
++ log_error_write(srv, __FILE__, __LINE__, "sbd",
++ "proxy - found a host",
++ host->host, host->port);
++ }
++
+ return HANDLER_GO_ON;
+ }
+
+ static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
+ plugin_data *p = p_d;
+-
++
+ proxy_connection_close(srv, con->plugin_ctx[p->id]);
+
+ return HANDLER_GO_ON;
+@@ -1276,11 +1245,11 @@
+ size_t i, n, k;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
+- if (!s) continue;
++
++ if (!s) continue;
+
+ /* get the extensions for all configs */
+-
++
+ for (k = 0; k < s->extensions->used; k++) {
+ data_array *extension = (data_array *)s->extensions->data[k];
+
+@@ -1290,8 +1259,8 @@
+
+ if (!host->is_disabled ||
+ srv->cur_ts - host->disable_ts < 5) continue;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbd",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbd",
+ "proxy - re-enabled:",
+ host->host, host->port);
+
+@@ -1317,8 +1286,8 @@
+ p->handle_uri_clean = mod_proxy_check_extension;
+ p->handle_subrequest = mod_proxy_handle_subrequest;
+ p->handle_trigger = mod_proxy_trigger;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_redirect.c lighttpd-1.4.12/src/mod_redirect.c
+--- lighttpd-1.4.11/src/mod_redirect.c 2006-02-08 15:38:06.000000000 +0200
++++ lighttpd-1.4.12/src/mod_redirect.c 2006-07-11 21:23:40.000000000 +0300
+@@ -22,35 +22,35 @@
+ PLUGIN_DATA;
+ buffer *match_buf;
+ buffer *location;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ INIT_FUNC(mod_redirect_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->match_buf = buffer_init();
+ p->location = buffer_init();
+-
++
+ return p;
+ }
+
+ FREE_FUNC(mod_redirect_free) {
+ plugin_data *p = p_d;
+-
++
+ if (!p) return HANDLER_GO_ON;
+
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ pcre_keyvalue_buffer_free(s->redirect);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+@@ -59,9 +59,9 @@
+
+ buffer_free(p->match_buf);
+ buffer_free(p->location);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -69,195 +69,137 @@
+ plugin_data *p = p_d;
+ data_unset *du;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ /* 0 */
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+ size_t j;
+ array *ca;
+ data_array *da = (data_array *)du;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->redirect = pcre_keyvalue_buffer_init();
+-
++
+ cv[0].destination = s->redirect;
+-
++
+ p->config_storage[i] = s;
+ ca = ((data_config *)srv->config_context->data[i])->value;
+-
++
+ if (0 != config_insert_values_global(srv, ca, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (NULL == (du = array_get_element(ca, "url.redirect"))) {
+ /* no url.redirect defined */
+ continue;
+ }
+-
++
+ if (du->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "sss",
++ log_error_write(srv, __FILE__, __LINE__, "sss",
+ "unexpected type for key: ", "url.redirect", "array of strings");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ da = (data_array *)du;
+-
++
+ for (j = 0; j < da->value->used; j++) {
+ if (da->value->data[j]->type != TYPE_STRING) {
+- log_error_write(srv, __FILE__, __LINE__, "sssbs",
+- "unexpected type for key: ",
+- "url.redirect",
++ log_error_write(srv, __FILE__, __LINE__, "sssbs",
++ "unexpected type for key: ",
++ "url.redirect",
+ "[", da->value->data[j]->key, "](string)");
+-
++
+ return HANDLER_ERROR;
+ }
+-
+- if (0 != pcre_keyvalue_buffer_append(s->redirect,
++
++ if (0 != pcre_keyvalue_buffer_append(s->redirect,
+ ((data_string *)(da->value->data[j]))->key->ptr,
+ ((data_string *)(da->value->data[j]))->value->ptr)) {
+-
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "pcre-compile failed for", da->value->data[j]->key);
+ }
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+ #ifdef HAVE_PCRE_H
+ static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
++
+ p->conf.redirect = s->redirect;
+-
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (0 == strcmp(du->key->ptr, "url.redirect")) {
+ p->conf.redirect = s->redirect;
+ p->conf.context = dc;
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+ #endif
+ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
+ #ifdef HAVE_PCRE_H
+ plugin_data *p = p_data;
+- size_t i;
++ int i;
+
+- /*
++ /*
+ * REWRITE URL
+- *
++ *
+ * e.g. redirect /base/ to /index.php?section=base
+- *
++ *
+ */
+-
++
+ mod_redirect_patch_connection(srv, con, p);
+-
++
+ buffer_copy_string_buffer(p->match_buf, con->request.uri);
+-
+- for (i = 0; i < p->conf.redirect->used; i++) {
+- pcre *match;
+- pcre_extra *extra;
+- const char *pattern;
+- size_t pattern_len;
+- int n;
+- pcre_keyvalue *kv = p->conf.redirect->kv[i];
+-# define N 10
+- int ovec[N * 3];
+-
+- match = kv->key;
+- extra = kv->key_extra;
+- pattern = kv->value->ptr;
+- pattern_len = kv->value->used - 1;
+-
+- if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
+- if (n != PCRE_ERROR_NOMATCH) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "execution error while matching: ", n);
+- return HANDLER_ERROR;
+- }
+- } else {
+- const char **list;
+- size_t start, end;
+- size_t k;
+-
+- /* it matched */
+- pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
+-
+- /* search for $[0-9] */
+-
+- buffer_reset(p->location);
+-
+- start = 0; end = pattern_len;
+- for (k = 0; k < pattern_len; k++) {
+- if ((pattern[k] == '$' || pattern[k] == '%') &&
+- isdigit((unsigned char)pattern[k + 1])) {
+- /* got one */
+-
+- size_t num = pattern[k + 1] - '0';
+-
+- end = k;
+-
+- buffer_append_string_len(p->location, pattern + start, end - start);
+-
+- if (pattern[k] == '$') {
+- /* n is always > 0 */
+- if (num < (size_t)n) {
+- buffer_append_string(p->location, list[num]);
+- }
+- } else {
+- config_append_cond_match_buffer(con, p->conf.context, p->location, num);
+- }
+-
+- k++;
+- start = k + 1;
+- }
+- }
+-
+- buffer_append_string_len(p->location, pattern + start, pattern_len - start);
+-
+- pcre_free(list);
+-
+- response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
+-
+- con->http_status = 301;
+- con->file_finished = 1;
+-
+- return HANDLER_FINISHED;
+- }
++ i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
++
++ if (i >= 0) {
++ response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
++
++ con->http_status = 301;
++ con->file_finished = 1;
++
++ return HANDLER_FINISHED;
++ }
++ else if (i != PCRE_ERROR_NOMATCH) {
++ log_error_write(srv, __FILE__, __LINE__, "s",
++ "execution error while matching", i);
+ }
+ #undef N
+-
++
+ #else
+ UNUSED(srv);
+ UNUSED(con);
+ UNUSED(p_data);
+ #endif
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -265,13 +207,13 @@
+ int mod_redirect_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("redirect");
+-
++
+ p->init = mod_redirect_init;
+ p->handle_uri_clean = mod_redirect_uri_handler;
+ p->set_defaults = mod_redirect_set_defaults;
+ p->cleanup = mod_redirect_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_rewrite.c lighttpd-1.4.12/src/mod_rewrite.c
+--- lighttpd-1.4.11/src/mod_rewrite.c 2005-09-29 20:59:10.000000000 +0300
++++ lighttpd-1.4.12/src/mod_rewrite.c 2006-07-11 21:23:39.000000000 +0300
+@@ -13,24 +13,8 @@
+ #endif
+
+ typedef struct {
+-#ifdef HAVE_PCRE_H
+- pcre *key;
+-#endif
+-
+- buffer *value;
+-
+- int once;
+-} rewrite_rule;
+-
+-typedef struct {
+- rewrite_rule **ptr;
+-
+- size_t used;
+- size_t size;
+-} rewrite_rule_buffer;
+-
+-typedef struct {
+- rewrite_rule_buffer *rewrite;
++ pcre_keyvalue_buffer *rewrite;
++ buffer *once;
+ data_config *context; /* to which apply me */
+ } plugin_config;
+
+@@ -42,20 +26,20 @@
+ typedef struct {
+ PLUGIN_DATA;
+ buffer *match_buf;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ static handler_ctx * handler_ctx_init() {
+ handler_ctx * hctx;
+-
++
+ hctx = calloc(1, sizeof(*hctx));
+-
++
+ hctx->state = REWRITE_STATE_UNSET;
+ hctx->loops = 0;
+-
++
+ return hctx;
+ }
+
+@@ -63,207 +47,136 @@
+ free(hctx);
+ }
+
+-rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
+- rewrite_rule_buffer *kvb;
+-
+- kvb = calloc(1, sizeof(*kvb));
+-
+- return kvb;
+-}
+-
+-int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
+-#ifdef HAVE_PCRE_H
+- size_t i;
+- const char *errptr;
+- int erroff;
+-
+- if (!key) return -1;
+-
+- if (kvb->size == 0) {
+- kvb->size = 4;
+- kvb->used = 0;
+-
+- kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
+-
+- for(i = 0; i < kvb->size; i++) {
+- kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
+- }
+- } else if (kvb->used == kvb->size) {
+- kvb->size += 4;
+-
+- kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
+-
+- for(i = kvb->used; i < kvb->size; i++) {
+- kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
+- }
+- }
+-
+- if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
+- 0, &errptr, &erroff, NULL))) {
+-
+- return -1;
+- }
+-
+- kvb->ptr[kvb->used]->value = buffer_init();
+- buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
+- kvb->ptr[kvb->used]->once = once;
+-
+- kvb->used++;
+-
+- return 0;
+-#else
+- UNUSED(kvb);
+- UNUSED(value);
+- UNUSED(once);
+- UNUSED(key);
+-
+- return -1;
+-#endif
+-}
+-
+-void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
+-#ifdef HAVE_PCRE_H
+- size_t i;
+-
+- for (i = 0; i < kvb->size; i++) {
+- if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
+- if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
+- free(kvb->ptr[i]);
+- }
+-
+- if (kvb->ptr) free(kvb->ptr);
+-#endif
+-
+- free(kvb);
+-}
+-
+
+ INIT_FUNC(mod_rewrite_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->match_buf = buffer_init();
+-
++
+ return p;
+ }
+
+ FREE_FUNC(mod_rewrite_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ buffer_free(p->match_buf);
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+- rewrite_rule_buffer_free(s->rewrite);
+-
++ pcre_keyvalue_buffer_free(s->rewrite);
++ buffer_free(s->once);
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
+ data_unset *du;
+-
++
+ if (NULL != (du = array_get_element(ca, option))) {
+ data_array *da = (data_array *)du;
+ size_t j;
+-
++
+ if (du->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "sss",
++ log_error_write(srv, __FILE__, __LINE__, "sss",
+ "unexpected type for key: ", option, "array of strings");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ da = (data_array *)du;
+-
++
+ for (j = 0; j < da->value->used; j++) {
+ if (da->value->data[j]->type != TYPE_STRING) {
+- log_error_write(srv, __FILE__, __LINE__, "sssbs",
+- "unexpected type for key: ",
+- option,
++ log_error_write(srv, __FILE__, __LINE__, "sssbs",
++ "unexpected type for key: ",
++ option,
+ "[", da->value->data[j]->key, "](string)");
+-
++
+ return HANDLER_ERROR;
+ }
+-
+- if (0 != rewrite_rule_buffer_append(s->rewrite,
+- ((data_string *)(da->value->data[j]))->key,
+- ((data_string *)(da->value->data[j]))->value,
+- once)) {
++
++ if (0 != pcre_keyvalue_buffer_append(s->rewrite,
++ ((data_string *)(da->value->data[j]))->key->ptr,
++ ((data_string *)(da->value->data[j]))->value->ptr)) {
+ #ifdef HAVE_PCRE_H
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "pcre-compile failed for", da->value->data[j]->key);
+ #else
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "pcre support is missing, please install libpcre and the headers");
+ #endif
+ }
++
++ if (once) {
++ buffer_append_string_len(s->once, CONST_STR_LEN("1"));
++ } else {
++ buffer_append_string_len(s->once, CONST_STR_LEN("0"));
++ }
+ }
+ }
+-
++
+ return 0;
+ }
+
+ SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "url.rewrite-repeat", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "url.rewrite-once", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+-
+- /* old names, still supported
+- *
++
++ /* old names, still supported
++ *
+ * url.rewrite remapped to url.rewrite-once
+ * url.rewrite-final is url.rewrite-once
+- *
++ *
+ */
+ { "url.rewrite", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { "url.rewrite-final", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ /* 0 */
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+ array *ca;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+- s->rewrite = rewrite_rule_buffer_init();
+-
+- cv[0].destination = s->rewrite;
+- cv[1].destination = s->rewrite;
+- cv[2].destination = s->rewrite;
+-
++ s->rewrite = pcre_keyvalue_buffer_init();
++ s->once = buffer_init();
++
+ p->config_storage[i] = s;
+ ca = ((data_config *)srv->config_context->data[i])->value;
+-
++
+ if (0 != config_insert_values_global(srv, ca, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ parse_config_entry(srv, s, ca, "url.rewrite-once", 1);
+ parse_config_entry(srv, s, ca, "url.rewrite-final", 1);
+ parse_config_entry(srv, s, ca, "url.rewrite", 1);
+ parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+ #ifdef HAVE_PCRE_H
+@@ -271,157 +184,107 @@
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+ p->conf.rewrite = s->rewrite;
+-
++ p->conf.once = s->once;
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ if (COMP_HTTP_URL == dc->comp) continue;
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
+ p->conf.rewrite = s->rewrite;
++ p->conf.once = s->once;
+ p->conf.context = dc;
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
+ p->conf.rewrite = s->rewrite;
++ p->conf.once = s->once;
+ p->conf.context = dc;
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
+ p->conf.rewrite = s->rewrite;
++ p->conf.once = s->once;
+ p->conf.context = dc;
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
+ p->conf.rewrite = s->rewrite;
++ p->conf.once = s->once;
+ p->conf.context = dc;
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+ #endif
+ URIHANDLER_FUNC(mod_rewrite_con_reset) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+-
++
+ if (con->plugin_ctx[p->id]) {
+ handler_ctx_free(con->plugin_ctx[p->id]);
+ con->plugin_ctx[p->id] = NULL;
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ URIHANDLER_FUNC(mod_rewrite_uri_handler) {
+ #ifdef HAVE_PCRE_H
+ plugin_data *p = p_d;
+- size_t i;
++ int i;
+ handler_ctx *hctx;
+
+- /*
++ /*
+ * REWRITE URL
+- *
++ *
+ * e.g. rewrite /base/ to /index.php?section=base
+- *
++ *
+ */
+-
++
+ if (con->plugin_ctx[p->id]) {
+ hctx = con->plugin_ctx[p->id];
+-
++
+ if (hctx->loops++ > 100) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
+ }
+-
++
+ mod_rewrite_patch_connection(srv, con, p);
+
+ if (!p->conf.rewrite) return HANDLER_GO_ON;
+-
++
+ buffer_copy_string_buffer(p->match_buf, con->request.uri);
+-
+- for (i = 0; i < p->conf.rewrite->used; i++) {
+- pcre *match;
+- const char *pattern;
+- size_t pattern_len;
+- int n;
+- rewrite_rule *rule = p->conf.rewrite->ptr[i];
+-# define N 10
+- int ovec[N * 3];
+-
+- match = rule->key;
+- pattern = rule->value->ptr;
+- pattern_len = rule->value->used - 1;
+-
+- if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
+- if (n != PCRE_ERROR_NOMATCH) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "execution error while matching: ", n);
+- return HANDLER_ERROR;
+- }
+- } else {
+- const char **list;
+- size_t start, end;
+- size_t k;
+-
+- /* it matched */
+- pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
+-
+- /* search for $[0-9] */
+-
+- buffer_reset(con->request.uri);
+-
+- start = 0; end = pattern_len;
+- for (k = 0; k < pattern_len; k++) {
+- if ((pattern[k] == '$' || pattern[k] == '%') &&
+- isdigit((unsigned char)pattern[k + 1])) {
+- /* got one */
+-
+- size_t num = pattern[k + 1] - '0';
+-
+- end = k;
+-
+- buffer_append_string_len(con->request.uri, pattern + start, end - start);
+-
+- if (pattern[k] == '$') {
+- /* n is always > 0 */
+- if (num < (size_t)n) {
+- buffer_append_string(con->request.uri, list[num]);
+- }
+- } else {
+- config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
+- }
+-
+- k++;
+- start = k + 1;
+- }
+- }
+-
+- buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
+-
+- pcre_free(list);
+-
+- hctx = handler_ctx_init();
+-
+- con->plugin_ctx[p->id] = hctx;
+-
+- if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
+-
+- return HANDLER_COMEBACK;
+- }
++ i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
++
++ if (i >= 0) {
++ hctx = handler_ctx_init();
++
++ con->plugin_ctx[p->id] = hctx;
++
++ if (p->conf.once->ptr[i] == '1')
++ hctx->state = REWRITE_STATE_FINISHED;
++
++ return HANDLER_COMEBACK;
++ }
++ else if (i != PCRE_ERROR_NOMATCH) {
++ log_error_write(srv, __FILE__, __LINE__, "s",
++ "execution error while matching", i);
+ }
+ #undef N
+-
++
+ #else
+ UNUSED(srv);
+ UNUSED(con);
+@@ -434,17 +297,17 @@
+ int mod_rewrite_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("rewrite");
+-
++
+ p->init = mod_rewrite_init;
+ /* it has to stay _raw as we are matching on uri + querystring
+ */
+-
++
+ p->handle_uri_raw = mod_rewrite_uri_handler;
+ p->set_defaults = mod_rewrite_set_defaults;
+ p->cleanup = mod_rewrite_free;
+ p->connection_reset = mod_rewrite_con_reset;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_rrdtool.c lighttpd-1.4.12/src/mod_rrdtool.c
+--- lighttpd-1.4.11/src/mod_rrdtool.c 2005-08-22 01:52:24.000000000 +0300
++++ lighttpd-1.4.12/src/mod_rrdtool.c 2006-07-11 21:23:40.000000000 +0300
+@@ -5,7 +5,6 @@
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+-#include <unistd.h>
+ #include <errno.h>
+ #include <time.h>
+
+@@ -20,10 +19,14 @@
+ /* no need for waitpid if we don't have fork */
+ #include <sys/wait.h>
+ #endif
++
++#include "sys-files.h"
++#include "sys-process.h"
++
+ typedef struct {
+ buffer *path_rrdtool_bin;
+ buffer *path_rrd;
+-
++
+ double requests, *requests_ptr;
+ double bytes_written, *bytes_written_ptr;
+ double bytes_read, *bytes_read_ptr;
+@@ -31,84 +34,84 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *cmd;
+ buffer *resp;
+-
++
+ int read_fd, write_fd;
+ pid_t rrdtool_pid;
+-
++
+ int rrdtool_running;
+-
++
+ plugin_config **config_storage;
+ plugin_config conf;
+ } plugin_data;
+
+ INIT_FUNC(mod_rrd_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->resp = buffer_init();
+ p->cmd = buffer_init();
+-
++
+ return p;
+ }
+
+ FREE_FUNC(mod_rrd_free) {
+ plugin_data *p = p_d;
+ size_t i;
+-
++
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ buffer_free(s->path_rrdtool_bin);
+ buffer_free(s->path_rrd);
+-
++
+ free(s);
+ }
+ }
+ buffer_free(p->cmd);
+ buffer_free(p->resp);
+-
++
+ free(p->config_storage);
+-
++
+ if (p->rrdtool_pid) {
+ int status;
+ close(p->read_fd);
+ close(p->write_fd);
+-#ifdef HAVE_FORK
++#ifdef HAVE_FORK
+ /* collect status */
+ waitpid(p->rrdtool_pid, &status, 0);
+ #endif
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ int mod_rrd_create_pipe(server *srv, plugin_data *p) {
+ pid_t pid;
+-
++
+ int to_rrdtool_fds[2];
+ int from_rrdtool_fds[2];
+-#ifdef HAVE_FORK
++#ifdef HAVE_FORK
+ if (pipe(to_rrdtool_fds)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "pipe failed: ", strerror(errno));
+ return -1;
+ }
+-
++
+ if (pipe(from_rrdtool_fds)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "pipe failed: ", strerror(errno));
+ return -1;
+ }
+-
++
+ /* fork, execve */
+ switch (pid = fork()) {
+ case 0: {
+@@ -117,33 +120,33 @@
+ int argc;
+ int i = 0;
+ char *dash = "-";
+-
++
+ /* move stdout to from_rrdtool_fd[1] */
+ close(STDOUT_FILENO);
+ dup2(from_rrdtool_fds[1], STDOUT_FILENO);
+ close(from_rrdtool_fds[1]);
+ /* not needed */
+ close(from_rrdtool_fds[0]);
+-
++
+ /* move the stdin to to_rrdtool_fd[0] */
+ close(STDIN_FILENO);
+ dup2(to_rrdtool_fds[0], STDIN_FILENO);
+ close(to_rrdtool_fds[0]);
+ /* not needed */
+ close(to_rrdtool_fds[1]);
+-
++
+ close(STDERR_FILENO);
+-
++
+ if (srv->errorlog_mode == ERRORLOG_FILE) {
+ dup2(srv->errorlog_fd, STDERR_FILENO);
+ close(srv->errorlog_fd);
+ }
+-
++
+ /* set up args */
+ argc = 3;
+ args = malloc(sizeof(*args) * argc);
+ i = 0;
+-
++
+ args[i++] = p->conf.path_rrdtool_bin->ptr;
+ args[i++] = dash;
+ args[i++] = NULL;
+@@ -152,12 +155,12 @@
+ for (i = 3; i < 256; i++) {
+ close(i);
+ }
+-
++
+ /* exec the cgi */
+ execv(args[0], args);
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
+-
++
+ /* */
+ SEGFAULT();
+ break;
+@@ -168,19 +171,19 @@
+ break;
+ default: {
+ /* father */
+-
++
+ close(from_rrdtool_fds[1]);
+ close(to_rrdtool_fds[0]);
+-
++
+ /* register PID and wait for them asyncronously */
+ p->write_fd = to_rrdtool_fds[1];
+ p->read_fd = from_rrdtool_fds[0];
+ p->rrdtool_pid = pid;
+-
++
+ break;
+ }
+ }
+-
++
+ return 0;
+ #else
+ return -1;
+@@ -189,19 +192,19 @@
+
+ static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
+ struct stat st;
+-
++
+ /* check if DB already exists */
+ if (0 == stat(s->path_rrd->ptr, &st)) {
+ /* check if it is plain file */
+ if (!S_ISREG(st.st_mode)) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "not a regular file:", s->path_rrd);
+ return HANDLER_ERROR;
+ }
+ } else {
+ int r ;
+ /* create a new one */
+-
++
+ BUFFER_COPY_STRING_CONST(p->cmd, "create ");
+ buffer_append_string_buffer(p->cmd, s->path_rrd);
+ buffer_append_string(p->cmd, " --step 60 ");
+@@ -220,158 +223,155 @@
+ buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
+ buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
+ buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
+-
++
+ if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "rrdtool-write: failed", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ buffer_prepare_copy(p->resp, 4096);
+ if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "rrdtool-read: failed", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ p->resp->used = r;
+-
++
+ if (p->resp->ptr[0] != 'O' ||
+ p->resp->ptr[1] != 'K') {
+- log_error_write(srv, __FILE__, __LINE__, "sbb",
++ log_error_write(srv, __FILE__, __LINE__, "sbb",
+ "rrdtool-response:", p->cmd, p->resp);
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(path_rrdtool_bin);
+- PATCH(path_rrd);
+-
++
++ PATCH_OPTION(path_rrdtool_bin);
++ PATCH_OPTION(path_rrd);
++
+ p->conf.bytes_written_ptr = &(s->bytes_written);
+ p->conf.bytes_read_ptr = &(s->bytes_read);
+ p->conf.requests_ptr = &(s->requests);
+-
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
+- PATCH(path_rrd);
++ PATCH_OPTION(path_rrd);
+ /* get pointers to double values */
+-
++
+ p->conf.bytes_written_ptr = &(s->bytes_written);
+ p->conf.bytes_read_ptr = &(s->bytes_read);
+ p->conf.requests_ptr = &(s->requests);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "rrdtool.binary", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
+ { "rrdtool.db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->path_rrdtool_bin = buffer_init();
+ s->path_rrd = buffer_init();
+ s->requests = 0;
+ s->bytes_written = 0;
+ s->bytes_read = 0;
+-
++
+ cv[0].destination = s->path_rrdtool_bin;
+ cv[1].destination = s->path_rrd;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
+ /* path_rrdtool_bin is a global option */
+-
+- log_error_write(srv, __FILE__, __LINE__, "s",
++
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "rrdtool.binary can only be set as a global option.");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ }
+-
++
+ p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
+ p->rrdtool_running = 0;
+-
++
+ /* check for dir */
+-
++
+ if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "rrdtool.binary has to be set");
+ return HANDLER_ERROR;
+ }
+-
++
+ /* open the pipe to rrdtool */
+ if (mod_rrd_create_pipe(srv, p)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ p->rrdtool_running = 1;
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ TRIGGER_FUNC(mod_rrd_trigger) {
+ plugin_data *p = p_d;
+ size_t i;
+-
++
+ if (!p->rrdtool_running) return HANDLER_GO_ON;
+ if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+ int r;
+-
++
+ if (buffer_is_empty(s->path_rrd)) continue;
+-
++
+ /* write the data down every minute */
+-
++
+ if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
+-
++
+ BUFFER_COPY_STRING_CONST(p->cmd, "update ");
+ buffer_append_string_buffer(p->cmd, s->path_rrd);
+ BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
+@@ -381,69 +381,69 @@
+ BUFFER_APPEND_STRING_CONST(p->cmd, ":");
+ buffer_append_long(p->cmd, s->requests);
+ BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
+-
++
+ if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
+ p->rrdtool_running = 0;
+-
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "rrdtool-write: failed", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ buffer_prepare_copy(p->resp, 4096);
+ if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
+ p->rrdtool_running = 0;
+-
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "rrdtool-read: failed", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ p->resp->used = r;
+-
++
+ if (p->resp->ptr[0] != 'O' ||
+ p->resp->ptr[1] != 'K') {
+ p->rrdtool_running = 0;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbb",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbb",
+ "rrdtool-response:", p->cmd, p->resp);
+-
++
+ return HANDLER_ERROR;
+ }
+ s->requests = 0;
+ s->bytes_written = 0;
+ s->bytes_read = 0;
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ REQUESTDONE_FUNC(mod_rrd_account) {
+ plugin_data *p = p_d;
+-
++
+ mod_rrd_patch_connection(srv, con, p);
+-
++
+ *(p->conf.requests_ptr) += 1;
+ *(p->conf.bytes_written_ptr) += con->bytes_written;
+ *(p->conf.bytes_read_ptr) += con->bytes_read;
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ int mod_rrdtool_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("rrd");
+-
++
+ p->init = mod_rrd_init;
+ p->cleanup = mod_rrd_free;
+ p->set_defaults= mod_rrd_set_defaults;
+-
++
+ p->handle_trigger = mod_rrd_trigger;
+ p->handle_request_done = mod_rrd_account;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_scgi.c lighttpd-1.4.12/src/mod_scgi.c
+--- lighttpd-1.4.11/src/mod_scgi.c 2006-03-04 17:15:26.000000000 +0200
++++ lighttpd-1.4.12/src/mod_scgi.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,5 +1,4 @@
+ #include <sys/types.h>
+-#include <unistd.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <string.h>
+@@ -30,7 +29,9 @@
+ #endif
+
+ #include "sys-socket.h"
+-
++#include "sys-files.h"
++#include "sys-strings.h"
++#include "sys-process.h"
+
+ #ifndef UNIX_PATH_MAX
+ # define UNIX_PATH_MAX 108
+@@ -46,30 +47,29 @@
+ enum {EOL_UNSET, EOL_N, EOL_RN};
+
+ /*
+- *
++ *
+ * TODO:
+- *
++ *
+ * - add timeout for a connect to a non-scgi process
+ * (use state_timestamp + state)
+- *
++ *
+ */
+
+ typedef struct scgi_proc {
+ size_t id; /* id will be between 1 and max_procs */
+ buffer *socket; /* config.socket + "-" + id */
+ unsigned port; /* config.port + pno */
+-
+- pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
+
++ pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
+
+ size_t load; /* number of requests waiting on this process */
+
+ time_t last_used; /* see idle_timeout */
+ size_t requests; /* see max_requests */
+ struct scgi_proc *prev, *next; /* see first */
+-
++
+ time_t disable_ts; /* replace by host->something */
+-
++
+ int is_local;
+
+ enum { PROC_STATE_UNSET, /* init-phase */
+@@ -78,7 +78,7 @@
+ PROC_STATE_KILLED, /* was killed as we don't have the load anymore */
+ PROC_STATE_DIED, /* marked as dead, should be restarted */
+ PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
+- } state;
++ } state;
+ } scgi_proc;
+
+ typedef struct {
+@@ -86,20 +86,20 @@
+ * sorted by lowest load
+ *
+ * whenever a job is done move it up in the list
+- * until it is sorted, move it down as soon as the
++ * until it is sorted, move it down as soon as the
+ * job is started
+ */
+- scgi_proc *first;
+- scgi_proc *unused_procs;
++ scgi_proc *first;
++ scgi_proc *unused_procs;
+
+- /*
++ /*
+ * spawn at least min_procs, at max_procs.
+ *
+- * as soon as the load of the first entry
++ * as soon as the load of the first entry
+ * is max_load_per_proc we spawn a new one
+- * and add it to the first entry and give it
++ * and add it to the first entry and give it
+ * the load
+- *
++ *
+ */
+
+ unsigned short min_procs;
+@@ -111,44 +111,44 @@
+
+ /*
+ * kick the process from the list if it was not
+- * used for idle_timeout until min_procs is
++ * used for idle_timeout until min_procs is
+ * reached. this helps to get the processlist
+ * small again we had a small peak load.
+ *
+ */
+-
++
+ unsigned short idle_timeout;
+-
++
+ /*
+ * time after a disabled remote connection is tried to be re-enabled
+- *
+- *
++ *
++ *
+ */
+-
++
+ unsigned short disable_time;
+
+ /*
+ * same scgi processes get a little bit larger
+- * than wanted. max_requests_per_proc kills a
++ * than wanted. max_requests_per_proc kills a
+ * process after a number of handled requests.
+ *
+ */
+ size_t max_requests_per_proc;
+-
++
+
+ /* config */
+
+- /*
+- * host:port
++ /*
++ * host:port
+ *
+- * if host is one of the local IP adresses the
++ * if host is one of the local IP adresses the
+ * whole connection is local
+ *
+ * if tcp/ip should be used host AND port have
+- * to be specified
+- *
+- */
+- buffer *host;
++ * to be specified
++ *
++ */
++ buffer *host;
+ unsigned short port;
+
+ /*
+@@ -161,7 +161,7 @@
+ */
+ buffer *unixsocket;
+
+- /* if socket is local we can start the scgi
++ /* if socket is local we can start the scgi
+ * process ourself
+ *
+ * bin-path is the path to the binary
+@@ -169,19 +169,19 @@
+ * check min_procs and max_procs for the number
+ * of process to start-up
+ */
+- buffer *bin_path;
+-
+- /* bin-path is set bin-environment is taken to
++ buffer *bin_path;
++
++ /* bin-path is set bin-environment is taken to
+ * create the environement before starting the
+ * FastCGI process
+- *
++ *
+ */
+ array *bin_env;
+-
++
+ array *bin_env_copy;
+-
++
+ /*
+- * docroot-translation between URL->phys and the
++ * docroot-translation between URL->phys and the
+ * remote host
+ *
+ * reasons:
+@@ -192,7 +192,7 @@
+ buffer *docroot;
+
+ /*
+- * check_local tell you if the phys file is stat()ed
++ * check_local tell you if the phys file is stat()ed
+ * or not. FastCGI doesn't care if the service is
+ * remote. If the web-server side doesn't contain
+ * the scgi-files we should not stat() for them
+@@ -202,33 +202,33 @@
+
+ /*
+ * append PATH_INFO to SCRIPT_FILENAME
+- *
++ *
+ * php needs this if cgi.fix_pathinfo is provied
+- *
++ *
+ */
+-
++
+ ssize_t load; /* replace by host->load */
+
+ size_t max_id; /* corresponds most of the time to
+ num_procs.
+-
++
+ only if a process is killed max_id waits for the process itself
+ to die and decrements its afterwards */
+ } scgi_extension_host;
+
+ /*
+ * one extension can have multiple hosts assigned
+- * one host can spawn additional processes on the same
++ * one host can spawn additional processes on the same
+ * socket (if we control it)
+ *
+ * ext -> host -> procs
+ * 1:n 1:n
+ *
+- * if the scgi process is remote that whole goes down
++ * if the scgi process is remote that whole goes down
+ * to
+ *
+ * ext -> host -> procs
+- * 1:n 1:1
++ * 1:n 1:1
+ *
+ * in case of PHP and FCGI_CHILDREN we have again a procs
+ * but we don't control it directly.
+@@ -239,7 +239,7 @@
+ buffer *key; /* like .php */
+
+ scgi_extension_host **hosts;
+-
++
+ size_t used;
+ size_t size;
+ } scgi_extension;
+@@ -253,14 +253,14 @@
+
+
+ typedef struct {
+- scgi_exts *exts;
+-
++ scgi_exts *exts;
++
+ int debug;
+ } plugin_config;
+
+ typedef struct {
+ char **ptr;
+-
++
+ size_t size;
+ size_t used;
+ } char_array;
+@@ -268,52 +268,51 @@
+ /* generic plugin data, shared between all connections */
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *scgi_env;
+-
++
+ buffer *path;
+ buffer *parse_response;
+-
++
+ plugin_config **config_storage;
+-
++
+ plugin_config conf; /* this is only used as long as no handler_ctx is setup */
+ } plugin_data;
+
+ /* connection specific data */
+-typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
+- FCGI_STATE_WRITE, FCGI_STATE_READ
++typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
++ FCGI_STATE_WRITE, FCGI_STATE_READ
+ } scgi_connection_state_t;
+
+ typedef struct {
+- buffer *response;
++ buffer *response;
+ size_t response_len;
+ int response_type;
+ int response_padding;
+-
++
+ scgi_proc *proc;
+ scgi_extension_host *host;
+-
++
+ scgi_connection_state_t state;
+ time_t state_timestamp;
+-
++
+ int reconnects; /* number of reconnect attempts */
+-
++
+ read_buffer *rb;
+ chunkqueue *wb;
+-
++
+ buffer *response_header;
+-
++
+ int delayed; /* flag to mark that the connect() is delayed */
+-
++
+ size_t request_id;
+ int fd; /* fd to the scgi process */
+ int fde_ndx; /* index into the fd-event buffer */
+-
+ pid_t pid;
+ int got_proc;
+-
++
+ plugin_config conf;
+-
++
+ connection *remote_conn; /* dumb pointer */
+ plugin_data *plugin_data; /* dumb pointer */
+ } handler_ctx;
+@@ -328,28 +327,28 @@
+
+ static handler_ctx * handler_ctx_init() {
+ handler_ctx * hctx;
+-
++
+ hctx = calloc(1, sizeof(*hctx));
+ assert(hctx);
+-
++
+ hctx->fde_ndx = -1;
+-
++
+ hctx->response = buffer_init();
+ hctx->response_header = buffer_init();
+-
++
+ hctx->request_id = 0;
+ hctx->state = FCGI_STATE_INIT;
+ hctx->proc = NULL;
+-
++
+ hctx->response_len = 0;
+ hctx->response_type = 0;
+ hctx->response_padding = 0;
+ hctx->fd = -1;
+-
++
+ hctx->reconnects = 0;
+
+ hctx->wb = chunkqueue_init();
+-
++
+ return hctx;
+ }
+
+@@ -358,12 +357,12 @@
+ buffer_free(hctx->response_header);
+
+ chunkqueue_free(hctx->wb);
+-
++
+ if (hctx->rb) {
+ if (hctx->rb->ptr) free(hctx->rb->ptr);
+ free(hctx->rb);
+ }
+-
++
+ free(hctx);
+ }
+
+@@ -372,20 +371,20 @@
+
+ f = calloc(1, sizeof(*f));
+ f->socket = buffer_init();
+-
++
+ f->prev = NULL;
+ f->next = NULL;
+-
++
+ return f;
+ }
+
+ void scgi_process_free(scgi_proc *f) {
+ if (!f) return;
+-
++
+ scgi_process_free(f->next);
+-
++
+ buffer_free(f->socket);
+-
++
+ free(f);
+ }
+
+@@ -400,62 +399,62 @@
+ f->bin_path = buffer_init();
+ f->bin_env = array_init();
+ f->bin_env_copy = array_init();
+-
++
+ return f;
+ }
+
+ void scgi_host_free(scgi_extension_host *h) {
+ if (!h) return;
+-
++
+ buffer_free(h->host);
+ buffer_free(h->unixsocket);
+ buffer_free(h->docroot);
+ buffer_free(h->bin_path);
+ array_free(h->bin_env);
+ array_free(h->bin_env_copy);
+-
++
+ scgi_process_free(h->first);
+ scgi_process_free(h->unused_procs);
+-
++
+ free(h);
+-
++
+ }
+
+ scgi_exts *scgi_extensions_init() {
+ scgi_exts *f;
+
+ f = calloc(1, sizeof(*f));
+-
++
+ return f;
+ }
+
+ void scgi_extensions_free(scgi_exts *f) {
+ size_t i;
+-
++
+ if (!f) return;
+-
++
+ for (i = 0; i < f->used; i++) {
+ scgi_extension *fe;
+ size_t j;
+-
++
+ fe = f->exts[i];
+-
++
+ for (j = 0; j < fe->used; j++) {
+ scgi_extension_host *h;
+-
++
+ h = fe->hosts[j];
+-
++
+ scgi_host_free(h);
+ }
+-
++
+ buffer_free(fe->key);
+ free(fe->hosts);
+-
++
+ free(fe);
+ }
+-
++
+ free(f->exts);
+-
++
+ free(f);
+ }
+
+@@ -504,99 +503,103 @@
+ assert(fe->hosts);
+ }
+
+- fe->hosts[fe->used++] = fh;
++ fe->hosts[fe->used++] = fh;
+
+ return 0;
+-
++
+ }
+
+ INIT_FUNC(mod_scgi_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->scgi_env = buffer_init();
+-
++
+ p->path = buffer_init();
+ p->parse_response = buffer_init();
+-
++
+ return p;
+ }
+
+
+ FREE_FUNC(mod_scgi_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ buffer_free(p->scgi_env);
+ buffer_free(p->path);
+ buffer_free(p->parse_response);
+-
++
+ if (p->config_storage) {
+ size_t i, j, n;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+ scgi_exts *exts;
+-
++
+ if (!s) continue;
+-
++
+ exts = s->exts;
+
+ for (j = 0; j < exts->used; j++) {
+ scgi_extension *ex;
+-
++
+ ex = exts->exts[j];
+-
++
+ for (n = 0; n < ex->used; n++) {
+ scgi_proc *proc;
+ scgi_extension_host *host;
+-
++
+ host = ex->hosts[n];
+-
++
+ for (proc = host->first; proc; proc = proc->next) {
++#ifndef _WIN32
+ if (proc->pid != 0) kill(proc->pid, SIGTERM);
+-
+- if (proc->is_local &&
++#endif
++
++ if (proc->is_local &&
+ !buffer_is_empty(proc->socket)) {
+ unlink(proc->socket->ptr);
+ }
+ }
+-
++
+ for (proc = host->unused_procs; proc; proc = proc->next) {
++#ifndef _WIN32
+ if (proc->pid != 0) kill(proc->pid, SIGTERM);
+-
+- if (proc->is_local &&
++#endif
++
++ if (proc->is_local &&
+ !buffer_is_empty(proc->socket)) {
+ unlink(proc->socket->ptr);
+ }
+ }
+ }
+ }
+-
++
+ scgi_extensions_free(s->exts);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
+ char *dst;
+-
++
+ if (!key || !val) return -1;
+-
++
+ dst = malloc(key_len + val_len + 3);
+ memcpy(dst, key, key_len);
+ dst[key_len] = '=';
+ /* add the \0 from the value */
+ memcpy(dst + key_len + 1, val, val_len + 1);
+-
++
+ if (env->size == 0) {
+ env->size = 16;
+ env->ptr = malloc(env->size * sizeof(*env->ptr));
+@@ -604,13 +607,13 @@
+ env->size += 16;
+ env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
+ }
+-
++
+ env->ptr[env->used++] = dst;
+-
++
+ return 0;
+ }
+
+-static int scgi_spawn_connection(server *srv,
++static int scgi_spawn_connection(server *srv,
+ plugin_data *p,
+ scgi_extension_host *host,
+ scgi_proc *proc) {
+@@ -622,31 +625,27 @@
+ #endif
+ struct sockaddr_in scgi_addr_in;
+ struct sockaddr *scgi_addr;
+-
++
+ socklen_t servlen;
+-
++
+ #ifndef HAVE_FORK
+ return -1;
+ #endif
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sdb",
+ "new proc, socket:", proc->port, proc->socket);
+ }
+-
++
+ if (!buffer_is_empty(proc->socket)) {
+ memset(&scgi_addr, 0, sizeof(scgi_addr));
+-
++
+ #ifdef HAVE_SYS_UN_H
+ scgi_addr_un.sun_family = AF_UNIX;
+ strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
+-
+-#ifdef SUN_LEN
++
+ servlen = SUN_LEN(&scgi_addr_un);
+-#else
+- /* stevens says: */
+- servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
+-#endif
++
+ socket_type = AF_UNIX;
+ scgi_addr = (struct sockaddr *) &scgi_addr_un;
+ #else
+@@ -656,115 +655,115 @@
+ #endif
+ } else {
+ scgi_addr_in.sin_family = AF_INET;
+-
++
+ if (buffer_is_empty(host->host)) {
+ scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ struct hostent *he;
+-
++
+ /* set a usefull default */
+ scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+-
+-
++
++
+ if (NULL == (he = gethostbyname(host->host->ptr))) {
+- log_error_write(srv, __FILE__, __LINE__,
+- "sdb", "gethostbyname failed: ",
++ log_error_write(srv, __FILE__, __LINE__,
++ "sdb", "gethostbyname failed: ",
+ h_errno, host->host);
+ return -1;
+ }
+-
++
+ if (he->h_addrtype != AF_INET) {
+ log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
+ return -1;
+ }
+-
++
+ if (he->h_length != sizeof(struct in_addr)) {
+ log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
+ return -1;
+ }
+-
++
+ memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
+-
++
+ }
+ scgi_addr_in.sin_port = htons(proc->port);
+ servlen = sizeof(scgi_addr_in);
+-
++
+ socket_type = AF_INET;
+ scgi_addr = (struct sockaddr *) &scgi_addr_in;
+ }
+-
++
+ if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "failed:", strerror(errno));
+ return -1;
+ }
+-
++
+ if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
+ /* server is not up, spawn in */
+ pid_t child;
+ int val;
+-
++
+ if (!buffer_is_empty(proc->socket)) {
+ unlink(proc->socket->ptr);
+ }
+-
++
+ close(scgi_fd);
+-
++
+ /* reopen socket */
+ if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "socket failed:", strerror(errno));
+ return -1;
+ }
+-
++
+ val = 1;
+ if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "socketsockopt failed:", strerror(errno));
+ return -1;
+ }
+-
++
+ /* create socket */
+ if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbds",
+- "bind failed for:",
+- proc->socket,
+- proc->port,
++ log_error_write(srv, __FILE__, __LINE__, "sbds",
++ "bind failed for:",
++ proc->socket,
++ proc->port,
+ strerror(errno));
+ return -1;
+ }
+-
++
+ if (-1 == listen(scgi_fd, 1024)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "listen failed:", strerror(errno));
+ return -1;
+ }
+-
+-#ifdef HAVE_FORK
++
++#ifdef HAVE_FORK
+ switch ((child = fork())) {
+ case 0: {
+ buffer *b;
+ size_t i = 0;
+ int fd = 0;
+ char_array env;
+-
+-
++
++
+ /* create environment */
+ env.ptr = NULL;
+ env.size = 0;
+ env.used = 0;
+-
++
+ /* we don't need the client socket */
+ for (fd = 3; fd < 256; fd++) {
+ if (fd != 2 && fd != scgi_fd) close(fd);
+ }
+-
++
+ /* build clean environment */
+ if (host->bin_env_copy->used) {
+ for (i = 0; i < host->bin_env_copy->used; i++) {
+ data_string *ds = (data_string *)host->bin_env_copy->data[i];
+ char *ge;
+-
++
+ if (NULL != (ge = getenv(ds->value->ptr))) {
+ env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
+ }
+@@ -772,44 +771,44 @@
+ } else {
+ for (i = 0; environ[i]; i++) {
+ char *eq;
+-
++
+ if (NULL != (eq = strchr(environ[i], '='))) {
+ env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
+ }
+ }
+ }
+-
++
+ /* create environment */
+ for (i = 0; i < host->bin_env->used; i++) {
+ data_string *ds = (data_string *)host->bin_env->data[i];
+-
++
+ env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
+ }
+-
++
+ for (i = 0; i < env.used; i++) {
+ /* search for PHP_FCGI_CHILDREN */
+ if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
+ }
+-
++
+ /* not found, add a default */
+ if (i == env.used) {
+ env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
+ }
+-
++
+ env.ptr[env.used] = NULL;
+-
++
+ b = buffer_init();
+ buffer_copy_string(b, "exec ");
+ buffer_append_string_buffer(b, host->bin_path);
+-
++
+ /* exec the cgi */
+ execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "execl failed for:", host->bin_path, strerror(errno));
+-
++
+ exit(errno);
+-
++
+ break;
+ }
+ case -1:
+@@ -817,32 +816,32 @@
+ break;
+ default:
+ /* father */
+-
++
+ /* wait */
+ select(0, NULL, NULL, NULL, &tv);
+-
++
+ switch (waitpid(child, &status, WNOHANG)) {
+ case 0:
+ /* child still running after timeout, good */
+ break;
+ case -1:
+ /* no PID found ? should never happen */
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "pid not found:", strerror(errno));
+ return -1;
+ default:
+ /* the child should not terminate at all */
+ if (WIFEXITED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child exited (is this a SCGI binary ?):",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child exited (is this a SCGI binary ?):",
+ WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child signaled:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child signaled:",
+ WTERMSIG(status));
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child died somehow:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child died somehow:",
+ status);
+ }
+ return -1;
+@@ -852,26 +851,26 @@
+ proc->pid = child;
+ proc->last_used = srv->cur_ts;
+ proc->is_local = 1;
+-
++
+ break;
+ }
+ #endif
+ } else {
+ proc->is_local = 0;
+ proc->pid = 0;
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "(debug) socket is already used, won't spawn:",
+ proc->socket);
+ }
+ }
+-
++
+ proc->state = PROC_STATE_RUNNING;
+ host->active_procs++;
+-
++
+ close(scgi_fd);
+-
++
+ return 0;
+ }
+
+@@ -880,89 +879,89 @@
+ plugin_data *p = p_d;
+ data_unset *du;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "scgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "scgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+ array *ca;
+-
++
+ s = malloc(sizeof(plugin_config));
+ s->exts = scgi_extensions_init();
+ s->debug = 0;
+-
++
+ cv[0].destination = s->exts;
+ cv[1].destination = &(s->debug);
+-
++
+ p->config_storage[i] = s;
+ ca = ((data_config *)srv->config_context->data[i])->value;
+-
++
+ if (0 != config_insert_values_global(srv, ca, cv)) {
+ return HANDLER_ERROR;
+ }
+-
+- /*
++
++ /*
+ * <key> = ( ... )
+ */
+-
++
+ if (NULL != (du = array_get_element(ca, "scgi.server"))) {
+ size_t j;
+ data_array *da = (data_array *)du;
+-
++
+ if (du->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "sss",
++ log_error_write(srv, __FILE__, __LINE__, "sss",
+ "unexpected type for key: ", "scgi.server", "array of strings");
+-
++
+ return HANDLER_ERROR;
+ }
+-
+-
+- /*
+- * scgi.server = ( "<ext>" => ( ... ),
++
++
++ /*
++ * scgi.server = ( "<ext>" => ( ... ),
+ * "<ext>" => ( ... ) )
+ */
+-
++
+ for (j = 0; j < da->value->used; j++) {
+ size_t n;
+ data_array *da_ext = (data_array *)da->value->data[j];
+-
++
+ if (da->value->data[j]->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "sssbs",
+- "unexpected type for key: ", "scgi.server",
++ log_error_write(srv, __FILE__, __LINE__, "sssbs",
++ "unexpected type for key: ", "scgi.server",
+ "[", da->value->data[j]->key, "](string)");
+-
++
+ return HANDLER_ERROR;
+ }
+-
+- /*
+- * da_ext->key == name of the extension
++
++ /*
++ * da_ext->key == name of the extension
+ */
+-
+- /*
+- * scgi.server = ( "<ext>" =>
+- * ( "<host>" => ( ... ),
++
++ /*
++ * scgi.server = ( "<ext>" =>
++ * ( "<host>" => ( ... ),
+ * "<host>" => ( ... )
+- * ),
++ * ),
+ * "<ext>" => ... )
+ */
+-
++
+ for (n = 0; n < da_ext->value->used; n++) {
+ data_array *da_host = (data_array *)da_ext->value->data[n];
+-
++
+ scgi_extension_host *df;
+-
+- config_values_t fcv[] = {
++
++ config_values_t fcv[] = {
+ { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+-
++
+ { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
+ { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
+ { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
+@@ -970,37 +969,37 @@
+ { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
+ { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
+ { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
+-
++
+ { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
+ { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
+-
+-
++
++
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (da_host->type != TYPE_ARRAY) {
+- log_error_write(srv, __FILE__, __LINE__, "ssSBS",
+- "unexpected type for key:",
+- "scgi.server",
++ log_error_write(srv, __FILE__, __LINE__, "ssSBS",
++ "unexpected type for key:",
++ "scgi.server",
+ "[", da_host->key, "](string)");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ df = scgi_host_init();
+-
++
+ df->check_local = 1;
+ df->min_procs = 4;
+ df->max_procs = 4;
+ df->max_load_per_proc = 1;
+ df->idle_timeout = 60;
+ df->disable_time = 60;
+-
++
+ fcv[0].destination = df->host;
+ fcv[1].destination = df->docroot;
+ fcv[2].destination = df->unixsocket;
+ fcv[3].destination = df->bin_path;
+-
++
+ fcv[4].destination = &(df->check_local);
+ fcv[5].destination = &(df->port);
+ fcv[6].destination = &(df->min_procs);
+@@ -1008,47 +1007,47 @@
+ fcv[8].destination = &(df->max_load_per_proc);
+ fcv[9].destination = &(df->idle_timeout);
+ fcv[10].destination = &(df->disable_time);
+-
++
+ fcv[11].destination = df->bin_env;
+ fcv[12].destination = df->bin_env_copy;
+-
+-
++
++
+ if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
+ return HANDLER_ERROR;
+ }
+-
+- if ((!buffer_is_empty(df->host) || df->port) &&
++
++ if ((!buffer_is_empty(df->host) || df->port) &&
+ !buffer_is_empty(df->unixsocket)) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "either host+port or socket");
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ if (!buffer_is_empty(df->unixsocket)) {
+ /* unix domain socket */
+-
++
+ if (df->unixsocket->used > UNIX_PATH_MAX - 2) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "path of the unixdomain socket is too large");
+ return HANDLER_ERROR;
+ }
+ } else {
+ /* tcp/ip */
+-
+- if (buffer_is_empty(df->host) &&
++
++ if (buffer_is_empty(df->host) &&
+ buffer_is_empty(df->bin_path)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbbbs",
+- "missing key (string):",
++ log_error_write(srv, __FILE__, __LINE__, "sbbbs",
++ "missing key (string):",
+ da->key,
+ da_ext->key,
+ da_host->key,
+ "host");
+-
++
+ return HANDLER_ERROR;
+ } else if (df->port == 0) {
+- log_error_write(srv, __FILE__, __LINE__, "sbbbs",
+- "missing key (short):",
++ log_error_write(srv, __FILE__, __LINE__, "sbbbs",
++ "missing key (short):",
+ da->key,
+ da_ext->key,
+ da_host->key,
+@@ -1056,14 +1055,14 @@
+ return HANDLER_ERROR;
+ }
+ }
+-
+- if (!buffer_is_empty(df->bin_path)) {
++
++ if (!buffer_is_empty(df->bin_path)) {
+ /* a local socket + self spawning */
+ size_t pno;
+-
++
+ if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
+ if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
+-
++
+ if (s->debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
+ "--- scgi spawning local",
+@@ -1073,7 +1072,7 @@
+ "\n\tmin-procs:", df->min_procs,
+ "\n\tmax-procs:", df->max_procs);
+ }
+-
++
+ for (pno = 0; pno < df->min_procs; pno++) {
+ scgi_proc *proc;
+
+@@ -1088,7 +1087,7 @@
+ buffer_append_string(proc->socket, "-");
+ buffer_append_long(proc->socket, pno);
+ }
+-
++
+ if (s->debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
+ "--- scgi spawning",
+@@ -1096,53 +1095,53 @@
+ "\n\tsocket", df->unixsocket,
+ "\n\tcurrent:", pno, "/", df->min_procs);
+ }
+-
++
+ if (scgi_spawn_connection(srv, p, df, proc)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "[ERROR]: spawning fcgi failed.");
+ return HANDLER_ERROR;
+ }
+-
++
+ proc->next = df->first;
+ if (df->first) df->first->prev = proc;
+-
++
+ df->first = proc;
+ }
+ } else {
+ scgi_proc *fp;
+-
++
+ fp = scgi_process_init();
+ fp->id = df->num_procs++;
+ df->max_id++;
+ df->active_procs++;
+ fp->state = PROC_STATE_RUNNING;
+-
++
+ if (buffer_is_empty(df->unixsocket)) {
+ fp->port = df->port;
+ } else {
+ buffer_copy_string_buffer(fp->socket, df->unixsocket);
+ }
+-
++
+ df->first = fp;
+-
++
+ df->min_procs = 1;
+ df->max_procs = 1;
+ }
+-
++
+ /* if extension already exists, take it */
+ scgi_extension_insert(s->exts, da_ext->key, df);
+ }
+ }
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) {
+ hctx->state = state;
+ hctx->state_timestamp = srv->cur_ts;
+-
++
+ return 0;
+ }
+
+@@ -1150,34 +1149,34 @@
+ void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
+ plugin_data *p;
+ connection *con;
+-
++
+ if (NULL == hctx) return;
+-
++
+ p = hctx->plugin_data;
+ con = hctx->remote_conn;
+-
++
+ if (con->mode != p->id) {
+ WP();
+ return;
+ }
+-
++
+ if (hctx->fd != -1) {
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+ fdevent_unregister(srv->ev, hctx->fd);
+ close(hctx->fd);
+ srv->cur_fds--;
+ }
+-
++
+ if (hctx->host && hctx->proc) {
+ hctx->host->load--;
+-
++
+ if (hctx->got_proc) {
+ /* after the connect the process gets a load */
+ hctx->proc->load--;
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sddb",
+- "release proc:",
++ "release proc:",
+ hctx->fd,
+ hctx->proc->pid, hctx->proc->socket);
+ }
+@@ -1186,87 +1185,87 @@
+ scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
+ }
+
+-
++
+ handler_ctx_free(hctx);
+- con->plugin_ctx[p->id] = NULL;
++ con->plugin_ctx[p->id] = NULL;
+ }
+
+ static int scgi_reconnect(server *srv, handler_ctx *hctx) {
+ plugin_data *p = hctx->plugin_data;
+-
+- /* child died
+- *
+- * 1.
+- *
++
++ /* child died
++ *
++ * 1.
++ *
+ * connect was ok, connection was accepted
+ * but the php accept loop checks after the accept if it should die or not.
+- *
+- * if yes we can only detect it at a write()
+- *
++ *
++ * if yes we can only detect it at a write()
++ *
+ * next step is resetting this attemp and setup a connection again
+- *
++ *
+ * if we have more then 5 reconnects for the same request, die
+- *
+- * 2.
+- *
++ *
++ * 2.
++ *
+ * we have a connection but the child died by some other reason
+- *
++ *
+ */
+-
++
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+ fdevent_unregister(srv->ev, hctx->fd);
+ close(hctx->fd);
+ srv->cur_fds--;
+-
++
+ scgi_set_state(srv, hctx, FCGI_STATE_INIT);
+-
++
+ hctx->request_id = 0;
+ hctx->reconnects++;
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sddb",
+- "release proc:",
++ "release proc:",
+ hctx->fd,
+ hctx->proc->pid, hctx->proc->socket);
+ }
+-
++
+ hctx->proc->load--;
+ scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
+-
++
+ return 0;
+ }
+
+
+ static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
+ plugin_data *p = p_d;
+-
++
+ scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+
+ static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
+ size_t len;
+-
++
+ if (!key || !val) return -1;
+-
++
+ len = key_len + val_len + 2;
+-
++
+ buffer_prepare_append(env, len);
+
+- /* include the NUL */
++ /* include the NUL */
+ memcpy(env->ptr + env->used, key, key_len + 1);
+ env->used += key_len + 1;
+ memcpy(env->ptr + env->used, val, val_len + 1);
+ env->used += val_len + 1;
+-
++
+ return 0;
+ }
+
+
+ /**
+- *
++ *
+ * returns
+ * -1 error
+ * 0 connected
+@@ -1280,24 +1279,21 @@
+ struct sockaddr_un scgi_addr_un;
+ #endif
+ socklen_t servlen;
+-
++
+ scgi_extension_host *host = hctx->host;
+ scgi_proc *proc = hctx->proc;
+ int scgi_fd = hctx->fd;
+-
++
+ memset(&scgi_addr, 0, sizeof(scgi_addr));
+-
++
+ if (!buffer_is_empty(proc->socket)) {
+ #ifdef HAVE_SYS_UN_H
+ /* use the unix domain socket */
+ scgi_addr_un.sun_family = AF_UNIX;
+ strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
+-#ifdef SUN_LEN
++
+ servlen = SUN_LEN(&scgi_addr_un);
+-#else
+- /* stevens says: */
+- servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
+-#endif
++
+ scgi_addr = (struct sockaddr *) &scgi_addr_un;
+ #else
+ return -1;
+@@ -1305,105 +1301,105 @@
+ } else {
+ scgi_addr_in.sin_family = AF_INET;
+ if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "converting IP-adress failed for", host->host,
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
++ "converting IP-adress failed for", host->host,
+ "\nBe sure to specify an IP address here");
+-
++
+ return -1;
+ }
+ scgi_addr_in.sin_port = htons(proc->port);
+ servlen = sizeof(scgi_addr_in);
+-
++
+ scgi_addr = (struct sockaddr *) &scgi_addr_in;
+ }
+-
++
+ if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
+- if (errno == EINPROGRESS ||
++ if (errno == EINPROGRESS ||
+ errno == EALREADY ||
+ errno == EINTR) {
+ if (hctx->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connect delayed, will continue later:", scgi_fd);
+ }
+-
++
+ return 1;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sdsddb",
+- "connect failed:", scgi_fd,
++ log_error_write(srv, __FILE__, __LINE__, "sdsddb",
++ "connect failed:", scgi_fd,
+ strerror(errno), errno,
+ proc->port, proc->socket);
+
+ if (errno == EAGAIN) {
+ /* this is Linux only */
+-
+- log_error_write(srv, __FILE__, __LINE__, "s",
++
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "If this happend on Linux: You have been run out of local ports. "
+ "Check the manual, section Performance how to handle this.");
+- }
+-
++ }
++
+ return -1;
+ }
+ }
+ if (hctx->conf.debug > 1) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connect succeeded: ", scgi_fd);
+ }
+
+
+-
++
+ return 0;
+ }
+
+ static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
+ size_t i;
+-
++
+ for (i = 0; i < con->request.headers->used; i++) {
+ data_string *ds;
+-
++
+ ds = (data_string *)con->request.headers->data[i];
+-
++
+ if (ds->value->used && ds->key->used) {
+ size_t j;
+ buffer_reset(srv->tmp_buf);
+-
++
+ if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
+ BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
+ srv->tmp_buf->used--;
+ }
+-
++
+ buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
+ for (j = 0; j < ds->key->used - 1; j++) {
+- srv->tmp_buf->ptr[srv->tmp_buf->used++] =
+- light_isalpha(ds->key->ptr[j]) ?
++ srv->tmp_buf->ptr[srv->tmp_buf->used++] =
++ light_isalpha(ds->key->ptr[j]) ?
+ ds->key->ptr[j] & ~32 : '_';
+ }
+ srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
+-
++
+ scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
+ }
+ }
+-
++
+ for (i = 0; i < con->environment->used; i++) {
+ data_string *ds;
+-
++
+ ds = (data_string *)con->environment->data[i];
+-
++
+ if (ds->value->used && ds->key->used) {
+ size_t j;
+ buffer_reset(srv->tmp_buf);
+-
++
+ buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
+ for (j = 0; j < ds->key->used - 1; j++) {
+- srv->tmp_buf->ptr[srv->tmp_buf->used++] =
+- isalpha((unsigned char)ds->key->ptr[j]) ?
++ srv->tmp_buf->ptr[srv->tmp_buf->used++] =
++ isalpha((unsigned char)ds->key->ptr[j]) ?
+ toupper((unsigned char)ds->key->ptr[j]) : '_';
+ }
+ srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
+-
++
+ scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
+ }
+ }
+-
++
+ return 0;
+ }
+
+@@ -1415,20 +1411,20 @@
+ char b2[INET6_ADDRSTRLEN + 1];
+ #endif
+ buffer *b;
+-
++
+ plugin_data *p = hctx->plugin_data;
+ scgi_extension_host *host= hctx->host;
+
+ connection *con = hctx->remote_conn;
+ server_socket *srv_sock = con->srv_socket;
+-
++
+ sock_addr our_addr;
+ socklen_t our_addr_len;
+-
++
+ buffer_prepare_copy(p->scgi_env, 1024);
+
+ /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
+-
++
+ /* request.content_length < SSIZE_MAX, see request.c */
+ ltostr(buf, con->request.content_length);
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
+@@ -1436,13 +1432,13 @@
+
+
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
+-
++
+ if (con->server_name->used) {
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
+ } else {
+ #ifdef HAVE_IPV6
+- s = inet_ntop(srv_sock->addr.plain.sa_family,
+- srv_sock->addr.plain.sa_family == AF_INET6 ?
++ s = inet_ntop(srv_sock->addr.plain.sa_family,
++ srv_sock->addr.plain.sa_family == AF_INET6 ?
+ (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
+ (const void *) &(srv_sock->addr.ipv4.sin_addr),
+ b2, sizeof(b2)-1);
+@@ -1451,47 +1447,47 @@
+ #endif
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
+ }
+-
++
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
+-
+- ltostr(buf,
++
++ ltostr(buf,
+ #ifdef HAVE_IPV6
+ ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
+ #else
+ ntohs(srv_sock->addr.ipv4.sin_port)
+ #endif
+ );
+-
++
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
+-
++
+ /* get the server-side of the connection to the client */
+ our_addr_len = sizeof(our_addr);
+-
++
+ if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
+ s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
+ } else {
+ s = inet_ntop_cache_get_ip(srv, &(our_addr));
+ }
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
+-
+- ltostr(buf,
++
++ ltostr(buf,
+ #ifdef HAVE_IPV6
+ ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
+ #else
+ ntohs(con->dst_addr.ipv4.sin_port)
+ #endif
+ );
+-
++
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
+-
++
+ s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
+-
++
+ if (!buffer_is_empty(con->authed_user)) {
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
+ CONST_BUF_LEN(con->authed_user));
+ }
+-
++
+
+ /*
+ * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
+@@ -1500,12 +1496,12 @@
+ */
+
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
+-
++
+ if (!buffer_is_empty(con->request.pathinfo)) {
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
+-
++
+ /* PATH_TRANSLATED is only defined if PATH_INFO is set */
+-
++
+ if (!buffer_is_empty(host->docroot)) {
+ buffer_copy_string_buffer(p->path, host->docroot);
+ } else {
+@@ -1526,19 +1522,19 @@
+ */
+
+ if (!buffer_is_empty(host->docroot)) {
+- /*
+- * rewrite SCRIPT_FILENAME
+- *
++ /*
++ * rewrite SCRIPT_FILENAME
++ *
+ */
+-
++
+ buffer_copy_string_buffer(p->path, host->docroot);
+ buffer_append_string_buffer(p->path, con->uri.path);
+-
++
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
+ } else {
+ buffer_copy_string_buffer(p->path, con->physical.path);
+-
++
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
+ }
+@@ -1551,30 +1547,30 @@
+ } else {
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
+ }
+-
++
+ s = get_http_method_name(con->request.http_method);
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
+ s = get_http_version_name(con->request.http_version);
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
+-
++
+ #ifdef USE_OPENSSL
+ if (srv_sock->is_ssl) {
+ scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
+ }
+ #endif
+-
++
+ scgi_env_add_request_headers(srv, con, p);
+
+ b = chunkqueue_get_append_buffer(hctx->wb);
+-
++
+ buffer_append_long(b, p->scgi_env->used);
+ buffer_append_string_len(b, CONST_STR_LEN(":"));
+ buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used);
+ buffer_append_string_len(b, CONST_STR_LEN(","));
+
+ hctx->wb->bytes_in += b->used - 1;
+-
++
+ if (con->request.content_length) {
+ chunkqueue *req_cq = con->request_content_queue;
+ chunk *req_c;
+@@ -1587,7 +1583,7 @@
+
+ /* we announce toWrite octects
+ * now take all the request_content chunk that we need to fill this request
+- * */
++ * */
+
+ switch (req_c->type) {
+ case FILE_CHUNK:
+@@ -1615,32 +1611,32 @@
+
+ req_c->offset += weHave;
+ req_cq->bytes_out += weHave;
+-
++
+ hctx->wb->bytes_in += weHave;
+
+ break;
+ default:
+ break;
+ }
+-
++
+ offset += weHave;
+ }
+ }
+-
++
+ #if 0
+ for (i = 0; i < hctx->write_buffer->used; i++) {
+ fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]);
+ if ((i+1) % 16 == 0) {
+ size_t j;
+ for (j = i-15; j <= i; j++) {
+- fprintf(stderr, "%c",
++ fprintf(stderr, "%c",
+ isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+ #endif
+-
++
+ return 0;
+ }
+
+@@ -1648,32 +1644,32 @@
+ char *ns;
+ const char *s;
+ int line = 0;
+-
++
+ UNUSED(srv);
+-
++
+ buffer_copy_string_buffer(p->parse_response, in);
+-
+- for (s = p->parse_response->ptr;
+- NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
++
++ for (s = p->parse_response->ptr;
++ NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
+ s = ns + (eol == EOL_RN ? 2 : 1), line++) {
+ const char *key, *value;
+ int key_len;
+ data_string *ds;
+-
++
+ ns[0] = '\0';
+-
+- if (line == 0 &&
++
++ if (line == 0 &&
+ 0 == strncmp(s, "HTTP/1.", 7)) {
+ /* non-parsed header ... we parse them anyway */
+-
++
+ if ((s[7] == '1' ||
+ s[7] == '0') &&
+ s[8] == ' ') {
+ int status;
+ /* after the space should be a status code for us */
+-
++
+ status = strtol(s+9, NULL, 10);
+-
++
+ if (con->http_status >= 100 &&
+ con->http_status < 1000) {
+ /* we expected 3 digits and didn't got them */
+@@ -1682,27 +1678,27 @@
+ }
+ }
+ } else {
+-
++
+ key = s;
+ if (NULL == (value = strchr(s, ':'))) {
+ /* we expect: "<key>: <value>\r\n" */
+ continue;
+ }
+-
++
+ key_len = value - key;
+ value += 1;
+-
++
+ /* skip LWS */
+ while (*value == ' ' || *value == '\t') value++;
+-
++
+ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
+ ds = data_response_init();
+ }
+ buffer_copy_string_len(ds->key, key, key_len);
+ buffer_copy_string(ds->value, value);
+-
++
+ array_insert_unique(con->response.headers, (data_unset *)ds);
+-
++
+ switch(key_len) {
+ case 4:
+ if (0 == strncasecmp(key, "Date", key_len)) {
+@@ -1737,13 +1733,13 @@
+ }
+ }
+ }
+-
++
+ /* CGI/1.1 rev 03 - 7.2.1.2 */
+ if ((con->parsed_response & HTTP_LOCATION) &&
+ !(con->parsed_response & HTTP_STATUS)) {
+ con->http_status = 302;
+ }
+-
++
+ return 0;
+ }
+
+@@ -1751,10 +1747,10 @@
+ static int scgi_demux_response(server *srv, handler_ctx *hctx) {
+ plugin_data *p = hctx->plugin_data;
+ connection *con = hctx->remote_conn;
+-
++
+ while(1) {
+ int n;
+-
++
+ buffer_prepare_copy(hctx->response, 1024);
+ if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
+ if (errno == EAGAIN || errno == EINTR) {
+@@ -1765,143 +1761,143 @@
+ log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
+ return -1;
+ }
+-
++
+ if (n == 0) {
+ /* read finished */
+-
++
+ con->file_finished = 1;
+-
++
+ /* send final chunk */
+ http_chunk_append_mem(srv, con, NULL, 0);
+ joblist_append(srv, con);
+-
++
+ return 1;
+ }
+-
++
+ hctx->response->ptr[n] = '\0';
+ hctx->response->used = n+1;
+-
++
+ /* split header from body */
+-
++
+ if (con->file_started == 0) {
+ char *c;
+ int in_header = 0;
+ int header_end = 0;
+ int cp, eol = EOL_UNSET;
+ size_t used = 0;
+-
++
+ buffer_append_string_buffer(hctx->response_header, hctx->response);
+-
++
+ /* nph (non-parsed headers) */
+ if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
+-
++
+ /* search for the \r\n\r\n or \n\n in the string */
+ for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
+ if (*c == ':') in_header = 1;
+ else if (*c == '\n') {
+ if (in_header == 0) {
+ /* got a response without a response header */
+-
++
+ c = NULL;
+ header_end = 1;
+ break;
+ }
+-
++
+ if (eol == EOL_UNSET) eol = EOL_N;
+-
++
+ if (*(c+1) == '\n') {
+ header_end = 1;
+ break;
+ }
+-
++
+ } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
+ if (in_header == 0) {
+ /* got a response without a response header */
+-
++
+ c = NULL;
+ header_end = 1;
+ break;
+ }
+-
++
+ if (eol == EOL_UNSET) eol = EOL_RN;
+-
++
+ if (used > 3 &&
+- *(c+2) == '\r' &&
++ *(c+2) == '\r' &&
+ *(c+3) == '\n') {
+ header_end = 1;
+ break;
+ }
+-
++
+ /* skip the \n */
+ c++;
+ cp++;
+ used--;
+ }
+ }
+-
++
+ if (header_end) {
+ if (c == NULL) {
+ /* no header, but a body */
+-
++
+ if (con->request.http_version == HTTP_VERSION_1_1) {
+ con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
+ }
+-
++
+ http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
+ joblist_append(srv, con);
+ } else {
+ size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
+ size_t blen = hctx->response_header->used - hlen - 1;
+-
++
+ /* a small hack: terminate after at the second \r */
+ hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
+ hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
+-
++
+ /* parse the response header */
+ scgi_response_parse(srv, con, p, hctx->response_header, eol);
+-
++
+ /* enable chunked-transfer-encoding */
+ if (con->request.http_version == HTTP_VERSION_1_1 &&
+ !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
+ con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
+ }
+-
++
+ if ((hctx->response->used != hlen) && blen > 0) {
+ http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
+ joblist_append(srv, con);
+ }
+ }
+-
++
+ con->file_started = 1;
+ }
+ } else {
+ http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
+ joblist_append(srv, con);
+ }
+-
+-#if 0
++
++#if 0
+ log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
+ #endif
+ }
+-
++
+ return 0;
+ }
+
+
+ int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
+ scgi_proc *p;
+-
++
+ UNUSED(srv);
+-
+- /* we have been the smallest of the current list
+- * and we want to insert the node sorted as soon
++
++ /* we have been the smallest of the current list
++ * and we want to insert the node sorted as soon
+ * possible
+ *
+- * 1 0 0 0 1 1 1
+- * | ^
++ * 1 0 0 0 1 1 1
++ * | ^
+ * | |
+ * +------+
+- *
++ *
+ */
+
+ /* nothing to sort, only one element */
+@@ -1909,9 +1905,9 @@
+
+ for (p = proc; p->next && p->next->load < proc->load; p = p->next);
+
+- /* no need to move something
++ /* no need to move something
+ *
+- * 1 2 2 2 3 3 3
++ * 1 2 2 2 3 3 3
+ * ^
+ * |
+ * +
+@@ -1930,16 +1926,16 @@
+
+ if (proc->prev) proc->prev->next = proc->next;
+ if (proc->next) proc->next->prev = proc->prev;
+-
++
+ /* proc should be right of p */
+-
++
+ proc->next = p->next;
+ proc->prev = p;
+ if (p->next) p->next->prev = proc;
+ p->next = proc;
+ #if 0
+ for(p = host->first; p; p = p->next) {
+- log_error_write(srv, __FILE__, __LINE__, "dd",
++ log_error_write(srv, __FILE__, __LINE__, "dd",
+ p->pid, p->load);
+ }
+ #else
+@@ -1951,21 +1947,21 @@
+
+ int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
+ scgi_proc *p;
+-
++
+ UNUSED(srv);
+-
+- /* we have been the smallest of the current list
+- * and we want to insert the node sorted as soon
++
++ /* we have been the smallest of the current list
++ * and we want to insert the node sorted as soon
+ * possible
+ *
+- * 0 0 0 0 1 0 1
++ * 0 0 0 0 1 0 1
+ * ^ |
+ * | |
+ * +----------+
+ *
+ *
+ * the basic is idea is:
+- * - the last active scgi process should be still
++ * - the last active scgi process should be still
+ * in ram and is not swapped out yet
+ * - processes that are not reused will be killed
+ * after some time by the trigger-handler
+@@ -1975,7 +1971,7 @@
+ * ice-cold processes are propably unused since more
+ * than 'unused-timeout', are swaped out and won't be
+ * reused in the next seconds anyway.
+- *
++ *
+ */
+
+ /* nothing to sort, only one element */
+@@ -1984,16 +1980,16 @@
+ for (p = host->first; p != proc && p->load < proc->load; p = p->next);
+
+
+- /* no need to move something
++ /* no need to move something
+ *
+- * 1 2 2 2 3 3 3
++ * 1 2 2 2 3 3 3
+ * ^
+ * |
+ * +
+ *
+ */
+ if (p == proc) return 0;
+-
++
+ /* we have to move left. If we are already the first element
+ * we are done */
+ if (host->first == proc) return 0;
+@@ -2009,9 +2005,9 @@
+ p->prev = proc;
+
+ if (proc->prev == NULL) host->first = proc;
+-#if 0
++#if 0
+ for(p = host->first; p; p = p->next) {
+- log_error_write(srv, __FILE__, __LINE__, "dd",
++ log_error_write(srv, __FILE__, __LINE__, "dd",
+ p->pid, p->load);
+ }
+ #else
+@@ -2023,41 +2019,42 @@
+
+ static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
+ scgi_proc *proc;
+-
++
+ for (proc = host->first; proc; proc = proc->next) {
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
+- "proc:",
+- host->host, proc->port,
++ log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
++ "proc:",
++ host->host, proc->port,
+ proc->socket,
+ proc->state,
+ proc->is_local,
+ proc->load,
+ proc->pid);
+ }
+-
++
+ if (0 == proc->is_local) {
+- /*
+- * external servers might get disabled
+- *
+- * enable the server again, perhaps it is back again
++ /*
++ * external servers might get disabled
++ *
++ * enable the server again, perhaps it is back again
+ */
+-
++
+ if ((proc->state == PROC_STATE_DISABLED) &&
+ (srv->cur_ts - proc->disable_ts > host->disable_time)) {
+ proc->state = PROC_STATE_RUNNING;
+ host->active_procs++;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbdb",
+- "fcgi-server re-enabled:",
+- host->host, host->port,
++
++ log_error_write(srv, __FILE__, __LINE__, "sbdb",
++ "fcgi-server re-enabled:",
++ host->host, host->port,
+ host->unixsocket);
+ }
+ } else {
+ /* the child should not terminate at all */
+ int status;
+-
++
+ if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
++#ifndef _WIN32
+ switch(waitpid(proc->pid, &status, WNOHANG)) {
+ case 0:
+ /* child is still alive */
+@@ -2067,33 +2064,34 @@
+ default:
+ if (WIFEXITED(status)) {
+ #if 0
+- log_error_write(srv, __FILE__, __LINE__, "sdsd",
++ log_error_write(srv, __FILE__, __LINE__, "sdsd",
+ "child exited, pid:", proc->pid,
+ "status:", WEXITSTATUS(status));
+ #endif
+ } else if (WIFSIGNALED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child signaled:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child signaled:",
+ WTERMSIG(status));
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child died somehow:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child died somehow:",
+ status);
+ }
+-
++
+ proc->state = PROC_STATE_DIED;
+ break;
+ }
++#endif
+ }
+-
+- /*
++
++ /*
+ * local servers might died, but we restart them
+- *
++ *
+ */
+ if (proc->state == PROC_STATE_DIED &&
+ proc->load == 0) {
+ /* restart the child */
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
+ "--- scgi spawning",
+@@ -2101,18 +2099,18 @@
+ "\n\tsocket", host->unixsocket,
+ "\n\tcurrent:", 1, "/", host->min_procs);
+ }
+-
++
+ if (scgi_spawn_connection(srv, p, host, proc)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ERROR: spawning fcgi failed.");
+ return HANDLER_ERROR;
+ }
+-
++
+ scgi_proclist_sort_down(srv, host, proc);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+
+@@ -2121,13 +2119,13 @@
+ plugin_data *p = hctx->plugin_data;
+ scgi_extension_host *host= hctx->host;
+ connection *con = hctx->remote_conn;
+-
++
+ int ret;
+
+- /* sanity check */
++ /* sanity check */
+ if (!host ||
+ ((!host->host->used || !host->port) && !host->unixsocket->used)) {
+- log_error_write(srv, __FILE__, __LINE__, "sxddd",
++ log_error_write(srv, __FILE__, __LINE__, "sxddd",
+ "write-req: error",
+ host,
+ host->host->used,
+@@ -2135,179 +2133,180 @@
+ host->unixsocket->used);
+ return HANDLER_ERROR;
+ }
+-
++
+
+ switch(hctx->state) {
+ case FCGI_STATE_INIT:
+ ret = host->unixsocket->used ? AF_UNIX : AF_INET;
+-
++
+ if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
+ if (errno == EMFILE ||
+ errno == EINTR) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "wait for fd at connection:", con->fd);
+-
++
+ return HANDLER_WAIT_FOR_FD;
+ }
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssdd",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssdd",
+ "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
+ return HANDLER_ERROR;
+ }
+ hctx->fde_ndx = -1;
+-
++
+ srv->cur_fds++;
+-
++
+ fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
+-
++
+ if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "fcntl failed: ", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ /* fall through */
+ case FCGI_STATE_CONNECT:
+ if (hctx->state == FCGI_STATE_INIT) {
+- for (hctx->proc = hctx->host->first;
+- hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
++ for (hctx->proc = hctx->host->first;
++ hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
+ hctx->proc = hctx->proc->next);
+-
++
+ /* all childs are dead */
+ if (hctx->proc == NULL) {
+ hctx->fde_ndx = -1;
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ if (hctx->proc->is_local) {
+ hctx->pid = hctx->proc->pid;
+ }
+-
++
+ switch (scgi_establish_connection(srv, hctx)) {
+ case 1:
+ scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
+-
++
+ /* connection is in progress, wait for an event and call getsockopt() below */
+-
++
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+ case -1:
+ /* if ECONNREFUSED choose another connection -> FIXME */
+ hctx->fde_ndx = -1;
+-
++
+ return HANDLER_ERROR;
+ default:
+ /* everything is ok, go on */
+ break;
+ }
+
+-
++
+ } else {
+ int socket_error;
+ socklen_t socket_error_len = sizeof(socket_error);
+-
++
+ /* try to finish the connect() */
+ if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "getsockopt failed:", strerror(errno));
+-
++
+ return HANDLER_ERROR;
+ }
+ if (socket_error != 0) {
+ if (!hctx->proc->is_local || p->conf.debug) {
+ /* local procs get restarted */
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+- "establishing connection failed:", strerror(socket_error),
++ "establishing connection failed:", strerror(socket_error),
+ "port:", hctx->proc->port);
+ }
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ /* ok, we have the connection */
+-
++
+ hctx->proc->load++;
+ hctx->proc->last_used = srv->cur_ts;
+ hctx->got_proc = 1;
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sddbdd",
+- "got proc:",
++ "got proc:",
+ hctx->fd,
+- hctx->proc->pid,
+- hctx->proc->socket,
++ hctx->proc->pid,
++ hctx->proc->socket,
+ hctx->proc->port,
+ hctx->proc->load);
+ }
+
+ /* move the proc-list entry down the list */
+ scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
+-
++
+ scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
+ /* fall through */
+ case FCGI_STATE_PREPARE_WRITE:
+ scgi_create_env(srv, hctx);
+-
++
+ scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
+-
++
+ /* fall through */
+ case FCGI_STATE_WRITE:
+- ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
++ ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
+
+ chunkqueue_remove_finished_chunks(hctx->wb);
+-
++
+ if (-1 == ret) {
+ if (errno == ENOTCONN) {
+- /* the connection got dropped after accept()
+- *
+- * this is most of the time a PHP which dies
++ /* the connection got dropped after accept()
++ *
++ * this is most of the time a PHP which dies
+ * after PHP_FCGI_MAX_REQUESTS
+- *
+- */
++ *
++ */
+ if (hctx->wb->bytes_out == 0 &&
+ hctx->reconnects < 5) {
+- usleep(10000); /* take away the load of the webserver
+- * to let the php a chance to restart
++#ifndef _WIN32
++ usleep(10000); /* take away the load of the webserver
++ * to let the php a chance to restart
+ */
+-
++#endif
+ scgi_reconnect(srv, hctx);
+-
++
+ return HANDLER_WAIT_FOR_FD;
+ }
+-
++
+ /* not reconnected ... why
+- *
++ *
+ * far@#lighttpd report this for FreeBSD
+- *
++ *
+ */
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssosd",
+ "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
+ "write-offset:", hctx->wb->bytes_out,
+ "reconnect attempts:", hctx->reconnects);
+-
++
+ return HANDLER_ERROR;
+ }
+-
++
+ if ((errno != EAGAIN) &&
+ (errno != EINTR)) {
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssd",
+ "write failed:", strerror(errno), errno);
+-
++
+ return HANDLER_ERROR;
+ } else {
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+ }
+ }
+-
++
+ if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
+ /* we don't need the out event anymore */
+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
+@@ -2315,10 +2314,10 @@
+ scgi_set_state(srv, hctx, FCGI_STATE_READ);
+ } else {
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+ }
+-
++
+ break;
+ case FCGI_STATE_READ:
+ /* waiting for a response */
+@@ -2327,67 +2326,67 @@
+ log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
+ return HANDLER_ERROR;
+ }
+-
++
+ return HANDLER_WAIT_FOR_EVENT;
+ }
+
+ SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
+ plugin_data *p = p_d;
+-
++
+ handler_ctx *hctx = con->plugin_ctx[p->id];
+ scgi_proc *proc;
+ scgi_extension_host *host;
+-
++
+ if (NULL == hctx) return HANDLER_GO_ON;
+-
++
+ /* not my job */
+ if (con->mode != p->id) return HANDLER_GO_ON;
+-
++
+ /* ok, create the request */
+ switch(scgi_write_request(srv, hctx)) {
+ case HANDLER_ERROR:
+ proc = hctx->proc;
+ host = hctx->host;
+-
+- if (proc &&
++
++ if (proc &&
+ 0 == proc->is_local &&
+ proc->state != PROC_STATE_DISABLED) {
+ /* only disable remote servers as we don't manage them*/
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
+ host->host,
+ proc->port,
+ proc->socket);
+-
++
+ /* disable this server */
+ proc->disable_ts = srv->cur_ts;
+ proc->state = PROC_STATE_DISABLED;
+ host->active_procs--;
+ }
+-
++
+ if (hctx->state == FCGI_STATE_INIT ||
+ hctx->state == FCGI_STATE_CONNECT) {
+- /* connect() or getsockopt() failed,
+- * restart the request-handling
++ /* connect() or getsockopt() failed,
++ * restart the request-handling
+ */
+ if (proc && proc->is_local) {
+
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
++ log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
+ host->host,
+ proc->port,
+ proc->socket);
+ }
+
+- /*
++ /*
+ * several hctx might reference the same proc
+- *
++ *
+ * Only one of them should mark the proc as dead all the other
+ * ones should just take a new one.
+- *
++ *
+ * If a new proc was started with the old struct this might lead
+ * the mark a perfect proc as dead otherwise
+- *
++ *
+ */
+ if (proc->state == PROC_STATE_RUNNING &&
+ hctx->pid == proc->pid) {
+@@ -2395,25 +2394,25 @@
+ }
+ }
+ scgi_restart_dead_procs(srv, p, host);
+-
++
+ scgi_connection_cleanup(srv, hctx);
+-
++
+ buffer_reset(con->physical.path);
+ con->mode = DIRECT;
+ joblist_append(srv, con);
+-
+- /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
+- * and hope that the childs will be restarted
+- *
++
++ /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
++ * and hope that the childs will be restarted
++ *
+ */
+ return HANDLER_WAIT_FOR_FD;
+ } else {
+ scgi_connection_cleanup(srv, hctx);
+-
++
+ buffer_reset(con->physical.path);
+ con->mode = DIRECT;
+ con->http_status = 503;
+-
++
+ return HANDLER_FINISHED;
+ }
+ case HANDLER_WAIT_FOR_EVENT:
+@@ -2433,23 +2432,23 @@
+ static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
+ plugin_data *p;
+ connection *con;
+-
++
+ if (NULL == hctx) return HANDLER_GO_ON;
+-
++
+ p = hctx->plugin_data;
+ con = hctx->remote_conn;
+-
++
+ if (con->mode != p->id) return HANDLER_GO_ON;
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
+- "emergency exit: scgi:",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
++ "emergency exit: scgi:",
+ "connection-fd:", con->fd,
+ "fcgi-fd:", hctx->fd);
+-
+-
+-
++
++
++
+ scgi_connection_cleanup(srv, hctx);
+-
++
+ return HANDLER_FINISHED;
+ }
+
+@@ -2459,7 +2458,7 @@
+ handler_ctx *hctx = ctx;
+ connection *con = hctx->remote_conn;
+ plugin_data *p = hctx->plugin_data;
+-
++
+ scgi_proc *proc = hctx->proc;
+ scgi_extension_host *host= hctx->host;
+
+@@ -2471,15 +2470,15 @@
+ case 1:
+ /* we are done */
+ scgi_connection_cleanup(srv, hctx);
+-
++
+ joblist_append(srv, con);
+ return HANDLER_FINISHED;
+ case -1:
+ if (proc->pid && proc->state != PROC_STATE_DIED) {
+ int status;
+-
++
+ /* only fetch the zombie if it is not already done */
+-
++#ifndef _WIN32
+ switch(waitpid(proc->pid, &status, WNOHANG)) {
+ case 0:
+ /* child is still alive */
+@@ -2489,19 +2488,19 @@
+ default:
+ /* the child should not terminate at all */
+ if (WIFEXITED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sdsd",
++ log_error_write(srv, __FILE__, __LINE__, "sdsd",
+ "child exited, pid:", proc->pid,
+ "status:", WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child signaled:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child signaled:",
+ WTERMSIG(status));
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child died somehow:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child died somehow:",
+ status);
+ }
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
+ "--- scgi spawning",
+@@ -2509,40 +2508,41 @@
+ "\n\tsocket", host->unixsocket,
+ "\n\tcurrent:", 1, "/", host->min_procs);
+ }
+-
++
+ if (scgi_spawn_connection(srv, p, host, proc)) {
+ /* child died */
+ proc->state = PROC_STATE_DIED;
+ } else {
+ scgi_proclist_sort_down(srv, host, proc);
+ }
+-
++
+ break;
+ }
++#endif
+ }
+
+ if (con->file_started == 0) {
+ /* nothing has been send out yet, try to use another child */
+-
++
+ if (hctx->wb->bytes_out == 0 &&
+ hctx->reconnects < 5) {
+ scgi_reconnect(srv, hctx);
+-
+- log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
++
++ log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
+ "response not sent, request not sent, reconnection.",
+ "connection-fd:", con->fd,
+ "fcgi-fd:", hctx->fd);
+-
++
+ return HANDLER_WAIT_FOR_FD;
+ }
+-
+- log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
++
++ log_error_write(srv, __FILE__, __LINE__, "sosdsd",
+ "response not sent, request sent:", hctx->wb->bytes_out,
+ "connection-fd:", con->fd,
+ "fcgi-fd:", hctx->fd);
+-
++
+ scgi_connection_cleanup(srv, hctx);
+-
++
+ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+ buffer_reset(con->physical.path);
+ con->http_status = 500;
+@@ -2550,76 +2550,76 @@
+ } else {
+ /* response might have been already started, kill the connection */
+ scgi_connection_cleanup(srv, hctx);
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
++
++ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
+ "response already sent out, termination connection",
+ "connection-fd:", con->fd,
+ "fcgi-fd:", hctx->fd);
+-
++
+ connection_set_state(srv, con, CON_STATE_ERROR);
+ }
+
+ /* */
+-
+-
++
++
+ joblist_append(srv, con);
+ return HANDLER_FINISHED;
+ }
+ }
+-
++
+ if (revents & FDEVENT_OUT) {
+ if (hctx->state == FCGI_STATE_CONNECT ||
+ hctx->state == FCGI_STATE_WRITE) {
+ /* we are allowed to send something out
+- *
++ *
+ * 1. in a unfinished connect() call
+ * 2. in a unfinished write() call (long POST request)
+ */
+ return mod_scgi_handle_subrequest(srv, con, p);
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "got a FDEVENT_OUT and didn't know why:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "got a FDEVENT_OUT and didn't know why:",
+ hctx->state);
+ }
+ }
+-
++
+ /* perhaps this issue is already handled */
+ if (revents & FDEVENT_HUP) {
+ if (hctx->state == FCGI_STATE_CONNECT) {
+ /* getoptsock will catch this one (right ?)
+- *
+- * if we are in connect we might get a EINPROGRESS
+- * in the first call and a FDEVENT_HUP in the
++ *
++ * if we are in connect we might get a EINPROGRESS
++ * in the first call and a FDEVENT_HUP in the
+ * second round
+- *
++ *
+ * FIXME: as it is a bit ugly.
+- *
++ *
+ */
+ return mod_scgi_handle_subrequest(srv, con, p);
+ } else if (hctx->state == FCGI_STATE_READ &&
+ hctx->proc->port == 0) {
+ /* FIXME:
+- *
++ *
+ * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
+ * even if the FCGI_FIN packet is not received yet
+ */
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
+- "error: unexpected close of scgi connection for",
++ log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
++ "error: unexpected close of scgi connection for",
+ con->uri.path,
+- "(no scgi process on host: ",
++ "(no scgi process on host: ",
+ host->host,
+- ", port: ",
++ ", port: ",
+ host->port,
+ " ?)",
+ hctx->state);
+-
++
+ connection_set_state(srv, con, CON_STATE_ERROR);
+ scgi_connection_close(srv, hctx);
+ joblist_append(srv, con);
+ }
+ } else if (revents & FDEVENT_ERR) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "fcgi: got a FDEVENT_ERR. Don't know why.");
+ /* kill all connections to the scgi process */
+
+@@ -2628,42 +2628,39 @@
+ scgi_connection_close(srv, hctx);
+ joblist_append(srv, con);
+ }
+-
++
+ return HANDLER_FINISHED;
+ }
+-#define PATCH(x) \
+- p->conf.x = s->x;
++
+ static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(exts);
+- PATCH(debug);
+-
++
++ PATCH_OPTION(exts);
++ PATCH_OPTION(debug);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
+- PATCH(exts);
++ PATCH_OPTION(exts);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
+- PATCH(debug);
++ PATCH_OPTION(debug);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+-
+
+ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
+ plugin_data *p = p_d;
+@@ -2673,30 +2670,30 @@
+ size_t k;
+ buffer *fn;
+ scgi_extension *extension = NULL;
+-
++
+ /* Possibly, we processed already this request */
+ if (con->file_started == 1) return HANDLER_GO_ON;
+-
++
+ fn = uri_path_handler ? con->uri.path : con->physical.path;
+
+ if (buffer_is_empty(fn)) return HANDLER_GO_ON;
+
+ s_len = fn->used - 1;
+-
++
+ scgi_patch_connection(srv, con, p);
+
+ /* check if extension matches */
+ for (k = 0; k < p->conf.exts->used; k++) {
+ size_t ct_len;
+-
++
+ extension = p->conf.exts->exts[k];
+-
++
+ if (extension->key->used == 0) continue;
+-
++
+ ct_len = extension->key->used - 1;
+-
++
+ if (s_len < ct_len) continue;
+-
++
+ /* check extension in the form "/scgi_pattern" */
+ if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
+ break;
+@@ -2710,17 +2707,17 @@
+ if (k == p->conf.exts->used) {
+ return HANDLER_GO_ON;
+ }
+-
++
+ /* get best server */
+ for (k = 0, ndx = -1; k < extension->used; k++) {
+ scgi_extension_host *host = extension->hosts[k];
+-
++
+ /* we should have at least one proc that can do somthing */
+ if (host->active_procs == 0) continue;
+
+ if (used == -1 || host->load < used) {
+ used = host->load;
+-
++
+ ndx = k;
+ }
+ }
+@@ -2728,12 +2725,12 @@
+ /* found a server */
+ if (ndx != -1) {
+ scgi_extension_host *host = extension->hosts[ndx];
+-
+- /*
+- * if check-local is disabled, use the uri.path handler
+- *
++
++ /*
++ * if check-local is disabled, use the uri.path handler
++ *
+ */
+-
++
+ /* init handler-context */
+ if (uri_path_handler) {
+ if (host->check_local == 0) {
+@@ -2741,7 +2738,7 @@
+ char *pathinfo;
+
+ hctx = handler_ctx_init();
+-
++
+ hctx->remote_conn = con;
+ hctx->plugin_data = p;
+ hctx->host = host;
+@@ -2749,45 +2746,45 @@
+
+ hctx->conf.exts = p->conf.exts;
+ hctx->conf.debug = p->conf.debug;
+-
++
+ con->plugin_ctx[p->id] = hctx;
+-
++
+ host->load++;
+-
++
+ con->mode = p->id;
+
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
+ }
+
+- /* the prefix is the SCRIPT_NAME,
++ /* the prefix is the SCRIPT_NAME,
+ * everthing from start to the next slash
+ * this is important for check-local = "disable"
+- *
++ *
+ * if prefix = /admin.fcgi
+- *
++ *
+ * /admin.fcgi/foo/bar
+- *
++ *
+ * SCRIPT_NAME = /admin.fcgi
+ * PATH_INFO = /foo/bar
+- *
++ *
+ * if prefix = /fcgi-bin/
+- *
++ *
+ * /fcgi-bin/foo/bar
+- *
++ *
+ * SCRIPT_NAME = /fcgi-bin/foo
+ * PATH_INFO = /bar
+- *
++ *
+ */
+-
++
+ /* the rewrite is only done for /prefix/? matches */
+ if (extension->key->ptr[0] == '/' &&
+ con->uri.path->used > extension->key->used &&
+ NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
+- /* rewrite uri.path and pathinfo */
+-
++ /* rewrite uri.path and pathinfo */
++
+ buffer_copy_string(con->request.pathinfo, pathinfo);
+-
++
+ con->uri.path->used -= con->request.pathinfo->used - 1;
+ con->uri.path->ptr[con->uri.path->used - 1] = '\0';
+ }
+@@ -2796,21 +2793,21 @@
+ } else {
+ handler_ctx *hctx;
+ hctx = handler_ctx_init();
+-
++
+ hctx->remote_conn = con;
+ hctx->plugin_data = p;
+ hctx->host = host;
+ hctx->proc = NULL;
+-
++
+ hctx->conf.exts = p->conf.exts;
+ hctx->conf.debug = p->conf.debug;
+-
++
+ con->plugin_ctx[p->id] = hctx;
+-
++
+ host->load++;
+-
++
+ con->mode = p->id;
+-
++
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
+ }
+@@ -2821,11 +2818,11 @@
+ /* no handler found */
+ buffer_reset(con->physical.path);
+ con->http_status = 500;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "no fcgi-handler found for:",
++
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "no fcgi-handler found for:",
+ fn);
+-
++
+ return HANDLER_FINISHED;
+ }
+ return HANDLER_GO_ON;
+@@ -2844,19 +2841,19 @@
+ JOBLIST_FUNC(mod_scgi_handle_joblist) {
+ plugin_data *p = p_d;
+ handler_ctx *hctx = con->plugin_ctx[p->id];
+-
++
+ if (hctx == NULL) return HANDLER_GO_ON;
+
+ if (hctx->fd != -1) {
+ switch (hctx->state) {
+ case FCGI_STATE_READ:
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
+-
++
+ break;
+ case FCGI_STATE_CONNECT:
+ case FCGI_STATE_WRITE:
+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
+-
++
+ break;
+ case FCGI_STATE_INIT:
+ /* at reconnect */
+@@ -2873,21 +2870,21 @@
+
+ static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
+ plugin_data *p = p_d;
+-
++
+ return scgi_connection_close(srv, con->plugin_ctx[p->id]);
+ }
+
+ TRIGGER_FUNC(mod_scgi_handle_trigger) {
+ plugin_data *p = p_d;
+ size_t i, j, n;
+-
+-
++
++
+ /* perhaps we should kill a connect attempt after 10-15 seconds
+- *
++ *
+ * currently we wait for the TCP timeout which is on Linux 180 seconds
+- *
+- *
+- *
++ *
++ *
++ *
+ */
+
+ /* check all childs if they are still up */
+@@ -2904,47 +2901,47 @@
+ scgi_extension *ex;
+
+ ex = exts->exts[j];
+-
++
+ for (n = 0; n < ex->used; n++) {
+-
++
+ scgi_proc *proc;
+ unsigned long sum_load = 0;
+ scgi_extension_host *host;
+-
++
+ host = ex->hosts[n];
+-
++
+ scgi_restart_dead_procs(srv, p, host);
+-
++
+ for (proc = host->first; proc; proc = proc->next) {
+ sum_load += proc->load;
+ }
+-
++
+ if (host->num_procs &&
+ host->num_procs < host->max_procs &&
+ (sum_load / host->num_procs) > host->max_load_per_proc) {
+ /* overload, spawn new child */
+ scgi_proc *fp = NULL;
+-
++
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "overload detected, spawning a new child");
+ }
+-
++
+ for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
+-
++
+ if (fp) {
+ if (fp == host->unused_procs) host->unused_procs = fp->next;
+-
++
+ if (fp->next) fp->next->prev = NULL;
+-
++
+ host->max_id++;
+ } else {
+ fp = scgi_process_init();
+ fp->id = host->max_id++;
+ }
+-
++
+ host->num_procs++;
+-
++
+ if (buffer_is_empty(host->unixsocket)) {
+ fp->port = host->port + fp->id;
+ } else {
+@@ -2952,13 +2949,13 @@
+ buffer_append_string(fp->socket, "-");
+ buffer_append_long(fp->socket, fp->id);
+ }
+-
++
+ if (scgi_spawn_connection(srv, p, host, fp)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ERROR: spawning fcgi failed.");
+ return HANDLER_ERROR;
+ }
+-
++
+ fp->prev = NULL;
+ fp->next = host->first;
+ if (host->first) {
+@@ -2966,56 +2963,57 @@
+ }
+ host->first = fp;
+ }
+-
++
+ for (proc = host->first; proc; proc = proc->next) {
+ if (proc->load != 0) break;
+ if (host->num_procs <= host->min_procs) break;
+ if (proc->pid == 0) continue;
+-
++#ifndef _WIN32
+ if (srv->cur_ts - proc->last_used > host->idle_timeout) {
+ /* a proc is idling for a long time now,
+ * terminated it */
+-
++
+ if (p->conf.debug) {
+- log_error_write(srv, __FILE__, __LINE__, "ssbsd",
+- "idle-timeout reached, terminating child:",
+- "socket:", proc->socket,
++ log_error_write(srv, __FILE__, __LINE__, "ssbsd",
++ "idle-timeout reached, terminating child:",
++ "socket:", proc->socket,
+ "pid", proc->pid);
+ }
+-
+-
++
++
+ if (proc->next) proc->next->prev = proc->prev;
+ if (proc->prev) proc->prev->next = proc->next;
+-
++
+ if (proc->prev == NULL) host->first = proc->next;
+-
++
+ proc->prev = NULL;
+ proc->next = host->unused_procs;
+-
++
+ if (host->unused_procs) host->unused_procs->prev = proc;
+ host->unused_procs = proc;
+-
++
+ kill(proc->pid, SIGTERM);
+-
++
+ proc->state = PROC_STATE_KILLED;
+-
+- log_error_write(srv, __FILE__, __LINE__, "ssbsd",
+- "killed:",
+- "socket:", proc->socket,
++
++ log_error_write(srv, __FILE__, __LINE__, "ssbsd",
++ "killed:",
++ "socket:", proc->socket,
+ "pid", proc->pid);
+-
++
+ host->num_procs--;
+-
++
+ /* proc is now in unused, let the next second handle the next process */
+ break;
+- }
++ }
++#endif
+ }
+-
++
+ for (proc = host->unused_procs; proc; proc = proc->next) {
+ int status;
+-
++
+ if (proc->pid == 0) continue;
+-
++#ifndef _WIN32
+ switch (waitpid(proc->pid, &status, WNOHANG)) {
+ case 0:
+ /* child still running after timeout, good */
+@@ -3023,10 +3021,10 @@
+ case -1:
+ if (errno != EINTR) {
+ /* no PID found ? should never happen */
+- log_error_write(srv, __FILE__, __LINE__, "sddss",
++ log_error_write(srv, __FILE__, __LINE__, "sddss",
+ "pid ", proc->pid, proc->state,
+ "not found:", strerror(errno));
+-
++
+ #if 0
+ if (errno == ECHILD) {
+ /* someone else has cleaned up for us */
+@@ -3040,25 +3038,26 @@
+ /* the child should not terminate at all */
+ if (WIFEXITED(status)) {
+ if (proc->state != PROC_STATE_KILLED) {
+- log_error_write(srv, __FILE__, __LINE__, "sdb",
+- "child exited:",
++ log_error_write(srv, __FILE__, __LINE__, "sdb",
++ "child exited:",
+ WEXITSTATUS(status), proc->socket);
+ }
+ } else if (WIFSIGNALED(status)) {
+ if (WTERMSIG(status) != SIGTERM) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child signaled:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child signaled:",
+ WTERMSIG(status));
+ }
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "child died somehow:",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "child died somehow:",
+ status);
+ }
+ proc->pid = 0;
+ proc->state = PROC_STATE_UNSET;
+ host->max_id--;
+ }
++#endif
+ }
+ }
+ }
+@@ -3082,8 +3081,8 @@
+ p->handle_subrequest = mod_scgi_handle_subrequest;
+ p->handle_joblist = mod_scgi_handle_joblist;
+ p->handle_trigger = mod_scgi_handle_trigger;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_secure_download.c lighttpd-1.4.12/src/mod_secure_download.c
+--- lighttpd-1.4.11/src/mod_secure_download.c 2005-12-14 14:37:29.000000000 +0200
++++ lighttpd-1.4.12/src/mod_secure_download.c 2006-07-11 21:23:39.000000000 +0300
+@@ -25,7 +25,7 @@
+ #ifdef USE_OPENSSL
+ #define IN const
+ #else
+-#define IN
++#define IN
+ #endif
+ #define OUT
+
+@@ -36,28 +36,28 @@
+ buffer *doc_root;
+ buffer *secret;
+ buffer *uri_prefix;
+-
++
+ unsigned short timeout;
+ } plugin_config;
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *md5;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_secdownload_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->md5 = buffer_init();
+-
++
+ return p;
+ }
+
+@@ -65,27 +65,27 @@
+ FREE_FUNC(mod_secdownload_free) {
+ plugin_data *p = p_d;
+ UNUSED(srv);
+-
++
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ buffer_free(s->secret);
+ buffer_free(s->doc_root);
+ buffer_free(s->uri_prefix);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->md5);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -94,107 +94,103 @@
+ SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "secdownload.secret", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "secdownload.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { "secdownload.timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->secret = buffer_init();
+ s->doc_root = buffer_init();
+ s->uri_prefix = buffer_init();
+ s->timeout = 60;
+-
++
+ cv[0].destination = s->secret;
+ cv[1].destination = s->doc_root;
+ cv[2].destination = s->uri_prefix;
+ cv[3].destination = &(s->timeout);
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ /**
+ * checks if the supplied string is a MD5 string
+- *
++ *
+ * @param str a possible MD5 string
+ * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
+ */
+
+ int is_hex_len(const char *str, size_t len) {
+ size_t i;
+-
++
+ if (NULL == str) return 0;
+-
++
+ for (i = 0; i < len && *str; i++, str++) {
+ /* illegal characters */
+ if (!((*str >= '0' && *str <= '9') ||
+ (*str >= 'a' && *str <= 'f') ||
+- (*str >= 'A' && *str <= 'F'))
++ (*str >= 'A' && *str <= 'F'))
+ ) {
+ return 0;
+ }
+ }
+-
++
+ return i == len;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(secret);
+- PATCH(doc_root);
+- PATCH(uri_prefix);
+- PATCH(timeout);
+-
++
++ PATCH_OPTION(secret);
++ PATCH_OPTION(doc_root);
++ PATCH_OPTION(uri_prefix);
++ PATCH_OPTION(timeout);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
+- PATCH(secret);
++ PATCH_OPTION(secret);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
+- PATCH(doc_root);
++ PATCH_OPTION(doc_root);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
+- PATCH(uri_prefix);
++ PATCH_OPTION(uri_prefix);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
+- PATCH(timeout);
++ PATCH_OPTION(timeout);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+-
+
+ URIHANDLER_FUNC(mod_secdownload_uri_handler) {
+ plugin_data *p = p_d;
+@@ -203,88 +199,88 @@
+ const char *rel_uri, *ts_str, *md5_str;
+ time_t ts = 0;
+ size_t i;
+-
++
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_secdownload_patch_connection(srv, con, p);
+
+ if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
+-
++
+ if (buffer_is_empty(p->conf.secret)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "secdownload.secret has to be set");
+ return HANDLER_ERROR;
+ }
+-
++
+ if (buffer_is_empty(p->conf.doc_root)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "secdownload.document-root has to be set");
+ return HANDLER_ERROR;
+ }
+-
+- /*
++
++ /*
+ * /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
+ */
+-
++
+ if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
+-
++
+ md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
+-
++
+ if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
+ if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
+-
++
+ ts_str = md5_str + 32 + 1;
+-
++
+ if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
+ if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
+-
++
+ for (i = 0; i < 8; i++) {
+ ts = (ts << 4) + hex2int(*(ts_str + i));
+ }
+-
++
+ /* timed-out */
+- if (srv->cur_ts - ts > p->conf.timeout ||
++ if (srv->cur_ts - ts > p->conf.timeout ||
+ srv->cur_ts - ts < -p->conf.timeout) {
+ con->http_status = 408;
+-
++
+ return HANDLER_FINISHED;
+ }
+-
++
+ rel_uri = ts_str + 8;
+-
+- /* checking MD5
+- *
++
++ /* checking MD5
++ *
+ * <secret><rel-path><timestamp-hex>
+ */
+-
++
+ buffer_copy_string_buffer(p->md5, p->conf.secret);
+ buffer_append_string(p->md5, rel_uri);
+ buffer_append_string_len(p->md5, ts_str, 8);
+-
++
+ MD5_Init(&Md5Ctx);
+ MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
+ MD5_Final(HA1, &Md5Ctx);
+-
++
+ buffer_copy_string_hex(p->md5, (char *)HA1, 16);
+-
++
+ if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
+ con->http_status = 403;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sss",
++
++ log_error_write(srv, __FILE__, __LINE__, "sss",
+ "md5 invalid:",
+ md5_str, p->md5->ptr);
+-
++
+ return HANDLER_FINISHED;
+ }
+-
++
+ /* starting with the last / we should have relative-path to the docroot
+ */
+-
++
+ buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
+ buffer_copy_string(con->physical.rel_path, rel_uri);
+ buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
+ buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -293,13 +289,13 @@
+ int mod_secdownload_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("secdownload");
+-
++
+ p->init = mod_secdownload_init;
+ p->handle_physical = mod_secdownload_uri_handler;
+ p->set_defaults = mod_secdownload_set_defaults;
+ p->cleanup = mod_secdownload_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_setenv.c lighttpd-1.4.12/src/mod_setenv.c
+--- lighttpd-1.4.11/src/mod_setenv.c 2006-01-14 20:33:12.000000000 +0200
++++ lighttpd-1.4.12/src/mod_setenv.c 2006-07-11 21:23:40.000000000 +0300
+@@ -18,25 +18,25 @@
+ typedef struct {
+ array *request_header;
+ array *response_header;
+-
++
+ array *environment;
+ } plugin_config;
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ static handler_ctx * handler_ctx_init() {
+ handler_ctx * hctx;
+-
++
+ hctx = calloc(1, sizeof(*hctx));
+-
++
+ hctx->handled = 0;
+-
++
+ return hctx;
+ }
+
+@@ -48,36 +48,36 @@
+ /* init the plugin data */
+ INIT_FUNC(mod_setenv_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_setenv_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ array_free(s->request_header);
+ array_free(s->response_header);
+ array_free(s->environment);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -86,86 +86,83 @@
+ SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->request_header = array_init();
+ s->response_header = array_init();
+ s->environment = array_init();
+-
++
+ cv[0].destination = s->request_header;
+ cv[1].destination = s->response_header;
+ cv[2].destination = s->environment;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(request_header);
+- PATCH(response_header);
+- PATCH(environment);
+-
++
++ PATCH_OPTION(request_header);
++ PATCH_OPTION(response_header);
++ PATCH_OPTION(environment);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
+- PATCH(request_header);
++ PATCH_OPTION(request_header);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
+- PATCH(response_header);
++ PATCH_OPTION(response_header);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
- PATCH(environment);
+ PATCH_OPTION(environment);
}
}
}
-
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_setenv_uri_handler) {
+ plugin_data *p = p_d;
+ size_t k;
+ handler_ctx *hctx;
+-
++
+ if (con->plugin_ctx[p->id]) {
+ hctx = con->plugin_ctx[p->id];
+ } else {
+ hctx = handler_ctx_init();
+-
++
+ con->plugin_ctx[p->id] = hctx;
+ }
+
+@@ -180,52 +177,52 @@
+ for (k = 0; k < p->conf.request_header->used; k++) {
+ data_string *ds = (data_string *)p->conf.request_header->data[k];
+ data_string *ds_dst;
+-
++
+ if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
+ ds_dst = data_string_init();
+ }
+-
++
+ buffer_copy_string_buffer(ds_dst->key, ds->key);
+ buffer_copy_string_buffer(ds_dst->value, ds->value);
+-
++
+ array_insert_unique(con->request.headers, (data_unset *)ds_dst);
+ }
+-
++
+ for (k = 0; k < p->conf.environment->used; k++) {
+ data_string *ds = (data_string *)p->conf.environment->data[k];
+ data_string *ds_dst;
+-
++
+ if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
+ ds_dst = data_string_init();
+ }
+-
++
+ buffer_copy_string_buffer(ds_dst->key, ds->key);
+ buffer_copy_string_buffer(ds_dst->value, ds->value);
+-
++
+ array_insert_unique(con->environment, (data_unset *)ds_dst);
+ }
+-
++
+ for (k = 0; k < p->conf.response_header->used; k++) {
+ data_string *ds = (data_string *)p->conf.response_header->data[k];
+-
++
+ response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+
+ REQUESTDONE_FUNC(mod_setenv_reset) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+-
++
+ if (con->plugin_ctx[p->id]) {
+ handler_ctx_free(con->plugin_ctx[p->id]);
+ con->plugin_ctx[p->id] = NULL;
+ }
+
+- return HANDLER_GO_ON;
++ return HANDLER_GO_ON;
+ }
+
+ /* this function is called at dlopen() time and inits the callbacks */
+@@ -233,15 +230,15 @@
+ int mod_setenv_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("setenv");
+-
++
+ p->init = mod_setenv_init;
+ p->handle_uri_clean = mod_setenv_uri_handler;
+ p->set_defaults = mod_setenv_set_defaults;
+ p->cleanup = mod_setenv_free;
+-
++
+ p->handle_request_done = mod_setenv_reset;
+
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_simple_vhost.c lighttpd-1.4.12/src/mod_simple_vhost.c
+--- lighttpd-1.4.11/src/mod_simple_vhost.c 2005-11-18 15:16:13.000000000 +0200
++++ lighttpd-1.4.12/src/mod_simple_vhost.c 2006-07-11 21:23:40.000000000 +0300
+@@ -10,6 +10,8 @@
+
+ #include "plugin.h"
+
++#include "sys-files.h"
++
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+@@ -18,7 +20,7 @@
+ buffer *server_root;
+ buffer *default_host;
+ buffer *document_root;
+-
++
+ buffer *docroot_cache_key;
+ buffer *docroot_cache_value;
+ buffer *docroot_cache_servername;
+@@ -28,138 +30,138 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *doc_root;
+-
++
+ plugin_config **config_storage;
+- plugin_config conf;
++ plugin_config conf;
+ } plugin_data;
+
+ INIT_FUNC(mod_simple_vhost_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->doc_root = buffer_init();
+-
++
+ return p;
+ }
+
+ FREE_FUNC(mod_simple_vhost_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ buffer_free(s->document_root);
+ buffer_free(s->default_host);
+ buffer_free(s->server_root);
+-
++
+ buffer_free(s->docroot_cache_key);
+ buffer_free(s->docroot_cache_value);
+ buffer_free(s->docroot_cache_servername);
+-
++
+ free(s);
+ }
+-
++
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->doc_root);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "simple-vhost.server-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { "simple-vhost.default-host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { "simple-vhost.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { "simple-vhost.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+-
++
+ s->server_root = buffer_init();
+ s->default_host = buffer_init();
+ s->document_root = buffer_init();
+-
++
+ s->docroot_cache_key = buffer_init();
+ s->docroot_cache_value = buffer_init();
+ s->docroot_cache_servername = buffer_init();
+
+ s->debug = 0;
+-
++
+ cv[0].destination = s->server_root;
+ cv[1].destination = s->default_host;
+ cv[2].destination = s->document_root;
+ cv[3].destination = &(s->debug);
+-
+-
++
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
+ stat_cache_entry *sce = NULL;
+-
++
+ buffer_prepare_copy(out, 128);
+
+ if (p->conf.server_root->used) {
+ buffer_copy_string_buffer(out, p->conf.server_root);
+-
++
+ if (host->used) {
+ /* a hostname has to start with a alpha-numerical character
+ * and must not contain a slash "/"
+ */
+ char *dp;
+-
+- BUFFER_APPEND_SLASH(out);
+-
++
++ PATHNAME_APPEND_SLASH(out);
++
+ if (NULL == (dp = strchr(host->ptr, ':'))) {
+ buffer_append_string_buffer(out, host);
+ } else {
+ buffer_append_string_len(out, host->ptr, dp - host->ptr);
+ }
+ }
+- BUFFER_APPEND_SLASH(out);
+-
++ PATHNAME_APPEND_SLASH(out);
++
+ if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
+ buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
+ } else {
+ buffer_append_string_buffer(out, p->conf.document_root);
+- BUFFER_APPEND_SLASH(out);
++ PATHNAME_APPEND_SLASH(out);
+ }
+ } else {
+ buffer_copy_string_buffer(out, con->conf.document_root);
+- BUFFER_APPEND_SLASH(out);
++ PATHNAME_APPEND_SLASH(out);
+ }
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+@@ -169,57 +171,53 @@
+ } else if (!S_ISDIR(sce->st.st_mode)) {
+ return -1;
+ }
+-
++
+ return 0;
+ }
+
+-
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(server_root);
+- PATCH(default_host);
+- PATCH(document_root);
+-
+- PATCH(docroot_cache_key);
+- PATCH(docroot_cache_value);
+- PATCH(docroot_cache_servername);
+
+- PATCH(debug);
+-
++ PATCH_OPTION(server_root);
++ PATCH_OPTION(default_host);
++ PATCH_OPTION(document_root);
++
++ PATCH_OPTION(docroot_cache_key);
++ PATCH_OPTION(docroot_cache_value);
++ PATCH_OPTION(docroot_cache_servername);
++
++ PATCH_OPTION(debug);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
+- PATCH(server_root);
+- PATCH(docroot_cache_key);
+- PATCH(docroot_cache_value);
+- PATCH(docroot_cache_servername);
++ PATCH_OPTION(server_root);
++ PATCH_OPTION(docroot_cache_key);
++ PATCH_OPTION(docroot_cache_value);
++ PATCH_OPTION(docroot_cache_servername);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
+- PATCH(default_host);
++ PATCH_OPTION(default_host);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
+- PATCH(document_root);
++ PATCH_OPTION(document_root);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
+- PATCH(debug);
++ PATCH_OPTION(debug);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
+ plugin_data *p = p_data;
+@@ -227,12 +225,12 @@
+ /*
+ * cache the last successfull translation from hostname (authority) to docroot
+ * - this saves us a stat() call
+- *
++ *
+ */
+-
++
+ mod_simple_vhost_patch_connection(srv, con, p);
+-
+- if (p->conf.docroot_cache_key->used &&
++
++ if (p->conf.docroot_cache_key->used &&
+ con->uri.authority->used &&
+ buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
+ /* cache hit */
+@@ -243,8 +241,8 @@
+ if ((con->uri.authority->used == 0) ||
+ build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
+ /* not found, fallback the default-host */
+- if (build_doc_root(srv, con, p,
+- p->doc_root,
++ if (build_doc_root(srv, con, p,
++ p->doc_root,
+ p->conf.default_host)) {
+ return HANDLER_GO_ON;
+ } else {
+@@ -253,15 +251,15 @@
+ } else {
+ buffer_copy_string_buffer(con->server_name, con->uri.authority);
+ }
+-
++
+ /* copy to cache */
+ buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority);
+ buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root);
+ buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
+-
++
+ buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -269,13 +267,13 @@
+ int mod_simple_vhost_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("simple_vhost");
+-
++
+ p->init = mod_simple_vhost_init;
+ p->set_defaults = mod_simple_vhost_set_defaults;
+ p->handle_docroot = mod_simple_vhost_docroot;
+ p->cleanup = mod_simple_vhost_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_skeleton.c lighttpd-1.4.12/src/mod_skeleton.c
+--- lighttpd-1.4.11/src/mod_skeleton.c 2005-10-02 18:30:51.000000000 +0300
++++ lighttpd-1.4.12/src/mod_skeleton.c 2006-07-11 21:23:40.000000000 +0300
+@@ -14,13 +14,13 @@
+
+ /**
+ * this is a skeleton for a lighttpd plugin
+- *
++ *
+ * just replaces every occurance of 'skeleton' by your plugin name
+- *
++ *
+ * e.g. in vim:
+- *
++ *
+ * :%s/skeleton/myhandler/
+- *
++ *
+ */
+
+
+@@ -33,12 +33,12 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *match_buf;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ typedef struct {
+@@ -47,36 +47,36 @@
+
+ static handler_ctx * handler_ctx_init() {
+ handler_ctx * hctx;
+-
++
+ hctx = calloc(1, sizeof(*hctx));
+-
++
+ return hctx;
+ }
+
+ static void handler_ctx_free(handler_ctx *hctx) {
+-
++
+ free(hctx);
+ }
+
+ /* init the plugin data */
+ INIT_FUNC(mod_skeleton_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->match_buf = buffer_init();
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_skeleton_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+
+@@ -84,18 +84,18 @@
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+-
++
+ array_free(s->match);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->match_buf);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -104,91 +104,88 @@
+ SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "skeleton.array", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->match = array_init();
+-
++
+ cv[0].destination = s->match;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(match);
+-
++
++ PATCH_OPTION(match);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
+- PATCH(match);
++ PATCH_OPTION(match);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_skeleton_uri_handler) {
+ plugin_data *p = p_d;
+ int s_len;
+ size_t k, i;
+-
++
+ UNUSED(srv);
+
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_skeleton_patch_connection(srv, con, p);
+
+ s_len = con->uri.path->used - 1;
+-
++
+ for (k = 0; k < p->conf.match->used; k++) {
+ data_string *ds = (data_string *)p->conf.match->data[k];
+ int ct_len = ds->value->used - 1;
+-
++
+ if (ct_len > s_len) continue;
+ if (ds->value->used == 0) continue;
+-
++
+ if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
+ con->http_status = 403;
+-
++
+ return HANDLER_FINISHED;
+ }
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+@@ -198,13 +195,13 @@
+ int mod_skeleton_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("skeleton");
+-
++
+ p->init = mod_skeleton_init;
+ p->handle_uri_clean = mod_skeleton_uri_handler;
+ p->set_defaults = mod_skeleton_set_defaults;
+ p->cleanup = mod_skeleton_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_sql_vhost_core.c lighttpd-1.4.12/src/mod_sql_vhost_core.c
+--- lighttpd-1.4.11/src/mod_sql_vhost_core.c 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/src/mod_sql_vhost_core.c 2006-07-11 21:23:40.000000000 +0300
+@@ -0,0 +1,209 @@
++#include <stdio.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <string.h>
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include "plugin.h"
++#include "log.h"
++
++#include "stat_cache.h"
++
++#include "mod_sql_vhost_core.h"
++
++#define plugin_data mod_sql_vhost_core_plugin_data
++#define plugin_config mod_sql_vhost_core_plugin_config
++
++/* init the plugin data */
++INIT_FUNC(mod_sql_vhost_core_init) {
++ plugin_data *p;
++
++ p = calloc(1, sizeof(*p));
++
++ p->docroot = buffer_init();
++ p->host = buffer_init();
++
++ return p;
++}
++
++/* cleanup the plugin data */
++SERVER_FUNC(mod_sql_vhost_core_cleanup) {
++ plugin_data *p = p_d;
++
++ UNUSED(srv);
++
++ if (!p) return HANDLER_GO_ON;
++
++ if (p->config_storage) {
++ size_t i;
++ for (i = 0; i < srv->config_context->used; i++) {
++ plugin_config *s = p->config_storage[i];
++
++ if (!s) continue;
++
++ buffer_free(s->db);
++ buffer_free(s->user);
++ buffer_free(s->pass);
++ buffer_free(s->sock);
++ buffer_free(s->backend);
++
++ free(s);
++ }
++ free(p->config_storage);
++ }
++ buffer_free(p->docroot);
++ buffer_free(p->host);
++
++ free(p);
++
++ return HANDLER_GO_ON;
++}
++
++/* set configuration values */
++SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
++ plugin_data *p = p_d;
++
++ size_t i = 0;
++
++ config_values_t cv[] = {
++ { "sql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
++ { "sql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
++ { "sql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
++ { "sql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
++ { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
++ { "sql-vhost.hostname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
++ { "sql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
++ { "sql-vhost.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
++
++ /* backward compat */
++ { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
++ { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
++ { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
++ { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
++ { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
++ { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
++ { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
++
++ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
++ };
++
++ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
++
++ for (i = 0; i < srv->config_context->used; i++) {
++ plugin_config *s;
++
++ s = calloc(1, sizeof(plugin_config));
++ s->db = buffer_init();
++ s->user = buffer_init();
++ s->pass = buffer_init();
++ s->sock = buffer_init();
++ s->hostname = buffer_init();
++ s->backend = buffer_init();
++ s->port = 0; /* default port for mysql */
++ s->select_vhost = buffer_init();
++ s->backend_data = NULL;
++
++ cv[0].destination = s->db;
++ cv[1].destination = s->user;
++ cv[2].destination = s->pass;
++ cv[3].destination = s->sock;
++ cv[4].destination = s->select_vhost;
++ cv[5].destination = s->hostname;
++ cv[6].destination = &(s->port);
++ cv[7].destination = s->backend;
++
++ /* backend compat */
++ cv[8].destination = cv[0].destination;
++ cv[9].destination = cv[1].destination;
++ cv[10].destination = cv[2].destination;
++ cv[11].destination = cv[3].destination;
++ cv[12].destination = cv[4].destination;
++ cv[13].destination = cv[5].destination;
++ cv[14].destination = cv[6].destination;
++
++ p->config_storage[i] = s;
++
++ if (config_insert_values_global(srv,
++ ((data_config *)srv->config_context->data[i])->value,
++ cv)) return HANDLER_ERROR;
++
++ /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
++ }
++
++ return HANDLER_GO_ON;
++}
++
++static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
++ size_t i;
++ plugin_config *s = p->config_storage[0];
++
++ PATCH_OPTION(backend_data);
++ PATCH_OPTION(get_vhost);
++
++ /* skip the first, the global context */
++ for (i = 1; i < srv->config_context->used; i++) {
++ data_config *dc = (data_config *)srv->config_context->data[i];
++ s = p->config_storage[i];
++
++ /* condition didn't match */
++ if (!config_check_cond(srv, con, dc)) continue;
++
++ if (s->backend_data) {
++ PATCH_OPTION(backend_data);
++ PATCH_OPTION(get_vhost);
++ }
++ }
++
++ return 0;
++}
++
++/* handle document root request */
++CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
++ plugin_data *p = p_d;
++ stat_cache_entry *sce;
++
++ /* no host specified? */
++ if (!con->uri.authority->used) return HANDLER_GO_ON;
++
++ mod_sql_vhost_core_patch_connection(srv, con, p);
++
++ /* do we have backend ? */
++ if (!p->conf.get_vhost) return HANDLER_GO_ON;
++
++ /* ask the backend for the data */
++ if (0 != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
++ return HANDLER_GO_ON;
++ }
++
++ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
++ log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->docroot);
++ return HANDLER_GO_ON;
++ }
++ if (!S_ISDIR(sce->st.st_mode)) {
++ log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->docroot);
++ return HANDLER_GO_ON;
++ }
++
++ buffer_copy_string_buffer(con->server_name, p->host);
++ buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
++
++ return HANDLER_GO_ON;
++}
++
++/* this function is called at dlopen() time and inits the callbacks */
++int mod_sql_vhost_core_plugin_init(plugin *p) {
++ p->version = LIGHTTPD_VERSION_ID;
++ p->name = buffer_init_string("mod_sql_vhost_core");
++
++ p->init = mod_sql_vhost_core_init;
++ p->cleanup = mod_sql_vhost_core_cleanup;
++
++ p->set_defaults = mod_sql_vhost_core_set_defaults;
++ p->handle_docroot = mod_sql_vhost_core_handle_docroot;
++
++ return 0;
++}
++
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_sql_vhost_core.h lighttpd-1.4.12/src/mod_sql_vhost_core.h
+--- lighttpd-1.4.11/src/mod_sql_vhost_core.h 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/src/mod_sql_vhost_core.h 2006-07-11 21:23:40.000000000 +0300
+@@ -0,0 +1,49 @@
++#ifndef _MOD_SQL_VHOST_CORE_H_
++#define _MOD_SQL_VHOST_CORE_H_
++
++#include "buffer.h"
++#include "plugin.h"
++
++#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
++ (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
++
++#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
++
++#define SQLVHOST_BACKEND_GETVHOST(name) \
++ SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
++
++#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
++ SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
++
++typedef struct {
++ buffer *db;
++ buffer *user;
++ buffer *pass;
++ buffer *sock;
++
++ buffer *hostname;
++ unsigned short port;
++
++ buffer *backend;
++ void *backend_data;
++
++ buffer *select_vhost;
++
++ SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
++} mod_sql_vhost_core_plugin_config;
++
++/* global plugin data */
++typedef struct {
++ PLUGIN_DATA;
++
++ buffer *docroot;
++ buffer *host;
++
++ mod_sql_vhost_core_plugin_config **config_storage;
++
++ mod_sql_vhost_core_plugin_config conf;
++} mod_sql_vhost_core_plugin_data;
++
++
++
++#endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi.c lighttpd-1.4.12/src/mod_ssi.c
+--- lighttpd-1.4.11/src/mod_ssi.c 2006-03-04 17:09:48.000000000 +0200
++++ lighttpd-1.4.12/src/mod_ssi.c 2006-07-11 21:23:40.000000000 +0300
+@@ -6,7 +6,6 @@
+ #include <string.h>
+ #include <errno.h>
+ #include <time.h>
+-#include <unistd.h>
+
+ #include "base.h"
+ #include "log.h"
+@@ -23,6 +22,8 @@
+ #include "inet_ntop_cache.h"
+
+ #include "sys-socket.h"
++#include "sys-strings.h"
++#include "sys-files.h"
+
+ #ifdef HAVE_PWD_H
+ #include <pwd.h>
+@@ -39,15 +40,15 @@
+ /* init the plugin data */
+ INIT_FUNC(mod_ssi_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->timefmt = buffer_init();
+ p->stat_fn = buffer_init();
+-
++
+ p->ssi_vars = array_init();
+ p->ssi_cgi_env = array_init();
+-
++
+ return p;
+ }
+
+@@ -55,21 +56,21 @@
+ FREE_FUNC(mod_ssi_free) {
+ plugin_data *p = p_d;
+ UNUSED(srv);
+-
++
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ array_free(s->ssi_extension);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ array_free(p->ssi_vars);
+ array_free(p->ssi_cgi_env);
+ #ifdef HAVE_PCRE_H
+@@ -77,9 +78,9 @@
+ #endif
+ buffer_free(p->timefmt);
+ buffer_free(p->stat_fn);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -92,36 +93,36 @@
+ const char *errptr;
+ int erroff;
+ #endif
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "ssi.extension", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->ssi_extension = array_init();
+-
++
+ cv[0].destination = s->ssi_extension;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ #ifdef HAVE_PCRE_H
+ /* allow 2 params */
+ if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
+ log_error_write(srv, __FILE__, __LINE__, "sds",
+- "ssi: pcre ",
++ "ssi: pcre ",
+ erroff, errptr);
+ return HANDLER_ERROR;
+ }
+@@ -130,52 +131,52 @@
+ "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
+ return HANDLER_ERROR;
+ #endif
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ int ssi_env_add(array *env, const char *key, const char *val) {
+ data_string *ds;
+-
++
+ if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
+ ds = data_string_init();
+ }
+ buffer_copy_string(ds->key, key);
+ buffer_copy_string(ds->value, val);
+-
++
+ array_insert_unique(env, (data_unset *)ds);
+-
++
+ return 0;
+ }
+
+ /**
+ *
+ * the next two functions are take from fcgi.c
+- *
++ *
+ */
+
+ static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
+ size_t i;
+-
++
+ for (i = 0; i < con->request.headers->used; i++) {
+ data_string *ds;
+-
++
+ ds = (data_string *)con->request.headers->data[i];
+-
++
+ if (ds->value->used && ds->key->used) {
+ size_t j;
+ buffer_reset(srv->tmp_buf);
+-
++
+ /* don't forward the Authorization: Header */
+ if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
+ continue;
+ }
+-
++
+ if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
+ buffer_copy_string(srv->tmp_buf, "HTTP_");
+ srv->tmp_buf->used--;
+ }
+-
++
+ buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
+ for (j = 0; j < ds->key->used - 1; j++) {
+ char c = '_';
+@@ -189,33 +190,33 @@
+ srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
+ }
+ srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
+-
++
+ ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
+ }
+ }
+-
++
+ return 0;
+ }
+
+ static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
+ char buf[32];
+-
++
+ server_socket *srv_sock = con->srv_socket;
+-
++
+ #ifdef HAVE_IPV6
+ char b2[INET6_ADDRSTRLEN + 1];
+ #endif
+
+ #define CONST_STRING(x) \
+ x
+-
++
+ array_reset(p->ssi_cgi_env);
+-
++
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
+ #ifdef HAVE_IPV6
+- inet_ntop(srv_sock->addr.plain.sa_family,
+- srv_sock->addr.plain.sa_family == AF_INET6 ?
++ inet_ntop(srv_sock->addr.plain.sa_family,
++ srv_sock->addr.plain.sa_family == AF_INET6 ?
+ (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
+ (const void *) &(srv_sock->addr.ipv4.sin_addr),
+ b2, sizeof(b2)-1)
+@@ -224,28 +225,28 @@
+ #endif
+ );
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
+-
+- ltostr(buf,
++
++ ltostr(buf,
+ #ifdef HAVE_IPV6
+ ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
+ #else
+ ntohs(srv_sock->addr.ipv4.sin_port)
+ #endif
+ );
+-
++
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
+-
++
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
+ inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
+-
++
+ if (con->authed_user->used) {
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
+ con->authed_user->ptr);
+ }
+-
++
+ if (con->request.content_length > 0) {
+ /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
+-
++
+ /* request.content_length < SSIZE_MAX, see request.c */
+ ltostr(buf, con->request.content_length);
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
+@@ -271,30 +272,30 @@
+ if (con->request.pathinfo->used) {
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
+ }
+-
++
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
+-
++
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
+ ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
+-
++
+ ssi_env_add_request_headers(srv, con, p);
+-
++
+ return 0;
+ }
+
+-static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
++static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
+ const char **l, size_t n) {
+ size_t i, ssicmd = 0;
+ char buf[255];
+ buffer *b = NULL;
+-
+- struct {
++
++ struct {
+ const char *var;
+- enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
++ enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
+ SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
+ SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
+ } ssicmds[] = {
+@@ -310,27 +311,27 @@
+ { "endif", SSI_ENDIF },
+ { "else", SSI_ELSE },
+ { "exec", SSI_EXEC },
+-
++
+ { NULL, SSI_UNSET }
+ };
+-
++
+ for (i = 0; ssicmds[i].var; i++) {
+ if (0 == strcmp(l[1], ssicmds[i].var)) {
+ ssicmd = ssicmds[i].type;
+ break;
+ }
+ }
+-
++
+ switch(ssicmd) {
+ case SSI_ECHO: {
+ /* echo */
+ int var = 0, enc = 0;
+ const char *var_val = NULL;
+ stat_cache_entry *sce = NULL;
+-
+- struct {
++
++ struct {
+ const char *var;
+- enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
++ enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
+ SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
+ } echovars[] = {
+ { "DATE_GMT", SSI_ECHO_DATE_GMT },
+@@ -339,27 +340,27 @@
+ { "DOCUMENT_URI", SSI_ECHO_DOCUMENT_URI },
+ { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
+ { "USER_NAME", SSI_ECHO_USER_NAME },
+-
++
+ { NULL, SSI_ECHO_UNSET }
+ };
+-
+- struct {
++
++ struct {
+ const char *var;
+ enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
+ } encvars[] = {
+ { "url", SSI_ENC_URL },
+ { "none", SSI_ENC_NONE },
+ { "entity", SSI_ENC_ENTITY },
+-
++
+ { NULL, SSI_ENC_UNSET }
+ };
+-
++
+ for (i = 2; i < n; i += 2) {
+ if (0 == strcmp(l[i], "var")) {
+ int j;
+-
++
+ var_val = l[i+1];
+-
++
+ for (j = 0; echovars[j].var; j++) {
+ if (0 == strcmp(l[i+1], echovars[j].var)) {
+ var = echovars[j].type;
+@@ -368,7 +369,7 @@
+ }
+ } else if (0 == strcmp(l[i], "encoding")) {
+ int j;
+-
++
+ for (j = 0; encvars[j].var; j++) {
+ if (0 == strcmp(l[i+1], encvars[j].var)) {
+ enc = encvars[j].type;
+@@ -377,26 +378,26 @@
+ }
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: unknow attribute for ",
++ "ssi: unknow attribute for ",
+ l[1], l[i]);
+ }
+ }
+-
++
+ if (p->if_is_false) break;
+-
++
+ if (!var_val) {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: ",
++ "ssi: ",
+ l[1], "var is missing");
+ break;
+ }
+
+ stat_cache_get_entry(srv, con, con->physical.path, &sce);
+-
++
+ switch(var) {
+ case SSI_ECHO_USER_NAME: {
+ struct passwd *pw;
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+ #ifdef HAVE_PWD_H
+ if (NULL == (pw = getpwuid(sce->st.st_uid))) {
+@@ -411,7 +412,7 @@
+ }
+ case SSI_ECHO_LAST_MODIFIED: {
+ time_t t = sce->st.st_mtime;
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+ if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
+ buffer_copy_string(b, "(none)");
+@@ -422,7 +423,7 @@
+ }
+ case SSI_ECHO_DATE_LOCAL: {
+ time_t t = time(NULL);
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+ if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
+ buffer_copy_string(b, "(none)");
+@@ -433,7 +434,7 @@
+ }
+ case SSI_ECHO_DATE_GMT: {
+ time_t t = time(NULL);
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+ if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
+ buffer_copy_string(b, "(none)");
+@@ -444,7 +445,7 @@
+ }
+ case SSI_ECHO_DOCUMENT_NAME: {
+ char *sl;
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+ if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
+ buffer_copy_string_buffer(b, con->physical.path);
+@@ -461,15 +462,15 @@
+ default: {
+ data_string *ds;
+ /* check if it is a cgi-var */
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+-
++
+ if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
+ buffer_copy_string_buffer(b, ds->value);
+ } else {
+ buffer_copy_string(b, "(none)");
+ }
+-
++
+ break;
+ }
+ }
+@@ -481,7 +482,7 @@
+ const char * file_path = NULL, *virt_path = NULL;
+ struct stat st;
+ char *sl;
+-
++
+ for (i = 2; i < n; i += 2) {
+ if (0 == strcmp(l[i], "file")) {
+ file_path = l[i+1];
+@@ -489,28 +490,28 @@
+ virt_path = l[i+1];
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: unknow attribute for ",
++ "ssi: unknow attribute for ",
+ l[1], l[i]);
+ }
+ }
+-
++
+ if (!file_path && !virt_path) {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: ",
++ "ssi: ",
+ l[1], "file or virtual are missing");
+ break;
+ }
+-
++
+ if (file_path && virt_path) {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: ",
++ "ssi: ",
+ l[1], "only one of file and virtual is allowed here");
+ break;
+ }
+-
+-
++
++
+ if (p->if_is_false) break;
+-
++
+ if (file_path) {
+ /* current doc-root */
+ if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
+@@ -519,46 +520,46 @@
+ buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
+ }
+
+- buffer_copy_string(srv->tmp_buf, file_path);
++ buffer_copy_string(srv->tmp_buf, file_path);
+ buffer_urldecode_path(srv->tmp_buf);
+- buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
+- buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
++ buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
++ buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
+ } else {
+ /* virtual */
+-
++
+ if (virt_path[0] == '/') {
+ buffer_copy_string(p->stat_fn, virt_path);
+ } else {
+ /* there is always a / */
+ sl = strrchr(con->uri.path->ptr, '/');
+-
++
+ buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
+ buffer_append_string(p->stat_fn, virt_path);
+ }
+-
++
+ buffer_urldecode_path(p->stat_fn);
+ buffer_path_simplify(srv->tmp_buf, p->stat_fn);
+-
++
+ /* we have an uri */
+-
++
+ buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
+ buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
+ }
+-
++
+ if (0 == stat(p->stat_fn->ptr, &st)) {
+ time_t t = st.st_mtime;
+-
++
+ switch (ssicmd) {
+ case SSI_FSIZE:
+ b = chunkqueue_get_append_buffer(con->write_queue);
+ if (p->sizefmt) {
+ int j = 0;
+ const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
+-
++
+ off_t s = st.st_size;
+-
++
+ for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
+-
++
+ buffer_copy_off_t(b, s);
+ buffer_append_string(b, abr[j]);
+ } else {
+@@ -579,7 +580,7 @@
+ }
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "ssi: stating failed ",
++ "ssi: stating failed ",
+ p->stat_fn, strerror(errno));
+ }
+ break;
+@@ -593,33 +594,33 @@
+ val = l[i+1];
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: unknow attribute for ",
++ "ssi: unknow attribute for ",
+ l[1], l[i]);
+ }
+ }
+-
++
+ if (p->if_is_false) break;
+-
++
+ if (key && val) {
+ data_string *ds;
+-
++
+ if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
+ ds = data_string_init();
+ }
+ buffer_copy_string(ds->key, key);
+ buffer_copy_string(ds->value, val);
+-
++
+ array_insert_unique(p->ssi_vars, (data_unset *)ds);
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: var and value have to be set in",
++ "ssi: var and value have to be set in",
+ l[0], l[1]);
+ }
+ break;
+ }
+- case SSI_CONFIG:
++ case SSI_CONFIG:
+ if (p->if_is_false) break;
+-
++
+ for (i = 2; i < n; i += 2) {
+ if (0 == strcmp(l[i], "timefmt")) {
+ buffer_copy_string(p->timefmt, l[i+1]);
+@@ -632,63 +633,65 @@
+ log_error_write(srv, __FILE__, __LINE__, "sssss",
+ "ssi: unknow value for attribute '",
+ l[i],
+- "' for ",
++ "' for ",
+ l[1], l[i+1]);
+ }
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: unknow attribute for ",
++ "ssi: unknow attribute for ",
+ l[1], l[i]);
+ }
+ }
+ break;
+ case SSI_PRINTENV:
+ if (p->if_is_false) break;
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+ buffer_copy_string(b, "<pre>");
+ for (i = 0; i < p->ssi_vars->used; i++) {
+ data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
+-
++
+ buffer_append_string_buffer(b, ds->key);
+ buffer_append_string(b, ": ");
+ buffer_append_string_buffer(b, ds->value);
+ buffer_append_string(b, "<br />");
+-
++
+ }
+ buffer_append_string(b, "</pre>");
+-
++
+ break;
+ case SSI_EXEC: {
++#ifndef _WIN32
++
+ const char *cmd = NULL;
+ pid_t pid;
+ int from_exec_fds[2];
+-
++
+ for (i = 2; i < n; i += 2) {
+ if (0 == strcmp(l[i], "cmd")) {
+ cmd = l[i+1];
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: unknow attribute for ",
++ "ssi: unknow attribute for ",
+ l[1], l[i]);
+ }
+ }
+-
++
+ if (p->if_is_false) break;
+-
++
+ /* create a return pipe and send output to the html-page
+- *
+- * as exec is assumed evil it is implemented synchronously
++ *
++ * as exec is assumed evil it is implemented synchronously
+ */
+-
++
+ if (!cmd) break;
+-#ifdef HAVE_FORK
++
+ if (pipe(from_exec_fds)) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "pipe failed: ", strerror(errno));
+ return -1;
+ }
+-
++
+ /* fork, execve */
+ switch (pid = fork()) {
+ case 0: {
+@@ -698,14 +701,14 @@
+ close(from_exec_fds[1]);
+ /* not needed */
+ close(from_exec_fds[0]);
+-
++
+ /* close stdin */
+ close(STDIN_FILENO);
+-
++
+ execl("/bin/sh", "sh", "-c", cmd, NULL);
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
+-
++
+ /* */
+ SEGFAULT();
+ break;
+@@ -718,9 +721,9 @@
+ /* father */
+ int status;
+ ssize_t r;
+-
++
+ close(from_exec_fds[1]);
+-
++
+ /* wait for the client to end */
+ if (-1 == waitpid(pid, &status, 0)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
+@@ -730,7 +733,7 @@
+
+ while(1) {
+ if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "unexpected end-of-file (perhaps the ssi-exec process died)");
+ return -1;
+ }
+@@ -738,10 +741,10 @@
+ if (toread > 0) {
+ b = chunkqueue_get_append_buffer(con->write_queue);
+
+- buffer_prepare_copy(b, toread + 1);
++ buffer_prepare_copy(b, toread + 1);
+
+ if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
+- /* read failed */
++ /* read failed */
+ break;
+ } else {
+ b->used = r;
+@@ -755,59 +758,58 @@
+ log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
+ }
+ close(from_exec_fds[0]);
+-
++
+ break;
+ }
+ }
+ #else
+-
+ return -1;
+ #endif
+-
++
+ break;
+ }
+ case SSI_IF: {
+ const char *expr = NULL;
+-
++
+ for (i = 2; i < n; i += 2) {
+ if (0 == strcmp(l[i], "expr")) {
+ expr = l[i+1];
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: unknow attribute for ",
++ "ssi: unknow attribute for ",
+ l[1], l[i]);
+ }
+ }
+-
++
+ if (!expr) {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: ",
++ "ssi: ",
+ l[1], "expr missing");
+ break;
+ }
+-
++
+ if ((!p->if_is_false) &&
+- ((p->if_is_false_level == 0) ||
++ ((p->if_is_false_level == 0) ||
+ (p->if_level < p->if_is_false_level))) {
+ switch (ssi_eval_expr(srv, con, p, expr)) {
+ case -1:
+- case 0:
+- p->if_is_false = 1;
++ case 0:
++ p->if_is_false = 1;
+ p->if_is_false_level = p->if_level;
+ break;
+- case 1:
+- p->if_is_false = 0;
++ case 1:
++ p->if_is_false = 0;
+ break;
+ }
+ }
+-
++
+ p->if_level++;
+-
++
+ break;
+ }
+ case SSI_ELSE:
+ p->if_level--;
+-
++
+ if (p->if_is_false) {
+ if ((p->if_level == p->if_is_false_level) &&
+ (p->if_is_false_endif == 0)) {
+@@ -815,11 +817,11 @@
+ }
+ } else {
+ p->if_is_false = 1;
+-
++
+ p->if_is_false_level = p->if_level;
+ }
+ p->if_level++;
+-
++
+ break;
+ case SSI_ELIF: {
+ const char *expr = NULL;
+@@ -828,52 +830,52 @@
+ expr = l[i+1];
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: unknow attribute for ",
++ "ssi: unknow attribute for ",
+ l[1], l[i]);
+ }
+ }
+-
++
+ if (!expr) {
+ log_error_write(srv, __FILE__, __LINE__, "sss",
+- "ssi: ",
++ "ssi: ",
+ l[1], "expr missing");
+ break;
+ }
+-
++
+ p->if_level--;
+-
++
+ if (p->if_level == p->if_is_false_level) {
+ if ((p->if_is_false) &&
+ (p->if_is_false_endif == 0)) {
+ switch (ssi_eval_expr(srv, con, p, expr)) {
+ case -1:
+- case 0:
+- p->if_is_false = 1;
++ case 0:
++ p->if_is_false = 1;
+ p->if_is_false_level = p->if_level;
+ break;
+- case 1:
+- p->if_is_false = 0;
++ case 1:
++ p->if_is_false = 0;
+ break;
+ }
+ } else {
+- p->if_is_false = 1;
++ p->if_is_false = 1;
+ p->if_is_false_level = p->if_level;
+ p->if_is_false_endif = 1;
+ }
+ }
+-
++
+ p->if_level++;
+-
++
+ break;
+ }
+ case SSI_ENDIF:
+ p->if_level--;
+-
++
+ if (p->if_level == p->if_is_false_level) {
+ p->if_is_false = 0;
+ p->if_is_false_endif = 0;
+ }
+-
++
+ break;
+ default:
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+@@ -881,41 +883,41 @@
+ l[1]);
+ break;
+ }
+-
++
+ return 0;
+-
++
+ }
+
+ static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
+ stream s;
+ #ifdef HAVE_PCRE_H
+ int i, n;
+-
++
+ #define N 10
+ int ovec[N * 3];
+ #endif
+-
++
+ /* get a stream to the file */
+-
++
+ array_reset(p->ssi_vars);
+ array_reset(p->ssi_cgi_env);
+ buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z");
+ p->sizefmt = 0;
+ build_ssi_cgi_vars(srv, con, p);
+ p->if_is_false = 0;
+-
++
+ if (-1 == stream_open(&s, con->physical.path)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "stream-open: ", con->physical.path);
+ return -1;
+ }
+-
+-
++
++
+ /**
+- * <!--#element attribute=value attribute=value ... -->
+- *
++ * <!--#element attribute=value attribute=value ... -->
++ *
+ * config DONE
+- * errmsg -- missing
++ * errmsg -- missing
+ * sizefmt DONE
+ * timefmt DONE
+ * echo DONE
+@@ -937,13 +939,13 @@
+ * set DONE
+ * var DONE
+ * value DONE
+- *
++ *
+ * if DONE
+ * elif DONE
+ * else DONE
+ * endif DONE
+- *
+- *
++ *
++ *
+ * expressions
+ * AND, OR DONE
+ * comp DONE
+@@ -951,118 +953,115 @@
+ * $... DONE
+ * '...' DONE
+ * ( ... ) DONE
+- *
+- *
+- *
++ *
++ *
++ *
+ * ** all DONE **
+- * DATE_GMT
+- * The current date in Greenwich Mean Time.
+- * DATE_LOCAL
+- * The current date in the local time zone.
+- * DOCUMENT_NAME
+- * The filename (excluding directories) of the document requested by the user.
+- * DOCUMENT_URI
+- * 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.
+- * LAST_MODIFIED
+- * The last modification date of the document requested by the user.
+- * USER_NAME
++ * DATE_GMT
++ * The current date in Greenwich Mean Time.
++ * DATE_LOCAL
++ * The current date in the local time zone.
++ * DOCUMENT_NAME
++ * The filename (excluding directories) of the document requested by the user.
++ * DOCUMENT_URI
++ * 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.
++ * LAST_MODIFIED
++ * The last modification date of the document requested by the user.
++ * USER_NAME
+ * Contains the owner of the file which included it.
+- *
++ *
+ */
+-#ifdef HAVE_PCRE_H
++#ifdef HAVE_PCRE_H
+ for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
+ const char **l;
+ /* take everything from last offset to current match pos */
+-
++
+ if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
+-
++
+ pcre_get_substring_list(s.start, ovec, n, &l);
+ process_ssi_stmt(srv, con, p, l, n);
+ pcre_free_substring_list(l);
+ }
+-
++
+ switch(n) {
+ case PCRE_ERROR_NOMATCH:
+ /* copy everything/the rest */
+ chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
+-
++
+ break;
+ default:
+ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "execution error while matching: ", n);
+ break;
+ }
+-#endif
+-
+-
++#endif
++
++
+ stream_close(&s);
+-
++
+ con->file_started = 1;
+ con->file_finished = 1;
+-
++
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
+-
++
+ /* reset physical.path */
+ buffer_reset(con->physical.path);
+-
++
+ return 0;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(ssi_extension);
+-
++
++ PATCH_OPTION(ssi_extension);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
+- PATCH(ssi_extension);
++ PATCH_OPTION(ssi_extension);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_ssi_physical_path) {
+ plugin_data *p = p_d;
+ size_t k;
+-
++
+ if (con->physical.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_ssi_patch_connection(srv, con, p);
+-
++
+ for (k = 0; k < p->conf.ssi_extension->used; k++) {
+ data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
+-
++
+ if (ds->value->used == 0) continue;
+-
++
+ if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
+ /* handle ssi-request */
+-
++
+ if (mod_ssi_handle_request(srv, con, p)) {
+ /* on error */
+ con->http_status = 500;
+ }
+-
++
+ return HANDLER_FINISHED;
+ }
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+@@ -1072,13 +1071,13 @@
+ int mod_ssi_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("ssi");
+-
++
+ p->init = mod_ssi_init;
+ p->handle_subrequest_start = mod_ssi_physical_path;
+ p->set_defaults = mod_ssi_set_defaults;
+ p->cleanup = mod_ssi_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi.h lighttpd-1.4.12/src/mod_ssi.h
+--- lighttpd-1.4.11/src/mod_ssi.h 2005-08-11 01:26:39.000000000 +0300
++++ lighttpd-1.4.12/src/mod_ssi.h 2006-07-11 21:23:40.000000000 +0300
+@@ -19,23 +19,23 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
+-#ifdef HAVE_PCRE_H
++
++#ifdef HAVE_PCRE_H
+ pcre *ssi_regex;
+-#endif
++#endif
+ buffer *timefmt;
+ int sizefmt;
+-
++
+ buffer *stat_fn;
+-
++
+ array *ssi_vars;
+ array *ssi_cgi_env;
+-
++
+ int if_level, if_is_false_level, if_is_false, if_is_false_endif;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi_expr.c lighttpd-1.4.12/src/mod_ssi_expr.c
+--- lighttpd-1.4.11/src/mod_ssi_expr.c 2005-08-11 01:26:48.000000000 +0300
++++ lighttpd-1.4.12/src/mod_ssi_expr.c 2006-07-11 21:23:40.000000000 +0300
+@@ -11,9 +11,9 @@
+ const char *input;
+ size_t offset;
+ size_t size;
+-
++
+ int line_pos;
+-
++
+ int in_key;
+ int in_brace;
+ int in_cond;
+@@ -21,15 +21,15 @@
+
+ ssi_val_t *ssi_val_init() {
+ ssi_val_t *s;
+-
++
+ s = calloc(1, sizeof(*s));
+-
++
+ return s;
+ }
+
+ void ssi_val_free(ssi_val_t *s) {
+ if (s->str) buffer_free(s->str);
+-
++
+ free(s);
+ }
+
+@@ -45,175 +45,175 @@
+ ssi_tokenizer_t *t, int *token_id, buffer *token) {
+ int tid = 0;
+ size_t i;
+-
++
+ UNUSED(con);
+
+ for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
+ char c = t->input[t->offset];
+ data_string *ds;
+-
++
+ switch (c) {
+- case '=':
++ case '=':
+ tid = TK_EQ;
+-
++
+ t->offset++;
+ t->line_pos++;
+-
++
+ buffer_copy_string(token, "(=)");
+-
++
+ break;
+ case '>':
+ if (t->input[t->offset + 1] == '=') {
+ t->offset += 2;
+ t->line_pos += 2;
+-
++
+ tid = TK_GE;
+-
++
+ buffer_copy_string(token, "(>=)");
+ } else {
+ t->offset += 1;
+ t->line_pos += 1;
+-
++
+ tid = TK_GT;
+-
++
+ buffer_copy_string(token, "(>)");
+ }
+-
++
+ break;
+ case '<':
+ if (t->input[t->offset + 1] == '=') {
+ t->offset += 2;
+ t->line_pos += 2;
+-
++
+ tid = TK_LE;
+-
++
+ buffer_copy_string(token, "(<=)");
+ } else {
+ t->offset += 1;
+ t->line_pos += 1;
+-
++
+ tid = TK_LT;
+-
++
+ buffer_copy_string(token, "(<)");
+ }
+-
++
+ break;
+-
++
+ case '!':
+ if (t->input[t->offset + 1] == '=') {
+ t->offset += 2;
+ t->line_pos += 2;
+-
++
+ tid = TK_NE;
+-
++
+ buffer_copy_string(token, "(!=)");
+ } else {
+ t->offset += 1;
+ t->line_pos += 1;
+-
++
+ tid = TK_NOT;
+-
++
+ buffer_copy_string(token, "(!)");
+ }
+-
++
+ break;
+ case '&':
+ if (t->input[t->offset + 1] == '&') {
+ t->offset += 2;
+ t->line_pos += 2;
+-
++
+ tid = TK_AND;
+-
++
+ buffer_copy_string(token, "(&&)");
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "pos:", t->line_pos,
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "pos:", t->line_pos,
+ "missing second &");
+ return -1;
+ }
+-
++
+ break;
+ case '|':
+ if (t->input[t->offset + 1] == '|') {
+ t->offset += 2;
+ t->line_pos += 2;
+-
++
+ tid = TK_OR;
+-
++
+ buffer_copy_string(token, "(||)");
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "pos:", t->line_pos,
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "pos:", t->line_pos,
+ "missing second |");
+ return -1;
+ }
+-
++
+ break;
+ case '\t':
+ case ' ':
+ t->offset++;
+ t->line_pos++;
+ break;
+-
++
+ case '\'':
+ /* search for the terminating " */
+ for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
+-
++
+ if (t->input[t->offset + i]) {
+ tid = TK_VALUE;
+-
++
+ buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
+-
++
+ t->offset += i + 1;
+ t->line_pos += i + 1;
+ } else {
+ /* ERROR */
+-
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "pos:", t->line_pos,
++
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "pos:", t->line_pos,
+ "missing closing quote");
+-
++
+ return -1;
+ }
+-
++
+ break;
+ case '(':
+ t->offset++;
+ t->in_brace++;
+-
++
+ tid = TK_LPARAN;
+-
++
+ buffer_copy_string(token, "(");
+ break;
+ case ')':
+ t->offset++;
+ t->in_brace--;
+-
++
+ tid = TK_RPARAN;
+-
++
+ buffer_copy_string(token, ")");
+ break;
+ case '$':
+ if (t->input[t->offset + 1] == '{') {
+ for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
+-
++
+ if (t->input[t->offset + i] != '}') {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "pos:", t->line_pos,
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "pos:", t->line_pos,
+ "missing closing quote");
+-
++
+ return -1;
+ }
+-
++
+ buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
+ } else {
+ for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_'; i++);
+-
++
+ buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
+ }
+-
++
+ tid = TK_VALUE;
+-
++
+ if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
+ buffer_copy_string_buffer(token, ds->value);
+ } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
+@@ -221,16 +221,16 @@
+ } else {
+ buffer_copy_string(token, "");
+ }
+-
++
+ t->offset += i;
+ t->line_pos += i;
+-
++
+ break;
+ default:
+ for (i = 0; isgraph(t->input[t->offset + i]); i++) {
+ char d = t->input[t->offset + i];
+ switch(d) {
+- case ' ':
++ case ' ':
+ case '\t':
+ case ')':
+ case '(':
+@@ -244,25 +244,25 @@
+ break;
+ }
+ }
+-
++
+ tid = TK_VALUE;
+-
++
+ buffer_copy_string_len(token, t->input + t->offset, i);
+-
++
+ t->offset += i;
+ t->line_pos += i;
+-
++
+ break;
+ }
+ }
+-
++
+ if (tid) {
+ *token_id = tid;
+-
++
+ return 1;
+ } else if (t->offset < t->size) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "pos:", t->line_pos,
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "pos:", t->line_pos,
+ "foobar");
+ }
+ return 0;
+@@ -275,50 +275,50 @@
+ buffer *token;
+ ssi_ctx_t context;
+ int ret;
+-
++
+ t.input = expr;
+ t.offset = 0;
+ t.size = strlen(expr);
+ t.line_pos = 1;
+-
++
+ t.in_key = 1;
+ t.in_brace = 0;
+ t.in_cond = 0;
+-
++
+ context.ok = 1;
+ context.srv = srv;
+-
++
+ /* default context */
+-
++
+ pParser = ssiexprparserAlloc( malloc );
+ token = buffer_init();
+ while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
+ ssiexprparser(pParser, token_id, token, &context);
+-
++
+ token = buffer_init();
+ }
+ ssiexprparser(pParser, 0, token, &context);
+ ssiexprparserFree(pParser, free );
+-
++
+ buffer_free(token);
+-
++
+ if (ret == -1) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "expr parser failed");
+ return -1;
+ }
+-
++
+ if (context.ok == 0) {
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "pos:", t.line_pos,
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "pos:", t.line_pos,
+ "parser failed somehow near here");
+ return -1;
+ }
+ #if 0
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
++ log_error_write(srv, __FILE__, __LINE__, "ssd",
+ "expr: ",
+ expr,
+ context.val.bo);
+-#endif
++#endif
+ return context.val.bo;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi_expr.h lighttpd-1.4.12/src/mod_ssi_expr.h
+--- lighttpd-1.4.11/src/mod_ssi_expr.h 2005-08-11 01:26:48.000000000 +0300
++++ lighttpd-1.4.12/src/mod_ssi_expr.h 2006-07-11 21:23:40.000000000 +0300
+@@ -5,16 +5,16 @@
+
+ typedef struct {
+ enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
+-
++
+ buffer *str;
+ int bo;
+ } ssi_val_t;
+
+ typedef struct {
+ int ok;
+-
++
+ ssi_val_t val;
+-
++
+ void *srv;
+ } ssi_ctx_t;
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi_exprparser.c lighttpd-1.4.12/src/mod_ssi_exprparser.c
+--- lighttpd-1.4.11/src/mod_ssi_exprparser.c 2005-10-03 00:40:25.000000000 +0300
++++ lighttpd-1.4.12/src/mod_ssi_exprparser.c 2006-07-11 21:49:18.000000000 +0300
+@@ -18,10 +18,10 @@
+ /* Next is all token values, in a form suitable for use by makeheaders.
+ ** This section will be null unless lemon is run with the -m switch.
+ */
+-/*
++/*
+ ** These constants (all generated automatically by the parser generator)
+ ** specify the various kinds of tokens (terminals) that the parser
+-** understands.
++** understands.
+ **
+ ** Each symbol here is a terminal symbol in the grammar.
+ */
+@@ -38,7 +38,7 @@
+ ** and nonterminals. "int" is used otherwise.
+ ** YYNOCODE is a number of type YYCODETYPE which corresponds
+ ** to no legal terminal or nonterminal number. This
+-** number is used to fill in empty slots of the hash
++** number is used to fill in empty slots of the hash
+ ** table.
+ ** YYFALLBACK If defined, this indicates that one or more tokens
+ ** have fall-back values which should be used if the
+@@ -47,7 +47,7 @@
+ ** and nonterminal numbers. "unsigned char" is
+ ** used if there are fewer than 250 rules and
+ ** states combined. "int" is used otherwise.
+-** ssiexprparserTOKENTYPE is the data type used for minor tokens given
++** ssiexprparserTOKENTYPE is the data type used for minor tokens given
+ ** directly to the parser from the tokenizer.
+ ** YYMINORTYPE is the data type used for all minor tokens.
+ ** This is typically a union of many types, one of
+@@ -91,7 +91,7 @@
+ /* Next are that tables used to determine what action to take based on the
+ ** current state and lookahead token. These tables are used to implement
+ ** functions that take a state number and lookahead value and return an
+-** action integer.
++** action integer.
+ **
+ ** Suppose the action integer is N. Then the action is determined as
+ ** follows
+@@ -116,7 +116,7 @@
+ ** If the index value yy_shift_ofst[S]+X is out of range or if the value
+ ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
+ ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
+-** and that yy_default[S] should be used instead.
++** and that yy_default[S] should be used instead.
+ **
+ ** The formula above is for computing the action when the lookahead is
+ ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
+@@ -168,7 +168,7 @@
+
+ /* The next table maps tokens into fallback tokens. If a construct
+ ** like the following:
+-**
++**
+ ** %fallback ID X Y Z.
+ **
+ ** appears in the grammer, then ID becomes a fallback token for X, Y,
+@@ -219,10 +219,10 @@
+ #endif /* NDEBUG */
+
+ #ifndef NDEBUG
+-/*
++/*
+ ** Turn parser tracing on by giving a stream to which to write the trace
+ ** and a prompt to preface each trace message. Tracing is turned off
+-** by making either argument NULL
++** by making either argument NULL
+ **
+ ** Inputs:
+ ** <ul>
+@@ -247,7 +247,7 @@
+ #ifndef NDEBUG
+ /* For tracing shifts, the names of all terminals and nonterminals
+ ** are required. The following table supplies these names */
+-static const char *yyTokenName[] = {
++static const char *yyTokenName[] = {
+ "$", "AND", "OR", "EQ",
+ "NE", "GT", "GE", "LT",
+ "LE", "NOT", "LPARAN", "RPARAN",
+@@ -295,7 +295,7 @@
+ #endif
+ }
+
+-/*
++/*
+ ** This function allocates a new parser.
+ ** The only argument is a pointer to a function which works like
+ ** malloc.
+@@ -326,7 +326,7 @@
+ /* Here is inserted the actions which take place when a
+ ** terminal or non-terminal is destroyed. This can happen
+ ** when the symbol is popped from the stack during a
+- ** reduce or during error processing or when a parser is
++ ** reduce or during error processing or when a parser is
+ ** being destroyed before it is finished parsing.
+ **
+ ** Note: during a reduce, the only symbols destroyed are those
+@@ -379,7 +379,7 @@
+ return yymajor;
+ }
+
+-/*
++/*
+ ** Deallocate and destroy a parser. Destructors are all called for
+ ** all stack elements before shutting the parser down.
+ **
+@@ -415,7 +415,7 @@
+ ){
+ int i;
+ int stateno = pParser->yystack[pParser->yyidx].stateno;
+-
++
+ /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
+ i = yy_shift_ofst[stateno];
+ if( i==YY_SHIFT_USE_DFLT ){
+@@ -459,7 +459,7 @@
+ ){
+ int i;
+ int stateno = pParser->yystack[pParser->yyidx].stateno;
+-
++
+ i = yy_reduce_ofst[stateno];
+ if( i==YY_REDUCE_USE_DFLT ){
+ return yy_default[stateno];
+@@ -559,7 +559,7 @@
+ ssiexprparserARG_FETCH;
+ yymsp = &yypParser->yystack[yypParser->yyidx];
+ #ifndef NDEBUG
+- if( yyTraceFILE && yyruleno>=0
++ if( yyTraceFILE && yyruleno>=0
+ && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
+ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
+ yyRuleName[yyruleno]);
+@@ -872,7 +872,7 @@
+ #ifdef YYERRORSYMBOL
+ /* A syntax error has occurred.
+ ** The response to an error depends upon whether or not the
+- ** grammar defines an error token "ERROR".
++ ** grammar defines an error token "ERROR".
+ **
+ ** This is what we do if the grammar does define ERROR:
+ **
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_staticfile.c lighttpd-1.4.12/src/mod_staticfile.c
+--- lighttpd-1.4.11/src/mod_staticfile.c 2006-02-15 14:31:14.000000000 +0200
++++ lighttpd-1.4.12/src/mod_staticfile.c 2006-07-11 21:23:39.000000000 +0300
+@@ -14,9 +14,11 @@
+ #include "http_chunk.h"
+ #include "response.h"
+
++#include "sys-files.h"
++#include "sys-strings.h"
+ /**
+ * this is a staticfile for a lighttpd plugin
+- *
++ *
+ */
+
+
+@@ -29,48 +31,48 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *range_buf;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_staticfile_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->range_buf = buffer_init();
+-
++
+ return p;
+ }
+
+-/* detroy the plugin data */
++/* destroy the plugin data */
+ FREE_FUNC(mod_staticfile_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ array_free(s->exclude_ext);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+ buffer_free(p->range_buf);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -79,63 +81,60 @@
+ SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->exclude_ext = array_init();
+-
++
+ cv[0].destination = s->exclude_ext;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(exclude_ext);
+-
++
++ PATCH_OPTION(exclude_ext);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
+- PATCH(exclude_ext);
++ PATCH_OPTION(exclude_ext);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
+ int multipart = 0;
+@@ -146,69 +145,69 @@
+ data_string *ds;
+ stat_cache_entry *sce = NULL;
+ buffer *content_type = NULL;
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+ SEGFAULT();
+ }
+-
++
+ start = 0;
+ end = sce->st.st_size - 1;
+-
++
+ con->response.content_length = 0;
+-
++
+ if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
+ content_type = ds->value;
+ }
+-
++
+ for (s = con->request.http_range, error = 0;
+ !error && *s && NULL != (minus = strchr(s, '-')); ) {
+ char *err;
+ off_t la, le;
+-
++
+ if (s == minus) {
+ /* -<stop> */
+-
++
+ le = strtoll(s, &err, 10);
+-
++
+ if (le == 0) {
+ /* RFC 2616 - 14.35.1 */
+-
++
+ con->http_status = 416;
+ error = 1;
+ } else if (*err == '\0') {
+ /* end */
+ s = err;
+-
++
+ end = sce->st.st_size - 1;
+ start = sce->st.st_size + le;
+ } else if (*err == ',') {
+ multipart = 1;
+ s = err + 1;
+-
++
+ end = sce->st.st_size - 1;
+ start = sce->st.st_size + le;
+ } else {
+ error = 1;
+ }
+-
++
+ } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
+ /* <start>- */
+-
++
+ la = strtoll(s, &err, 10);
+-
++
+ if (err == minus) {
+ /* ok */
+-
++
+ if (*(err + 1) == '\0') {
+ s = err + 1;
+-
++
+ end = sce->st.st_size - 1;
+ start = la;
+-
++
+ } else if (*(err + 1) == ',') {
+ multipart = 1;
+ s = err + 2;
+-
++
+ end = sce->st.st_size - 1;
+ start = la;
+ } else {
+@@ -220,64 +219,64 @@
+ }
+ } else {
+ /* <start>-<stop> */
+-
++
+ la = strtoll(s, &err, 10);
+-
++
+ if (err == minus) {
+ le = strtoll(minus+1, &err, 10);
+-
++
+ /* RFC 2616 - 14.35.1 */
+ if (la > le) {
+ error = 1;
+ }
+-
++
+ if (*err == '\0') {
+ /* ok, end*/
+ s = err;
+-
++
+ end = le;
+ start = la;
+ } else if (*err == ',') {
+ multipart = 1;
+ s = err + 1;
+-
++
+ end = le;
+ start = la;
+ } else {
+ /* error */
+-
++
+ error = 1;
+ }
+ } else {
+ /* error */
+-
++
+ error = 1;
+ }
+ }
+-
++
+ if (!error) {
+ if (start < 0) start = 0;
+-
++
+ /* RFC 2616 - 14.35.1 */
+ if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
+-
++
+ if (start > sce->st.st_size - 1) {
+ error = 1;
+-
++
+ con->http_status = 416;
+ }
+ }
+-
++
+ if (!error) {
+ if (multipart) {
+ /* write boundary-header */
+ buffer *b;
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+-
++
+ buffer_copy_string(b, "\r\n--");
+ buffer_append_string(b, boundary);
+-
++
+ /* write Content-Range */
+ buffer_append_string(b, "\r\nContent-Range: bytes ");
+ buffer_append_off_t(b, start);
+@@ -285,54 +284,54 @@
+ buffer_append_off_t(b, end);
+ buffer_append_string(b, "/");
+ buffer_append_off_t(b, sce->st.st_size);
+-
++
+ buffer_append_string(b, "\r\nContent-Type: ");
+ buffer_append_string_buffer(b, content_type);
+-
++
+ /* write END-OF-HEADER */
+ buffer_append_string(b, "\r\n\r\n");
+-
++
+ con->response.content_length += b->used - 1;
+-
++
+ }
+-
++
+ chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
+ con->response.content_length += end - start + 1;
+ }
+ }
+-
++
+ /* something went wrong */
+ if (error) return -1;
+-
++
+ if (multipart) {
+ /* add boundary end */
+ buffer *b;
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+-
++
+ buffer_copy_string_len(b, "\r\n--", 4);
+ buffer_append_string(b, boundary);
+ buffer_append_string_len(b, "--\r\n", 4);
+-
++
+ con->response.content_length += b->used - 1;
+-
++
+ /* set header-fields */
+-
++
+ buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
+ buffer_append_string(p->range_buf, boundary);
+-
++
+ /* overwrite content-type */
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
+ } else {
+ /* add Content-Range-header */
+-
++
+ buffer_copy_string(p->range_buf, "bytes ");
+ buffer_append_off_t(p->range_buf, start);
+ buffer_append_string(p->range_buf, "-");
+ buffer_append_off_t(p->range_buf, end);
+ buffer_append_string(p->range_buf, "/");
+ buffer_append_off_t(p->range_buf, sce->st.st_size);
+-
++
+ response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
+ }
+
+@@ -347,12 +346,12 @@
+ stat_cache_entry *sce = NULL;
+ buffer *mtime;
+ data_string *ds;
+-
++
+ /* someone else has done a decision for us */
+ if (con->http_status != 0) return HANDLER_GO_ON;
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+ if (con->physical.path->used == 0) return HANDLER_GO_ON;
+-
++
+ /* someone else has handled this request */
+ if (con->mode != DIRECT) return HANDLER_GO_ON;
+
+@@ -365,52 +364,52 @@
+ default:
+ return HANDLER_GO_ON;
+ }
+-
++
+ mod_staticfile_patch_connection(srv, con, p);
+-
++
+ s_len = con->uri.path->used - 1;
+-
++
+ /* ignore certain extensions */
+ for (k = 0; k < p->conf.exclude_ext->used; k++) {
+- ds = (data_string *)p->conf.exclude_ext->data[k];
+-
++ ds = (data_string *)p->conf.exclude_ext->data[k];
++
+ if (ds->value->used == 0) continue;
+
+ if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
+ return HANDLER_GO_ON;
+ }
+ }
+-
++
+
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- handling file as static file");
+ }
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+ con->http_status = 403;
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "sbsb",
+ "not a regular file:", con->uri.path,
+ "->", con->physical.path);
+-
++
+ return HANDLER_FINISHED;
+ }
+-
+- /* we only handline regular files */
++
++ /* we only handle regular files */
+ if (!S_ISREG(sce->st.st_mode)) {
+ con->http_status = 404;
+-
++
+ if (con->conf.log_file_not_found) {
+ log_error_write(srv, __FILE__, __LINE__, "sbsb",
+ "not a regular file:", con->uri.path,
+ "->", sce->name);
+ }
+-
++
+ return HANDLER_FINISHED;
+ }
+
+- /* mod_compress might set several data directly, don't overwrite them */
+-
++ /* mod_compress might set several parameters directly; don't overwrite them */
++
+ /* set response content-type, if not set already */
+
+ if (NULL == array_get_element(con->response.headers, "Content-Type")) {
+@@ -420,15 +419,15 @@
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
+ }
+ }
+-
++
+ if (NULL == array_get_element(con->response.headers, "ETag")) {
+ /* generate e-tag */
+ etag_mutate(con->physical.etag, sce->etag);
+-
++
+ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
+ }
+ response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
+-
++
+ /* prepare header */
+ if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
+ mtime = strftime_cache_get(srv, sce->st.st_mtime);
+@@ -444,34 +443,34 @@
+ /* check if we have a conditional GET */
+
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) {
+- /* if the value is the same as our ETag, we do a Range-request,
++ /* if the value is the same as our ETag, we do a Range-request,
+ * otherwise a full 200 */
+
+ if (!buffer_is_equal(ds->value, con->physical.etag)) {
+ do_range_request = 0;
+ }
+ }
+-
++
+ if (do_range_request) {
+ /* content prepared, I'm done */
+ con->file_finished = 1;
+-
++
+ if (0 == http_response_parse_range(srv, con, p)) {
+ con->http_status = 206;
+ }
+ return HANDLER_FINISHED;
+ }
+ }
+-
++
+ /* if we are still here, prepare body */
+-
+- /* we add it here for all requests
+- * the HEAD request will drop it afterwards again
++
++ /* we add it here for all requests
++ * the HEAD request will drop it afterwards again
+ */
+ http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
+-
++
+ con->file_finished = 1;
+-
++
+ return HANDLER_FINISHED;
+ }
+
+@@ -480,13 +479,13 @@
+ int mod_staticfile_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("staticfile");
+-
++
+ p->init = mod_staticfile_init;
+ p->handle_subrequest_start = mod_staticfile_subrequest;
+ p->set_defaults = mod_staticfile_set_defaults;
+ p->cleanup = mod_staticfile_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_status.c lighttpd-1.4.12/src/mod_status.c
+--- lighttpd-1.4.11/src/mod_status.c 2006-01-10 21:45:32.000000000 +0200
++++ lighttpd-1.4.12/src/mod_status.c 2006-07-11 21:23:40.000000000 +0300
+@@ -4,7 +4,6 @@
+ #include <fcntl.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <unistd.h>
+ #include <errno.h>
+ #include <time.h>
+ #include <stdio.h>
+@@ -29,114 +28,114 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ double traffic_out;
+ double requests;
+-
++
+ double mod_5s_traffic_out[5];
+ double mod_5s_requests[5];
+ size_t mod_5s_ndx;
+-
++
+ double rel_traffic_out;
+ double rel_requests;
+-
++
+ double abs_traffic_out;
+ double abs_requests;
+-
++
+ double bytes_written;
+-
++
+ buffer *module_list;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ INIT_FUNC(mod_status_init) {
+ plugin_data *p;
+ size_t i;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->traffic_out = p->requests = 0;
+ p->rel_traffic_out = p->rel_requests = 0;
+ p->abs_traffic_out = p->abs_requests = 0;
+ p->bytes_written = 0;
+ p->module_list = buffer_init();
+-
++
+ for (i = 0; i < 5; i++) {
+ p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
+ }
+-
++
+ return p;
+ }
+
+ FREE_FUNC(mod_status_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ buffer_free(p->module_list);
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ buffer_free(s->status_url);
+ buffer_free(s->statistics_url);
+ buffer_free(s->config_url);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
+-
++
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ SETDEFAULTS_FUNC(mod_status_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "status.status-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { "status.config-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { "status.enable-sort", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
+ { "status.statistics-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->config_url = buffer_init();
+ s->status_url = buffer_init();
+ s->sort = 1;
+ s->statistics_url = buffer_init();
+-
++
+ cv[0].destination = s->status_url;
+ cv[1].destination = s->config_url;
+ cv[2].destination = &(s->sort);
+ cv[3].destination = s->statistics_url;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -151,7 +150,7 @@
+ buffer_append_string(b, value);
+ BUFFER_APPEND_STRING_CONST(b, "</td>\n");
+ BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
+-
++
+ return 0;
+ }
+
+@@ -161,13 +160,13 @@
+ buffer_append_string(b, key);
+ BUFFER_APPEND_STRING_CONST(b, "</th>\n");
+ BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
+-
++
+ return 0;
+ }
+
+ static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
+ plugin_data *p = p_d;
+-
++
+ if (p->conf.sort) {
+ BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">");
+ buffer_append_string(b, key);
+@@ -177,13 +176,13 @@
+ buffer_append_string(b, key);
+ BUFFER_APPEND_STRING_CONST(b, "</th>\n");
+ }
+-
++
+ return 0;
+ }
+
+ static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
+ *multiplier = ' ';
+-
++
+ if (*avg > size) { *avg /= size; *multiplier = 'k'; }
+ if (*avg > size) { *avg /= size; *multiplier = 'M'; }
+ if (*avg > size) { *avg /= size; *multiplier = 'G'; }
+@@ -202,21 +201,21 @@
+ size_t j;
+ double avg;
+ char multiplier = '\0';
+- char buf[32];
++ char buf[128];
+ time_t ts;
+-
++
+ int days, hours, mins, seconds;
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+
+- BUFFER_COPY_STRING_CONST(b,
++ BUFFER_COPY_STRING_CONST(b,
+ "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
+ " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
+ " <head>\n"
+ " <title>Status</title>\n");
+-
++
+ BUFFER_APPEND_STRING_CONST(b,
+ " <style type=\"text/css\">\n"
+ " table.status { border: black solid thin; }\n"
+@@ -226,14 +225,14 @@
+ " a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
+ " span.sortarrow { color: white; text-decoration: none; }\n"
+ " </style>\n");
+-
++
+ if (p->conf.sort) {
+ BUFFER_APPEND_STRING_CONST(b,
+ "<script type=\"text/javascript\">\n"
+ "// <!--\n"
+ "var sort_column;\n"
+ "var prev_span = null;\n");
+-
++
+ BUFFER_APPEND_STRING_CONST(b,
+ "function get_inner_text(el) {\n"
+ " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
+@@ -251,7 +250,7 @@
+ " }\n"
+ " return str;\n"
+ "}\n");
+-
++
+ BUFFER_APPEND_STRING_CONST(b,
+ "function sortfn(a,b) {\n"
+ " var at = get_inner_text(a.cells[sort_column]);\n"
+@@ -266,7 +265,7 @@
+ " else return 1;\n"
+ " }\n"
+ "}\n");
+-
++
+ BUFFER_APPEND_STRING_CONST(b,
+ "function resort(lnk) {\n"
+ " var span = lnk.childNodes[1];\n"
+@@ -276,7 +275,7 @@
+ " rows[j-1] = table.rows[j];\n"
+ " sort_column = lnk.parentNode.cellIndex;\n"
+ " rows.sort(sortfn);\n");
+-
++
+ BUFFER_APPEND_STRING_CONST(b,
+ " if (prev_span != null) prev_span.innerHTML = '';\n"
+ " if (span.getAttribute('sortdir')=='down') {\n"
+@@ -294,175 +293,175 @@
+ "// -->\n"
+ "</script>\n");
+ }
+-
+- BUFFER_APPEND_STRING_CONST(b,
++
++ BUFFER_APPEND_STRING_CONST(b,
+ " </head>\n"
+ " <body>\n");
+-
+-
+-
++
++
++
+ /* connection listing */
+ BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
+-
+- BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
+- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
++
++ BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
++ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
+ buffer_append_string_buffer(b, con->uri.authority);
+- BUFFER_APPEND_STRING_CONST(b, " (");
++ BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
+ buffer_append_string_buffer(b, con->server_name);
+- BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
+- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
+-
++ BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
++ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
++
+ ts = srv->cur_ts - srv->startup_ts;
+-
++
+ days = ts / (60 * 60 * 24);
+ ts %= (60 * 60 * 24);
+-
++
+ hours = ts / (60 * 60);
+ ts %= (60 * 60);
+-
++
+ mins = ts / (60);
+ ts %= (60);
+-
++
+ seconds = ts;
+-
++
+ if (days) {
+ buffer_append_long(b, days);
+ BUFFER_APPEND_STRING_CONST(b, " days ");
+ }
+-
++
+ if (hours) {
+ buffer_append_long(b, hours);
+ BUFFER_APPEND_STRING_CONST(b, " hours ");
+ }
+-
++
+ if (mins) {
+ buffer_append_long(b, mins);
+ BUFFER_APPEND_STRING_CONST(b, " min ");
+ }
+-
++
+ buffer_append_long(b, seconds);
+ BUFFER_APPEND_STRING_CONST(b, " s");
+-
++
+ BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
+-
++
+ ts = srv->startup_ts;
+-
+- strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
++
++ strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
+ buffer_append_string(b, buf);
+ BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
+-
+-
++
++
+ BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
+-
+- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
++
++ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
+ avg = p->abs_requests;
+
+ mod_status_get_multiplier(&avg, &multiplier, 1000);
+-
++
+ buffer_append_long(b, avg);
+- BUFFER_APPEND_STRING_CONST(b, " ");
++ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
+ if (multiplier) buffer_append_string_len(b, &multiplier, 1);
+- BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
+-
+- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
++ BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
++
++ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
+ avg = p->abs_traffic_out;
+
+ mod_status_get_multiplier(&avg, &multiplier, 1024);
+
+ sprintf(buf, "%.2f", avg);
+ buffer_append_string(b, buf);
+- BUFFER_APPEND_STRING_CONST(b, " ");
++ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_mult\">");
+ if (multiplier) buffer_append_string_len(b, &multiplier, 1);
+- BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
++ BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
+
+
+
+ BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
+-
+- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
++
++ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
+ avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
+
+ mod_status_get_multiplier(&avg, &multiplier, 1000);
+
+ buffer_append_long(b, avg);
+- BUFFER_APPEND_STRING_CONST(b, " ");
++ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
+ if (multiplier) buffer_append_string_len(b, &multiplier, 1);
+- BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
+-
+- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
++ BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
++
++ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
+ avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
+
+ mod_status_get_multiplier(&avg, &multiplier, 1024);
+
+ sprintf(buf, "%.2f", avg);
+ buffer_append_string(b, buf);
+- BUFFER_APPEND_STRING_CONST(b, " ");
++ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
+ if (multiplier) buffer_append_string_len(b, &multiplier, 1);
+- BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
++ BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
++
++
+
+-
+-
+ BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n");
+ for (j = 0, avg = 0; j < 5; j++) {
+ avg += p->mod_5s_requests[j];
+ }
+-
++
+ avg /= 5;
+-
+- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
++
++ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
+
+ mod_status_get_multiplier(&avg, &multiplier, 1000);
+
+ buffer_append_long(b, avg);
+- BUFFER_APPEND_STRING_CONST(b, " ");
++ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
+ if (multiplier) buffer_append_string_len(b, &multiplier, 1);
+-
+- BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
+-
++
++ BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
++
+ for (j = 0, avg = 0; j < 5; j++) {
+ avg += p->mod_5s_traffic_out[j];
+ }
+-
++
+ avg /= 5;
+-
+- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
++
++ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
+
+ mod_status_get_multiplier(&avg, &multiplier, 1024);
+
+ sprintf(buf, "%.2f", avg);
+ buffer_append_string(b, buf);
+- BUFFER_APPEND_STRING_CONST(b, " ");
++ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
+ if (multiplier) buffer_append_string_len(b, &multiplier, 1);
+- BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
+-
++ BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
++
+ BUFFER_APPEND_STRING_CONST(b, "</table>\n");
+-
+-
++
++
+ BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n");
+ BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n");
+ BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n");
+ BUFFER_APPEND_STRING_CONST(b, "q = request-start, Q = request-end\n");
+ BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
+-
+- BUFFER_APPEND_STRING_CONST(b, "<b>");
++
++ BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
+ buffer_append_long(b, srv->conns->used);
+- BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
+-
++ BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
++
+ for (j = 0; j < srv->conns->used; j++) {
+ connection *c = srv->conns->ptr[j];
+ const char *state = connection_get_short_state(c->state);
+-
++
+ buffer_append_string_len(b, state, 1);
+-
++
+ if (((j + 1) % 50) == 0) {
+ BUFFER_APPEND_STRING_CONST(b, "\n");
+ }
+ }
+-
++
+ BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
+-
+- BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
++
++ BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
+ BUFFER_APPEND_STRING_CONST(b, "<tr>");
+ mod_status_header_append_sort(b, p_d, "Client IP");
+ mod_status_header_append_sort(b, p_d, "Read");
+@@ -473,16 +472,16 @@
+ mod_status_header_append_sort(b, p_d, "URI");
+ mod_status_header_append_sort(b, p_d, "File");
+ BUFFER_APPEND_STRING_CONST(b, "</tr>\n");
+-
++
+ for (j = 0; j < srv->conns->used; j++) {
+ connection *c = srv->conns->ptr[j];
+-
+- BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
+-
++
++ BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
++
+ buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
+-
+- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
+-
++
++ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
++
+ if (con->request.content_length) {
+ buffer_append_long(b, c->request_content_queue->bytes_in);
+ BUFFER_APPEND_STRING_CONST(b, "/");
+@@ -490,55 +489,55 @@
+ } else {
+ BUFFER_APPEND_STRING_CONST(b, "0/0");
+ }
+-
+- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
+-
++
++ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
++
+ buffer_append_off_t(b, chunkqueue_written(c->write_queue));
+ BUFFER_APPEND_STRING_CONST(b, "/");
+ buffer_append_off_t(b, chunkqueue_length(c->write_queue));
+-
+- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
+-
++
++ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
++
+ buffer_append_string(b, connection_get_state(c->state));
+-
+- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
+-
++
++ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
++
+ buffer_append_long(b, srv->cur_ts - c->request_start);
+-
+- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
+-
++
++ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
++
+ if (buffer_is_empty(c->server_name)) {
+ buffer_append_string_buffer(b, c->uri.authority);
+ }
+ else {
+ buffer_append_string_buffer(b, c->server_name);
+ }
+-
+- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
+-
++
++ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
++
+ if (!buffer_is_empty(c->uri.path)) {
+ buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
+ }
+-
+- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
+-
++
++ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
++
+ buffer_append_string_buffer(b, c->physical.path);
+-
++
+ BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
+ }
+-
+-
+- BUFFER_APPEND_STRING_CONST(b,
++
++
++ BUFFER_APPEND_STRING_CONST(b,
+ "</table>\n");
+-
+-
+- BUFFER_APPEND_STRING_CONST(b,
++
++
++ BUFFER_APPEND_STRING_CONST(b,
+ " </body>\n"
+ "</html>\n"
+ );
+-
++
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
+-
++
+ return 0;
+ }
+
+@@ -548,7 +547,7 @@
+ buffer *b;
+ double avg;
+ time_t ts;
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+
+ /* output total number of requests */
+@@ -556,19 +555,19 @@
+ avg = p->abs_requests;
+ buffer_append_long(b, avg);
+ BUFFER_APPEND_STRING_CONST(b, "\n");
+-
++
+ /* output total traffic out in kbytes */
+ BUFFER_APPEND_STRING_CONST(b, "Total kBytes: ");
+ avg = p->abs_traffic_out / 1024;
+ buffer_append_long(b, avg);
+ BUFFER_APPEND_STRING_CONST(b, "\n");
+-
++
+ /* output uptime */
+ BUFFER_APPEND_STRING_CONST(b, "Uptime: ");
+ ts = srv->cur_ts - srv->startup_ts;
+ buffer_append_long(b, ts);
+ BUFFER_APPEND_STRING_CONST(b, "\n");
+-
++
+ /* output busy servers */
+ BUFFER_APPEND_STRING_CONST(b, "BusyServers: ");
+ buffer_append_long(b, srv->conns->used);
+@@ -577,7 +576,7 @@
+ /* set text/plain output */
+
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
+-
++
+ return 0;
+ }
+
+@@ -591,10 +590,10 @@
+ /* we have nothing to send */
+ con->http_status = 204;
+ con->file_finished = 1;
+-
++
+ return HANDLER_FINISHED;
+ }
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+
+ for (i = 0; i < st->used; i++) {
+@@ -605,27 +604,27 @@
+ buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
+ buffer_append_string(b, "\n");
+ }
+-
++
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
+-
++
+ con->http_status = 200;
+ con->file_finished = 1;
+-
++
+ return HANDLER_FINISHED;
+ }
+
+
+ static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
+-
++
+ if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
+ mod_status_handle_server_status_text(srv, con, p_d);
+ } else {
+ mod_status_handle_server_status_html(srv, con, p_d);
+ }
+-
++
+ con->http_status = 200;
+ con->file_finished = 1;
+-
++
+ return HANDLER_FINISHED;
+ }
+
+@@ -634,9 +633,9 @@
+ plugin_data *p = p_d;
+ buffer *b, *m = p->module_list;
+ size_t i;
+-
+- struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
+- {
++
++ struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
++ {
+ /* - poll is most reliable
+ * - select works everywhere
+ * - linux-* are experimental
+@@ -661,10 +660,10 @@
+ #endif
+ { FDEVENT_HANDLER_UNSET, NULL }
+ };
+-
++
+ b = chunkqueue_get_append_buffer(con->write_queue);
+-
+- BUFFER_COPY_STRING_CONST(b,
++
++ BUFFER_COPY_STRING_CONST(b,
+ "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
+ " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
+@@ -675,7 +674,7 @@
+ " <body>\n"
+ " <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
+ " <table border=\"1\">\n");
+-
++
+ mod_status_header_append(b, "Server-Features");
+ #ifdef HAVE_PCRE_H
+ mod_status_row_append(b, "RegEx Conditionals", "enabled");
+@@ -683,21 +682,21 @@
+ mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
+ #endif
+ mod_status_header_append(b, "Network Engine");
+-
++
+ for (i = 0; event_handlers[i].name; i++) {
+ if (event_handlers[i].et == srv->event_handler) {
+ mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
+ break;
+ }
+ }
+-
++
+ mod_status_header_append(b, "Config-File-Settings");
+-
++
+ for (i = 0; i < srv->plugins.used; i++) {
+ plugin **ps = srv->plugins.ptr;
+-
++
+ plugin *pl = ps[i];
+-
++
+ if (i == 0) {
+ buffer_copy_string_buffer(m, pl->name);
+ } else {
+@@ -705,137 +704,135 @@
+ buffer_append_string_buffer(m, pl->name);
+ }
+ }
+-
++
+ mod_status_row_append(b, "Loaded Modules", m->ptr);
+-
++
+ BUFFER_APPEND_STRING_CONST(b, " </table>\n");
+-
+- BUFFER_APPEND_STRING_CONST(b,
++
++ BUFFER_APPEND_STRING_CONST(b,
+ " </body>\n"
+ "</html>\n"
+ );
+-
++
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
+-
++
+ con->http_status = 200;
+ con->file_finished = 1;
+-
++
+ return HANDLER_FINISHED;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(status_url);
+- PATCH(config_url);
+- PATCH(sort);
+- PATCH(statistics_url);
+-
++
++ PATCH_OPTION(status_url);
++ PATCH_OPTION(config_url);
++ PATCH_OPTION(sort);
++ PATCH_OPTION(statistics_url);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
+- PATCH(status_url);
++ PATCH_OPTION(status_url);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
+- PATCH(config_url);
++ PATCH_OPTION(config_url);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
+- PATCH(sort);
++ PATCH_OPTION(sort);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
+- PATCH(statistics_url);
+- }
++ PATCH_OPTION(statistics_url);
++ }
+ }
+ }
+-
++
+ return 0;
+ }
+
+ static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
+ plugin_data *p = p_d;
+-
++
+ mod_status_patch_connection(srv, con, p);
+-
+- if (!buffer_is_empty(p->conf.status_url) &&
++
++ if (!buffer_is_empty(p->conf.status_url) &&
+ buffer_is_equal(p->conf.status_url, con->uri.path)) {
+ return mod_status_handle_server_status(srv, con, p_d);
+- } else if (!buffer_is_empty(p->conf.config_url) &&
++ } else if (!buffer_is_empty(p->conf.config_url) &&
+ buffer_is_equal(p->conf.config_url, con->uri.path)) {
+ return mod_status_handle_server_config(srv, con, p_d);
+- } else if (!buffer_is_empty(p->conf.statistics_url) &&
++ } else if (!buffer_is_empty(p->conf.statistics_url) &&
+ buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
+ return mod_status_handle_server_statistics(srv, con, p_d);
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ TRIGGER_FUNC(mod_status_trigger) {
+ plugin_data *p = p_d;
+ size_t i;
+-
++
+ /* check all connections */
+ for (i = 0; i < srv->conns->used; i++) {
+ connection *c = srv->conns->ptr[i];
+-
++
+ p->bytes_written += c->bytes_written_cur_second;
+ }
+-
++
+ /* a sliding average */
+ p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
+ p->mod_5s_requests [p->mod_5s_ndx] = p->requests;
+-
++
+ p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
+-
++
+ p->abs_traffic_out += p->bytes_written;
+ p->rel_traffic_out += p->bytes_written;
+-
++
+ p->bytes_written = 0;
+-
++
+ /* reset storage - second */
+ p->traffic_out = 0;
+ p->requests = 0;
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ REQUESTDONE_FUNC(mod_status_account) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ p->requests++;
+ p->rel_requests++;
+ p->abs_requests++;
+-
++
+ p->bytes_written += con->bytes_written_cur_second;
+-
++
+ return HANDLER_GO_ON;
+ }
+
+ int mod_status_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("status");
+-
++
+ p->init = mod_status_init;
+ p->cleanup = mod_status_free;
+ p->set_defaults= mod_status_set_defaults;
+-
++
+ p->handle_uri_clean = mod_status_handler;
+ p->handle_trigger = mod_status_trigger;
+ p->handle_request_done = mod_status_account;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_trigger_b4_dl.c lighttpd-1.4.12/src/mod_trigger_b4_dl.c
+--- lighttpd-1.4.11/src/mod_trigger_b4_dl.c 2005-09-23 22:53:55.000000000 +0300
++++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c 2006-07-11 21:23:39.000000000 +0300
+@@ -24,18 +24,18 @@
+
+ /**
+ * this is a trigger_b4_dl for a lighttpd plugin
+- *
++ *
+ */
+
+ /* plugin config for all request/connections */
+
+ typedef struct {
+ buffer *db_filename;
+-
++
+ buffer *trigger_url;
+ buffer *download_url;
+ buffer *deny_url;
+-
++
+ array *mc_hosts;
+ buffer *mc_namespace;
+ #if defined(HAVE_PCRE_H)
+@@ -46,58 +46,58 @@
+ GDBM_FILE db;
+ #endif
+
+-#if defined(HAVE_MEMCACHE_H)
++#if defined(HAVE_MEMCACHE_H)
+ struct memcache *mc;
+ #endif
+-
++
+ unsigned short trigger_timeout;
+ unsigned short debug;
+ } plugin_config;
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *tmp_buf;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_trigger_b4_dl_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->tmp_buf = buffer_init();
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_trigger_b4_dl_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+-
++
+ buffer_free(s->db_filename);
+ buffer_free(s->download_url);
+ buffer_free(s->trigger_url);
+ buffer_free(s->deny_url);
+-
++
+ buffer_free(s->mc_namespace);
+ array_free(s->mc_hosts);
+-
++
+ #if defined(HAVE_PCRE_H)
+ if (s->trigger_regex) pcre_free(s->trigger_regex);
+ if (s->download_regex) pcre_free(s->download_regex);
+@@ -108,16 +108,16 @@
+ #if defined(HAVE_MEMCACHE_H)
+ if (s->mc) mc_free(s->mc);
+ #endif
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->tmp_buf);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -126,9 +126,9 @@
+ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+-
+- config_values_t cv[] = {
++
++
++ config_values_t cv[] = {
+ { "trigger-before-download.gdbm-filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "trigger-before-download.trigger-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "trigger-before-download.download-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+@@ -139,18 +139,18 @@
+ { "trigger-before-download.debug", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+ #if defined(HAVE_PCRE_H)
+ const char *errptr;
+ int erroff;
+ #endif
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->db_filename = buffer_init();
+ s->download_url = buffer_init();
+@@ -158,7 +158,7 @@
+ s->deny_url = buffer_init();
+ s->mc_hosts = array_init();
+ s->mc_namespace = buffer_init();
+-
++
+ cv[0].destination = s->db_filename;
+ cv[1].destination = s->trigger_url;
+ cv[2].destination = s->download_url;
+@@ -167,41 +167,41 @@
+ cv[5].destination = s->mc_hosts;
+ cv[6].destination = s->mc_namespace;
+ cv[7].destination = &(s->debug);
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ #if defined(HAVE_GDBM_H)
+ if (!buffer_is_empty(s->db_filename)) {
+ if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "gdbm-open failed");
+ return HANDLER_ERROR;
+ }
+ }
+ #endif
+-#if defined(HAVE_PCRE_H)
++#if defined(HAVE_PCRE_H)
+ if (!buffer_is_empty(s->download_url)) {
+ if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
+ 0, &errptr, &erroff, NULL))) {
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
+- "compiling regex for download-url failed:",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
++ "compiling regex for download-url failed:",
+ s->download_url, "pos:", erroff);
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ if (!buffer_is_empty(s->trigger_url)) {
+ if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
+ 0, &errptr, &erroff, NULL))) {
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbss",
+- "compiling regex for trigger-url failed:",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbss",
++ "compiling regex for trigger-url failed:",
+ s->trigger_url, "pos:", erroff);
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+@@ -211,100 +211,97 @@
+ #if defined(HAVE_MEMCACHE_H)
+ size_t k;
+ s->mc = mc_new();
+-
++
+ for (k = 0; k < s->mc_hosts->used; k++) {
+ data_string *ds = (data_string *)s->mc_hosts->data[k];
+-
++
+ if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "connection to host failed:",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "connection to host failed:",
+ ds->value);
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+ #else
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
+ return HANDLER_ERROR;
+ #endif
+ }
+-
++
+
+ #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
+ return HANDLER_ERROR;
+ #endif
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
++
+ #if defined(HAVE_GDBM)
+- PATCH(db);
+-#endif
++ PATCH_OPTION(db);
++#endif
+ #if defined(HAVE_PCRE_H)
+- PATCH(download_regex);
+- PATCH(trigger_regex);
+-#endif
+- PATCH(trigger_timeout);
+- PATCH(deny_url);
+- PATCH(mc_namespace);
+- PATCH(debug);
++ PATCH_OPTION(download_regex);
++ PATCH_OPTION(trigger_regex);
++#endif
++ PATCH_OPTION(trigger_timeout);
++ PATCH_OPTION(deny_url);
++ PATCH_OPTION(mc_namespace);
++ PATCH_OPTION(debug);
+ #if defined(HAVE_MEMCACHE_H)
+- PATCH(mc);
++ PATCH_OPTION(mc);
+ #endif
+-
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
+ #if defined(HAVE_PCRE_H)
+- PATCH(download_regex);
++ PATCH_OPTION(download_regex);
+ #endif
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
+ # if defined(HAVE_PCRE_H)
+- PATCH(trigger_regex);
++ PATCH_OPTION(trigger_regex);
+ # endif
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
+ #if defined(HAVE_GDBM_H)
+- PATCH(db);
++ PATCH_OPTION(db);
+ #endif
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
+- PATCH(trigger_timeout);
++ PATCH_OPTION(trigger_timeout);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
+- PATCH(debug);
++ PATCH_OPTION(debug);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
+- PATCH(deny_url);
++ PATCH_OPTION(deny_url);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
+- PATCH(mc_namespace);
++ PATCH_OPTION(mc_namespace);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
+ #if defined(HAVE_MEMCACHE_H)
+- PATCH(mc);
++ PATCH_OPTION(mc);
+ #endif
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
+ plugin_data *p = p_d;
+@@ -315,20 +312,20 @@
+ int n;
+ # define N 10
+ int ovec[N * 3];
+-
++
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_trigger_b4_dl_patch_connection(srv, con, p);
+-
++
+ if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
+-
++
+ # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
+ return HANDLER_GO_ON;
+ # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
+ if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
+ if (p->conf.db && p->conf.mc) {
+ /* can't decide which one */
+-
++
+ return HANDLER_GO_ON;
+ }
+ # elif defined(HAVE_GDBM_H)
+@@ -336,12 +333,12 @@
+ # else
+ if (!p->conf.mc) return HANDLER_GO_ON;
+ # endif
+-
++
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) {
+ /* X-Forwarded-For contains the ip behind the proxy */
+-
++
+ remote_ip = ds->value->ptr;
+-
++
+ /* memcache can't handle spaces */
+ } else {
+ remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
+@@ -350,13 +347,13 @@
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
+ }
+-
++
+ /* check if URL is a trigger -> insert IP into DB */
+ if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
+ if (n != PCRE_ERROR_NOMATCH) {
+ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "execution error while matching:", n);
+-
++
+ return HANDLER_ERROR;
+ }
+ } else {
+@@ -364,34 +361,34 @@
+ if (p->conf.db) {
+ /* the trigger matched */
+ datum key, val;
+-
++
+ key.dptr = (char *)remote_ip;
+ key.dsize = strlen(remote_ip);
+-
++
+ val.dptr = (char *)&(srv->cur_ts);
+ val.dsize = sizeof(srv->cur_ts);
+-
++
+ if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "insert failed");
+ }
+ }
+ # endif
+-# if defined(HAVE_MEMCACHE_H)
++# if defined(HAVE_MEMCACHE_H)
+ if (p->conf.mc) {
+ size_t i;
+ buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
+ buffer_append_string(p->tmp_buf, remote_ip);
+-
++
+ for (i = 0; i < p->tmp_buf->used - 1; i++) {
+ if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
+ }
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
+ }
+
+- if (0 != mc_set(p->conf.mc,
++ if (0 != mc_set(p->conf.mc,
+ CONST_BUF_LEN(p->tmp_buf),
+ (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
+ p->conf.trigger_timeout, 0)) {
+@@ -401,7 +398,7 @@
+ }
+ # endif
+ }
+-
++
+ /* check if URL is a download -> check IP in DB, update timestamp */
+ if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
+ if (n != PCRE_ERROR_NOMATCH) {
+@@ -411,93 +408,93 @@
+ }
+ } else {
+ /* the download uri matched */
+-# if defined(HAVE_GDBM_H)
++# if defined(HAVE_GDBM_H)
+ if (p->conf.db) {
+ datum key, val;
+ time_t last_hit;
+-
++
+ key.dptr = (char *)remote_ip;
+ key.dsize = strlen(remote_ip);
+-
++
+ val = gdbm_fetch(p->conf.db, key);
+-
++
+ if (val.dptr == NULL) {
+ /* not found, redirect */
+-
++
+ response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
+-
++
+ con->http_status = 307;
+-
++
+ return HANDLER_FINISHED;
+ }
+-
++
+ last_hit = *(time_t *)(val.dptr);
+-
++
+ free(val.dptr);
+-
++
+ if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
+ /* found, but timeout, redirect */
+-
++
+ response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
+ con->http_status = 307;
+-
++
+ if (p->conf.db) {
+ if (0 != gdbm_delete(p->conf.db, key)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "delete failed");
+ }
+ }
+-
++
+ return HANDLER_FINISHED;
+ }
+-
++
+ val.dptr = (char *)&(srv->cur_ts);
+ val.dsize = sizeof(srv->cur_ts);
+-
++
+ if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "insert failed");
+ }
+ }
+ # endif
+-
+-# if defined(HAVE_MEMCACHE_H)
++
++# if defined(HAVE_MEMCACHE_H)
+ if (p->conf.mc) {
+ void *r;
+ size_t i;
+-
++
+ buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
+ buffer_append_string(p->tmp_buf, remote_ip);
+-
++
+ for (i = 0; i < p->tmp_buf->used - 1; i++) {
+ if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
+ }
+-
++
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
+ }
+
+ /**
+- *
++ *
+ * memcached is do expiration for us, as long as we can fetch it every thing is ok
+- * and the timestamp is updated
+- *
++ * and the timestamp is updated
++ *
+ */
+- if (NULL == (r = mc_aget(p->conf.mc,
++ if (NULL == (r = mc_aget(p->conf.mc,
+ CONST_BUF_LEN(p->tmp_buf)
+ ))) {
+-
++
+ response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
+-
++
+ con->http_status = 307;
+-
++
+ return HANDLER_FINISHED;
+ }
+-
++
+ free(r);
+-
++
+ /* set a new timeout */
+- if (0 != mc_set(p->conf.mc,
++ if (0 != mc_set(p->conf.mc,
+ CONST_BUF_LEN(p->tmp_buf),
+ (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
+ p->conf.trigger_timeout, 0)) {
+@@ -507,13 +504,13 @@
+ }
+ # endif
+ }
+-
++
+ #else
+ UNUSED(srv);
+ UNUSED(con);
+ UNUSED(p_d);
+ #endif
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -521,21 +518,21 @@
+ TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
+ plugin_data *p = p_d;
+ size_t i;
+-
++
+ /* check DB each minute */
+ if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
+-
++
+ /* cleanup */
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+ datum key, val, okey;
+-
++
+ if (!s->db) continue;
+-
++
+ okey.dptr = NULL;
+-
+- /* according to the manual this loop + delete does delete all entries on its way
+- *
++
++ /* according to the manual this loop + delete does delete all entries on its way
++ *
+ * we don't care as the next round will remove them. We don't have to perfect here.
+ */
+ for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
+@@ -544,21 +541,21 @@
+ free(okey.dptr);
+ okey.dptr = NULL;
+ }
+-
++
+ val = gdbm_fetch(s->db, key);
+-
++
+ last_hit = *(time_t *)(val.dptr);
+-
++
+ free(val.dptr);
+-
++
+ if (srv->cur_ts - last_hit > s->trigger_timeout) {
+ gdbm_delete(s->db, key);
+ }
+-
++
+ okey = key;
+ }
+ if (okey.dptr) free(okey.dptr);
+-
++
+ /* reorg once a day */
+ if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
+ }
+@@ -571,7 +568,7 @@
+ int mod_trigger_b4_dl_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("trigger_b4_dl");
+-
++
+ p->init = mod_trigger_b4_dl_init;
+ p->handle_uri_clean = mod_trigger_b4_dl_uri_handler;
+ p->set_defaults = mod_trigger_b4_dl_set_defaults;
+@@ -579,8 +576,8 @@
+ p->handle_trigger = mod_trigger_b4_dl_handle_trigger;
+ #endif
+ p->cleanup = mod_trigger_b4_dl_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_userdir.c lighttpd-1.4.12/src/mod_userdir.c
+--- lighttpd-1.4.11/src/mod_userdir.c 2005-10-28 16:48:28.000000000 +0300
++++ lighttpd-1.4.12/src/mod_userdir.c 2006-07-11 21:23:40.000000000 +0300
+@@ -10,6 +10,7 @@
+ #include "response.h"
+
+ #include "plugin.h"
++#include "sys-files.h"
+
+ #ifdef HAVE_PWD_H
+ #include <pwd.h>
+@@ -25,54 +26,54 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *username;
+ buffer *temp_path;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_userdir_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->username = buffer_init();
+ p->temp_path = buffer_init();
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_userdir_free) {
+ plugin_data *p = p_d;
+-
++
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ array_free(s->include_user);
+ array_free(s->exclude_user);
+ buffer_free(s->path);
+ buffer_free(s->basepath);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ buffer_free(p->username);
+ buffer_free(p->temp_path);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -81,81 +82,78 @@
+ SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "userdir.path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { "userdir.basepath", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->exclude_user = array_init();
+ s->include_user = array_init();
+ s->path = buffer_init();
+ s->basepath = buffer_init();
+-
++
+ cv[0].destination = s->path;
+ cv[1].destination = s->exclude_user;
+ cv[2].destination = s->include_user;
+ cv[3].destination = s->basepath;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(path);
+- PATCH(exclude_user);
+- PATCH(include_user);
+- PATCH(basepath);
+-
++
++ PATCH_OPTION(path);
++ PATCH_OPTION(exclude_user);
++ PATCH_OPTION(include_user);
++ PATCH_OPTION(basepath);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
+- PATCH(path);
++ PATCH_OPTION(path);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
+- PATCH(exclude_user);
++ PATCH_OPTION(exclude_user);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
+- PATCH(include_user);
++ PATCH_OPTION(include_user);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
+- PATCH(basepath);
++ PATCH_OPTION(basepath);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_userdir_docroot_handler) {
+ plugin_data *p = p_d;
+@@ -169,18 +167,18 @@
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+
+ mod_userdir_patch_connection(srv, con, p);
+-
++
+ uri_len = con->uri.path->used - 1;
+-
++
+ /* /~user/foo.html -> /home/user/public_html/foo.html */
+-
++
+ if (con->uri.path->ptr[0] != '/' ||
+ con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
+-
++
+ if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
+ /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
+ http_response_redirect_to_directory(srv, con);
+-
++
+ return HANDLER_FINISHED;
+ }
+
+@@ -188,10 +186,10 @@
+ if (0 == rel_url - (con->uri.path->ptr + 2)) {
+ return HANDLER_GO_ON;
+ }
+-
++
+ buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
+-
+- if (buffer_is_empty(p->conf.basepath)
++
++ if (buffer_is_empty(p->conf.basepath)
+ #ifdef HAVE_PWD_H
+ && NULL == (pwd = getpwnam(p->username->ptr))
+ #endif
+@@ -200,31 +198,31 @@
+ return HANDLER_GO_ON;
+ }
+
+-
++
+ for (k = 0; k < p->conf.exclude_user->used; k++) {
+ data_string *ds = (data_string *)p->conf.exclude_user->data[k];
+-
++
+ if (buffer_is_equal(ds->value, p->username)) {
+ /* user in exclude list */
+ return HANDLER_GO_ON;
+ }
+ }
+-
++
+ if (p->conf.include_user->used) {
+ int found_user = 0;
+ for (k = 0; k < p->conf.include_user->used; k++) {
+ data_string *ds = (data_string *)p->conf.include_user->data[k];
+-
++
+ if (buffer_is_equal(ds->value, p->username)) {
+ /* user in include list */
+ found_user = 1;
+ break;
+ }
+ }
+-
++
+ if (!found_user) return HANDLER_GO_ON;
+ }
+-
++
+ /* we build the physical path */
+
+ if (buffer_is_empty(p->conf.basepath)) {
+@@ -252,23 +250,23 @@
+ }
+
+ buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
+- BUFFER_APPEND_SLASH(p->temp_path);
++ PATHNAME_APPEND_SLASH(p->temp_path);
+ buffer_append_string_buffer(p->temp_path, p->username);
+ }
+- BUFFER_APPEND_SLASH(p->temp_path);
+- buffer_append_string_buffer(p->temp_path, p->conf.path);
++ PATHNAME_APPEND_SLASH(p->temp_path);
++ buffer_append_string_buffer(p->temp_path, p->conf.path);
+
+ if (buffer_is_empty(p->conf.basepath)) {
+ struct stat st;
+ int ret;
+-
++
+ ret = stat(p->temp_path->ptr, &st);
+ if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
+ return HANDLER_GO_ON;
+- }
++ }
+ }
+
+- BUFFER_APPEND_SLASH(p->temp_path);
++ PATHNAME_APPEND_SLASH(p->temp_path);
+ buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
+ buffer_copy_string_buffer(con->physical.path, p->temp_path);
+
+@@ -282,13 +280,13 @@
+ int mod_userdir_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("userdir");
+-
++
+ p->init = mod_userdir_init;
+ p->handle_physical = mod_userdir_docroot_handler;
+ p->set_defaults = mod_userdir_set_defaults;
+ p->cleanup = mod_userdir_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_usertrack.c lighttpd-1.4.12/src/mod_usertrack.c
+--- lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200
++++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-11 21:23:40.000000000 +0300
+@@ -24,44 +24,44 @@
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_usertrack_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_usertrack_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+-
++
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+-
++
+ buffer_free(s->cookie_name);
+ buffer_free(s->cookie_domain);
+-
++
+ free(s);
+ }
+ free(p->config_storage);
+ }
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -70,38 +70,38 @@
+ SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "usertrack.cookie-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "usertrack.cookie-max-age", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "usertrack.cookie-domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+-
+- { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
++
++ { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->cookie_name = buffer_init();
+ s->cookie_domain = buffer_init();
+ s->cookie_max_age = 0;
+-
++
+ cv[0].destination = s->cookie_name;
+ cv[1].destination = &(s->cookie_max_age);
+ cv[2].destination = s->cookie_domain;
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+-
++
+ if (buffer_is_empty(s->cookie_name)) {
+ buffer_copy_string(s->cookie_name, "TRACKID");
+ } else {
+@@ -109,68 +109,65 @@
+ for (j = 0; j < s->cookie_name->used - 1; j++) {
+ char c = s->cookie_name->ptr[j] | 32;
+ if (c < 'a' || c > 'z') {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "invalid character in usertrack.cookie-name:",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "invalid character in usertrack.cookie-name:",
+ s->cookie_name);
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+ }
+-
++
+ if (!buffer_is_empty(s->cookie_domain)) {
+ size_t j;
+ for (j = 0; j < s->cookie_domain->used - 1; j++) {
+ char c = s->cookie_domain->ptr[j];
+ if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "invalid character in usertrack.cookie-domain:",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "invalid character in usertrack.cookie-domain:",
+ s->cookie_domain);
+-
++
+ return HANDLER_ERROR;
+ }
+ }
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(cookie_name);
+- PATCH(cookie_domain);
+- PATCH(cookie_max_age);
+-
++
++ PATCH_OPTION(cookie_name);
++ PATCH_OPTION(cookie_domain);
++ PATCH_OPTION(cookie_max_age);
++
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
+- PATCH(cookie_name);
++ PATCH_OPTION(cookie_name);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
+- PATCH(cookie_max_age);
++ PATCH_OPTION(cookie_max_age);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
+- PATCH(cookie_domain);
++ PATCH_OPTION(cookie_domain);
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_usertrack_uri_handler) {
+ plugin_data *p = p_d;
+@@ -178,38 +175,38 @@
+ unsigned char h[16];
+ MD5_CTX Md5Ctx;
+ char hh[32];
+-
++
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_usertrack_patch_connection(srv, con, p);
+-
++
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
+ char *g;
+ /* we have a cookie, does it contain a valid name ? */
+-
+- /* parse the cookie
+- *
++
++ /* parse the cookie
++ *
+ * check for cookiename + (WS | '=')
+- *
++ *
+ */
+-
++
+ if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
+ char *nc;
+-
++
+ /* skip WS */
+ for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
+-
++
+ if (*nc == '=') {
+ /* ok, found the key of our own cookie */
+-
++
+ if (strlen(nc) > 32) {
+ /* i'm lazy */
+ return HANDLER_GO_ON;
+ }
+ }
+ }
+- }
+-
++ }
++
+ /* set a cookie */
+ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
+ ds = data_response_init();
+@@ -217,39 +214,39 @@
+ buffer_copy_string(ds->key, "Set-Cookie");
+ buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
+ buffer_append_string(ds->value, "=");
+-
++
+
+ /* taken from mod_auth.c */
+-
++
+ /* generate shared-secret */
+ MD5_Init(&Md5Ctx);
+ MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
+ MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
+-
++
+ /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
+ ltostr(hh, srv->cur_ts);
+ MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
+ ltostr(hh, rand());
+ MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
+-
++
+ MD5_Final(h, &Md5Ctx);
+-
++
+ buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
+ buffer_append_string(ds->value, "; Path=/");
+ buffer_append_string(ds->value, "; Version=1");
+-
++
+ if (!buffer_is_empty(p->conf.cookie_domain)) {
+ buffer_append_string(ds->value, "; Domain=");
+ buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
+ }
+-
++
+ if (p->conf.cookie_max_age) {
+ buffer_append_string(ds->value, "; max-age=");
+ buffer_append_long(ds->value, p->conf.cookie_max_age);
+ }
+-
++
+ array_insert_unique(con->response.headers, (data_unset *)ds);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -258,13 +255,13 @@
+ int mod_usertrack_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("usertrack");
+-
++
+ p->init = mod_usertrack_init;
+ p->handle_uri_clean = mod_usertrack_uri_handler;
+ p->set_defaults = mod_usertrack_set_defaults;
+ p->cleanup = mod_usertrack_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_webdav.c lighttpd-1.4.12/src/mod_webdav.c
+--- lighttpd-1.4.11/src/mod_webdav.c 2006-03-03 01:28:58.000000000 +0200
++++ lighttpd-1.4.12/src/mod_webdav.c 2006-07-11 21:23:40.000000000 +0300
+@@ -3,13 +3,10 @@
+ #include <ctype.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <dirent.h>
+ #include <errno.h>
+-#include <unistd.h>
+ #include <fcntl.h>
+ #include <stdio.h>
+ #include <assert.h>
+-#include <sys/mman.h>
+
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+@@ -23,6 +20,11 @@
+ #include <sqlite3.h>
+ #endif
+
++#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
++#define USE_LOCKS
++#include <uuid/uuid.h>
++#endif
++
+ #include "base.h"
+ #include "log.h"
+ #include "buffer.h"
+@@ -33,13 +35,16 @@
+ #include "stream.h"
+ #include "stat_cache.h"
+
++#include "sys-files.h"
++#include "sys-mmap.h"
++#include "sys-strings.h"
+
+ /**
+ * this is a webdav for a lighttpd plugin
+ *
+- * at least a very basic one.
++ * at least a very basic one.
+ * - for now it is read-only and we only support PROPFIND
+- *
++ *
+ */
+
+
+@@ -58,64 +63,70 @@
+ sqlite3_stmt *stmt_delete_prop;
+ sqlite3_stmt *stmt_select_prop;
+ sqlite3_stmt *stmt_select_propnames;
+-
++
+ sqlite3_stmt *stmt_delete_uri;
+ sqlite3_stmt *stmt_move_uri;
+ sqlite3_stmt *stmt_copy_uri;
++
++ sqlite3_stmt *stmt_remove_lock;
++ sqlite3_stmt *stmt_create_lock;
++ sqlite3_stmt *stmt_read_lock;
++ sqlite3_stmt *stmt_read_lock_by_uri;
++ sqlite3_stmt *stmt_refresh_lock;
+ #endif
+ } plugin_config;
+
+ typedef struct {
+ PLUGIN_DATA;
+-
++
+ buffer *tmp_buf;
+ request_uri uri;
+ physical physical;
+
+ plugin_config **config_storage;
+-
+- plugin_config conf;
++
++ plugin_config conf;
+ } plugin_data;
+
+ /* init the plugin data */
+ INIT_FUNC(mod_webdav_init) {
+ plugin_data *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
+ p->tmp_buf = buffer_init();
+
+ p->uri.scheme = buffer_init();
+ p->uri.path_raw = buffer_init();
+ p->uri.path = buffer_init();
+ p->uri.authority = buffer_init();
+-
++
+ p->physical.path = buffer_init();
+ p->physical.rel_path = buffer_init();
+ p->physical.doc_root = buffer_init();
+ p->physical.basedir = buffer_init();
+-
++
+ return p;
+ }
+
+ /* detroy the plugin data */
+ FREE_FUNC(mod_webdav_free) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+-
++
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+-
++
+ buffer_free(s->sqlite_db_name);
+ #ifdef USE_PROPPATCH
+- if (s->sql) {
++ if (s->sql) {
+ sqlite3_finalize(s->stmt_delete_prop);
+ sqlite3_finalize(s->stmt_delete_uri);
+ sqlite3_finalize(s->stmt_copy_uri);
+@@ -123,9 +134,15 @@
+ sqlite3_finalize(s->stmt_update_prop);
+ sqlite3_finalize(s->stmt_select_prop);
+ sqlite3_finalize(s->stmt_select_propnames);
++
++ sqlite3_finalize(s->stmt_read_lock);
++ sqlite3_finalize(s->stmt_read_lock_by_uri);
++ sqlite3_finalize(s->stmt_create_lock);
++ sqlite3_finalize(s->stmt_remove_lock);
++ sqlite3_finalize(s->stmt_refresh_lock);
+ sqlite3_close(s->sql);
+ }
+-#endif
++#endif
+ free(s);
+ }
+ free(p->config_storage);
+@@ -135,16 +152,16 @@
+ buffer_free(p->uri.path_raw);
+ buffer_free(p->uri.path);
+ buffer_free(p->uri.authority);
+-
++
+ buffer_free(p->physical.path);
+ buffer_free(p->physical.rel_path);
+ buffer_free(p->physical.doc_root);
+ buffer_free(p->physical.basedir);
+-
++
+ buffer_free(p->tmp_buf);
+-
++
+ free(p);
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -153,32 +170,32 @@
+ SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+-
+- config_values_t cv[] = {
++
++ config_values_t cv[] = {
+ { "webdav.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { "webdav.is-readonly", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+ { "webdav.sqlite-db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { "webdav.log-xml", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+-
++
+ if (!p) return HANDLER_ERROR;
+-
++
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+-
++
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+-
++
+ s = calloc(1, sizeof(plugin_config));
+ s->sqlite_db_name = buffer_init();
+-
++
+ cv[0].destination = &(s->enabled);
+ cv[1].destination = &(s->is_readonly);
+ cv[2].destination = s->sqlite_db_name;
+ cv[3].destination = &(s->log_xml);
+-
++
+ p->config_storage[i] = s;
+-
++
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+@@ -193,8 +210,26 @@
+ return HANDLER_ERROR;
+ }
+
+- if (SQLITE_OK != sqlite3_prepare(s->sql,
+- CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
++ if (SQLITE_OK != sqlite3_exec(s->sql,
++ "CREATE TABLE properties ("
++ " resource TEXT NOT NULL,"
++ " prop TEXT NOT NULL,"
++ " ns TEXT NOT NULL,"
++ " value TEXT NOT NULL,"
++ " PRIMARY KEY(resource, prop, ns))",
++ NULL, NULL, &err)) {
++
++ if (0 != strcmp(err, "table properties already exists")) {
++ log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
++ sqlite3_free(err);
++
++ return HANDLER_ERROR;
++ }
++ sqlite3_free(err);
++ }
++
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
+ &(s->stmt_select_prop), &next_stmt)) {
+ /* prepare failed */
+
+@@ -202,8 +237,8 @@
+ return HANDLER_ERROR;
+ }
+
+- if (SQLITE_OK != sqlite3_prepare(s->sql,
+- CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
+ &(s->stmt_select_propnames), &next_stmt)) {
+ /* prepare failed */
+
+@@ -211,16 +246,67 @@
+ return HANDLER_ERROR;
+ }
+
+- if (SQLITE_OK != sqlite3_exec(s->sql,
+- "CREATE TABLE properties ("
++
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
++ &(s->stmt_update_prop), &next_stmt)) {
++ /* prepare failed */
++
++ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
++ return HANDLER_ERROR;
++ }
++
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
++ &(s->stmt_delete_prop), &next_stmt)) {
++ /* prepare failed */
++ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
++
++ return HANDLER_ERROR;
++ }
++
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
++ &(s->stmt_delete_uri), &next_stmt)) {
++ /* prepare failed */
++ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
++
++ return HANDLER_ERROR;
++ }
++
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
++ &(s->stmt_copy_uri), &next_stmt)) {
++ /* prepare failed */
++ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
++
++ return HANDLER_ERROR;
++ }
++
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
++ &(s->stmt_move_uri), &next_stmt)) {
++ /* prepare failed */
++ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
++
++ return HANDLER_ERROR;
++ }
++
++ /* LOCKS */
++
++ if (SQLITE_OK != sqlite3_exec(s->sql,
++ "CREATE TABLE locks ("
++ " locktoken TEXT NOT NULL,"
+ " resource TEXT NOT NULL,"
+- " prop TEXT NOT NULL,"
+- " ns TEXT NOT NULL,"
+- " value TEXT NOT NULL,"
+- " PRIMARY KEY(resource, prop, ns))",
++ " lockscope TEXT NOT NULL,"
++ " locktype TEXT NOT NULL,"
++ " owner TEXT NOT NULL,"
++ " depth INT NOT NULL,"
++ " timeout TIMESTAMP NOT NULL,"
++ " PRIMARY KEY(locktoken))",
+ NULL, NULL, &err)) {
+
+- if (0 != strcmp(err, "table properties already exists")) {
++ if (0 != strcmp(err, "table locks already exists")) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
+ sqlite3_free(err);
+
+@@ -228,127 +314,138 @@
+ }
+ sqlite3_free(err);
+ }
+-
+- if (SQLITE_OK != sqlite3_prepare(s->sql,
+- CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
+- &(s->stmt_update_prop), &next_stmt)) {
++
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
++ &(s->stmt_create_lock), &next_stmt)) {
+ /* prepare failed */
++ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
+
+- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
+ return HANDLER_ERROR;
+ }
+
+- if (SQLITE_OK != sqlite3_prepare(s->sql,
+- CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
+- &(s->stmt_delete_prop), &next_stmt)) {
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
++ &(s->stmt_remove_lock), &next_stmt)) {
+ /* prepare failed */
+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
+
+ return HANDLER_ERROR;
+ }
+
+- if (SQLITE_OK != sqlite3_prepare(s->sql,
+- CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
+- &(s->stmt_delete_uri), &next_stmt)) {
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
++ &(s->stmt_read_lock), &next_stmt)) {
+ /* prepare failed */
+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
+
+ return HANDLER_ERROR;
+ }
+
+- if (SQLITE_OK != sqlite3_prepare(s->sql,
+- CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
+- &(s->stmt_copy_uri), &next_stmt)) {
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
++ &(s->stmt_read_lock_by_uri), &next_stmt)) {
+ /* prepare failed */
+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
+
+ return HANDLER_ERROR;
+ }
+
+- if (SQLITE_OK != sqlite3_prepare(s->sql,
+- CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
+- &(s->stmt_move_uri), &next_stmt)) {
++ if (SQLITE_OK != sqlite3_prepare(s->sql,
++ CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
++ &(s->stmt_refresh_lock), &next_stmt)) {
+ /* prepare failed */
+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
+
+ return HANDLER_ERROR;
+ }
++
++
+ #else
+ log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
+ return HANDLER_ERROR;
+ #endif
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+-#define PATCH(x) \
+- p->conf.x = s->x;
+ static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+-
+- PATCH(enabled);
+- PATCH(is_readonly);
+- PATCH(log_xml);
+-
++
++ PATCH_OPTION(enabled);
++ PATCH_OPTION(is_readonly);
++ PATCH_OPTION(log_xml);
++
+ #ifdef USE_PROPPATCH
+- PATCH(sql);
+- PATCH(stmt_update_prop);
+- PATCH(stmt_delete_prop);
+- PATCH(stmt_select_prop);
+- PATCH(stmt_select_propnames);
+-
+- PATCH(stmt_delete_uri);
+- PATCH(stmt_move_uri);
+- PATCH(stmt_copy_uri);
++ PATCH_OPTION(sql);
++ PATCH_OPTION(stmt_update_prop);
++ PATCH_OPTION(stmt_delete_prop);
++ PATCH_OPTION(stmt_select_prop);
++ PATCH_OPTION(stmt_select_propnames);
++
++ PATCH_OPTION(stmt_delete_uri);
++ PATCH_OPTION(stmt_move_uri);
++ PATCH_OPTION(stmt_copy_uri);
++
++ PATCH_OPTION(stmt_remove_lock);
++ PATCH_OPTION(stmt_refresh_lock);
++ PATCH_OPTION(stmt_create_lock);
++ PATCH_OPTION(stmt_read_lock);
++ PATCH_OPTION(stmt_read_lock_by_uri);
+ #endif
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+-
++
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+-
++
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+-
++
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
+- PATCH(enabled);
++ PATCH_OPTION(enabled);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
+- PATCH(is_readonly);
++ PATCH_OPTION(is_readonly);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
+- PATCH(log_xml);
++ PATCH_OPTION(log_xml);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
+ #ifdef USE_PROPPATCH
+- PATCH(sql);
+- PATCH(stmt_update_prop);
+- PATCH(stmt_delete_prop);
+- PATCH(stmt_select_prop);
+- PATCH(stmt_select_propnames);
+-
+- PATCH(stmt_delete_uri);
+- PATCH(stmt_move_uri);
+- PATCH(stmt_copy_uri);
++ PATCH_OPTION(sql);
++ PATCH_OPTION(stmt_update_prop);
++ PATCH_OPTION(stmt_delete_prop);
++ PATCH_OPTION(stmt_select_prop);
++ PATCH_OPTION(stmt_select_propnames);
++
++ PATCH_OPTION(stmt_delete_uri);
++ PATCH_OPTION(stmt_move_uri);
++ PATCH_OPTION(stmt_copy_uri);
++
++ PATCH_OPTION(stmt_remove_lock);
++ PATCH_OPTION(stmt_refresh_lock);
++ PATCH_OPTION(stmt_create_lock);
++ PATCH_OPTION(stmt_read_lock);
++ PATCH_OPTION(stmt_read_lock_by_uri);
+ #endif
+ }
+ }
+ }
+-
++
+ return 0;
+ }
+-#undef PATCH
+
+ URIHANDLER_FUNC(mod_webdav_uri_handler) {
+ plugin_data *p = p_d;
+-
++
+ UNUSED(srv);
+
+ if (con->uri.path->used == 0) return HANDLER_GO_ON;
+-
++
+ mod_webdav_patch_connection(srv, con, p);
+
+ if (!p->conf.enabled) return HANDLER_GO_ON;
+@@ -362,20 +459,20 @@
+ if (p->conf.is_readonly) {
+ response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
+ } else {
+- response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
++ response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
+ }
+ break;
+ default:
+ break;
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+-static int webdav_gen_prop_tag(server *srv, connection *con,
+- char *prop_name,
+- char *prop_ns,
+- char *value,
++static int webdav_gen_prop_tag(server *srv, connection *con,
++ char *prop_name,
++ char *prop_ns,
++ char *value,
+ buffer *b) {
+
+ UNUSED(srv);
+@@ -414,7 +511,7 @@
+ buffer_append_string_buffer(b, dst->rel_path);
+ buffer_append_string(b,"</D:href>\n");
+ buffer_append_string(b,"<D:status>\n");
+-
++
+ if (con->request.http_version == HTTP_VERSION_1_1) {
+ BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
+ } else {
+@@ -458,11 +555,11 @@
+
+ /* bind the values to the insert */
+
+- sqlite3_bind_text(stmt, 1,
+- dst->rel_path->ptr,
++ sqlite3_bind_text(stmt, 1,
++ dst->rel_path->ptr,
+ dst->rel_path->used - 1,
+ SQLITE_TRANSIENT);
+-
++
+ if (SQLITE_DONE != sqlite3_step(stmt)) {
+ /* */
+ WP();
+@@ -493,14 +590,14 @@
+ (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
+ continue;
+ /* ignore the parent dir */
+- }
++ }
+
+ buffer_copy_string_buffer(d.path, dst->path);
+- BUFFER_APPEND_SLASH(d.path);
++ PATHNAME_APPEND_SLASH(d.path);
+ buffer_append_string(d.path, de->d_name);
+-
++
+ buffer_copy_string_buffer(d.rel_path, dst->rel_path);
+- BUFFER_APPEND_SLASH(d.rel_path);
++ PATHNAME_APPEND_SLASH(d.rel_path);
+ buffer_append_string(d.rel_path, de->d_name);
+
+ /* stat and unlink afterwards */
+@@ -508,7 +605,7 @@
+ /* don't about it yet, rmdir will fail too */
+ } else if (S_ISDIR(st.st_mode)) {
+ have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
+-
++
+ /* try to unlink it */
+ if (-1 == rmdir(d.path->ptr)) {
+ switch(errno) {
+@@ -535,11 +632,11 @@
+
+ /* bind the values to the insert */
+
+- sqlite3_bind_text(stmt, 1,
+- d.rel_path->ptr,
++ sqlite3_bind_text(stmt, 1,
++ d.rel_path->ptr,
+ d.rel_path->used - 1,
+ SQLITE_TRANSIENT);
+-
++
+ if (SQLITE_DONE != sqlite3_step(stmt)) {
+ /* */
+ WP();
+@@ -569,7 +666,7 @@
+ if (stream_open(&s, src->path)) {
+ return 403;
+ }
+-
++
+ if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) {
+ /* opening the destination failed for some reason */
+ switch(errno) {
+@@ -601,7 +698,7 @@
+ break;
+ }
+ }
+-
++
+ stream_close(&s);
+ close(ofd);
+
+@@ -614,16 +711,16 @@
+ sqlite3_reset(stmt);
+
+ /* bind the values to the insert */
+- sqlite3_bind_text(stmt, 1,
+- dst->rel_path->ptr,
++ sqlite3_bind_text(stmt, 1,
++ dst->rel_path->ptr,
+ dst->rel_path->used - 1,
+ SQLITE_TRANSIENT);
+
+- sqlite3_bind_text(stmt, 2,
+- src->rel_path->ptr,
++ sqlite3_bind_text(stmt, 2,
++ src->rel_path->ptr,
+ src->rel_path->used - 1,
+ SQLITE_TRANSIENT);
+-
++
+ if (SQLITE_DONE != sqlite3_step(stmt)) {
+ /* */
+ WP();
+@@ -655,21 +752,21 @@
+ (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
+ continue;
+ }
+-
++
+ buffer_copy_string_buffer(s.path, src->path);
+- BUFFER_APPEND_SLASH(s.path);
++ PATHNAME_APPEND_SLASH(s.path);
+ buffer_append_string(s.path, de->d_name);
+
+ buffer_copy_string_buffer(d.path, dst->path);
+- BUFFER_APPEND_SLASH(d.path);
++ PATHNAME_APPEND_SLASH(d.path);
+ buffer_append_string(d.path, de->d_name);
+
+ buffer_copy_string_buffer(s.rel_path, src->rel_path);
+- BUFFER_APPEND_SLASH(s.rel_path);
++ PATHNAME_APPEND_SLASH(s.rel_path);
+ buffer_append_string(s.rel_path, de->d_name);
+
+ buffer_copy_string_buffer(d.rel_path, dst->rel_path);
+- BUFFER_APPEND_SLASH(d.rel_path);
++ PATHNAME_APPEND_SLASH(d.rel_path);
+ buffer_append_string(d.rel_path, de->d_name);
+
+ if (-1 == stat(s.path->ptr, &st)) {
+@@ -692,16 +789,16 @@
+ sqlite3_reset(stmt);
+
+ /* bind the values to the insert */
+- sqlite3_bind_text(stmt, 1,
+- dst->rel_path->ptr,
++ sqlite3_bind_text(stmt, 1,
++ dst->rel_path->ptr,
+ dst->rel_path->used - 1,
+ SQLITE_TRANSIENT);
+
+- sqlite3_bind_text(stmt, 2,
+- src->rel_path->ptr,
++ sqlite3_bind_text(stmt, 2,
++ src->rel_path->ptr,
+ src->rel_path->used - 1,
+ SQLITE_TRANSIENT);
+-
++
+ if (SQLITE_DONE != sqlite3_step(stmt)) {
+ /* */
+ WP();
+@@ -721,7 +818,7 @@
+ buffer_free(s.rel_path);
+ buffer_free(d.path);
+ buffer_free(d.rel_path);
+-
++
+ closedir(srcdir);
+ }
+
+@@ -748,12 +845,12 @@
+ if (S_ISDIR(sce->st.st_mode)) {
+ buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
+ found = 1;
+- } else if(S_ISREG(sce->st.st_mode)) {
++ } else if(S_ISREG(sce->st.st_mode)) {
+ for (k = 0; k < con->conf.mimetypes->used; k++) {
+ data_string *ds = (data_string *)con->conf.mimetypes->data[k];
+-
++
+ if (ds->key->used == 0) continue;
+-
++
+ if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
+ buffer_append_string(b,"<D:getcontenttype>");
+ buffer_append_string_buffer(b, ds->value);
+@@ -807,23 +904,23 @@
+
+ /* bind the values to the insert */
+
+- sqlite3_bind_text(stmt, 1,
+- dst->rel_path->ptr,
++ sqlite3_bind_text(stmt, 1,
++ dst->rel_path->ptr,
+ dst->rel_path->used - 1,
+ SQLITE_TRANSIENT);
+- sqlite3_bind_text(stmt, 2,
++ sqlite3_bind_text(stmt, 2,
+ prop_name,
+ strlen(prop_name),
+ SQLITE_TRANSIENT);
+- sqlite3_bind_text(stmt, 3,
++ sqlite3_bind_text(stmt, 3,
+ prop_ns,
+ strlen(prop_ns),
+ SQLITE_TRANSIENT);
+
+ /* it is the PK */
+- while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
++ while (SQLITE_ROW == sqlite3_step(stmt)) {
+ /* there is a row for us, we only expect a single col 'value' */
+- webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
++ webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
+ found = 1;
+ }
+ }
+@@ -840,7 +937,7 @@
+ char *prop;
+ } webdav_property;
+
+-webdav_property live_properties[] = {
++webdav_property live_properties[] = {
+ { "DAV:", "creationdate" },
+ { "DAV:", "displayname" },
+ { "DAV:", "getcontentlanguage" },
+@@ -871,8 +968,8 @@
+ webdav_property *prop;
+
+ prop = props->ptr[i];
+-
+- if (0 != webdav_get_property(srv, con, p,
++
++ if (0 != webdav_get_property(srv, con, p,
+ dst, prop->prop, prop->ns, b_200)) {
+ webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
+ }
+@@ -916,12 +1013,12 @@
+ if (-1 == c->file.fd && /* open the file if not already open */
+ -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+-
++
+ return -1;
+ }
+-
++
+ if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
+- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
++ log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
+ strerror(errno), c->file.name, c->file.fd);
+
+ return -1;
+@@ -938,7 +1035,7 @@
+ if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
+ log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
+ }
+-
++
+ c->offset += weHave;
+ cq->bytes_out += weHave;
+
+@@ -956,7 +1053,7 @@
+ if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
+ log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
+ }
+-
++
+ c->offset += weHave;
+ cq->bytes_out += weHave;
+
+@@ -991,6 +1088,113 @@
+ }
+ #endif
+
++int webdav_lockdiscovery(server *srv, connection *con,
++ buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
++
++ buffer *b;
++
++ response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
++
++ response_header_overwrite(srv, con,
++ CONST_STR_LEN("Content-Type"),
++ CONST_STR_LEN("text/xml; charset=\"utf-8\""));
++
++ b = chunkqueue_get_append_buffer(con->write_queue);
++
++ buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
++
++ buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
++ buffer_append_string(b,"<D:lockdiscovery>\n");
++ buffer_append_string(b,"<D:activelock>\n");
++
++ buffer_append_string(b,"<D:lockscope>");
++ buffer_append_string(b,"<D:");
++ buffer_append_string(b, lockscope);
++ buffer_append_string(b, "/>");
++ buffer_append_string(b,"</D:lockscope>\n");
++
++ buffer_append_string(b,"<D:locktype>");
++ buffer_append_string(b,"<D:");
++ buffer_append_string(b, locktype);
++ buffer_append_string(b, "/>");
++ buffer_append_string(b,"</D:locktype>\n");
++
++ buffer_append_string(b,"<D:depth>");
++ buffer_append_string(b, depth == 0 ? "0" : "infinity");
++ buffer_append_string(b,"</D:depth>\n");
++
++ buffer_append_string(b,"<D:timeout>");
++ buffer_append_string(b, "Second-600");
++ buffer_append_string(b,"</D:timeout>\n");
++
++ buffer_append_string(b,"<D:owner>");
++ buffer_append_string(b,"</D:owner>\n");
++
++ buffer_append_string(b,"<D:locktoken>");
++ buffer_append_string(b, "<D:href>");
++ buffer_append_string_buffer(b, locktoken);
++ buffer_append_string(b, "</D:href>");
++ buffer_append_string(b,"</D:locktoken>\n");
++
++ buffer_append_string(b,"</D:activelock>\n");
++ buffer_append_string(b,"</D:lockdiscovery>\n");
++ buffer_append_string(b,"</D:prop>\n");
++
++ return 0;
++}
++/**
++ * check if resource is having the right locks to access to resource
++ *
++ *
++ *
++ */
++int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
++ int has_lock = 1;
++
++#ifdef USE_LOCKS
++ data_string *ds;
++
++ /**
++ * If can have
++ * - <lock-token>
++ * - [etag]
++ *
++ * there is NOT, AND and OR
++ * and a list can be tagged
++ *
++ * (<lock-token>) is untagged
++ * <tag> (<lock-token>) is tagged
++ *
++ * as long as we don't handle collections it is simple. :)
++ *
++ * X-Litmus: locks: 11 (owner_modify)
++ * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
++ *
++ * X-Litmus: locks: 16 (fail_cond_put)
++ * If: (<DAV:no-lock> ["-1622396671"])
++ */
++ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
++ } else {
++ /* we didn't provided a lock-token -> */
++ /* if the resource is locked -> 423 */
++
++ sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
++
++ sqlite3_reset(stmt);
++
++ sqlite3_bind_text(stmt, 1,
++ CONST_BUF_LEN(uri),
++ SQLITE_TRANSIENT);
++
++ while (SQLITE_ROW == sqlite3_step(stmt)) {
++ has_lock = 0;
++ }
++ }
++#endif
++
++ return has_lock;
++}
++
+ URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
+ plugin_data *p = p_d;
+ buffer *b;
+@@ -1001,7 +1205,8 @@
+ buffer *prop_200;
+ buffer *prop_404;
+ webdav_properties *req_props;
+-
++ stat_cache_entry *sce = NULL;
++
+ UNUSED(srv);
+
+ if (!p->conf.enabled) return HANDLER_GO_ON;
+@@ -1019,7 +1224,19 @@
+ req_props = NULL;
+
+ /* is there a content-body ? */
+-
++
++ switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
++ case HANDLER_ERROR:
++ if (errno == ENOENT) {
++ con->http_status = 404;
++ return HANDLER_FINISHED;
++ }
++ break;
++ default:
++ break;
++ }
++
++
+ #ifdef USE_PROPPATCH
+ /* any special requests or just allprop ? */
+ if (con->request.content_length) {
+@@ -1087,12 +1304,12 @@
+ /* get all property names (EMPTY) */
+ sqlite3_reset(stmt);
+ /* bind the values to the insert */
+-
+- sqlite3_bind_text(stmt, 1,
+- con->uri.path->ptr,
++
++ sqlite3_bind_text(stmt, 1,
++ con->uri.path->ptr,
+ con->uri.path->used - 1,
+ SQLITE_TRANSIENT);
+-
++
+ if (SQLITE_DONE != sqlite3_step(stmt)) {
+ WP();
+ }
+@@ -1115,13 +1332,13 @@
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
+
+ b = chunkqueue_get_append_buffer(con->write_queue);
+-
++
+ buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+
+ buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
+
+ /* allprop */
+-
++
+ prop_200 = buffer_init();
+ prop_404 = buffer_init();
+
+@@ -1129,7 +1346,7 @@
+ case 0:
+ /* Depth: 0 */
+ webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
+-
++
+ buffer_append_string(b,"<D:response>\n");
+ buffer_append_string(b,"<D:href>");
+ buffer_append_string_buffer(b, con->uri.scheme);
+@@ -1145,9 +1362,9 @@
+ buffer_append_string_buffer(b, prop_200);
+
+ buffer_append_string(b,"</D:prop>\n");
+-
++
+ buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
+-
++
+ buffer_append_string(b,"</D:propstat>\n");
+ }
+ if (!buffer_is_empty(prop_404)) {
+@@ -1157,16 +1374,16 @@
+ buffer_append_string_buffer(b, prop_404);
+
+ buffer_append_string(b,"</D:prop>\n");
+-
++
+ buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
+-
++
+ buffer_append_string(b,"</D:propstat>\n");
+ }
+
+ buffer_append_string(b,"</D:response>\n");
+
+ break;
+- case 1:
++ case 1:
+ if (NULL != (dir = opendir(con->physical.path->ptr))) {
+ struct dirent *de;
+ physical d;
+@@ -1179,16 +1396,16 @@
+ if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
+ continue;
+ /* ignore the parent dir */
+- }
++ }
+
+ buffer_copy_string_buffer(d.path, dst->path);
+- BUFFER_APPEND_SLASH(d.path);
++ PATHNAME_APPEND_SLASH(d.path);
+
+ buffer_copy_string_buffer(d.rel_path, dst->rel_path);
+- BUFFER_APPEND_SLASH(d.rel_path);
++ PATHNAME_APPEND_SLASH(d.rel_path);
+
+ if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
+- /* don't append the . */
++ /* don't append the . */
+ } else {
+ buffer_append_string(d.path, de->d_name);
+ buffer_append_string(d.rel_path, de->d_name);
+@@ -1198,7 +1415,7 @@
+ buffer_reset(prop_404);
+
+ webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
+-
++
+ buffer_append_string(b,"<D:response>\n");
+ buffer_append_string(b,"<D:href>");
+ buffer_append_string_buffer(b, con->uri.scheme);
+@@ -1214,9 +1431,9 @@
+ buffer_append_string_buffer(b, prop_200);
+
+ buffer_append_string(b,"</D:prop>\n");
+-
++
+ buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
+-
++
+ buffer_append_string(b,"</D:propstat>\n");
+ }
+ if (!buffer_is_empty(prop_404)) {
+@@ -1226,9 +1443,9 @@
+ buffer_append_string_buffer(b, prop_404);
+
+ buffer_append_string(b,"</D:prop>\n");
+-
++
+ buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
+-
++
+ buffer_append_string(b,"</D:propstat>\n");
+ }
+
+@@ -1275,7 +1492,7 @@
+
+ return HANDLER_FINISHED;
+ }
+-
++
+ /* let's create the directory */
+
+ if (-1 == mkdir(con->physical.path->ptr, 0700)) {
+@@ -1303,7 +1520,13 @@
+ con->http_status = 403;
+ return HANDLER_FINISHED;
+ }
+-
++
++ /* does the client have a lock for this connection ? */
++ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
++ con->http_status = 423;
++ return HANDLER_FINISHED;
++ }
++
+ /* stat and unlink afterwards */
+ if (-1 == stat(con->physical.path->ptr, &st)) {
+ /* don't about it yet, unlink will fail too */
+@@ -1323,7 +1546,7 @@
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
+
+ b = chunkqueue_get_append_buffer(con->write_queue);
+-
++
+ buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+
+ buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
+@@ -1331,7 +1554,7 @@
+ buffer_append_string_buffer(b, multi_status_resp);
+
+ buffer_append_string(b,"</D:multistatus>\n");
+-
++
+ if (p->conf.log_xml) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
+ }
+@@ -1340,7 +1563,7 @@
+ con->file_finished = 1;
+ } else {
+ /* everything went fine, remove the directory */
+-
++
+ if (-1 == rmdir(con->physical.path->ptr)) {
+ switch(errno) {
+ case ENOENT:
+@@ -1375,97 +1598,174 @@
+ case HTTP_METHOD_PUT: {
+ int fd;
+ chunkqueue *cq = con->request_content_queue;
++ chunk *c;
++ data_string *ds_range;
+
+ if (p->conf.is_readonly) {
+ con->http_status = 403;
+ return HANDLER_FINISHED;
+ }
+
++ /* is a exclusive lock set on the source */
++ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
++ con->http_status = 423;
++ return HANDLER_FINISHED;
++ }
++
++
+ assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
+
+- /* taken what we have in the request-body and write it to a file */
+- if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
+- /* we can't open the file */
+- con->http_status = 403;
+- } else {
+- chunk *c;
++ /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
++ * - most important Content-Range
++ *
++ *
++ * Example: Content-Range: bytes 100-1037/1038 */
+
+- con->http_status = 201; /* created */
+- con->file_finished = 1;
++ if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
++ const char *num = ds_range->value->ptr;
++ off_t offset;
++ char *err = NULL;
+
+- for (c = cq->first; c; c = cq->first) {
+- int r = 0;
++ if (0 != strncmp(num, "bytes ", 6)) {
++ con->http_status = 501; /* not implemented */
+
+- /* copy all chunks */
+- switch(c->type) {
+- case FILE_CHUNK:
+-
+- if (c->file.mmap.start == MAP_FAILED) {
+- if (-1 == c->file.fd && /* open the file if not already open */
+- -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+-
+- return -1;
+- }
+-
+- if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
+- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
+- strerror(errno), c->file.name, c->file.fd);
++ return HANDLER_FINISHED;
++ }
+
+- return -1;
+- }
++ /* we only support <num>- ... */
+
+- c->file.mmap.length = c->file.length;
++ num += 6;
+
+- close(c->file.fd);
+- c->file.fd = -1;
+-
+- /* chunk_reset() or chunk_free() will cleanup for us */
+- }
+-
+- if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
+- switch(errno) {
+- case ENOSPC:
+- con->http_status = 507;
+-
+- break;
+- default:
+- con->http_status = 403;
+- break;
+- }
+- }
+- break;
+- case MEM_CHUNK:
+- if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
+- switch(errno) {
+- case ENOSPC:
+- con->http_status = 507;
+-
+- break;
+- default:
+- con->http_status = 403;
+- break;
+- }
+- }
++ /* skip WS */
++ while (*num == ' ' || *num == '\t') num++;
++
++ if (*num == '\0') {
++ con->http_status = 501; /* not implemented */
++
++ return HANDLER_FINISHED;
++ }
++
++ offset = strtoll(num, &err, 10);
++
++ if (*err != '-' || offset < 0) {
++ con->http_status = 501; /* not implemented */
++
++ return HANDLER_FINISHED;
++ }
++
++ if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
++ switch (errno) {
++ case ENOENT:
++ con->http_status = 404; /* not found */
+ break;
+- case UNUSED_CHUNK:
++ default:
++ con->http_status = 403; /* not found */
+ break;
+ }
++ return HANDLER_FINISHED;
++ }
++
++ if (-1 == lseek(fd, offset, SEEK_SET)) {
++ con->http_status = 501; /* not implemented */
++
++ close(fd);
++
++ return HANDLER_FINISHED;
++ }
++ con->http_status = 200; /* modified */
++ } else {
++ /* take what we have in the request-body and write it to a file */
++
++ /* if the file doesn't exist, create it */
++ if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
++ if (errno == ENOENT &&
++ -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
++ /* we can't open the file */
++ con->http_status = 403;
+
+- if (r > 0) {
+- c->offset += r;
+- cq->bytes_out += r;
++ return HANDLER_FINISHED;
+ } else {
+- break;
++ con->http_status = 201; /* created */
++ }
++ } else {
++ con->http_status = 200; /* modified */
++ }
++ }
++
++ con->file_finished = 1;
++
++ for (c = cq->first; c; c = cq->first) {
++ int r = 0;
++
++ /* copy all chunks */
++ switch(c->type) {
++ case FILE_CHUNK:
++
++ if (c->file.mmap.start == MAP_FAILED) {
++ if (-1 == c->file.fd && /* open the file if not already open */
++ -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
++ log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
++
++ return -1;
++ }
++
++ if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
++ log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
++ strerror(errno), c->file.name, c->file.fd);
++
++ return -1;
++ }
++
++ c->file.mmap.length = c->file.length;
++
++ close(c->file.fd);
++ c->file.fd = -1;
++
++ /* chunk_reset() or chunk_free() will cleanup for us */
++ }
++
++ if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
++ switch(errno) {
++ case ENOSPC:
++ con->http_status = 507;
++
++ break;
++ default:
++ con->http_status = 403;
++ break;
++ }
+ }
+- chunkqueue_remove_finished_chunks(cq);
++ break;
++ case MEM_CHUNK:
++ if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
++ switch(errno) {
++ case ENOSPC:
++ con->http_status = 507;
++
++ break;
++ default:
++ con->http_status = 403;
++ break;
++ }
++ }
++ break;
++ case UNUSED_CHUNK:
++ break;
+ }
+- close(fd);
+
++ if (r > 0) {
++ c->offset += r;
++ cq->bytes_out += r;
++ } else {
++ break;
++ }
++ chunkqueue_remove_finished_chunks(cq);
+ }
++ close(fd);
++
+ return HANDLER_FINISHED;
+ }
+- case HTTP_METHOD_MOVE:
++ case HTTP_METHOD_MOVE:
+ case HTTP_METHOD_COPY: {
+ buffer *destination = NULL;
+ char *sep, *start;
+@@ -1475,7 +1775,15 @@
+ con->http_status = 403;
+ return HANDLER_FINISHED;
+ }
+-
++
++ /* is a exclusive lock set on the source */
++ if (con->request.http_method == HTTP_METHOD_MOVE) {
++ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
++ con->http_status = 423;
++ return HANDLER_FINISHED;
++ }
++ }
++
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
+ destination = ds->value;
+ } else {
+@@ -1549,10 +1857,10 @@
+ }
+
+ buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
+- BUFFER_APPEND_SLASH(p->physical.path);
++ PATHNAME_APPEND_SLASH(p->physical.path);
+ buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
+
+- /* don't add a second / */
++ /* don't add a second / */
+ if (p->physical.rel_path->ptr[0] == '/') {
+ buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
+ } else {
+@@ -1613,6 +1921,12 @@
+ /* it is just a file, good */
+ int r;
+
++ /* does the client have a lock for this connection ? */
++ if (!webdav_has_lock(srv, con, p, p->uri.path)) {
++ con->http_status = 423;
++ return HANDLER_FINISHED;
++ }
++
+ /* destination exists */
+ if (0 == (r = stat(p->physical.path->ptr, &st))) {
+ if (S_ISDIR(st.st_mode)) {
+@@ -1636,7 +1950,7 @@
+ return HANDLER_FINISHED;
+ }
+ } else if (overwrite == 0) {
+- /* destination exists, but overwrite is not set */
++ /* destination exists, but overwrite is not set */
+ con->http_status = 412;
+ return HANDLER_FINISHED;
+ } else {
+@@ -1655,16 +1969,16 @@
+ sqlite3_reset(stmt);
+
+ /* bind the values to the insert */
+- sqlite3_bind_text(stmt, 1,
+- p->uri.path->ptr,
++ sqlite3_bind_text(stmt, 1,
++ p->uri.path->ptr,
+ p->uri.path->used - 1,
+ SQLITE_TRANSIENT);
+
+- sqlite3_bind_text(stmt, 2,
+- con->uri.path->ptr,
++ sqlite3_bind_text(stmt, 2,
++ con->uri.path->ptr,
+ con->uri.path->used - 1,
+ SQLITE_TRANSIENT);
+-
++
+ if (SQLITE_DONE != sqlite3_step(stmt)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
+ }
+@@ -1691,12 +2005,17 @@
+
+ return HANDLER_FINISHED;
+ }
+- case HTTP_METHOD_PROPPATCH: {
++ case HTTP_METHOD_PROPPATCH:
+ if (p->conf.is_readonly) {
+ con->http_status = 403;
+ return HANDLER_FINISHED;
+ }
+
++ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
++ con->http_status = 423;
++ return HANDLER_FINISHED;
++ }
++
+ /* check if destination exists */
+ if (-1 == stat(con->physical.path->ptr, &st)) {
+ switch(errno) {
+@@ -1737,7 +2056,7 @@
+
+ sqlite3_stmt *stmt;
+
+- stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
++ stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
+ p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
+
+ for (props = cmd->children; props; props = props->next) {
+@@ -1762,34 +2081,35 @@
+
+ /* bind the values to the insert */
+
+- sqlite3_bind_text(stmt, 1,
+- con->uri.path->ptr,
++ sqlite3_bind_text(stmt, 1,
++ con->uri.path->ptr,
+ con->uri.path->used - 1,
+ SQLITE_TRANSIENT);
+- sqlite3_bind_text(stmt, 2,
++ sqlite3_bind_text(stmt, 2,
+ (char *)prop->name,
+ strlen((char *)prop->name),
+ SQLITE_TRANSIENT);
+ if (prop->ns) {
+- sqlite3_bind_text(stmt, 3,
++ sqlite3_bind_text(stmt, 3,
+ (char *)prop->ns->href,
+ strlen((char *)prop->ns->href),
+ SQLITE_TRANSIENT);
+ } else {
+- sqlite3_bind_text(stmt, 3,
++ sqlite3_bind_text(stmt, 3,
+ "",
+ 0,
+ SQLITE_TRANSIENT);
+ }
+ if (stmt == p->conf.stmt_update_prop) {
+- sqlite3_bind_text(stmt, 4,
++ sqlite3_bind_text(stmt, 4,
+ (char *)xmlNodeGetContent(prop),
+ strlen((char *)xmlNodeGetContent(prop)),
+ SQLITE_TRANSIENT);
+ }
+-
++
+ if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "sql-set failed:", sqlite3_errmsg(p->conf.sql));
+ }
+ }
+ }
+@@ -1804,7 +2124,7 @@
+
+ goto propmatch_cleanup;
+ }
+-
++
+ con->http_status = 400;
+ } else {
+ if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
+@@ -1821,6 +2141,7 @@
+ }
+
+ propmatch_cleanup:
++
+ xmlFreeDoc(xml);
+ } else {
+ con->http_status = 400;
+@@ -1830,11 +2151,307 @@
+ #endif
+ con->http_status = 501;
+ return HANDLER_FINISHED;
+- }
++ case HTTP_METHOD_LOCK:
++ /**
++ * a mac wants to write
++ *
++ * LOCK /dav/expire.txt HTTP/1.1\r\n
++ * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
++ * Accept: * / *\r\n
++ * Depth: 0\r\n
++ * Timeout: Second-600\r\n
++ * Content-Type: text/xml; charset=\"utf-8\"\r\n
++ * Content-Length: 229\r\n
++ * Connection: keep-alive\r\n
++ * Host: 192.168.178.23:1025\r\n
++ * \r\n
++ * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
++ * <D:lockinfo xmlns:D=\"DAV:\">\n
++ * <D:lockscope><D:exclusive/></D:lockscope>\n
++ * <D:locktype><D:write/></D:locktype>\n
++ * <D:owner>\n
++ * <D:href>http://www.apple.com/webdav_fs/</D:href>\n
++ * </D:owner>\n
++ * </D:lockinfo>\n
++ */
++
++ if (depth != 0 && depth != -1) {
++ con->http_status = 400;
++
++ return HANDLER_FINISHED;
++ }
++
++#ifdef USE_LOCKS
++ if (con->request.content_length) {
++ xmlDocPtr xml;
++ buffer *hdr_if = NULL;
++
++ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
++ hdr_if = ds->value;
++ }
++
++ /* we don't support Depth: Infinity on locks */
++ if (hdr_if == NULL && depth == -1) {
++ con->http_status = 409; /* Conflict */
++
++ return HANDLER_FINISHED;
++ }
++
++ if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
++ xmlNode *rootnode = xmlDocGetRootElement(xml);
++
++ assert(rootnode);
++
++ if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
++ xmlNode *lockinfo;
++ const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
++
++ for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
++ if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
++ xmlNode *value;
++ for (value = lockinfo->children; value; value = value->next) {
++ if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
++ (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
++ lockscope = value->name;
++ } else {
++ con->http_status = 400;
++
++ xmlFreeDoc(xml);
++ return HANDLER_FINISHED;
++ }
++ }
++ } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
++ xmlNode *value;
++ for (value = lockinfo->children; value; value = value->next) {
++ if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
++ locktype = value->name;
++ } else {
++ con->http_status = 400;
++
++ xmlFreeDoc(xml);
++ return HANDLER_FINISHED;
++ }
++ }
++
++ } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
++ }
++ }
++
++ if (lockscope && locktype) {
++ sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
++
++ /* is this resourse already locked ? */
++
++ /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
++ * FROM locks
++ * WHERE resource = ? */
++
++ if (stmt) {
++
++ sqlite3_reset(stmt);
++
++ sqlite3_bind_text(stmt, 1,
++ p->uri.path->ptr,
++ p->uri.path->used - 1,
++ SQLITE_TRANSIENT);
++
++ /* it is the PK */
++ while (SQLITE_ROW == sqlite3_step(stmt)) {
++ /* we found a lock
++ * 1. is it compatible ?
++ * 2. is it ours */
++ char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
++
++ if (strcmp(sql_lockscope, "exclusive")) {
++ con->http_status = 423;
++ } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
++ /* resourse is locked with a shared lock
++ * client wants exclusive */
++ con->http_status = 423;
++ }
++ }
++ if (con->http_status == 423) {
++ xmlFreeDoc(xml);
++ return HANDLER_FINISHED;
++ }
++ }
++
++ stmt = p->conf.stmt_create_lock;
++ if (stmt) {
++ /* create a lock-token */
++ uuid_t id;
++ char uuid[37] /* 36 + \0 */;
++
++ uuid_generate(id);
++ uuid_unparse(id, uuid);
++
++ buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
++ buffer_append_string(p->tmp_buf, uuid);
++
++ /* "CREATE TABLE locks ("
++ * " locktoken TEXT NOT NULL,"
++ * " resource TEXT NOT NULL,"
++ * " lockscope TEXT NOT NULL,"
++ * " locktype TEXT NOT NULL,"
++ * " owner TEXT NOT NULL,"
++ * " depth INT NOT NULL,"
++ */
++
++ sqlite3_reset(stmt);
++
++ sqlite3_bind_text(stmt, 1,
++ CONST_BUF_LEN(p->tmp_buf),
++ SQLITE_TRANSIENT);
++
++ sqlite3_bind_text(stmt, 2,
++ CONST_BUF_LEN(con->uri.path),
++ SQLITE_TRANSIENT);
++
++ sqlite3_bind_text(stmt, 3,
++ lockscope,
++ xmlStrlen(lockscope),
++ SQLITE_TRANSIENT);
++
++ sqlite3_bind_text(stmt, 4,
++ locktype,
++ xmlStrlen(locktype),
++ SQLITE_TRANSIENT);
++
++ /* owner */
++ sqlite3_bind_text(stmt, 5,
++ "",
++ 0,
++ SQLITE_TRANSIENT);
++
++ /* depth */
++ sqlite3_bind_int(stmt, 6,
++ depth);
++
++
++ if (SQLITE_DONE != sqlite3_step(stmt)) {
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "create lock:", sqlite3_errmsg(p->conf.sql));
++ }
++
++ /* looks like we survived */
++ webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
++
++ con->http_status = 201;
++ con->file_finished = 1;
++ }
++ }
++ }
++
++ xmlFreeDoc(xml);
++ return HANDLER_FINISHED;
++ } else {
++ con->http_status = 400;
++ return HANDLER_FINISHED;
++ }
++ } else {
++
++ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
++ buffer *locktoken = ds->value;
++ sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
++
++ /* remove the < > around the token */
++ if (locktoken->used < 6) {
++ con->http_status = 400;
++
++ return HANDLER_FINISHED;
++ }
++
++ buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
++
++ sqlite3_reset(stmt);
++
++ sqlite3_bind_text(stmt, 1,
++ CONST_BUF_LEN(p->tmp_buf),
++ SQLITE_TRANSIENT);
++
++ if (SQLITE_DONE != sqlite3_step(stmt)) {
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "refresh lock:", sqlite3_errmsg(p->conf.sql));
++ }
++
++ webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
++
++ con->http_status = 200;
++ con->file_finished = 1;
++ return HANDLER_FINISHED;
++ } else {
++ /* we need a lock-token to refresh */
++ con->http_status = 400;
++
++ return HANDLER_FINISHED;
++ }
++ }
++ break;
++#else
++ con->http_status = 501;
++ return HANDLER_FINISHED;
++#endif
++ case HTTP_METHOD_UNLOCK:
++#ifdef USE_LOCKS
++ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
++ buffer *locktoken = ds->value;
++ sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
++
++ /* remove the < > around the token */
++ if (locktoken->used < 4) {
++ con->http_status = 400;
++
++ return HANDLER_FINISHED;
++ }
++
++ /**
++ * FIXME:
++ *
++ * if the resourse is locked:
++ * - by us: unlock
++ * - by someone else: 401
++ * if the resource is not locked:
++ * - 412
++ * */
++
++ buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
++
++ sqlite3_reset(stmt);
++
++ sqlite3_bind_text(stmt, 1,
++ CONST_BUF_LEN(p->tmp_buf),
++ SQLITE_TRANSIENT);
++
++ sqlite3_bind_text(stmt, 2,
++ CONST_BUF_LEN(con->uri.path),
++ SQLITE_TRANSIENT);
++
++ if (SQLITE_DONE != sqlite3_step(stmt)) {
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "remove lock:", sqlite3_errmsg(p->conf.sql));
++ }
++
++ if (0 == sqlite3_changes(p->conf.sql)) {
++ con->http_status = 401;
++ } else {
++ con->http_status = 204;
++ }
++ return HANDLER_FINISHED;
++ } else {
++ /* we need a lock-token to unlock */
++ con->http_status = 400;
++
++ return HANDLER_FINISHED;
++ }
++ break;
++#else
++ con->http_status = 501;
++ return HANDLER_FINISHED;
++#endif
+ default:
+ break;
+ }
+-
++
+ /* not found */
+ return HANDLER_GO_ON;
+ }
+@@ -1845,14 +2462,14 @@
+ int mod_webdav_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("webdav");
+-
++
+ p->init = mod_webdav_init;
+ p->handle_uri_clean = mod_webdav_uri_handler;
+ p->handle_physical = mod_webdav_subrequest_handler;
+ p->set_defaults = mod_webdav_set_defaults;
+ p->cleanup = mod_webdav_free;
+-
++
+ p->data = NULL;
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network.c lighttpd-1.4.12/src/network.c
+--- lighttpd-1.4.11/src/network.c 2006-03-04 16:45:46.000000000 +0200
++++ lighttpd-1.4.12/src/network.c 2006-07-11 21:23:39.000000000 +0300
+@@ -1,14 +1,14 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+-#include <sys/time.h>
+
+ #include <errno.h>
+ #include <fcntl.h>
+-#include <unistd.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <assert.h>
+
++#include <stdio.h>
++
+ #include "network.h"
+ #include "fdevent.h"
+ #include "log.h"
+@@ -19,11 +19,12 @@
+ #include "network_backends.h"
+ #include "sys-mmap.h"
+ #include "sys-socket.h"
++#include "sys-files.h"
+
+ #ifdef USE_OPENSSL
+-# include <openssl/ssl.h>
+-# include <openssl/err.h>
+-# include <openssl/rand.h>
++# include <openssl/ssl.h>
++# include <openssl/err.h>
++# include <openssl/rand.h>
+ #endif
+
+ handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
+@@ -31,11 +32,11 @@
+ server_socket *srv_socket = (server_socket *)context;
+ connection *con;
+ int loops = 0;
+-
++
+ UNUSED(context);
+-
++
+ if (revents != FDEVENT_IN) {
+- log_error_write(srv, __FILE__, __LINE__, "sdd",
++ log_error_write(srv, __FILE__, __LINE__, "sdd",
+ "strange event for server socket",
+ srv_socket->fd,
+ revents);
+@@ -44,12 +45,12 @@
+
+ /* accept()s at most 100 connections directly
+ *
+- * we jump out after 100 to give the waiting connections a chance */
++ * we jump out after 100 to give the waiting connections a chance */
+ for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
+ handler_t r;
+-
++
+ connection_state_machine(srv, con);
+-
++
+ switch(r = plugins_call_handle_joblist(srv, con)) {
+ case HANDLER_FINISHED:
+ case HANDLER_GO_ON:
+@@ -72,18 +73,18 @@
+ buffer *b;
+ int is_unix_domain_socket = 0;
+ int fd;
+-
++
+ #ifdef SO_ACCEPTFILTER
+ struct accept_filter_arg afa;
+ #endif
+
+-#ifdef __WIN32
++#ifdef _WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+-
++
+ wVersionRequested = MAKEWORD( 2, 2 );
+-
++
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ /* Tell the user that we could not find a usable */
+@@ -91,37 +92,37 @@
+ return -1;
+ }
+ #endif
+-
++
+ srv_socket = calloc(1, sizeof(*srv_socket));
+ srv_socket->fd = -1;
+-
++
+ srv_socket->srv_token = buffer_init();
+ buffer_copy_string_buffer(srv_socket->srv_token, host_token);
+-
++
+ b = buffer_init();
+ buffer_copy_string_buffer(b, host_token);
+-
+- /* ipv4:port
++
++ /* ipv4:port
+ * [ipv6]:port
+ */
+ if (NULL == (sp = strrchr(b->ptr, ':'))) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
+-
++
+ return -1;
+ }
+-
++
+ host = b->ptr;
+-
++
+ /* check for [ and ] */
+ if (b->ptr[0] == '[' && *(sp-1) == ']') {
+ *(sp-1) = '\0';
+ host++;
+-
++
+ s->use_ipv6 = 1;
+ }
+-
++
+ *(sp++) = '\0';
+-
++
+ port = strtol(sp, NULL, 10);
+
+ if (host[0] == '/') {
+@@ -129,17 +130,17 @@
+ is_unix_domain_socket = 1;
+ } else if (port == 0 || port > 65535) {
+ log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
+-
++
+ return -1;
+ }
+-
++
+ if (*host == '\0') host = NULL;
+
+ if (is_unix_domain_socket) {
+ #ifdef HAVE_SYS_UN_H
+
+ srv_socket->addr.plain.sa_family = AF_UNIX;
+-
++
+ if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
+ return -1;
+@@ -154,7 +155,7 @@
+ #ifdef HAVE_IPV6
+ if (s->use_ipv6) {
+ srv_socket->addr.plain.sa_family = AF_INET6;
+-
++
+ if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
+ return -1;
+@@ -162,7 +163,7 @@
+ srv_socket->use_ipv6 = 1;
+ }
+ #endif
+-
++
+ if (srv_socket->fd == -1) {
+ srv_socket->addr.plain.sa_family = AF_INET;
+ if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
+@@ -170,16 +171,16 @@
+ return -1;
+ }
+ }
+-
++
+ /* */
+ srv->cur_fds = srv_socket->fd;
+-
++
+ val = 1;
+ if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
+ return -1;
+ }
+-
++
+ switch(srv_socket->addr.plain.sa_family) {
+ #ifdef HAVE_IPV6
+ case AF_INET6:
+@@ -190,23 +191,23 @@
+ } else {
+ struct addrinfo hints, *res;
+ int r;
+-
++
+ memset(&hints, 0, sizeof(hints));
+-
++
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+-
++
+ if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
+- log_error_write(srv, __FILE__, __LINE__,
+- "sssss", "getaddrinfo failed: ",
++ log_error_write(srv, __FILE__, __LINE__,
++ "sssss", "getaddrinfo failed: ",
+ gai_strerror(r), "'", host, "'");
+-
++
+ return -1;
+ }
+-
++
+ memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
+-
++
+ freeaddrinfo(res);
+ }
+ srv_socket->addr.ipv6.sin6_port = htons(port);
+@@ -221,33 +222,34 @@
+ } else {
+ struct hostent *he;
+ if (NULL == (he = gethostbyname(host))) {
+- log_error_write(srv, __FILE__, __LINE__,
+- "sds", "gethostbyname failed: ",
++ log_error_write(srv, __FILE__, __LINE__,
++ "sds", "gethostbyname failed: ",
+ h_errno, host);
+ return -1;
+ }
+-
++
+ if (he->h_addrtype != AF_INET) {
+ log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
+ return -1;
+ }
+-
++
+ if (he->h_length != sizeof(struct in_addr)) {
+ log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
+ return -1;
+ }
+-
++
+ memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
+ }
+ srv_socket->addr.ipv4.sin_port = htons(port);
+-
++
+ addr_len = sizeof(struct sockaddr_in);
+-
++
+ break;
++#ifndef _WIN32
+ case AF_UNIX:
+ srv_socket->addr.un.sun_family = AF_UNIX;
+ strcpy(srv_socket->addr.un.sun_path, host);
+-
++
+ #ifdef SUN_LEN
+ addr_len = SUN_LEN(&srv_socket->addr.un);
+ #else
+@@ -259,8 +261,8 @@
+ if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
+ close(fd);
+
+- log_error_write(srv, __FILE__, __LINE__, "ss",
+- "server socket is still in use:",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "server socket is still in use:",
+ host);
+
+
+@@ -275,88 +277,89 @@
+ case ENOENT:
+ break;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "testing socket failed:",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "testing socket failed:",
+ host, strerror(errno));
+
+ return -1;
+ }
+
+ break;
++#endif
+ default:
+ addr_len = 0;
+-
++
+ return -1;
+ }
+-
++
+ if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
+ switch(srv_socket->addr.plain.sa_family) {
+ case AF_UNIX:
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+- "can't bind to socket:",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "can't bind to socket:",
+ host, strerror(errno));
+ break;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "ssds",
+- "can't bind to port:",
++ log_error_write(srv, __FILE__, __LINE__, "ssds",
++ "can't bind to port:",
+ host, port, strerror(errno));
+ break;
+ }
+ return -1;
+ }
+-
++
+ if (-1 == listen(srv_socket->fd, 128 * 8)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
+ return -1;
+ }
+-
++
+ if (s->is_ssl) {
+ #ifdef USE_OPENSSL
+ if (srv->ssl_is_init == 0) {
+ SSL_load_error_strings();
+ SSL_library_init();
+ srv->ssl_is_init = 1;
+-
++
+ if (0 == RAND_status()) {
+- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+ "not enough entropy in the pool");
+ return -1;
+ }
+ }
+-
++
+ if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
+- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+ }
+-
++
+ if (buffer_is_empty(s->ssl_pemfile)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
+ return -1;
+ }
+-
++
+ if (!buffer_is_empty(s->ssl_ca_file)) {
+ if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
+- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
+ return -1;
+ }
+ }
+-
++
+ if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
+- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
+ return -1;
+ }
+-
++
+ if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
+- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
+ return -1;
+ }
+-
++
+ if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
+- log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
+ "Private key does not match the certificate public key, reason:",
+ ERR_error_string(ERR_get_error(), NULL),
+ s->ssl_pemfile);
+@@ -364,15 +367,15 @@
+ }
+ srv_socket->ssl_ctx = s->ssl_ctx;
+ #else
+-
++
+ buffer_free(srv_socket->srv_token);
+ free(srv_socket);
+-
++
+ buffer_free(b);
+-
+- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
++
++ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+ "ssl requested but openssl support is not compiled in");
+-
++
+ return -1;
+ #endif
+ } else {
+@@ -390,10 +393,10 @@
+ }
+ #endif
+ }
+-
++
+ srv_socket->is_ssl = s->is_ssl;
+ srv_socket->fde_ndx = -1;
+-
++
+ if (srv->srv_sockets.size == 0) {
+ srv->srv_sockets.size = 4;
+ srv->srv_sockets.used = 0;
+@@ -402,11 +405,10 @@
+ srv->srv_sockets.size += 4;
+ srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
+ }
+-
++
+ srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
+-
+ buffer_free(b);
+-
++
+ return 0;
+ }
+
+@@ -414,45 +416,58 @@
+ size_t i;
+ for (i = 0; i < srv->srv_sockets.used; i++) {
+ server_socket *srv_socket = srv->srv_sockets.ptr[i];
+-
++
+ if (srv_socket->fd != -1) {
+ /* check if server fd are already registered */
+ if (srv_socket->fde_ndx != -1) {
+ fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
+ fdevent_unregister(srv->ev, srv_socket->fd);
+ }
+-
++
+ close(srv_socket->fd);
+ }
+-
++
++ if (srv_socket->is_ssl) {
++#ifdef USE_OPENSSL
++ SSL_CTX_free(srv_socket->ssl_ctx);
++#endif
++ }
++
+ buffer_free(srv_socket->srv_token);
+-
++
+ free(srv_socket);
+ }
+-
++
++#ifdef USE_OPENSSL
++ ERR_free_strings();
++#endif
+ free(srv->srv_sockets.ptr);
+-
++
return 0;
}
--#undef PATCH
- URIHANDLER_FUNC(mod_setenv_uri_handler) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_simple_vhost.c 2005-11-18 15:16:13.000000000 +0200
-+++ lighttpd/src/mod_simple_vhost.c 2006-07-11 21:23:40.087855227 +0300
-@@ -10,6 +10,8 @@
+ typedef enum {
+ NETWORK_BACKEND_UNSET,
++
+ NETWORK_BACKEND_WRITE,
+ NETWORK_BACKEND_WRITEV,
+ NETWORK_BACKEND_LINUX_SENDFILE,
+ NETWORK_BACKEND_FREEBSD_SENDFILE,
+- NETWORK_BACKEND_SOLARIS_SENDFILEV
++ NETWORK_BACKEND_SOLARIS_SENDFILEV,
++
++ NETWORK_BACKEND_WIN32_SEND,
++ NETWORK_BACKEND_WIN32_TRANSMITFILE,
+ } network_backend_t;
+
+ int network_init(server *srv) {
+ buffer *b;
+ size_t i;
+ network_backend_t backend;
+-
+- struct nb_map {
+- network_backend_t nb;
+- const char *name;
+- } network_backends[] = {
++
++ struct nb_map {
++ network_backend_t nb;
++ const char *name;
++ } network_backends[] = {
+ /* lowest id wins */
+ #if defined USE_LINUX_SENDFILE
+ { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" },
+@@ -466,21 +481,30 @@
+ #if defined USE_WRITEV
+ { NETWORK_BACKEND_WRITEV, "writev" },
+ #endif
++#if defined USE_WRITE
+ { NETWORK_BACKEND_WRITE, "write" },
++#endif
++#if defined USE_WIN32_TRANSMITFILE
++ { NETWORK_BACKEND_WIN32_TRANSMITFILE, "win32-transmitfile" },
++#endif
++#if defined USE_WIN32_SEND
++ { NETWORK_BACKEND_WIN32_SEND, "win32-send" },
++#endif
++
+ { NETWORK_BACKEND_UNSET, NULL }
+ };
+-
++
+ b = buffer_init();
+-
++
+ buffer_copy_string_buffer(b, srv->srvconf.bindhost);
+ buffer_append_string(b, ":");
+ buffer_append_long(b, srv->srvconf.port);
+-
++
+ if (0 != network_server_init(srv, b, srv->config_storage[0])) {
+ return -1;
+ }
+ buffer_free(b);
+-
++
+ #ifdef USE_OPENSSL
+ srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
+ #endif
+@@ -500,54 +524,80 @@
+ if (NULL == network_backends[i].name) {
+ /* we don't know it */
+
+- log_error_write(srv, __FILE__, __LINE__, "sb",
+- "server.network-backend has a unknown value:",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
++ "server.network-backend has a unknown value:",
+ srv->srvconf.network_backend);
+
+ return -1;
+ }
+ }
+
++#define SET_NETWORK_BACKEND(read, write) \
++ srv->network_backend_write = network_write_chunkqueue_##write;\
++ srv->network_backend_read = network_read_chunkqueue_##read
++
++#define SET_NETWORK_BACKEND_SSL(read, write) \
++ srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
++ srv->network_ssl_backend_read = network_read_chunkqueue_##read
++
+ switch(backend) {
++
++#ifdef USE_WIN32_SEND
++ case NETWORK_BACKEND_WIN32_SEND:
++ SET_NETWORK_BACKEND(win32recv, win32send);
++ break;
++#ifdef USE_WIN32_TRANSMITFILE
++ case NETWORK_BACKEND_WIN32_TRANSMITFILE:
++ SET_NETWORK_BACKEND(win32recv, win32transmitfile);
++ break;
++#endif
++#endif
++
++#ifdef USE_WRITE
+ case NETWORK_BACKEND_WRITE:
+- srv->network_backend_write = network_write_chunkqueue_write;
++ SET_NETWORK_BACKEND(read, write);
+ break;
++
+ #ifdef USE_WRITEV
+ case NETWORK_BACKEND_WRITEV:
+- srv->network_backend_write = network_write_chunkqueue_writev;
++ SET_NETWORK_BACKEND(read, writev);
+ break;
+ #endif
+ #ifdef USE_LINUX_SENDFILE
+ case NETWORK_BACKEND_LINUX_SENDFILE:
+- srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
++ SET_NETWORK_BACKEND(read, linuxsendfile);
+ break;
+ #endif
+ #ifdef USE_FREEBSD_SENDFILE
+ case NETWORK_BACKEND_FREEBSD_SENDFILE:
+- srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
++ SET_NETWORK_BACKEND(read, freebsdsendfile);
+ break;
+ #endif
+ #ifdef USE_SOLARIS_SENDFILEV
+ case NETWORK_BACKEND_SOLARIS_SENDFILEV:
+- srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
++ SET_NETWORK_BACKEND(read, solarissendfilev);
+ break;
+ #endif
++#endif
+ default:
+ return -1;
+ }
++#ifdef USE_OPENSSL
++ SET_NETWORK_BACKEND_SSL(openssl, openssl);
++#endif
+
+ /* check for $SERVER["socket"] */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ specific_config *s = srv->config_storage[i];
+ size_t j;
+-
++
+ /* not our stage */
+ if (COMP_SERVER_SOCKET != dc->comp) continue;
+-
++
+ if (dc->cond != CONFIG_COND_EQ) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
+-
++
+ return -1;
+ }
+
+@@ -558,36 +608,47 @@
+ break;
+ }
+ }
+-
++
+ if (j == srv->srv_sockets.used) {
+ if (0 != network_server_init(srv, dc->string, s)) return -1;
+ }
+ }
+-
++
+ return 0;
+ }
+
+ int network_register_fdevents(server *srv) {
+ size_t i;
+-
+ if (-1 == fdevent_reset(srv->ev)) {
+ return -1;
+ }
+-
+ /* register fdevents after reset */
+ for (i = 0; i < srv->srv_sockets.used; i++) {
+ server_socket *srv_socket = srv->srv_sockets.ptr[i];
+-
+ fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
+ fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
+ }
+ return 0;
+ }
+
+-int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
+- int ret = -1;
++network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
++ server_socket *srv_socket = con->srv_socket;
++
++ if (srv_socket->is_ssl) {
++#ifdef USE_OPENSSL
++ return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
++#else
++ return NETWORK_STATUS_FATAL_ERROR;
++#endif
++ } else {
++ return srv->network_backend_read(srv, con, con->fd, cq);
++ }
++}
++
++network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
++ network_status_t ret = NETWORK_STATUS_UNSET;
+ off_t written = 0;
+-#ifdef TCP_CORK
++#ifdef TCP_CORK
+ int corked = 0;
+ #endif
+ server_socket *srv_socket = con->srv_socket;
+@@ -600,11 +661,11 @@
+ joblist_append(srv, con);
+
+ return 1;
+- }
++ }
+
+ written = cq->bytes_out;
+
+-#ifdef TCP_CORK
++#ifdef TCP_CORK
+ /* Linux: put a cork into the socket as we want to combine the write() calls
+ * but only if we really have multiple chunks
+ */
+@@ -613,7 +674,7 @@
+ setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
+ }
+ #endif
+-
++
+ if (srv_socket->is_ssl) {
+ #ifdef USE_OPENSSL
+ ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
+@@ -621,12 +682,17 @@
+ } else {
+ ret = srv->network_backend_write(srv, con, con->fd, cq);
+ }
+-
+- if (ret >= 0) {
++
++ switch (ret) {
++ case NETWORK_STATUS_WAIT_FOR_EVENT:
++ case NETWORK_STATUS_SUCCESS:
+ chunkqueue_remove_finished_chunks(cq);
+- ret = chunkqueue_is_empty(cq) ? 0 : 1;
++
++ break;
++ default:
++ break;
+ }
+-
++
+ #ifdef TCP_CORK
+ if (corked) {
+ corked = 0;
+@@ -639,13 +705,13 @@
+ con->bytes_written_cur_second += written;
+
+ *(con->conf.global_bytes_per_second_cnt_ptr) += written;
+-
++
+ if (con->conf.kbytes_per_second &&
+ (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
+ /* we reached the traffic limit */
+
+ con->traffic_limit_reached = 1;
+ joblist_append(srv, con);
+- }
++ }
+ return ret;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network.h lighttpd-1.4.12/src/network.h
+--- lighttpd-1.4.11/src/network.h 2005-08-11 01:26:42.000000000 +0300
++++ lighttpd-1.4.12/src/network.h 2006-07-11 21:23:39.000000000 +0300
+@@ -3,7 +3,8 @@
+
+ #include "server.h"
+
+-int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
++network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
++network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
+
+ int network_init(server *srv);
+ int network_close(server *srv);
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_backends.h lighttpd-1.4.12/src/network_backends.h
+--- lighttpd-1.4.11/src/network_backends.h 2005-10-24 15:13:51.000000000 +0300
++++ lighttpd-1.4.12/src/network_backends.h 2006-07-11 21:23:40.000000000 +0300
+@@ -43,16 +43,52 @@
+ # define USE_AIX_SENDFILE
+ #endif
+
++/**
++* unix can use read/write or recv/send on sockets
++* win32 only recv/send
++*/
++#ifdef _WIN32
++# define USE_WIN32_SEND
++/* wait for async-io support
++# define USE_WIN32_TRANSMITFILE
++*/
++#else
++# define USE_WRITE
++#endif
++
+ #include "base.h"
++#include "network.h"
++
++#define NETWORK_BACKEND_WRITE_CHUNK(x) \
++ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c)
++
++#define NETWORK_BACKEND_WRITE(x) \
++ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
++#define NETWORK_BACKEND_READ(x) \
++ network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
- #include "plugin.h"
++NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
++
++NETWORK_BACKEND_WRITE(write);
++NETWORK_BACKEND_WRITE(writev);
++NETWORK_BACKEND_WRITE(linuxsendfile);
++NETWORK_BACKEND_WRITE(freebsdsendfile);
++NETWORK_BACKEND_WRITE(solarissendfilev);
++
++NETWORK_BACKEND_WRITE(win32transmitfile);
++NETWORK_BACKEND_WRITE(win32send);
++
++NETWORK_BACKEND_READ(read);
++NETWORK_BACKEND_READ(win32recv);
-+#include "sys-files.h"
+-int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
+-int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
+-int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
+-int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
+-int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
+ #ifdef USE_OPENSSL
+-int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
++#define NETWORK_BACKEND_WRITE_SSL(x) \
++ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
++#define NETWORK_BACKEND_READ_SSL(x) \
++ network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
+
- #ifdef HAVE_CONFIG_H
- #include "config.h"
++NETWORK_BACKEND_WRITE_SSL(openssl);
++NETWORK_BACKEND_READ_SSL(openssl);
#endif
-@@ -139,7 +141,7 @@
- */
- char *dp;
-
-- BUFFER_APPEND_SLASH(out);
-+ PATHNAME_APPEND_SLASH(out);
-
- if (NULL == (dp = strchr(host->ptr, ':'))) {
- buffer_append_string_buffer(out, host);
-@@ -147,17 +149,17 @@
- buffer_append_string_len(out, host->ptr, dp - host->ptr);
- }
- }
-- BUFFER_APPEND_SLASH(out);
-+ PATHNAME_APPEND_SLASH(out);
-
- if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
- buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
- } else {
- buffer_append_string_buffer(out, p->conf.document_root);
-- BUFFER_APPEND_SLASH(out);
-+ PATHNAME_APPEND_SLASH(out);
- }
- } else {
- buffer_copy_string_buffer(out, con->conf.document_root);
-- BUFFER_APPEND_SLASH(out);
-+ PATHNAME_APPEND_SLASH(out);
- }
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
-@@ -173,22 +175,19 @@
- return 0;
- }
--
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(server_root);
-- PATCH(default_host);
-- PATCH(document_root);
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_freebsd_sendfile.c lighttpd-1.4.12/src/network_freebsd_sendfile.c
+--- lighttpd-1.4.11/src/network_freebsd_sendfile.c 2005-10-22 12:28:18.000000000 +0300
++++ lighttpd-1.4.12/src/network_freebsd_sendfile.c 2006-07-11 21:23:40.000000000 +0300
+@@ -26,142 +26,61 @@
+
+ #ifndef UIO_MAXIOV
+ # ifdef __FreeBSD__
+-/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
++/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
+ # define UIO_MAXIOV 1024
+ # endif
+ #endif
+
+-int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
++NETWORK_BACKEND_WRITE(freebsdsendfile) {
+ chunk *c;
+ size_t chunks_written = 0;
-
-- PATCH(docroot_cache_key);
-- PATCH(docroot_cache_value);
-- PATCH(docroot_cache_servername);
-+ PATCH_OPTION(server_root);
-+ PATCH_OPTION(default_host);
-+ PATCH_OPTION(document_root);
+
-+ PATCH_OPTION(docroot_cache_key);
-+ PATCH_OPTION(docroot_cache_value);
-+ PATCH_OPTION(docroot_cache_servername);
-
-- PATCH(debug);
-+ PATCH_OPTION(debug);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -203,23 +202,22 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
-- PATCH(server_root);
-- PATCH(docroot_cache_key);
-- PATCH(docroot_cache_value);
-- PATCH(docroot_cache_servername);
-+ PATCH_OPTION(server_root);
-+ PATCH_OPTION(docroot_cache_key);
-+ PATCH_OPTION(docroot_cache_value);
-+ PATCH_OPTION(docroot_cache_servername);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
-- PATCH(default_host);
-+ PATCH_OPTION(default_host);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
-- PATCH(document_root);
-+ PATCH_OPTION(document_root);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
-- PATCH(debug);
-+ PATCH_OPTION(debug);
+ for(c = cq->first; c; c = c->next, chunks_written++) {
+ int chunk_finished = 0;
+-
++ network_status_t ret;
++
+ switch(c->type) {
+- case MEM_CHUNK: {
+- char * offset;
+- size_t toSend;
+- ssize_t r;
+-
+- size_t num_chunks, i;
+- struct iovec chunks[UIO_MAXIOV];
+- chunk *tc;
+- size_t num_bytes = 0;
+-
+- /* we can't send more then SSIZE_MAX bytes in one chunk */
+-
+- /* build writev list
+- *
+- * 1. limit: num_chunks < UIO_MAXIOV
+- * 2. limit: num_bytes < SSIZE_MAX
+- */
+- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
+-
+- for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
+- if (tc->mem->used == 0) {
+- chunks[i].iov_base = tc->mem->ptr;
+- chunks[i].iov_len = 0;
+- } else {
+- offset = tc->mem->ptr + tc->offset;
+- toSend = tc->mem->used - 1 - tc->offset;
+-
+- chunks[i].iov_base = offset;
+-
+- /* protect the return value of writev() */
+- if (toSend > SSIZE_MAX ||
+- num_bytes + toSend > SSIZE_MAX) {
+- chunks[i].iov_len = SSIZE_MAX - num_bytes;
+-
+- num_chunks = i + 1;
+- break;
+- } else {
+- chunks[i].iov_len = toSend;
+- }
+-
+- num_bytes += toSend;
+- }
+- }
+-
+- if ((r = writev(fd, chunks, num_chunks)) < 0) {
+- switch (errno) {
+- case EAGAIN:
+- case EINTR:
+- r = 0;
+- break;
+- case EPIPE:
+- case ECONNRESET:
+- return -2;
+- default:
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
+- "writev failed:", strerror(errno), fd);
+-
+- return -1;
+- }
++ case MEM_CHUNK:
++ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
+
+- r = 0;
+- }
+-
+- /* check which chunks have been written */
+- cq->bytes_out += r;
+-
+- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
+- if (r >= (ssize_t)chunks[i].iov_len) {
+- /* written */
+- r -= chunks[i].iov_len;
+- tc->offset += chunks[i].iov_len;
+-
+- if (chunk_finished) {
+- /* skip the chunks from further touches */
+- chunks_written++;
+- c = c->next;
+- } else {
+- /* chunks_written + c = c->next is done in the for()*/
+- chunk_finished++;
+- }
+- } else {
+- /* partially written */
+-
+- tc->offset += r;
+- chunk_finished = 0;
+-
+- break;
+- }
++ if (ret != NETWORK_STATUS_SUCCESS) {
++ return ret;
+ }
+-
++
++ chunk_finished = 1;
++
+ break;
+- }
+ case FILE_CHUNK: {
+ off_t offset, r;
+ size_t toSend;
+ stat_cache_entry *sce = NULL;
+ int ifd;
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ strerror(errno), c->file.name);
+- return -1;
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ offset = c->file.start + c->offset;
+ /* limit the toSend to 2^31-1 bytes in a chunk */
+- toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
++ toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
+ ((1 << 30) - 1) : c->file.length - c->offset;
+-
++
+ if (offset > sce->st.st_size) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ r = 0;
+-
++
+ /* FreeBSD sendfile() */
+ if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
+ switch(errno) {
+@@ -169,39 +88,39 @@
+ break;
+ case ENOTCONN:
+ close(ifd);
+- return -2;
++ return NETWORK_STATUS_CONNECTION_CLOSE;
+ default:
+ log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
+ close(ifd);
+- return -1;
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
}
- }
- }
-
- return 0;
- }
--#undef PATCH
-
- static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
- plugin_data *p = p_data;
---- lighttpd-1.4.11/src/mod_skeleton.c 2005-10-02 18:30:51.000000000 +0300
-+++ lighttpd/src/mod_skeleton.c 2006-07-11 21:23:40.019850968 +0300
-@@ -132,13 +132,11 @@
- return HANDLER_GO_ON;
- }
-
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(match);
-+ PATCH_OPTION(match);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -153,14 +151,13 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
-- PATCH(match);
-+ PATCH_OPTION(match);
+ close(ifd);
+-
++
+ c->offset += r;
+ cq->bytes_out += r;
+-
++
+ if (c->offset == c->file.length) {
+ chunk_finished = 1;
}
+-
++
+ break;
+ }
+ default:
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+-
++
+ return -1;
+ }
+-
++
+ if (!chunk_finished) {
+ /* not finished yet */
+-
++
+ break;
}
}
-
- return 0;
- }
--#undef PATCH
- URIHANDLER_FUNC(mod_skeleton_uri_handler) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_ssi.c 2006-03-04 17:09:48.000000000 +0200
-+++ lighttpd/src/mod_ssi.c 2006-07-11 21:23:40.159859737 +0300
-@@ -6,7 +6,6 @@
- #include <string.h>
- #include <errno.h>
- #include <time.h>
--#include <unistd.h>
+- return chunks_written;
++ return NETWORK_STATUS_SUCCESS;
+ }
- #include "base.h"
- #include "log.h"
-@@ -23,6 +22,8 @@
- #include "inet_ntop_cache.h"
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_linux_sendfile.c lighttpd-1.4.12/src/network_linux_sendfile.c
+--- lighttpd-1.4.11/src/network_linux_sendfile.c 2006-02-15 20:02:36.000000000 +0200
++++ lighttpd-1.4.12/src/network_linux_sendfile.c 2006-07-11 21:23:40.000000000 +0300
+@@ -26,122 +26,54 @@
+ /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
+ #undef HAVE_POSIX_FADVISE
- #include "sys-socket.h"
-+#include "sys-strings.h"
-+#include "sys-files.h"
+-int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
+- chunk *c;
++NETWORK_BACKEND_WRITE(linuxsendfile) {
++ chunk *c, *tc;
+ size_t chunks_written = 0;
+-
++
+ for(c = cq->first; c; c = c->next, chunks_written++) {
+ int chunk_finished = 0;
+-
++ network_status_t ret;
++
+ switch(c->type) {
+- case MEM_CHUNK: {
+- char * offset;
+- size_t toSend;
+- ssize_t r;
+-
+- size_t num_chunks, i;
+- struct iovec chunks[UIO_MAXIOV];
+- chunk *tc;
+- size_t num_bytes = 0;
+-
+- /* we can't send more then SSIZE_MAX bytes in one chunk */
+-
+- /* build writev list
+- *
+- * 1. limit: num_chunks < UIO_MAXIOV
+- * 2. limit: num_bytes < SSIZE_MAX
+- */
+- for (num_chunks = 0, tc = c;
+- tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
+- tc = tc->next, num_chunks++);
+-
+- for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
+- if (tc->mem->used == 0) {
+- chunks[i].iov_base = tc->mem->ptr;
+- chunks[i].iov_len = 0;
+- } else {
+- offset = tc->mem->ptr + tc->offset;
+- toSend = tc->mem->used - 1 - tc->offset;
+-
+- chunks[i].iov_base = offset;
+-
+- /* protect the return value of writev() */
+- if (toSend > SSIZE_MAX ||
+- num_bytes + toSend > SSIZE_MAX) {
+- chunks[i].iov_len = SSIZE_MAX - num_bytes;
+-
+- num_chunks = i + 1;
+- break;
+- } else {
+- chunks[i].iov_len = toSend;
+- }
+-
+- num_bytes += toSend;
+- }
+- }
+-
+- if ((r = writev(fd, chunks, num_chunks)) < 0) {
+- switch (errno) {
+- case EAGAIN:
+- case EINTR:
+- r = 0;
+- break;
+- case EPIPE:
+- case ECONNRESET:
+- return -2;
+- default:
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
+- "writev failed:", strerror(errno), fd);
+-
+- return -1;
+- }
+- }
+-
+- /* check which chunks have been written */
+- cq->bytes_out += r;
++ case MEM_CHUNK:
++ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
- #ifdef HAVE_PWD_H
- #include <pwd.h>
-@@ -660,6 +661,8 @@
-
- break;
- case SSI_EXEC: {
-+#ifndef _WIN32
+- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
+- if (r >= (ssize_t)chunks[i].iov_len) {
+- /* written */
+- r -= chunks[i].iov_len;
+- tc->offset += chunks[i].iov_len;
+-
++ /* check which chunks are finished now */
++ for (tc = c; tc; tc = tc->next) {
++ /* finished the chunk */
++ if (tc->offset == tc->mem->used - 1) {
++ /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
+ if (chunk_finished) {
+- /* skip the chunks from further touches */
+- chunks_written++;
+ c = c->next;
+ } else {
+- /* chunks_written + c = c->next is done in the for()*/
+- chunk_finished++;
++ chunk_finished = 1;
+ }
+ } else {
+- /* partially written */
+-
+- tc->offset += r;
+- chunk_finished = 0;
+-
+ break;
+ }
+ }
+-
+
- const char *cmd = NULL;
- pid_t pid;
- int from_exec_fds[2];
-@@ -682,7 +685,7 @@
- */
-
- if (!cmd) break;
--#ifdef HAVE_FORK
++ if (ret != NETWORK_STATUS_SUCCESS) {
++ return ret;
++ }
++
+ break;
+- }
+ case FILE_CHUNK: {
+ ssize_t r;
+ off_t offset;
+ size_t toSend;
+ stat_cache_entry *sce = NULL;
+-
++
+ offset = c->file.start + c->offset;
+ /* limit the toSend to 2^31-1 bytes in a chunk */
+- toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
++ toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
+ ((1 << 30) - 1) : c->file.length - c->offset;
+-
+- /* open file if not already opened */
+
- if (pipe(from_exec_fds)) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "pipe failed: ", strerror(errno));
-@@ -760,7 +763,6 @@
- }
- }
- #else
--
- return -1;
++ /* open file if not already opened */
+ if (-1 == c->file.fd) {
+ if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+-
++
+ return -1;
+ }
+ #ifdef FD_CLOEXEC
+@@ -151,7 +83,7 @@
+ /* tell the kernel that we want to stream the file */
+ if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
+ if (ENOSYS != errno) {
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
++ log_error_write(srv, __FILE__, __LINE__, "ssd",
+ "posix_fadvise failed:", strerror(errno), c->file.fd);
+ }
+ }
+@@ -168,7 +100,7 @@
+ case ECONNRESET:
+ return -2;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
++ log_error_write(srv, __FILE__, __LINE__, "ssd",
+ "sendfile failed:", strerror(errno), fd);
+ return -1;
+ }
+@@ -179,7 +111,7 @@
+ *
+ * - the file shrinked -> error
+ * - the remote side closed inbetween -> remote-close */
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+ /* file is gone ? */
+ return -1;
+@@ -196,22 +128,22 @@
+ #ifdef HAVE_POSIX_FADVISE
+ #if 0
+ #define K * 1024
+-#define M * 1024 K
++#define M * 1024 K
+ #define READ_AHEAD 4 M
+ /* check if we need a new chunk */
+ if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
+ /* tell the kernel that we want to stream the file */
+ if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
++ log_error_write(srv, __FILE__, __LINE__, "ssd",
+ "posix_fadvise failed:", strerror(errno), c->file.fd);
+ }
+ }
#endif
-
-@@ -1008,13 +1010,11 @@
- return 0;
- }
+ #endif
+-
++
+ c->offset += r;
+ cq->bytes_out += r;
+-
++
+ if (c->offset == c->file.length) {
+ chunk_finished = 1;
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(ssi_extension);
-+ PATCH_OPTION(ssi_extension);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -1029,14 +1029,13 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
-- PATCH(ssi_extension);
-+ PATCH_OPTION(ssi_extension);
+@@ -222,19 +154,19 @@
+ c->file.fd = -1;
+ }
}
+-
++
+ break;
+ }
+ default:
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+-
++
+ return -1;
+ }
+-
++
+ if (!chunk_finished) {
+ /* not finished yet */
+-
++
+ break;
}
}
-
- return 0;
- }
--#undef PATCH
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_openssl.c lighttpd-1.4.12/src/network_openssl.c
+--- lighttpd-1.4.11/src/network_openssl.c 2005-11-17 14:53:29.000000000 +0200
++++ lighttpd-1.4.12/src/network_openssl.c 2006-07-11 21:23:40.000000000 +0300
+@@ -23,17 +23,87 @@
+ #include "log.h"
+ #include "stat_cache.h"
- URIHANDLER_FUNC(mod_ssi_physical_path) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_staticfile.c 2006-02-15 14:31:14.000000000 +0200
-+++ lighttpd/src/mod_staticfile.c 2006-07-11 21:23:39.979848462 +0300
-@@ -14,6 +14,8 @@
- #include "http_chunk.h"
- #include "response.h"
+-# include <openssl/ssl.h>
+-# include <openssl/err.h>
++# include <openssl/ssl.h>
++# include <openssl/err.h>
-+#include "sys-files.h"
-+#include "sys-strings.h"
- /**
- * this is a staticfile for a lighttpd plugin
- *
-@@ -48,7 +50,7 @@
- return p;
- }
+-int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
++NETWORK_BACKEND_READ_SSL(openssl) {
++ buffer *b;
++ off_t len;
++
++ b = chunkqueue_get_append_buffer(cq);
++ buffer_prepare_copy(b, 8192);
++ len = SSL_read(ssl, b->ptr, b->size - 1);
++
++ log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
++
++ if (len < 0) {
++ int r, ssl_err;
++
++ switch ((r = SSL_get_error(con->ssl, len))) {
++ case SSL_ERROR_WANT_READ:
++ return NETWORK_STATUS_WAIT_FOR_EVENT;
++ case SSL_ERROR_SYSCALL:
++ /**
++ * man SSL_get_error()
++ *
++ * SSL_ERROR_SYSCALL
++ * Some I/O error occurred. The OpenSSL error queue may contain more
++ * information on the error. If the error queue is empty (i.e.
++ * ERR_get_error() returns 0), ret can be used to find out more about
++ * the error: If ret == 0, an EOF was observed that violates the
++ * protocol. If ret == -1, the underlying BIO reported an I/O error
++ * (for socket I/O on Unix systems, consult errno for details).
++ *
++ */
++ while((ssl_err = ERR_get_error())) {
++ /* get all errors from the error-queue */
++ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
++ r, ERR_error_string(ssl_err, NULL));
++ }
++
++ switch(errno) {
++ default:
++ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
++ len, r, errno,
++ strerror(errno));
++ break;
++ }
++
++ break;
++ case SSL_ERROR_ZERO_RETURN:
++ /* clean shutdown on the remote side */
++
++ if (r == 0) {
++ /* FIXME: later */
++ }
++
++ /* fall thourgh */
++ default:
++ while((ssl_err = ERR_get_error())) {
++ /* get all errors from the error-queue */
++ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
++ r, ERR_error_string(ssl_err, NULL));
++ }
++ break;
++ }
++ }
++
++ assert(len > 0);
++ b->used += len;
++ b->ptr[b->used - 1] = '\0';
++
++ return NETWORK_STATUS_SUCCESS;
++}
++
++
++NETWORK_BACKEND_WRITE_SSL(openssl) {
+ int ssl_r;
+ chunk *c;
+ size_t chunks_written = 0;
--/* detroy the plugin data */
-+/* destroy the plugin data */
- FREE_FUNC(mod_staticfile_free) {
- plugin_data *p = p_d;
-
-@@ -107,13 +109,11 @@
- return HANDLER_GO_ON;
- }
+ /* this is a 64k sendbuffer
+ *
+- * it has to stay at the same location all the time to satisfy the needs
++ * it has to stay at the same location all the time to satisfy the needs
+ * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
+ *
+ * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
+@@ -43,14 +113,14 @@
+ * In reality we would like to use mmap() but we don't have a guarantee that
+ * we get the same mmap() address for each call. On openbsd the mmap() address
+ * even randomized.
+- * That means either we keep the mmap() open or we do a read() into a
+- * constant buffer
++ * That means either we keep the mmap() open or we do a read() into a
++ * constant buffer
+ * */
+ #define LOCAL_SEND_BUFSIZE (64 * 1024)
+ static char *local_send_buffer = NULL;
+
+ /* the remote side closed the connection before without shutdown request
+- * - IE
++ * - IE
+ * - wget
+ * if keep-alive is disabled */
+
+@@ -60,32 +130,34 @@
+
+ for(c = cq->first; c; c = c->next) {
+ int chunk_finished = 0;
+-
++
+ switch(c->type) {
+ case MEM_CHUNK: {
+ char * offset;
+ size_t toSend;
+- ssize_t r;
+-
++ ssize_t r = 0;
++
+ if (c->mem->used == 0) {
+ chunk_finished = 1;
+ break;
+ }
+-
++
+ offset = c->mem->ptr + c->offset;
+ toSend = c->mem->used - 1 - c->offset;
+-
++
+ /**
+ * SSL_write man-page
+- *
++ *
+ * WARNING
+ * When an SSL_write() operation has to be repeated because of
+ * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
+ * repeated with the same arguments.
+- *
++ *
++ * SSL_write(..., 0) return 0 which is handle as an error (Success)
++ * checking toSend and not calling SSL_write() is simpler
+ */
+-
+- if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
++
++ if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
+ unsigned long err;
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(exclude_ext);
-+ PATCH_OPTION(exclude_ext);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -128,14 +128,13 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
-- PATCH(exclude_ext);
-+ PATCH_OPTION(exclude_ext);
+ switch ((ssl_r = SSL_get_error(ssl, r))) {
+@@ -95,7 +167,7 @@
+ /* perhaps we have error waiting in our error-queue */
+ if (0 != (err = ERR_get_error())) {
+ do {
+- log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+ ssl_r, r,
+ ERR_error_string(err, NULL));
+ } while((err = ERR_get_error()));
+@@ -105,43 +177,43 @@
+ case EPIPE:
+ return -2;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
+ ssl_r, r, errno,
+ strerror(errno));
+ break;
+ }
+ } else {
+ /* neither error-queue nor errno ? */
+- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
++ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
+ ssl_r, r, errno,
+ strerror(errno));
+ }
+-
++
+ return -1;
+ case SSL_ERROR_ZERO_RETURN:
+ /* clean shutdown on the remote side */
+-
++
+ if (r == 0) return -2;
+-
++
+ /* fall through */
+ default:
+ while((err = ERR_get_error())) {
+- log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+ ssl_r, r,
+ ERR_error_string(err, NULL));
+ }
+-
++
+ return -1;
+ }
+ } else {
+ c->offset += r;
+ cq->bytes_out += r;
+ }
+-
++
+ if (c->offset == (off_t)c->mem->used - 1) {
+ chunk_finished = 1;
}
+-
++
+ break;
}
- }
-
- return 0;
- }
--#undef PATCH
+ case FILE_CHUNK: {
+@@ -150,7 +222,7 @@
+ stat_cache_entry *sce = NULL;
+ int ifd;
+ int write_wait = 0;
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ strerror(errno), c->file.name);
+@@ -164,13 +236,13 @@
+
+ do {
+ off_t offset = c->file.start + c->offset;
+- off_t toSend = c->file.length - c->offset;
++ off_t toSend = c->file.length - c->offset;
- static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
- int multipart = 0;
-@@ -396,7 +395,7 @@
- return HANDLER_FINISHED;
- }
-
-- /* we only handline regular files */
-+ /* we only handle regular files */
- if (!S_ISREG(sce->st.st_mode)) {
- con->http_status = 404;
-
-@@ -409,7 +408,7 @@
- return HANDLER_FINISHED;
- }
+ if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
+-
++
+ if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
+-
++
+ return -1;
+ }
-- /* mod_compress might set several data directly, don't overwrite them */
-+ /* mod_compress might set several parameters directly; don't overwrite them */
-
- /* set response content-type, if not set already */
+@@ -183,9 +255,9 @@
+ }
---- lighttpd-1.4.11/src/mod_status.c 2006-01-10 21:45:32.000000000 +0200
-+++ lighttpd/src/mod_status.c 2006-07-11 21:23:40.131857983 +0300
-@@ -4,7 +4,6 @@
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
--#include <unistd.h>
- #include <errno.h>
- #include <time.h>
- #include <stdio.h>
-@@ -202,7 +201,7 @@
- size_t j;
- double avg;
- char multiplier = '\0';
-- char buf[32];
-+ char buf[128];
- time_t ts;
-
- int days, hours, mins, seconds;
-@@ -304,13 +303,13 @@
- /* connection listing */
- BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
-
-- BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
-- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
-+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
- buffer_append_string_buffer(b, con->uri.authority);
-- BUFFER_APPEND_STRING_CONST(b, " (");
-+ BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
- buffer_append_string_buffer(b, con->server_name);
-- BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
-- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
-+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
-
- ts = srv->cur_ts - srv->startup_ts;
-
-@@ -348,58 +347,58 @@
-
- ts = srv->startup_ts;
-
-- strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
-+ strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
- buffer_append_string(b, buf);
- BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
-
-
- BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
-
-- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
- avg = p->abs_requests;
+ s = local_send_buffer;
+-
++
+ close(ifd);
+-
++
+ if ((r = SSL_write(ssl, s, toSend)) <= 0) {
+ unsigned long err;
+
+@@ -197,7 +269,7 @@
+ /* perhaps we have error waiting in our error-queue */
+ if (0 != (err = ERR_get_error())) {
+ do {
+- log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+ ssl_r, r,
+ ERR_error_string(err, NULL));
+ } while((err = ERR_get_error()));
+@@ -207,58 +279,58 @@
+ case EPIPE:
+ return -2;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
+ ssl_r, r, errno,
+ strerror(errno));
+ break;
+ }
+ } else {
+ /* neither error-queue nor errno ? */
+- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
++ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
+ ssl_r, r, errno,
+ strerror(errno));
+ }
+-
++
+ return -1;
+ case SSL_ERROR_ZERO_RETURN:
+ /* clean shutdown on the remote side */
+-
++
+ if (r == 0) return -2;
+-
++
+ /* fall thourgh */
+ default:
+ while((err = ERR_get_error())) {
+- log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
++ log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+ ssl_r, r,
+ ERR_error_string(err, NULL));
+ }
+-
++
+ return -1;
+ }
+ } else {
+ c->offset += r;
+ cq->bytes_out += r;
+ }
+-
++
+ if (c->offset == c->file.length) {
+ chunk_finished = 1;
+ }
+ } while(!chunk_finished && !write_wait);
+-
++
+ break;
+ }
+ default:
+ log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
+-
++
+ return -1;
+ }
+-
++
+ if (!chunk_finished) {
+ /* not finished yet */
+-
++
+ break;
+ }
+-
++
+ chunks_written++;
+ }
- mod_status_get_multiplier(&avg, &multiplier, 1000);
-
- buffer_append_long(b, avg);
-- BUFFER_APPEND_STRING_CONST(b, " ");
-+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
-- BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
-+ BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
-
-- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
- avg = p->abs_traffic_out;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_solaris_sendfilev.c lighttpd-1.4.12/src/network_solaris_sendfilev.c
+--- lighttpd-1.4.11/src/network_solaris_sendfilev.c 2005-10-22 12:28:27.000000000 +0300
++++ lighttpd-1.4.12/src/network_solaris_sendfilev.c 2006-07-11 21:23:40.000000000 +0300
+@@ -29,114 +29,34 @@
+ #endif
- mod_status_get_multiplier(&avg, &multiplier, 1024);
+ /**
+- * a very simple sendfilev() interface for solaris which can be optimised a lot more
++ * a very simple sendfilev() interface for solaris which can be optimised a lot more
+ * as solaris sendfilev() supports 'sending everythin in one syscall()'
+- *
+- * If you want such an interface and need the performance, just give me an account on
+- * a solaris box.
++ *
++ * If you want such an interface and need the performance, just give me an account on
++ * a solaris box.
+ * - jan@kneschke.de
+ */
- sprintf(buf, "%.2f", avg);
- buffer_append_string(b, buf);
-- BUFFER_APPEND_STRING_CONST(b, " ");
-+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_mult\">");
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
-- BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
-+ BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
+-int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
++NETWORK_BACKEND_WRITE(solarissendfilev) {
+ chunk *c;
+ size_t chunks_written = 0;
+-
++
+ for(c = cq->first; c; c = c->next, chunks_written++) {
+ int chunk_finished = 0;
+-
++ network_status_t ret;
++
+ switch(c->type) {
+- case MEM_CHUNK: {
+- char * offset;
+- size_t toSend;
+- ssize_t r;
+-
+- size_t num_chunks, i;
+- struct iovec chunks[UIO_MAXIOV];
+- chunk *tc;
+-
+- size_t num_bytes = 0;
+-
+- /* we can't send more then SSIZE_MAX bytes in one chunk */
+-
+- /* build writev list
+- *
+- * 1. limit: num_chunks < UIO_MAXIOV
+- * 2. limit: num_bytes < SSIZE_MAX
+- */
+- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
+-
+- for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
+- if (tc->mem->used == 0) {
+- chunks[i].iov_base = tc->mem->ptr;
+- chunks[i].iov_len = 0;
+- } else {
+- offset = tc->mem->ptr + tc->offset;
+- toSend = tc->mem->used - 1 - tc->offset;
+-
+- chunks[i].iov_base = offset;
+-
+- /* protect the return value of writev() */
+- if (toSend > SSIZE_MAX ||
+- num_bytes + toSend > SSIZE_MAX) {
+- chunks[i].iov_len = SSIZE_MAX - num_bytes;
+-
+- num_chunks = i + 1;
+- break;
+- } else {
+- chunks[i].iov_len = toSend;
+- }
+-
+- num_bytes += toSend;
+- }
+- }
+-
+- if ((r = writev(fd, chunks, num_chunks)) < 0) {
+- switch (errno) {
+- case EAGAIN:
+- case EINTR:
+- r = 0;
+- break;
+- case EPIPE:
+- case ECONNRESET:
+- return -2;
+- default:
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
+- "writev failed:", strerror(errno), fd);
+-
+- return -1;
+- }
+- }
+-
+- /* check which chunks have been written */
+- cq->bytes_out += r;
+-
+- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
+- if (r >= (ssize_t)chunks[i].iov_len) {
+- /* written */
+- r -= chunks[i].iov_len;
+- tc->offset += chunks[i].iov_len;
+-
+- if (chunk_finished) {
+- /* skip the chunks from further touches */
+- chunks_written++;
+- c = c->next;
+- } else {
+- /* chunks_written + c = c->next is done in the for()*/
+- chunk_finished++;
+- }
+- } else {
+- /* partially written */
+-
+- tc->offset += r;
+- chunk_finished = 0;
+-
+- break;
+- }
++ case MEM_CHUNK:
++ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
++
++ if (ret != NETWORK_STATUS_SUCCESS) {
++ return ret;
+ }
+-
++
++ chunk_finished = 1;
++
+ break;
+- }
+ case FILE_CHUNK: {
+ ssize_t r;
+ off_t offset;
+@@ -144,25 +64,25 @@
+ sendfilevec_t fvec;
+ stat_cache_entry *sce = NULL;
+ int ifd;
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ strerror(errno), c->file.name);
+ return -1;
+ }
+-
++
+ offset = c->file.start + c->offset;
+ toSend = c->file.length - c->offset;
+-
++
+ if (offset > sce->st.st_size) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
+-
++
+ return -1;
+ }
+ if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+-
++
+ return -1;
+ }
- BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
-
-- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
- avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
+@@ -170,44 +90,43 @@
+ fvec.sfv_flag = 0;
+ fvec.sfv_off = offset;
+ fvec.sfv_len = toSend;
+-
++
+ /* Solaris sendfilev() */
+ if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
+ if (errno != EAGAIN) {
+ log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
+-
++
+ close(ifd);
+- return -1;
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ r = 0;
+ }
+-
++
+ close(ifd);
+ c->offset += written;
+ cq->bytes_out += written;
+-
++
+ if (c->offset == c->file.length) {
+ chunk_finished = 1;
+ }
+-
++
+ break;
+ }
+ default:
+-
+ log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ if (!chunk_finished) {
+ /* not finished yet */
+-
++
+ break;
+ }
+ }
- mod_status_get_multiplier(&avg, &multiplier, 1000);
+- return chunks_written;
++ return NETWORK_STATUS_SUCCESS;
+ }
- buffer_append_long(b, avg);
-- BUFFER_APPEND_STRING_CONST(b, " ");
-+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
-- BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
-+ BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
-
-- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
- avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_write.c lighttpd-1.4.12/src/network_write.c
+--- lighttpd-1.4.11/src/network_write.c 2005-10-22 12:27:56.000000000 +0300
++++ lighttpd-1.4.12/src/network_write.c 2006-07-11 21:23:39.000000000 +0300
+@@ -1,11 +1,11 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+-#include <sys/time.h>
++
+ #include <errno.h>
+ #include <fcntl.h>
+-#include <unistd.h>
+ #include <string.h>
+ #include <stdlib.h>
++#include <assert.h>
- mod_status_get_multiplier(&avg, &multiplier, 1024);
+ #include "network.h"
+ #include "fdevent.h"
+@@ -13,9 +13,12 @@
+ #include "stat_cache.h"
- sprintf(buf, "%.2f", avg);
- buffer_append_string(b, buf);
-- BUFFER_APPEND_STRING_CONST(b, " ");
-+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
-- BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
-+ BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
+ #include "sys-socket.h"
++#include "sys-files.h"
-
-
-@@ -410,15 +409,15 @@
-
- avg /= 5;
-
-- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
+ #include "network_backends.h"
- mod_status_get_multiplier(&avg, &multiplier, 1000);
++#ifdef USE_WRITE
++
+ #ifdef HAVE_SYS_FILIO_H
+ # include <sys/filio.h>
+ #endif
+@@ -24,47 +27,86 @@
+ #include <sys/resource.h>
+ #endif
- buffer_append_long(b, avg);
-- BUFFER_APPEND_STRING_CONST(b, " ");
-+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
-
-- BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
-+ BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
-
- for (j = 0, avg = 0; j < 5; j++) {
- avg += p->mod_5s_traffic_out[j];
-@@ -426,15 +425,15 @@
-
- avg /= 5;
-
-- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
+-int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
++/**
++* fill the chunkqueue will all the data that we can get
++*
++* this might be optimized into a readv() which uses the chunks
++* as vectors
++*/
++NETWORK_BACKEND_READ(read) {
++ int toread;
++ buffer *b;
++ off_t r;
++
++ /* check how much we have to read */
++ if (ioctl(fd, FIONREAD, &toread)) {
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "ioctl failed: ",
++ fd);
++ return NETWORK_STATUS_FATAL_ERROR;
++ }
++
++ if (toread == 0) return NETWORK_STATUS_WAIT_FOR_EVENT;
++
++ /*
++ * our chunk queue is quiet large already
++ *
++ * let's buffer it to disk
++ */
++
++ b = chunkqueue_get_append_buffer(cq);
++
++ buffer_prepare_copy(b, toread);
++
++ if (-1 == (r = read(fd, b->ptr, toread))) {
++ log_error_write(srv, __FILE__, __LINE__, "sds",
++ "unexpected end-of-file (perhaps the proxy process died):",
++ fd, strerror(errno));
++ return NETWORK_STATUS_FATAL_ERROR;
++ }
++
++ /* this should be catched by the b > 0 above */
++ assert(r);
++ b->used += r + 1;
++ b->ptr[b->used - 1] = '\0';
++
++ return NETWORK_STATUS_SUCCESS;
++}
++
++NETWORK_BACKEND_WRITE(write) {
+ chunk *c;
+ size_t chunks_written = 0;
+-
++
+ for(c = cq->first; c; c = c->next) {
+ int chunk_finished = 0;
+-
++
+ switch(c->type) {
+ case MEM_CHUNK: {
+ char * offset;
+ size_t toSend;
+ ssize_t r;
+-
++
+ if (c->mem->used == 0) {
+ chunk_finished = 1;
+ break;
+ }
+-
++
+ offset = c->mem->ptr + c->offset;
+ toSend = c->mem->used - 1 - c->offset;
+-#ifdef __WIN32
+- if ((r = send(fd, offset, toSend, 0)) < 0) {
+- log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
+-
+- return -1;
+- }
+-#else
++
+ if ((r = write(fd, offset, toSend)) < 0) {
+ log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-#endif
+-
++
+ c->offset += r;
+ cq->bytes_out += r;
+-
++
+ if (c->offset == (off_t)c->mem->used - 1) {
+ chunk_finished = 1;
+ }
+-
++
+ break;
+ }
+ case FILE_CHUNK: {
+@@ -76,93 +118,89 @@
+ size_t toSend;
+ stat_cache_entry *sce = NULL;
+ int ifd;
+-
++
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ strerror(errno), c->file.name);
+- return -1;
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ offset = c->file.start + c->offset;
+ toSend = c->file.length - c->offset;
+-
++
+ if (offset > sce->st.st_size) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
- mod_status_get_multiplier(&avg, &multiplier, 1024);
+ if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ #if defined USE_MMAP
+ if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
- sprintf(buf, "%.2f", avg);
- buffer_append_string(b, buf);
-- BUFFER_APPEND_STRING_CONST(b, " ");
-+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
-- BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
-+ BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
-
- BUFFER_APPEND_STRING_CONST(b, "</table>\n");
-
-@@ -445,9 +444,9 @@
- BUFFER_APPEND_STRING_CONST(b, "q = request-start, Q = request-end\n");
- BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
-
-- BUFFER_APPEND_STRING_CONST(b, "<b>");
-+ BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
- buffer_append_long(b, srv->conns->used);
-- BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
-+ BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
-
- for (j = 0; j < srv->conns->used; j++) {
- connection *c = srv->conns->ptr[j];
-@@ -462,7 +461,7 @@
-
- BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
-
-- BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
-+ BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
- BUFFER_APPEND_STRING_CONST(b, "<tr>");
- mod_status_header_append_sort(b, p_d, "Client IP");
- mod_status_header_append_sort(b, p_d, "Read");
-@@ -477,11 +476,11 @@
- for (j = 0; j < srv->conns->used; j++) {
- connection *c = srv->conns->ptr[j];
-
-- BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
-
- buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
-
-- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
-+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
-
- if (con->request.content_length) {
- buffer_append_long(b, c->request_content_queue->bytes_in);
-@@ -491,21 +490,21 @@
- BUFFER_APPEND_STRING_CONST(b, "0/0");
+ close(ifd);
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+ close(ifd);
+
+ if ((r = write(fd, p + offset, toSend)) <= 0) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
+ munmap(p, sce->st.st_size);
+- return -1;
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ munmap(p, sce->st.st_size);
+ #else
+ buffer_prepare_copy(srv->tmp_buf, toSend);
+-
++
+ lseek(ifd, offset, SEEK_SET);
+ if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
+ close(ifd);
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+ close(ifd);
+
+ if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+ #endif
+ c->offset += r;
+ cq->bytes_out += r;
+-
++
+ if (c->offset == c->file.length) {
+ chunk_finished = 1;
+ }
+-
++
+ break;
}
-
-- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
-+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
-
- buffer_append_off_t(b, chunkqueue_written(c->write_queue));
- BUFFER_APPEND_STRING_CONST(b, "/");
- buffer_append_off_t(b, chunkqueue_length(c->write_queue));
-
-- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
-
- buffer_append_string(b, connection_get_state(c->state));
-
-- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
-+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
-
- buffer_append_long(b, srv->cur_ts - c->request_start);
-
-- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
-
- if (buffer_is_empty(c->server_name)) {
- buffer_append_string_buffer(b, c->uri.authority);
-@@ -514,13 +513,13 @@
- buffer_append_string_buffer(b, c->server_name);
+ default:
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
}
-
-- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
-
- if (!buffer_is_empty(c->uri.path)) {
- buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
+-
++
+ if (!chunk_finished) {
+ /* not finished yet */
+-
++
+ break;
}
-
-- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
-+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
-
- buffer_append_string_buffer(b, c->physical.path);
-
-@@ -723,16 +722,14 @@
- return HANDLER_FINISHED;
+-
++
+ chunks_written++;
+ }
+
+- return chunks_written;
++ return NETWORK_STATUS_SUCCESS;
}
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(status_url);
-- PATCH(config_url);
-- PATCH(sort);
-- PATCH(statistics_url);
-+ PATCH_OPTION(status_url);
-+ PATCH_OPTION(config_url);
-+ PATCH_OPTION(sort);
-+ PATCH_OPTION(statistics_url);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -747,13 +744,13 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
-- PATCH(status_url);
-+ PATCH_OPTION(status_url);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
-- PATCH(config_url);
-+ PATCH_OPTION(config_url);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
-- PATCH(sort);
-+ PATCH_OPTION(sort);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
-- PATCH(statistics_url);
-+ PATCH_OPTION(statistics_url);
- }
- }
- }
---- lighttpd-1.4.11/src/mod_trigger_b4_dl.c 2005-09-23 22:53:55.000000000 +0300
-+++ lighttpd/src/mod_trigger_b4_dl.c 2006-07-11 21:23:39.991849214 +0300
-@@ -241,25 +241,23 @@
- return HANDLER_GO_ON;
- }
+-#if 0
+-network_write_init(void) {
+- p->write = network_write_write_chunkset;
+-}
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_writev.c lighttpd-1.4.12/src/network_writev.c
+--- lighttpd-1.4.11/src/network_writev.c 2006-02-15 01:02:36.000000000 +0200
++++ lighttpd-1.4.12/src/network_writev.c 2006-07-11 21:23:40.000000000 +0300
+@@ -28,10 +28,10 @@
+
+ #ifndef UIO_MAXIOV
+ # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
+-/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
++/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
+ # define UIO_MAXIOV 1024
+ # elif defined(__sgi)
+-/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
++/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
+ # define UIO_MAXIOV 512
+ # elif defined(__sun)
+ /* Solaris (and SunOS?) defines IOV_MAX instead */
+@@ -51,105 +51,119 @@
+ #define LOCAL_BUFFERING 1
+ #endif
+
+-int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
+- chunk *c;
++NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
++ char * offset;
++ size_t toSend;
++ ssize_t r;
++
++ size_t num_chunks, i;
++ struct iovec chunks[UIO_MAXIOV];
++ chunk *tc; /* transfer chunks */
++ size_t num_bytes = 0;
++
++ /* we can't send more then SSIZE_MAX bytes in one chunk */
++
++ /* build writev list
++ *
++ * 1. limit: num_chunks < UIO_MAXIOV
++ * 2. limit: num_bytes < SSIZE_MAX
++ */
++ for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
++
++ for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
++ if (tc->mem->used == 0) {
++ chunks[i].iov_base = tc->mem->ptr;
++ chunks[i].iov_len = 0;
++ } else {
++ offset = tc->mem->ptr + tc->offset;
++ toSend = tc->mem->used - 1 - tc->offset;
++
++ chunks[i].iov_base = offset;
++
++ /* protect the return value of writev() */
++ if (toSend > SSIZE_MAX ||
++ num_bytes + toSend > SSIZE_MAX) {
++ chunks[i].iov_len = SSIZE_MAX - num_bytes;
++
++ num_chunks = i + 1;
++ break;
++ } else {
++ chunks[i].iov_len = toSend;
++ }
++
++ num_bytes += toSend;
++ }
++ }
++
++ if ((r = writev(fd, chunks, num_chunks)) < 0) {
++ switch (errno) {
++ case EAGAIN:
++ case EINTR:
++ r = 0;
++ break;
++ case EPIPE:
++ case ECONNRESET:
++ return NETWORK_STATUS_CONNECTION_CLOSE;
++ default:
++ log_error_write(srv, __FILE__, __LINE__, "ssd",
++ "writev failed:", strerror(errno), fd);
++
++ return NETWORK_STATUS_FATAL_ERROR;
++ }
++ }
++
++ cq->bytes_out += r;
++
++ /* check which chunks have been written */
++
++ for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
++ if (r >= (ssize_t)chunks[i].iov_len) {
++ /* written */
++ r -= chunks[i].iov_len;
++ tc->offset += chunks[i].iov_len;
++ } else {
++ /* partially written */
++
++ tc->offset += r;
++ break;
++ }
++ }
++
++ return NETWORK_STATUS_SUCCESS;
++}
++
++NETWORK_BACKEND_WRITE(writev) {
++ chunk *c, *tc;
+ size_t chunks_written = 0;
+-
++
+ for(c = cq->first; c; c = c->next) {
+ int chunk_finished = 0;
+-
++ network_status_t ret;
++
+ switch(c->type) {
+- case MEM_CHUNK: {
+- char * offset;
+- size_t toSend;
+- ssize_t r;
+-
+- size_t num_chunks, i;
+- struct iovec chunks[UIO_MAXIOV];
+- chunk *tc;
+- size_t num_bytes = 0;
+-
+- /* we can't send more then SSIZE_MAX bytes in one chunk */
+-
+- /* build writev list
+- *
+- * 1. limit: num_chunks < UIO_MAXIOV
+- * 2. limit: num_bytes < SSIZE_MAX
+- */
+- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
+-
+- for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
+- if (tc->mem->used == 0) {
+- chunks[i].iov_base = tc->mem->ptr;
+- chunks[i].iov_len = 0;
+- } else {
+- offset = tc->mem->ptr + tc->offset;
+- toSend = tc->mem->used - 1 - tc->offset;
+-
+- chunks[i].iov_base = offset;
+-
+- /* protect the return value of writev() */
+- if (toSend > SSIZE_MAX ||
+- num_bytes + toSend > SSIZE_MAX) {
+- chunks[i].iov_len = SSIZE_MAX - num_bytes;
+-
+- num_chunks = i + 1;
+- break;
+- } else {
+- chunks[i].iov_len = toSend;
+- }
+-
+- num_bytes += toSend;
+- }
+- }
+-
+- if ((r = writev(fd, chunks, num_chunks)) < 0) {
+- switch (errno) {
+- case EAGAIN:
+- case EINTR:
+- r = 0;
+- break;
+- case EPIPE:
+- case ECONNRESET:
+- return -2;
+- default:
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
+- "writev failed:", strerror(errno), fd);
+-
+- return -1;
+- }
+- }
+-
+- cq->bytes_out += r;
++ case MEM_CHUNK:
++ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
+
+- /* check which chunks have been written */
+-
+- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
+- if (r >= (ssize_t)chunks[i].iov_len) {
+- /* written */
+- r -= chunks[i].iov_len;
+- tc->offset += chunks[i].iov_len;
+-
++ /* check which chunks are finished now */
++ for (tc = c; tc; tc = tc->next) {
++ /* finished the chunk */
++ if (tc->offset == tc->mem->used - 1) {
++ /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
+ if (chunk_finished) {
+- /* skip the chunks from further touches */
+- chunks_written++;
+ c = c->next;
+ } else {
+- /* chunks_written + c = c->next is done in the for()*/
+- chunk_finished++;
++ chunk_finished = 1;
+ }
+ } else {
+- /* partially written */
+-
+- tc->offset += r;
+- chunk_finished = 0;
+-
+ break;
+ }
+ }
+-
++
++ if (ret != NETWORK_STATUS_SUCCESS) {
++ return ret;
++ }
++
+ break;
+- }
+ case FILE_CHUNK: {
+ ssize_t r;
+ off_t abs_offset;
+@@ -159,26 +173,26 @@
+ #define KByte * 1024
+ #define MByte * 1024 KByte
+ #define GByte * 1024 MByte
+- const off_t we_want_to_mmap = 512 KByte;
++ const off_t we_want_to_mmap = 512 KByte;
+ char *start = NULL;
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- #if defined(HAVE_GDBM)
-- PATCH(db);
-+ PATCH_OPTION(db);
- #endif
- #if defined(HAVE_PCRE_H)
-- PATCH(download_regex);
-- PATCH(trigger_regex);
-+ PATCH_OPTION(download_regex);
-+ PATCH_OPTION(trigger_regex);
- #endif
-- PATCH(trigger_timeout);
-- PATCH(deny_url);
-- PATCH(mc_namespace);
-- PATCH(debug);
-+ PATCH_OPTION(trigger_timeout);
-+ PATCH_OPTION(deny_url);
-+ PATCH_OPTION(mc_namespace);
-+ PATCH_OPTION(debug);
- #if defined(HAVE_MEMCACHE_H)
-- PATCH(mc);
-+ PATCH_OPTION(mc);
- #endif
-
- /* skip the first, the global context */
-@@ -276,27 +274,27 @@
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ strerror(errno), c->file.name);
+- return -1;
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
- #if defined(HAVE_PCRE_H)
-- PATCH(download_regex);
-+ PATCH_OPTION(download_regex);
- #endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
- # if defined(HAVE_PCRE_H)
-- PATCH(trigger_regex);
-+ PATCH_OPTION(trigger_regex);
- # endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
- #if defined(HAVE_GDBM_H)
-- PATCH(db);
-+ PATCH_OPTION(db);
- #endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
-- PATCH(trigger_timeout);
-+ PATCH_OPTION(trigger_timeout);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
-- PATCH(debug);
-+ PATCH_OPTION(debug);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
-- PATCH(deny_url);
-+ PATCH_OPTION(deny_url);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
-- PATCH(mc_namespace);
-+ PATCH_OPTION(mc_namespace);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
- #if defined(HAVE_MEMCACHE_H)
-- PATCH(mc);
-+ PATCH_OPTION(mc);
- #endif
+ abs_offset = c->file.start + c->offset;
+-
++
+ if (abs_offset > sce->st.st_size) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "file was shrinked:", c->file.name);
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
}
- }
-@@ -304,7 +302,6 @@
-
- return 0;
- }
--#undef PATCH
- URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_userdir.c 2005-10-28 16:48:28.000000000 +0300
-+++ lighttpd/src/mod_userdir.c 2006-07-11 21:23:40.091855478 +0300
-@@ -10,6 +10,7 @@
- #include "response.h"
+- /* mmap the buffer
+- * - first mmap
++ /* mmap the buffer
++ * - first mmap
+ * - new mmap as the we are at the end of the last one */
+ if (c->file.mmap.start == MAP_FAILED ||
+ abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
+@@ -188,7 +202,7 @@
+ * adaptive mem-mapping
+ * the problem:
+ * we mmap() the whole file. If someone has alot large files and 32bit
+- * machine the virtual address area will be unrun and we will have a failing
++ * machine the virtual address area will be unrun and we will have a failing
+ * mmap() call.
+ * solution:
+ * only mmap 16M in one chunk and move the window as soon as we have finished
+@@ -234,8 +248,8 @@
+ if (-1 == c->file.fd) { /* open the file if not already open */
+ if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
+ log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+ #ifdef FD_CLOEXEC
+ fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
+@@ -245,10 +259,10 @@
+ if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
+ /* close it here, otherwise we'd have to set FD_CLOEXEC */
- #include "plugin.h"
-+#include "sys-files.h"
+- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
++ log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
+ strerror(errno), c->file.name, c->file.fd);
- #ifdef HAVE_PWD_H
- #include <pwd.h>
-@@ -118,16 +119,14 @@
- return HANDLER_GO_ON;
- }
+- return -1;
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(path);
-- PATCH(exclude_user);
-- PATCH(include_user);
-- PATCH(basepath);
-+ PATCH_OPTION(path);
-+ PATCH_OPTION(exclude_user);
-+ PATCH_OPTION(include_user);
-+ PATCH_OPTION(basepath);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -142,20 +141,19 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
-- PATCH(path);
-+ PATCH_OPTION(path);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
-- PATCH(exclude_user);
-+ PATCH_OPTION(exclude_user);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
-- PATCH(include_user);
-+ PATCH_OPTION(include_user);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
-- PATCH(basepath);
-+ PATCH_OPTION(basepath);
+ c->file.mmap.length = to_mmap;
+@@ -258,7 +272,7 @@
+ #ifdef HAVE_MADVISE
+ /* don't advise files < 64Kb */
+ if (c->file.mmap.length > (64 KByte)) {
+- /* darwin 7 is returning EINVAL all the time and I don't know how to
++ /* darwin 7 is returning EINVAL all the time and I don't know how to
+ * detect this at runtime.i
+ *
+ * ignore the return value for now */
+@@ -274,12 +288,12 @@
+ toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
+
+ if (toSend < 0) {
+- log_error_write(srv, __FILE__, __LINE__, "soooo",
++ log_error_write(srv, __FILE__, __LINE__, "soooo",
+ "toSend is negative:",
+ toSend,
+ c->file.mmap.length,
+ abs_offset,
+- c->file.mmap.offset);
++ c->file.mmap.offset);
+ assert(toSend < 0);
+ }
+
+@@ -297,18 +311,18 @@
+ break;
+ case EPIPE:
+ case ECONNRESET:
+- return -2;
++ return NETWORK_STATUS_CONNECTION_CLOSE;
+ default:
+- log_error_write(srv, __FILE__, __LINE__, "ssd",
++ log_error_write(srv, __FILE__, __LINE__, "ssd",
+ "write failed:", strerror(errno), fd);
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
}
+-
++
+ c->offset += r;
+ cq->bytes_out += r;
+-
++
+ if (c->offset == c->file.length) {
+ chunk_finished = 1;
+
+@@ -318,26 +332,26 @@
+ c->file.mmap.start = MAP_FAILED;
+ }
+ }
+-
++
+ break;
+ }
+ default:
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+-
+- return -1;
++
++ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ if (!chunk_finished) {
+ /* not finished yet */
+-
++
+ break;
}
+-
++
+ chunks_written++;
}
-
- return 0;
+
+- return chunks_written;
++ return NETWORK_STATUS_SUCCESS;
}
--#undef PATCH
- URIHANDLER_FUNC(mod_userdir_docroot_handler) {
- plugin_data *p = p_d;
-@@ -252,10 +250,10 @@
- }
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/plugin.c lighttpd-1.4.12/src/plugin.c
+--- lighttpd-1.4.11/src/plugin.c 2006-02-08 14:00:54.000000000 +0200
++++ lighttpd-1.4.12/src/plugin.c 2006-07-11 21:23:40.000000000 +0300
+@@ -13,27 +13,27 @@
+ #include <valgrind/valgrind.h>
+ #endif
- buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
-- BUFFER_APPEND_SLASH(p->temp_path);
-+ PATHNAME_APPEND_SLASH(p->temp_path);
- buffer_append_string_buffer(p->temp_path, p->username);
- }
-- BUFFER_APPEND_SLASH(p->temp_path);
-+ PATHNAME_APPEND_SLASH(p->temp_path);
- buffer_append_string_buffer(p->temp_path, p->conf.path);
+-#ifndef __WIN32
++#ifndef _WIN32
+ #include <dlfcn.h>
+ #endif
+ /*
+- *
++ *
+ * if you change this enum to add a new callback, be sure
+ * - that PLUGIN_FUNC_SIZEOF is the last entry
+ * - that you add PLUGIN_TO_SLOT twice:
+- * 1. as callback-dispatcher
++ * 1. as callback-dispatcher
+ * 2. in plugins_call_init()
+- *
++ *
+ */
- if (buffer_is_empty(p->conf.basepath)) {
-@@ -268,7 +266,7 @@
- }
- }
+ typedef struct {
+ PLUGIN_DATA;
+ } plugin_data;
-- BUFFER_APPEND_SLASH(p->temp_path);
-+ PATHNAME_APPEND_SLASH(p->temp_path);
- buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
- buffer_copy_string_buffer(con->physical.path, p->temp_path);
+-typedef enum {
++typedef enum {
+ PLUGIN_FUNC_UNSET,
+- PLUGIN_FUNC_HANDLE_URI_CLEAN,
+- PLUGIN_FUNC_HANDLE_URI_RAW,
++ PLUGIN_FUNC_HANDLE_URI_CLEAN,
++ PLUGIN_FUNC_HANDLE_URI_RAW,
+ PLUGIN_FUNC_HANDLE_REQUEST_DONE,
+ PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
+ PLUGIN_FUNC_HANDLE_TRIGGER,
+@@ -44,38 +44,42 @@
+ PLUGIN_FUNC_HANDLE_DOCROOT,
+ PLUGIN_FUNC_HANDLE_PHYSICAL,
+ PLUGIN_FUNC_CONNECTION_RESET,
+- PLUGIN_FUNC_INIT,
++ PLUGIN_FUNC_INIT,
+ PLUGIN_FUNC_CLEANUP,
+ PLUGIN_FUNC_SET_DEFAULTS,
+-
++
+ PLUGIN_FUNC_SIZEOF
+ } plugin_t;
---- lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200
-+++ lighttpd/src/mod_usertrack.c 2006-07-11 21:23:40.115856981 +0300
-@@ -136,15 +136,13 @@
- return HANDLER_GO_ON;
+ static plugin *plugin_init(void) {
+ plugin *p;
+-
++
+ p = calloc(1, sizeof(*p));
+-
++
++ p->required_plugins = array_init();
++
+ return p;
}
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(cookie_name);
-- PATCH(cookie_domain);
-- PATCH(cookie_max_age);
-+ PATCH_OPTION(cookie_name);
-+ PATCH_OPTION(cookie_domain);
-+ PATCH_OPTION(cookie_max_age);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -159,18 +157,17 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
-- PATCH(cookie_name);
-+ PATCH_OPTION(cookie_name);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
-- PATCH(cookie_max_age);
-+ PATCH_OPTION(cookie_max_age);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
-- PATCH(cookie_domain);
-+ PATCH_OPTION(cookie_domain);
- }
- }
+ static void plugin_free(plugin *p) {
+ int use_dlclose = 1;
+ if (p->name) buffer_free(p->name);
++
++ array_free(p->required_plugins);
+ #ifdef HAVE_VALGRIND_VALGRIND_H
+ /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
+ #endif
+
+ #ifndef LIGHTTPD_STATIC
+- if (use_dlclose && p->lib) {
+-#ifdef __WIN32
++ if (use_dlclose && p->lib) {
++#ifdef _WIN32
+ FreeLibrary(p->lib);
+ #else
+ dlclose(p->lib);
+ #endif
}
-
+ #endif
+-
++
+ free(p);
+ }
+
+@@ -89,17 +93,17 @@
+ srv->plugins.size += 4;
+ srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
+ }
+-
++
+ ps = srv->plugins.ptr;
+ ps[srv->plugins.used++] = p;
+-
++
return 0;
}
--#undef PATCH
- URIHANDLER_FUNC(mod_usertrack_uri_handler) {
- plugin_data *p = p_d;
---- lighttpd-1.4.11/src/mod_webdav.c 2006-03-03 01:28:58.000000000 +0200
-+++ lighttpd/src/mod_webdav.c 2006-07-11 21:23:40.123857482 +0300
-@@ -3,13 +3,10 @@
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
--#include <dirent.h>
- #include <errno.h>
--#include <unistd.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <assert.h>
--#include <sys/mman.h>
+ /**
+- *
+- *
+- *
++ *
++ *
++ *
+ */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
-@@ -23,6 +20,11 @@
- #include <sqlite3.h>
+ #ifdef LIGHTTPD_STATIC
+@@ -121,30 +125,35 @@
+ #else
+ int plugins_load(server *srv) {
+ plugin *p;
++#ifdef _WIN32
++ FARPROC init;
++#else
+ int (*init)(plugin *pl);
++#endif
++
+ const char *error;
+- size_t i;
+-
++ size_t i, j, k;
++
+ for (i = 0; i < srv->srvconf.modules->used; i++) {
+ data_string *d = (data_string *)srv->srvconf.modules->data[i];
+ char *modules = d->value->ptr;
+-
++
+ buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
+
+ buffer_append_string(srv->tmp_buf, "/");
+ buffer_append_string(srv->tmp_buf, modules);
+-#if defined(__WIN32) || defined(__CYGWIN__)
++#if defined(_WIN32) || defined(__CYGWIN__)
+ buffer_append_string(srv->tmp_buf, ".dll");
+ #else
+ buffer_append_string(srv->tmp_buf, ".so");
+ #endif
+-
++
+ p = plugin_init();
+-#ifdef __WIN32
++#ifdef _WIN32
+ if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
+ LPVOID lpMsgBuf;
+ FormatMessage(
+- FORMAT_MESSAGE_ALLOCATE_BUFFER |
++ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ GetLastError(),
+@@ -152,36 +161,36 @@
+ (LPTSTR) &lpMsgBuf,
+ 0, NULL );
+
+- log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
++ log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
+ lpMsgBuf, srv->tmp_buf);
+-
++
+ plugin_free(p);
+-
++
+ return -1;
+
+ }
+-#else
++#else
+ if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
++ log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
+ srv->tmp_buf, dlerror());
+-
++
+ plugin_free(p);
+-
++
+ return -1;
+ }
+-
++
+ #endif
+ buffer_reset(srv->tmp_buf);
+ buffer_copy_string(srv->tmp_buf, modules);
+ buffer_append_string(srv->tmp_buf, "_plugin_init");
+
+-#ifdef __WIN32
++#ifdef _WIN32
+ init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
+
+ if (init == NULL) {
+ LPVOID lpMsgBuf;
+ FormatMessage(
+- FORMAT_MESSAGE_ALLOCATE_BUFFER |
++ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ GetLastError(),
+@@ -190,7 +199,7 @@
+ 0, NULL );
+
+ log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
+-
++
+ plugin_free(p);
+ return -1;
+ }
+@@ -203,24 +212,43 @@
+ #endif
+ if ((error = dlerror()) != NULL) {
+ log_error_write(srv, __FILE__, __LINE__, "s", error);
+-
++
+ plugin_free(p);
+ return -1;
+ }
+-
++
+ #endif
+ if ((*init)(p)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
+-
++
+ plugin_free(p);
+ return -1;
+ }
+ #if 0
+ log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
+ #endif
++ /* check if the required plugin is loaded */
++ for (k = 0; k < p->required_plugins->used; k++) {
++ data_string *req = (data_string *)p->required_plugins->data[k];
++
++ for (j = 0; j < i; j++) {
++ data_string *mod = (data_string *)srv->srvconf.modules->data[j];
++
++ if (buffer_is_equal(req->value, mod->value)) break;
++ }
++
++ if (j == i) {
++ /* not found */
++ log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
++
++ plugin_free(p);
++
++ return -1;
++ }
++ }
+ plugins_register(srv, p);
+ }
+-
++
+ return 0;
+ }
#endif
+@@ -253,8 +281,8 @@
+ }
-+#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
-+#define USE_LOCKS
-+#include <uuid/uuid.h>
-+#endif
+ /**
+- * plugins that use
+- *
++ * plugins that use
++ *
+ * - server *srv
+ * - connection *con
+ * - void *p_d (plugin_data *)
+@@ -301,12 +329,12 @@
+ }
+
+ /**
+- * plugins that use
+- *
++ * plugins that use
++ *
+ * - server *srv
+ * - void *p_d (plugin_data *)
+ */
+-
+
- #include "base.h"
- #include "log.h"
- #include "buffer.h"
-@@ -33,6 +35,9 @@
- #include "stream.h"
- #include "stat_cache.h"
+ PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
+ PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
+ PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
+@@ -314,18 +342,18 @@
-+#include "sys-files.h"
-+#include "sys-mmap.h"
-+#include "sys-strings.h"
+ #undef PLUGIN_TO_SLOT
+-#if 0
++#if 0
/**
- * this is a webdav for a lighttpd plugin
-@@ -62,6 +67,12 @@
- sqlite3_stmt *stmt_delete_uri;
- sqlite3_stmt *stmt_move_uri;
- sqlite3_stmt *stmt_copy_uri;
+- *
++ *
+ * special handler
+- *
++ *
+ */
+ handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
+ size_t i;
+ plugin **ps;
+-
+
-+ sqlite3_stmt *stmt_remove_lock;
-+ sqlite3_stmt *stmt_create_lock;
-+ sqlite3_stmt *stmt_read_lock;
-+ sqlite3_stmt *stmt_read_lock_by_uri;
-+ sqlite3_stmt *stmt_refresh_lock;
- #endif
- } plugin_config;
-
-@@ -123,6 +134,12 @@
- sqlite3_finalize(s->stmt_update_prop);
- sqlite3_finalize(s->stmt_select_prop);
- sqlite3_finalize(s->stmt_select_propnames);
+ ps = srv->plugins.ptr;
+-
+
-+ sqlite3_finalize(s->stmt_read_lock);
-+ sqlite3_finalize(s->stmt_read_lock_by_uri);
-+ sqlite3_finalize(s->stmt_create_lock);
-+ sqlite3_finalize(s->stmt_remove_lock);
-+ sqlite3_finalize(s->stmt_refresh_lock);
- sqlite3_close(s->sql);
- }
- #endif
-@@ -193,6 +210,24 @@
- return HANDLER_ERROR;
+ for (i = 0; i < srv->plugins.used; i++) {
+ plugin *p = ps[i];
+ if (p->handle_fdevent) {
+@@ -344,34 +372,34 @@
}
+ }
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+ #endif
+ /**
+- *
++ *
+ * - call init function of all plugins to init the plugin-internals
+ * - added each plugin that supports has callback to the corresponding slot
+- *
++ *
+ * - is only called once.
+ */
-+ if (SQLITE_OK != sqlite3_exec(s->sql,
-+ "CREATE TABLE properties ("
-+ " resource TEXT NOT NULL,"
-+ " prop TEXT NOT NULL,"
-+ " ns TEXT NOT NULL,"
-+ " value TEXT NOT NULL,"
-+ " PRIMARY KEY(resource, prop, ns))",
-+ NULL, NULL, &err)) {
+ handler_t plugins_call_init(server *srv) {
+ size_t i;
+ plugin **ps;
+-
+
-+ if (0 != strcmp(err, "table properties already exists")) {
-+ log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
-+ sqlite3_free(err);
+ ps = srv->plugins.ptr;
+-
+
-+ return HANDLER_ERROR;
-+ }
-+ sqlite3_free(err);
-+ }
+ /* fill slots */
+-
+
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
- &(s->stmt_select_prop), &next_stmt)) {
-@@ -211,23 +246,6 @@
- return HANDLER_ERROR;
- }
-
-- if (SQLITE_OK != sqlite3_exec(s->sql,
-- "CREATE TABLE properties ("
-- " resource TEXT NOT NULL,"
-- " prop TEXT NOT NULL,"
-- " ns TEXT NOT NULL,"
-- " value TEXT NOT NULL,"
-- " PRIMARY KEY(resource, prop, ns))",
-- NULL, NULL, &err)) {
--
-- if (0 != strcmp(err, "table properties already exists")) {
-- log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
-- sqlite3_free(err);
--
-- return HANDLER_ERROR;
-- }
-- sqlite3_free(err);
-- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
-@@ -273,6 +291,76 @@
-
- return HANDLER_ERROR;
- }
+ srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
+-
+
-+ /* LOCKS */
+ for (i = 0; i < srv->plugins.used; i++) {
+ size_t j;
+ /* check which calls are supported */
+-
+
-+ if (SQLITE_OK != sqlite3_exec(s->sql,
-+ "CREATE TABLE locks ("
-+ " locktoken TEXT NOT NULL,"
-+ " resource TEXT NOT NULL,"
-+ " lockscope TEXT NOT NULL,"
-+ " locktype TEXT NOT NULL,"
-+ " owner TEXT NOT NULL,"
-+ " depth INT NOT NULL,"
-+ " timeout TIMESTAMP NOT NULL,"
-+ " PRIMARY KEY(locktoken))",
-+ NULL, NULL, &err)) {
+ plugin *p = ps[i];
+-
+
-+ if (0 != strcmp(err, "table locks already exists")) {
-+ log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
-+ sqlite3_free(err);
+ #define PLUGIN_TO_SLOT(x, y) \
+ if (p->y) { \
+ plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
+@@ -384,11 +412,11 @@
+ slot[j] = p;\
+ break;\
+ }\
+- }
+-
+-
+- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
+- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
++ }
+
-+ return HANDLER_ERROR;
-+ }
-+ sqlite3_free(err);
-+ }
+
-+ if (SQLITE_OK != sqlite3_prepare(s->sql,
-+ CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
-+ &(s->stmt_create_lock), &next_stmt)) {
-+ /* prepare failed */
-+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
++ PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
++ PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
+ PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
+ PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
+ PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
+@@ -402,19 +430,19 @@
+ PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
+ PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
+ #undef PLUGIN_TO_SLOT
+-
+
-+ return HANDLER_ERROR;
-+ }
+ if (p->init) {
+ if (NULL == (p->data = p->init())) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "plugin-init failed for module", p->name);
+ return HANDLER_ERROR;
+ }
+-
+
-+ if (SQLITE_OK != sqlite3_prepare(s->sql,
-+ CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
-+ &(s->stmt_remove_lock), &next_stmt)) {
-+ /* prepare failed */
-+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
+ /* used for con->mode, DIRECT == 0, plugins above that */
+ ((plugin_data *)(p->data))->id = i + 1;
+-
+
-+ return HANDLER_ERROR;
-+ }
+ if (p->version != LIGHTTPD_VERSION_ID) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "plugin-version doesn't match lighttpd-version for", p->name);
+ return HANDLER_ERROR;
+ }
+@@ -422,29 +450,46 @@
+ p->data = NULL;
+ }
+ }
+-
+
-+ if (SQLITE_OK != sqlite3_prepare(s->sql,
-+ CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
-+ &(s->stmt_read_lock), &next_stmt)) {
-+ /* prepare failed */
-+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
+ return HANDLER_GO_ON;
+ }
+
++/**
++ * get the config-storage of the named plugin
++ */
++void *plugin_get_config(server *srv, const char *name) {
++ size_t i;
+
-+ return HANDLER_ERROR;
-+ }
++ for (i = 0; i < srv->plugins.used; i++) {
++ plugin *p = ((plugin **)srv->plugins.ptr)[i];
+
-+ if (SQLITE_OK != sqlite3_prepare(s->sql,
-+ CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
-+ &(s->stmt_read_lock_by_uri), &next_stmt)) {
-+ /* prepare failed */
-+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
++ if (buffer_is_equal_string(p->name, name, strlen(name))) {
++ return p->data;
++ }
++ }
+
-+ return HANDLER_ERROR;
-+ }
++ return NULL;
++}
+
-+ if (SQLITE_OK != sqlite3_prepare(s->sql,
-+ CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
-+ &(s->stmt_refresh_lock), &next_stmt)) {
-+ /* prepare failed */
-+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
+ void plugins_free(server *srv) {
+ size_t i;
+ plugins_call_cleanup(srv);
+-
+
-+ return HANDLER_ERROR;
-+ }
+ for (i = 0; i < srv->plugins.used; i++) {
+ plugin *p = ((plugin **)srv->plugins.ptr)[i];
+-
+
+ plugin_free(p);
+ }
+-
+
- #else
- log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
- return HANDLER_ERROR;
-@@ -283,26 +371,30 @@
- return HANDLER_GO_ON;
- }
+ for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
+ plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
+-
++
+ if (slot) free(slot);
+ }
+-
++
+ free(srv->plugin_slots);
+ srv->plugin_slots = NULL;
+-
++
+ free(srv->plugins.ptr);
+ srv->plugins.ptr = NULL;
+ srv->plugins.used = 0;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/plugin.h lighttpd-1.4.12/src/plugin.h
+--- lighttpd-1.4.11/src/plugin.h 2005-08-15 12:28:56.000000000 +0300
++++ lighttpd-1.4.12/src/plugin.h 2006-07-11 21:23:40.000000000 +0300
+@@ -12,6 +12,12 @@
--#define PATCH(x) \
-- p->conf.x = s->x;
- static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-- PATCH(enabled);
-- PATCH(is_readonly);
-- PATCH(log_xml);
-+ PATCH_OPTION(enabled);
-+ PATCH_OPTION(is_readonly);
-+ PATCH_OPTION(log_xml);
-
- #ifdef USE_PROPPATCH
-- PATCH(sql);
-- PATCH(stmt_update_prop);
-- PATCH(stmt_delete_prop);
-- PATCH(stmt_select_prop);
-- PATCH(stmt_select_propnames);
--
-- PATCH(stmt_delete_uri);
-- PATCH(stmt_move_uri);
-- PATCH(stmt_copy_uri);
-+ PATCH_OPTION(sql);
-+ PATCH_OPTION(stmt_update_prop);
-+ PATCH_OPTION(stmt_delete_prop);
-+ PATCH_OPTION(stmt_select_prop);
-+ PATCH_OPTION(stmt_select_propnames);
+ #define INIT_FUNC(x) \
+ static void *x()
++/*
++ * The PATCH_OPTION() macro is used in the patch_connection() functions
++ * of the modules to update the config object for the current request.
++ */
++#define PATCH_OPTION(x) \
++ p->conf.x = s->x
+
+ #define FREE_FUNC SERVER_FUNC
+ #define TRIGGER_FUNC SERVER_FUNC
+@@ -25,19 +31,19 @@
+ #define URIHANDLER_FUNC CONNECTION_FUNC
+
+ #define PLUGIN_DATA size_t id
+-
+
-+ PATCH_OPTION(stmt_delete_uri);
-+ PATCH_OPTION(stmt_move_uri);
-+ PATCH_OPTION(stmt_copy_uri);
+ typedef struct {
+ size_t version;
+-
+
-+ PATCH_OPTION(stmt_remove_lock);
-+ PATCH_OPTION(stmt_refresh_lock);
-+ PATCH_OPTION(stmt_create_lock);
-+ PATCH_OPTION(stmt_read_lock);
-+ PATCH_OPTION(stmt_read_lock_by_uri);
- #endif
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -317,22 +409,28 @@
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
-- PATCH(enabled);
-+ PATCH_OPTION(enabled);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
-- PATCH(is_readonly);
-+ PATCH_OPTION(is_readonly);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
-- PATCH(log_xml);
-+ PATCH_OPTION(log_xml);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
- #ifdef USE_PROPPATCH
-- PATCH(sql);
-- PATCH(stmt_update_prop);
-- PATCH(stmt_delete_prop);
-- PATCH(stmt_select_prop);
-- PATCH(stmt_select_propnames);
--
-- PATCH(stmt_delete_uri);
-- PATCH(stmt_move_uri);
-- PATCH(stmt_copy_uri);
-+ PATCH_OPTION(sql);
-+ PATCH_OPTION(stmt_update_prop);
-+ PATCH_OPTION(stmt_delete_prop);
-+ PATCH_OPTION(stmt_select_prop);
-+ PATCH_OPTION(stmt_select_propnames);
+ buffer *name; /* name of the plugin */
+-
+
-+ PATCH_OPTION(stmt_delete_uri);
-+ PATCH_OPTION(stmt_move_uri);
-+ PATCH_OPTION(stmt_copy_uri);
+ void *(* init) ();
+ handler_t (* set_defaults) (server *srv, void *p_d);
+ handler_t (* cleanup) (server *srv, void *p_d);
+ /* is called ... */
+ handler_t (* handle_trigger) (server *srv, void *p_d); /* once a second */
+ handler_t (* handle_sighup) (server *srv, void *p_d); /* at a signup */
+-
+
-+ PATCH_OPTION(stmt_remove_lock);
-+ PATCH_OPTION(stmt_refresh_lock);
-+ PATCH_OPTION(stmt_create_lock);
-+ PATCH_OPTION(stmt_read_lock);
-+ PATCH_OPTION(stmt_read_lock_by_uri);
+ handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d); /* after uri_raw is set */
+ handler_t (* handle_uri_clean) (server *srv, connection *con, void *p_d); /* after uri is set */
+ handler_t (* handle_docroot) (server *srv, connection *con, void *p_d); /* getting the document-root */
+@@ -45,20 +51,22 @@
+ handler_t (* handle_request_done) (server *srv, connection *con, void *p_d); /* at the end of a request */
+ handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d); /* at the end of a connection */
+ handler_t (* handle_joblist) (server *srv, connection *con, void *p_d); /* after all events are handled */
+-
+-
+-
+- handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
+-
+- /* when a handler for the request
++
++
++
++ handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
++
++ /* when a handler for the request
+ * has to be found
+ */
+ handler_t (* handle_subrequest) (server *srv, connection *con, void *p_d); /* */
+ handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* */
+ void *data;
+-
++
+ /* dlopen handle */
+ void *lib;
++
++ array *required_plugins;
+ } plugin;
+
+ int plugins_load(server *srv);
+@@ -88,5 +96,8 @@
+ int config_patch_connection(server *srv, connection *con, comp_key_t comp);
+ int config_check_cond(server *srv, connection *con, data_config *dc);
+ int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
++int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
++
++void *plugin_get_config(server *srv, const char *name);
+
+ #endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/proc_open.c lighttpd-1.4.12/src/proc_open.c
+--- lighttpd-1.4.11/src/proc_open.c 2005-08-11 01:26:39.000000000 +0300
++++ lighttpd-1.4.12/src/proc_open.c 2006-07-11 21:23:40.000000000 +0300
+@@ -13,13 +13,13 @@
#endif
- }
- }
-@@ -340,7 +438,6 @@
-
- return 0;
- }
--#undef PATCH
- URIHANDLER_FUNC(mod_webdav_uri_handler) {
- plugin_data *p = p_d;
-@@ -362,7 +459,7 @@
- if (p->conf.is_readonly) {
- response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
- } else {
-- response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
-+ response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
- }
- break;
- default:
-@@ -496,11 +593,11 @@
- }
- buffer_copy_string_buffer(d.path, dst->path);
-- BUFFER_APPEND_SLASH(d.path);
-+ PATHNAME_APPEND_SLASH(d.path);
- buffer_append_string(d.path, de->d_name);
-
- buffer_copy_string_buffer(d.rel_path, dst->rel_path);
-- BUFFER_APPEND_SLASH(d.rel_path);
-+ PATHNAME_APPEND_SLASH(d.rel_path);
- buffer_append_string(d.rel_path, de->d_name);
+-#ifdef WIN32
++#ifdef _WIN32
+ /* {{{ win32 stuff */
+ # define SHELLENV "ComSpec"
+ # define SECURITY_DC , SECURITY_ATTRIBUTES *security
+ # define SECURITY_CC , security
+ # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
+-static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
++static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
+ {
+ HANDLE copy, self = GetCurrentProcess();
- /* stat and unlink afterwards */
-@@ -657,19 +754,19 @@
- }
-
- buffer_copy_string_buffer(s.path, src->path);
-- BUFFER_APPEND_SLASH(s.path);
-+ PATHNAME_APPEND_SLASH(s.path);
- buffer_append_string(s.path, de->d_name);
+@@ -148,11 +148,14 @@
+ STARTUPINFO si;
+ BOOL procok;
+ SECURITY_ATTRIBUTES security;
+- const char *shell;
++ const char *shell = NULL;
++ const char *windir = NULL;
+ buffer *cmdline;
- buffer_copy_string_buffer(d.path, dst->path);
-- BUFFER_APPEND_SLASH(d.path);
-+ PATHNAME_APPEND_SLASH(d.path);
- buffer_append_string(d.path, de->d_name);
+- if (NULL == (shell = getenv(SHELLENV))) {
+- fprintf(stderr, "env %s is required", SHELLENV);
++ if (NULL == (shell = getenv(SHELLENV)) &&
++ NULL == (windir = getenv("SystemRoot")) &&
++ NULL == (windir = getenv("windir"))) {
++ fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
+ return -1;
+ }
- buffer_copy_string_buffer(s.rel_path, src->rel_path);
-- BUFFER_APPEND_SLASH(s.rel_path);
-+ PATHNAME_APPEND_SLASH(s.rel_path);
- buffer_append_string(s.rel_path, de->d_name);
+@@ -177,17 +180,23 @@
+ memset(&pi, 0, sizeof(pi));
- buffer_copy_string_buffer(d.rel_path, dst->rel_path);
-- BUFFER_APPEND_SLASH(d.rel_path);
-+ PATHNAME_APPEND_SLASH(d.rel_path);
- buffer_append_string(d.rel_path, de->d_name);
+ cmdline = buffer_init();
+- buffer_append_string(cmdline, shell);
++ if (shell) {
++ buffer_append_string(cmdline, shell);
++ } else {
++ buffer_append_string(cmdline, windir);
++ buffer_append_string(cmdline, "\\system32\\cmd.exe");
++ }
+ buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
+ buffer_append_string(cmdline, command);
+ procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
+ NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
+- buffer_free(cmdline);
- if (-1 == stat(s.path->ptr, &st)) {
-@@ -821,9 +918,9 @@
- SQLITE_TRANSIENT);
+ if (FALSE == procok) {
+- fprintf(stderr, "failed to CreateProcess");
++ fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
++ buffer_free(cmdline);
+ return -1;
+ }
++ buffer_free(cmdline);
- /* it is the PK */
-- while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
-+ while (SQLITE_ROW == sqlite3_step(stmt)) {
- /* there is a row for us, we only expect a single col 'value' */
-- webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
-+ webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
- found = 1;
- }
- }
-@@ -991,6 +1088,113 @@
+ proc->child = pi.hProcess;
+ CloseHandle(pi.hThread);
+@@ -226,8 +235,7 @@
+ const char *shell;
+
+ if (NULL == (shell = getenv(SHELLENV))) {
+- fprintf(stderr, "env %s is required", SHELLENV);
+- return -1;
++ shell = "/bin/sh";
+ }
+
+ if (proc_open_pipes(proc) != 0) {
+@@ -262,11 +270,11 @@
+ }
}
- #endif
+ /* }}} */
+-#endif /* WIN32 */
++#endif /* _WIN32 */
-+int webdav_lockdiscovery(server *srv, connection *con,
-+ buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
+ /* {{{ proc_read_fd_to_buffer */
+ static void proc_read_fd_to_buffer(int fd, buffer *b) {
+- ssize_t s;
++ int s; /* win32 has not ssize_t */
+
+ for (;;) {
+ buffer_prepare_append(b, 512);
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/proc_open.h lighttpd-1.4.12/src/proc_open.h
+--- lighttpd-1.4.11/src/proc_open.h 2005-08-11 01:26:39.000000000 +0300
++++ lighttpd-1.4.12/src/proc_open.h 2006-07-11 21:23:40.000000000 +0300
+@@ -1,7 +1,7 @@
+
+ #include "buffer.h"
+
+-#ifdef WIN32
++#ifdef _WIN32
+ #include <windows.h>
+ typedef HANDLE descriptor_t;
+ typedef HANDLE proc_pid_t;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/request.c lighttpd-1.4.12/src/request.c
+--- lighttpd-1.4.11/src/request.c 2006-03-05 11:58:09.000000000 +0200
++++ lighttpd-1.4.12/src/request.c 2006-07-11 21:23:40.000000000 +0300
+@@ -10,15 +10,17 @@
+ #include "keyvalue.h"
+ #include "log.h"
+
++#include "sys-strings.h"
+
-+ buffer *b;
+ static int request_check_hostname(server *srv, connection *con, buffer *host) {
+ enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
+ size_t i;
+ int label_len = 0;
+ size_t host_len;
+ char *colon;
+- int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
++ int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
+ int level = 0;
+-
+
-+ response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
+ UNUSED(srv);
+ UNUSED(con);
+
+@@ -32,17 +34,17 @@
+ * IPv6address = "[" ... "]"
+ * port = *digit
+ */
+-
++
+ /* no Host: */
+ if (!host || host->used == 0) return 0;
+-
++
+ host_len = host->used - 1;
+-
++
+ /* IPv6 adress */
+ if (host->ptr[0] == '[') {
+ char *c = host->ptr + 1;
+ int colon_cnt = 0;
+-
++
+ /* check portnumber */
+ for (; *c && *c != ']'; c++) {
+ if (*c == ':') {
+@@ -53,12 +55,12 @@
+ return -1;
+ }
+ }
+-
++
+ /* missing ] */
+ if (!*c) {
+ return -1;
+ }
+-
++
+ /* check port */
+ if (*(c+1) == ':') {
+ for (c += 2; *c; c++) {
+@@ -69,39 +71,39 @@
+ }
+ return 0;
+ }
+-
++
+ if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
+ char *c = colon + 1;
+-
++
+ /* check portnumber */
+ for (; *c; c++) {
+ if (!light_isdigit(*c)) return -1;
+ }
+-
+
-+ response_header_overwrite(srv, con,
-+ CONST_STR_LEN("Content-Type"),
-+ CONST_STR_LEN("text/xml; charset=\"utf-8\""));
+ /* remove the port from the host-len */
+ host_len = colon - host->ptr;
+ }
+-
+
-+ b = chunkqueue_get_append_buffer(con->write_queue);
+ /* Host is empty */
+ if (host_len == 0) return -1;
+-
+
-+ buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+ /* scan from the right and skip the \0 */
+ for (i = host_len - 1; i + 1 > 0; i--) {
+ const char c = host->ptr[i];
+
+ switch (stage) {
+- case TOPLABEL:
++ case TOPLABEL:
+ if (c == '.') {
+ /* only switch stage, if this is not the last character */
+ if (i != host_len - 1) {
+ if (label_len == 0) {
+ return -1;
+ }
+-
+
-+ buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
-+ buffer_append_string(b,"<D:lockdiscovery>\n");
-+ buffer_append_string(b,"<D:activelock>\n");
+ /* check the first character at right of the dot */
+ if (is_ip == 0) {
+ if (!light_isalpha(host->ptr[i+1])) {
+- return -1;
++ return -1;
+ }
+ } else if (!light_isdigit(host->ptr[i+1])) {
+ is_ip = 0;
+@@ -111,9 +113,9 @@
+ /* just digits */
+ is_ip = 1;
+ }
+-
+
-+ buffer_append_string(b,"<D:lockscope>");
-+ buffer_append_string(b,"<D:");
-+ buffer_append_string(b, lockscope);
-+ buffer_append_string(b, "/>");
-+ buffer_append_string(b,"</D:lockscope>\n");
+ stage = DOMAINLABEL;
+-
+
-+ buffer_append_string(b,"<D:locktype>");
-+ buffer_append_string(b,"<D:");
-+ buffer_append_string(b, locktype);
-+ buffer_append_string(b, "/>");
-+ buffer_append_string(b,"</D:locktype>\n");
+ label_len = 0;
+ level++;
+ } else if (i == 0) {
+@@ -135,7 +137,7 @@
+ }
+ label_len++;
+ }
+-
+
-+ buffer_append_string(b,"<D:depth>");
-+ buffer_append_string(b, depth == 0 ? "0" : "infinity");
-+ buffer_append_string(b,"</D:depth>\n");
+ break;
+ case DOMAINLABEL:
+ if (is_ip == 1) {
+@@ -143,7 +145,7 @@
+ if (label_len == 0) {
+ return -1;
+ }
+-
+
-+ buffer_append_string(b,"<D:timeout>");
-+ buffer_append_string(b, "Second-600");
-+ buffer_append_string(b,"</D:timeout>\n");
+ label_len = 0;
+ level++;
+ } else if (!light_isdigit(c)) {
+@@ -156,12 +158,12 @@
+ if (label_len == 0) {
+ return -1;
+ }
+-
+
-+ buffer_append_string(b,"<D:owner>");
-+ buffer_append_string(b,"</D:owner>\n");
+ /* c is either - or alphanum here */
+ if ('-' == host->ptr[i+1]) {
+ return -1;
+ }
+-
+
-+ buffer_append_string(b,"<D:locktoken>");
-+ buffer_append_string(b, "<D:href>");
-+ buffer_append_string_buffer(b, locktoken);
-+ buffer_append_string(b, "</D:href>");
-+ buffer_append_string(b,"</D:locktoken>\n");
+ label_len = 0;
+ level++;
+ } else if (i == 0) {
+@@ -176,20 +178,20 @@
+ label_len++;
+ }
+ }
+-
+
-+ buffer_append_string(b,"</D:activelock>\n");
-+ buffer_append_string(b,"</D:lockdiscovery>\n");
-+ buffer_append_string(b,"</D:prop>\n");
+ break;
+ }
+ }
+-
+
-+ return 0;
-+}
-+/**
-+ * check if resource is having the right locks to access to resource
-+ *
-+ *
-+ *
-+ */
-+int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
-+ int has_lock = 1;
+ /* a IP has to consist of 4 parts */
+ if (is_ip == 1 && level != 3) {
+ return -1;
+ }
+-
+
-+#ifdef USE_LOCKS
-+ data_string *ds;
+ if (label_len == 0) {
+ return -1;
+ }
+-
+
-+ /**
-+ * If can have
-+ * - <lock-token>
-+ * - [etag]
-+ *
-+ * there is NOT, AND and OR
-+ * and a list can be tagged
-+ *
-+ * (<lock-token>) is untagged
-+ * <tag> (<lock-token>) is tagged
-+ *
-+ * as long as we don't handle collections it is simple. :)
+ return 0;
+ }
+
+@@ -201,53 +203,53 @@
+ char *s;
+ size_t i;
+ int state = 0;
+- /*
+- * parse
+- *
++ /*
++ * parse
+ *
-+ * X-Litmus: locks: 11 (owner_modify)
-+ * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
+ * val1, val2, val3, val4
+- *
+ *
-+ * X-Litmus: locks: 16 (fail_cond_put)
-+ * If: (<DAV:no-lock> ["-1622396671"])
-+ */
-+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
-+ } else {
-+ /* we didn't provided a lock-token -> */
-+ /* if the resource is locked -> 423 */
+ * into a array (more or less a explode() incl. striping of whitespaces
+ */
+-
+
-+ sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
+ if (b->used == 0) return 0;
+-
+
-+ sqlite3_reset(stmt);
+ s = b->ptr;
+-
+
-+ sqlite3_bind_text(stmt, 1,
-+ CONST_BUF_LEN(uri),
-+ SQLITE_TRANSIENT);
+ for (i =0; i < b->used - 1; ) {
+ char *start = NULL, *end = NULL;
+ data_string *ds;
+-
+
-+ while (SQLITE_ROW == sqlite3_step(stmt)) {
-+ has_lock = 0;
-+ }
-+ }
-+#endif
+ switch (state) {
+ case 0: /* ws */
+-
+
-+ return has_lock;
-+}
+ /* skip ws */
+ for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
+-
+-
+
- URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
- plugin_data *p = p_d;
- buffer *b;
-@@ -1001,6 +1205,7 @@
- buffer *prop_200;
- buffer *prop_404;
- webdav_properties *req_props;
-+ stat_cache_entry *sce = NULL;
-
- UNUSED(srv);
-
-@@ -1020,6 +1225,18 @@
-
- /* is there a content-body ? */
-
-+ switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
-+ case HANDLER_ERROR:
-+ if (errno == ENOENT) {
-+ con->http_status = 404;
-+ return HANDLER_FINISHED;
-+ }
-+ break;
-+ default:
-+ break;
-+ }
+
+ state = 1;
+ break;
+ case 1: /* value */
+ start = s;
+-
+
- #ifdef USE_PROPPATCH
- /* any special requests or just allprop ? */
- if (con->request.content_length) {
-@@ -1182,10 +1399,10 @@
- }
-
- buffer_copy_string_buffer(d.path, dst->path);
-- BUFFER_APPEND_SLASH(d.path);
-+ PATHNAME_APPEND_SLASH(d.path);
+ for (; *s != ',' && i < b->used - 1; i++, s++);
+ end = s - 1;
+-
++
+ for (; (*end == ' ' || *end == '\t') && end > start; end--);
+-
++
+ if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
+ ds = data_string_init();
+ }
- buffer_copy_string_buffer(d.rel_path, dst->rel_path);
-- BUFFER_APPEND_SLASH(d.rel_path);
-+ PATHNAME_APPEND_SLASH(d.rel_path);
+ buffer_copy_string_len(ds->value, start, end-start+1);
+ array_insert_unique(vals, (data_unset *)ds);
+-
++
+ if (*s == ',') {
+ state = 0;
+ i++;
+ s++;
+ } else {
+ /* end of string */
+-
++
+ state = 2;
+ }
+ break;
+@@ -263,7 +265,7 @@
+ if (c <= 32) return 0;
+ if (c == 127) return 0;
+ if (c == 255) return 0;
+-
++
+ return 1;
+ }
- if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
- /* don't append the . */
-@@ -1304,6 +1521,12 @@
- return HANDLER_FINISHED;
- }
-
-+ /* does the client have a lock for this connection ? */
-+ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
-+ con->http_status = 423;
-+ return HANDLER_FINISHED;
-+ }
+@@ -271,28 +273,28 @@
+ char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
+ int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
+ char *value = NULL, *key = NULL;
+-
+
- /* stat and unlink afterwards */
- if (-1 == stat(con->physical.path->ptr, &st)) {
- /* don't about it yet, unlink will fail too */
-@@ -1375,22 +1598,100 @@
- case HTTP_METHOD_PUT: {
- int fd;
- chunkqueue *cq = con->request_content_queue;
-+ chunk *c;
-+ data_string *ds_range;
+ enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
+-
++
+ int line = 0;
+-
++
+ int request_line_stage = 0;
+ size_t i, first;
+-
++
+ int done = 0;
+-
++
+ data_string *ds = NULL;
+-
+- /*
+- * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
+- * Option : "^([-a-zA-Z]+): (.+)$"
++
++ /*
++ * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
++ * Option : "^([-a-zA-Z]+): (.+)$"
+ * End : "^$"
+ */
- if (p->conf.is_readonly) {
- con->http_status = 403;
- return HANDLER_FINISHED;
- }
+ if (con->conf.log_request_header) {
+- log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
+- "fd:", con->fd,
+- "request-len:", con->request.request->used,
++ log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
++ "fd:", con->fd,
++ "request-len:", con->request.request->used,
+ "\n", con->request.request);
+ }
-+ /* is a exclusive lock set on the source */
-+ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
-+ con->http_status = 423;
-+ return HANDLER_FINISHED;
-+ }
+@@ -300,13 +302,13 @@
+ con->request.request->ptr[0] == '\r' &&
+ con->request.request->ptr[1] == '\n') {
+ /* we are in keep-alive and might get \r\n after a previous POST request.*/
+-
+
+ buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
+ } else {
+ /* fill the local request buffer */
+ buffer_copy_string_buffer(con->parse_request, con->request.request);
+ }
+-
+
- assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
+ keep_alive_set = 0;
+ con_length_set = 0;
-- /* taken what we have in the request-body and write it to a file */
-- if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
-+ /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
-+ * - most important Content-Range
-+ *
-+ *
-+ * Example: Content-Range: bytes 100-1037/1038 */
+@@ -318,25 +320,25 @@
+ * */
+ for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
+ char *cur = con->parse_request->ptr + i;
+-
+
-+ if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
-+ const char *num = ds_range->value->ptr;
-+ off_t offset;
-+ char *err = NULL;
+ switch(*cur) {
+- case '\r':
++ case '\r':
+ if (con->parse_request->ptr[i+1] == '\n') {
+ http_method_t r;
+ char *nuri = NULL;
+ size_t j;
+-
+
-+ if (0 != strncmp(num, "bytes ", 6)) {
-+ con->http_status = 501; /* not implemented */
+ /* \r\n -> \0\0 */
+ con->parse_request->ptr[i] = '\0';
+ con->parse_request->ptr[i+1] = '\0';
+-
+
-+ return HANDLER_FINISHED;
-+ }
+ buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
+-
+
-+ /* we only support <num>- ... */
+ if (request_line_stage != 2) {
+ con->http_status = 400;
+ con->response.keep_alive = 0;
+ con->keep_alive = 0;
+-
+
-+ num += 6;
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+@@ -345,36 +347,36 @@
+ }
+ return 0;
+ }
+-
++
+ proto = con->parse_request->ptr + first;
+-
++
+ *(uri - 1) = '\0';
+ *(proto - 1) = '\0';
+-
++
+ /* we got the first one :) */
+ if (-1 == (r = get_http_method_key(method))) {
+ con->http_status = 501;
+ con->response.keep_alive = 0;
+ con->keep_alive = 0;
+-
++
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
+-
++
+ return 0;
+ }
+-
+
-+ /* skip WS */
-+ while (*num == ' ' || *num == '\t') num++;
+ con->request.http_method = r;
+-
+- /*
++
++ /*
+ * RFC2616 says:
+ *
+ * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+ *
+- * */
++ * */
+ if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
+ char * major = proto + sizeof("HTTP/") - 1;
+ char * minor = strchr(major, '.');
+@@ -413,10 +415,10 @@
+ }
+
+ if (major_num == 1 && minor_num == 1) {
+- con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
++ con->request.http_version = HTTP_VERSION_1_1;
+ } else if (major_num == 1 && minor_num == 0) {
+ con->request.http_version = HTTP_VERSION_1_0;
+- } else {
++ } else {
+ con->http_status = 505;
+
+ if (srv->srvconf.log_request_header_on_error) {
+@@ -439,30 +441,30 @@
+ }
+ return 0;
+ }
+-
+
-+ if (*num == '\0') {
-+ con->http_status = 501; /* not implemented */
+ if (0 == strncmp(uri, "http://", 7) &&
+ NULL != (nuri = strchr(uri + 7, '/'))) {
+ /* ignore the host-part */
+-
+
-+ return HANDLER_FINISHED;
-+ }
+ buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
+ } else {
+ /* everything looks good so far */
+ buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
+ }
+-
+
-+ offset = strtoll(num, &err, 10);
+ /* check uri for invalid characters */
+ for (j = 0; j < con->request.uri->used - 1; j++) {
+ if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
+ unsigned char buf[2];
+ con->http_status = 400;
+ con->keep_alive = 0;
+-
+
-+ if (*err != '-' || offset < 0) {
-+ con->http_status = 501; /* not implemented */
+ if (srv->srvconf.log_request_header_on_error) {
+ buf[0] = con->request.uri->ptr[j];
+ buf[1] = '\0';
+-
+
-+ return HANDLER_FINISHED;
-+ }
+ if (con->request.uri->ptr[j] > 32 &&
+- con->request.uri->ptr[j] != 127) {
++ con->request.uri->ptr[j] != 127) {
+ /* the character is printable -> print it */
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "invalid character in URI -> 400",
+@@ -473,20 +475,20 @@
+ "invalid character in URI -> 400",
+ con->request.uri->ptr[j]);
+ }
+-
+
-+ if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
-+ switch (errno) {
-+ case ENOENT:
-+ con->http_status = 404; /* not found */
-+ break;
-+ default:
-+ con->http_status = 403; /* not found */
-+ break;
-+ }
-+ return HANDLER_FINISHED;
-+ }
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
+-
+
-+ if (-1 == lseek(fd, offset, SEEK_SET)) {
-+ con->http_status = 501; /* not implemented */
+ return 0;
+ }
+ }
+-
+
-+ close(fd);
+ buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
+-
+
-+ return HANDLER_FINISHED;
-+ }
-+ con->http_status = 200; /* modified */
-+ } else {
-+ /* take what we have in the request-body and write it to a file */
+ con->http_status = 0;
+-
+
-+ /* if the file doesn't exist, create it */
-+ if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
-+ if (errno == ENOENT &&
-+ -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
- /* we can't open the file */
- con->http_status = 403;
-- } else {
-- chunk *c;
-
-+ return HANDLER_FINISHED;
-+ } else {
- con->http_status = 201; /* created */
-+ }
-+ } else {
-+ con->http_status = 200; /* modified */
-+ }
-+ }
+ i++;
+ line++;
+ first = i+1;
+@@ -494,14 +496,14 @@
+ break;
+ case ' ':
+ switch(request_line_stage) {
+- case 0:
++ case 0:
+ /* GET|POST|... */
+- method = con->parse_request->ptr + first;
++ method = con->parse_request->ptr + first;
+ first = i + 1;
+ break;
+ case 1:
+ /* /foobar/... */
+- uri = con->parse_request->ptr + first;
++ uri = con->parse_request->ptr + first;
+ first = i + 1;
+ break;
+ default:
+@@ -509,7 +511,7 @@
+ con->http_status = 400;
+ con->response.keep_alive = 0;
+ con->keep_alive = 0;
+-
+
- con->file_finished = 1;
-
- for (c = cq->first; c; c = cq->first) {
-@@ -1462,7 +1763,6 @@
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+@@ -518,12 +520,12 @@
+ }
+ return 0;
}
- close(fd);
-
-- }
- return HANDLER_FINISHED;
- }
- case HTTP_METHOD_MOVE:
-@@ -1476,6 +1776,14 @@
- return HANDLER_FINISHED;
- }
-
-+ /* is a exclusive lock set on the source */
-+ if (con->request.http_method == HTTP_METHOD_MOVE) {
-+ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
-+ con->http_status = 423;
-+ return HANDLER_FINISHED;
-+ }
-+ }
+-
+
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
- destination = ds->value;
- } else {
-@@ -1549,7 +1857,7 @@
+ request_line_stage++;
+ break;
}
-
- buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
-- BUFFER_APPEND_SLASH(p->physical.path);
-+ PATHNAME_APPEND_SLASH(p->physical.path);
- buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
-
- /* don't add a second / */
-@@ -1613,6 +1921,12 @@
- /* it is just a file, good */
- int r;
-
-+ /* does the client have a lock for this connection ? */
-+ if (!webdav_has_lock(srv, con, p, p->uri.path)) {
-+ con->http_status = 423;
-+ return HANDLER_FINISHED;
-+ }
+ }
+-
+
- /* destination exists */
- if (0 == (r = stat(p->physical.path->ptr, &st))) {
- if (S_ISDIR(st.st_mode)) {
-@@ -1691,12 +2005,17 @@
+ in_folding = 0;
- return HANDLER_FINISHED;
+ if (con->request.uri->used == 1) {
+@@ -540,30 +542,30 @@
+ return 0;
}
-- case HTTP_METHOD_PROPPATCH: {
-+ case HTTP_METHOD_PROPPATCH:
- if (p->conf.is_readonly) {
- con->http_status = 403;
- return HANDLER_FINISHED;
- }
-+ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
-+ con->http_status = 423;
-+ return HANDLER_FINISHED;
-+ }
+-
+
- /* check if destination exists */
- if (-1 == stat(con->physical.path->ptr, &st)) {
- switch(errno) {
-@@ -1789,7 +2108,8 @@
- }
-
- if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
-- log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
-+ log_error_write(srv, __FILE__, __LINE__, "ss",
-+ "sql-set failed:", sqlite3_errmsg(p->conf.sql));
- }
- }
- }
-@@ -1821,6 +2141,7 @@
+ for (; i < con->parse_request->used && !done; i++) {
+ char *cur = con->parse_request->ptr + i;
+-
++
+ if (is_key) {
+ size_t j;
+ int got_colon = 0;
+-
++
+ /**
+ * 1*<any CHAR except CTLs or separators>
+ * CTLs == 0-31 + 127
+- *
++ *
+ */
+ switch(*cur) {
+ case ':':
+ is_key = 0;
+-
++
+ value = cur + 1;
+-
++
+ if (is_ws_after_key == 0) {
+ key_len = i - first;
}
-
- propmatch_cleanup:
+ is_ws_after_key = 0;
+-
+
- xmlFreeDoc(xml);
- } else {
+ break;
+ case '(':
+ case ')':
+@@ -584,8 +586,8 @@
con->http_status = 400;
-@@ -1830,7 +2151,303 @@
- #endif
- con->http_status = 501;
- return HANDLER_FINISHED;
-+ case HTTP_METHOD_LOCK:
-+ /**
-+ * a mac wants to write
-+ *
-+ * LOCK /dav/expire.txt HTTP/1.1\r\n
-+ * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
-+ * Accept: * / *\r\n
-+ * Depth: 0\r\n
-+ * Timeout: Second-600\r\n
-+ * Content-Type: text/xml; charset=\"utf-8\"\r\n
-+ * Content-Length: 229\r\n
-+ * Connection: keep-alive\r\n
-+ * Host: 192.168.178.23:1025\r\n
-+ * \r\n
-+ * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
-+ * <D:lockinfo xmlns:D=\"DAV:\">\n
-+ * <D:lockscope><D:exclusive/></D:lockscope>\n
-+ * <D:locktype><D:write/></D:locktype>\n
-+ * <D:owner>\n
-+ * <D:href>http://www.apple.com/webdav_fs/</D:href>\n
-+ * </D:owner>\n
-+ * </D:lockinfo>\n
-+ */
+ con->keep_alive = 0;
+ con->response.keep_alive = 0;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbsds",
++
++ log_error_write(srv, __FILE__, __LINE__, "sbsds",
+ "invalid character in key", con->request.request, cur, *cur, "-> 400");
+ return 0;
+ case ' ':
+@@ -594,13 +596,13 @@
+ is_key = 0;
+ in_folding = 1;
+ value = cur;
+-
+
-+ if (depth != 0 && depth != -1) {
-+ con->http_status = 400;
+ break;
+ }
+-
+-
+
-+ return HANDLER_FINISHED;
-+ }
+
-+#ifdef USE_LOCKS
-+ if (con->request.content_length) {
-+ xmlDocPtr xml;
-+ buffer *hdr_if = NULL;
+ key_len = i - first;
+-
+
-+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
-+ hdr_if = ds->value;
-+ }
+ /* skip every thing up to the : */
+ for (j = 1; !got_colon; j++) {
+ switch(con->parse_request->ptr[j + i]) {
+@@ -610,40 +612,40 @@
+ continue;
+ case ':':
+ /* ok, done */
+-
+
-+ /* we don't support Depth: Infinity on locks */
-+ if (hdr_if == NULL && depth == -1) {
-+ con->http_status = 409; /* Conflict */
+ i += j - 1;
+ got_colon = 1;
+-
+
-+ return HANDLER_FINISHED;
-+ }
+ break;
+ default:
+ /* error */
+-
+
-+ if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
-+ xmlNode *rootnode = xmlDocGetRootElement(xml);
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
+-
+
-+ assert(rootnode);
+ con->http_status = 400;
+ con->response.keep_alive = 0;
+ con->keep_alive = 0;
+-
+
-+ if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
-+ xmlNode *lockinfo;
-+ const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
+ return 0;
+ }
+ }
+-
+
-+ for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
-+ if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
-+ xmlNode *value;
-+ for (value = lockinfo->children; value; value = value->next) {
-+ if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
-+ (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
-+ lockscope = value->name;
-+ } else {
-+ con->http_status = 400;
+ break;
+ case '\r':
+ if (con->parse_request->ptr[i+1] == '\n' && i == first) {
+ /* End of Header */
+ con->parse_request->ptr[i] = '\0';
+ con->parse_request->ptr[i+1] = '\0';
+-
+
-+ xmlFreeDoc(xml);
-+ return HANDLER_FINISHED;
-+ }
-+ }
-+ } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
-+ xmlNode *value;
-+ for (value = lockinfo->children; value; value = value->next) {
-+ if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
-+ locktype = value->name;
-+ } else {
-+ con->http_status = 400;
+ i++;
+-
++
+ done = 1;
+-
++
+ break;
+ } else {
+ if (srv->srvconf.log_request_header_on_error) {
+@@ -652,7 +654,7 @@
+ "request-header:\n",
+ con->request.request);
+ }
+-
+
-+ xmlFreeDoc(xml);
-+ return HANDLER_FINISHED;
-+ }
-+ }
+ con->http_status = 400;
+ con->keep_alive = 0;
+ con->response.keep_alive = 0;
+@@ -693,16 +695,16 @@
+ con->http_status = 400;
+ con->keep_alive = 0;
+ con->response.keep_alive = 0;
+-
+
-+ } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
-+ }
-+ }
+ if (srv->srvconf.log_request_header_on_error) {
+- log_error_write(srv, __FILE__, __LINE__, "sbsds",
++ log_error_write(srv, __FILE__, __LINE__, "sbsds",
+ "CTL character in key", con->request.request, cur, *cur, "-> 400");
+
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
+-
+
-+ if (lockscope && locktype) {
-+ sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
+ return 0;
+ default:
+ /* ok */
+@@ -710,25 +712,25 @@
+ }
+ } else {
+ switch(*cur) {
+- case '\r':
++ case '\r':
+ if (con->parse_request->ptr[i+1] == '\n') {
+ /* End of Headerline */
+ con->parse_request->ptr[i] = '\0';
+ con->parse_request->ptr[i+1] = '\0';
+-
+
-+ /* is this resourse already locked ? */
+ if (in_folding) {
+ if (!ds) {
+ /* 400 */
+-
+
-+ /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
-+ * FROM locks
-+ * WHERE resource = ? */
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
+-
+
-+ if (stmt) {
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
+
+-
+
-+ sqlite3_reset(stmt);
+ con->http_status = 400;
+ con->keep_alive = 0;
+ con->response.keep_alive = 0;
+@@ -738,9 +740,9 @@
+ } else {
+ int s_len;
+ key = con->parse_request->ptr + first;
+-
+
-+ sqlite3_bind_text(stmt, 1,
-+ p->uri.path->ptr,
-+ p->uri.path->used - 1,
-+ SQLITE_TRANSIENT);
+ s_len = cur - value;
+-
+
-+ /* it is the PK */
-+ while (SQLITE_ROW == sqlite3_step(stmt)) {
-+ /* we found a lock
-+ * 1. is it compatible ?
-+ * 2. is it ours */
-+ char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
+ if (s_len > 0) {
+ int cmp = 0;
+ if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
+@@ -748,86 +750,87 @@
+ }
+ buffer_copy_string_len(ds->key, key, key_len);
+ buffer_copy_string_len(ds->value, value, s_len);
+-
+- /* retreive values
+- *
+- *
++
++ /* retreive values
++ *
++ *
+ * the list of options is sorted to simplify the search
+ */
+-
+
-+ if (strcmp(sql_lockscope, "exclusive")) {
-+ con->http_status = 423;
-+ } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
-+ /* resourse is locked with a shared lock
-+ * client wants exclusive */
-+ con->http_status = 423;
-+ }
-+ }
-+ if (con->http_status == 423) {
-+ xmlFreeDoc(xml);
-+ return HANDLER_FINISHED;
-+ }
- }
+ if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
+ array *vals;
+ size_t vi;
+-
+
-+ stmt = p->conf.stmt_create_lock;
-+ if (stmt) {
-+ /* create a lock-token */
-+ uuid_t id;
-+ char uuid[37] /* 36 + \0 */;
+ /* split on , */
+-
+
-+ uuid_generate(id);
-+ uuid_unparse(id, uuid);
+ vals = srv->split_vals;
+
+ array_reset(vals);
+-
+
-+ buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
-+ buffer_append_string(p->tmp_buf, uuid);
+ http_request_split_value(vals, ds->value);
+-
+
-+ /* "CREATE TABLE locks ("
-+ * " locktoken TEXT NOT NULL,"
-+ * " resource TEXT NOT NULL,"
-+ * " lockscope TEXT NOT NULL,"
-+ * " locktype TEXT NOT NULL,"
-+ * " owner TEXT NOT NULL,"
-+ * " depth INT NOT NULL,"
-+ */
+ for (vi = 0; vi < vals->used; vi++) {
+ data_string *dsv = (data_string *)vals->data[vi];
+-
+
-+ sqlite3_reset(stmt);
+ if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
+ keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
+-
+
-+ sqlite3_bind_text(stmt, 1,
-+ CONST_BUF_LEN(p->tmp_buf),
-+ SQLITE_TRANSIENT);
+ break;
+ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
+ keep_alive_set = HTTP_CONNECTION_CLOSE;
+-
+
-+ sqlite3_bind_text(stmt, 2,
-+ CONST_BUF_LEN(con->uri.path),
-+ SQLITE_TRANSIENT);
+ break;
+ }
+ }
+-
++
+ } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
+ char *err;
+ unsigned long int r;
+ size_t j;
+-
++
+ if (con_length_set) {
+ con->http_status = 400;
+ con->keep_alive = 0;
+-
++
+ if (srv->srvconf.log_request_header_on_error) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "duplicate Content-Length-header -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
++ ds->free((data_unset *) ds);
+ return 0;
+ }
+-
+
-+ sqlite3_bind_text(stmt, 3,
-+ lockscope,
-+ xmlStrlen(lockscope),
-+ SQLITE_TRANSIENT);
+ if (ds->value->used == 0) SEGFAULT();
+-
+
-+ sqlite3_bind_text(stmt, 4,
-+ locktype,
-+ xmlStrlen(locktype),
-+ SQLITE_TRANSIENT);
+ for (j = 0; j < ds->value->used - 1; j++) {
+ char c = ds->value->ptr[j];
+ if (!isdigit((unsigned char)c)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "content-length broken:", ds->value, "-> 400");
+-
+
-+ /* owner */
-+ sqlite3_bind_text(stmt, 5,
-+ "",
-+ 0,
-+ SQLITE_TRANSIENT);
+ con->http_status = 400;
+ con->keep_alive = 0;
+-
+
-+ /* depth */
-+ sqlite3_bind_int(stmt, 6,
-+ depth);
+ array_insert_unique(con->request.headers, (data_unset *)ds);
+ return 0;
+ }
+ }
+-
+
+ r = strtoul(ds->value->ptr, &err, 10);
+-
+
-+ if (SQLITE_DONE != sqlite3_step(stmt)) {
-+ log_error_write(srv, __FILE__, __LINE__, "ss",
-+ "create lock:", sqlite3_errmsg(p->conf.sql));
-+ }
+ if (*err == '\0') {
+ con_length_set = 1;
+ con->request.content_length = r;
+ } else {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "content-length broken:", ds->value, "-> 400");
+-
+
-+ /* looks like we survived */
-+ webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
+ con->http_status = 400;
+ con->keep_alive = 0;
+-
+
-+ con->http_status = 201;
-+ con->file_finished = 1;
-+ }
-+ }
-+ }
+ array_insert_unique(con->request.headers, (data_unset *)ds);
+ return 0;
+ }
+@@ -838,23 +841,24 @@
+ } else {
+ con->http_status = 400;
+ con->keep_alive = 0;
+-
++
+ if (srv->srvconf.log_request_header_on_error) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "duplicate Content-Type-header -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
++ ds->free((data_unset *) ds);
+ return 0;
+ }
+ } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
+- /* HTTP 2616 8.2.3
++ /* HTTP 2616 8.2.3
+ * Expect: 100-continue
+- *
++ *
+ * -> (10.1.1) 100 (read content, process request, send final status-code)
+ * -> (10.4.18) 417 (close)
+- *
++ *
+ * (not handled at all yet, we always send 417 here)
+ *
+ * What has to be added ?
+@@ -863,10 +867,10 @@
+ * header
+ *
+ */
+-
++
+ con->http_status = 417;
+ con->keep_alive = 0;
+-
++
+ array_insert_unique(con->request.headers, (data_unset *)ds);
+ return 0;
+ } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
+@@ -875,14 +879,15 @@
+ } else {
+ con->http_status = 400;
+ con->keep_alive = 0;
+-
++
+ if (srv->srvconf.log_request_header_on_error) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "duplicate Host-header -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
++ ds->free((data_unset *) ds);
+ return 0;
+ }
+ } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
+@@ -897,14 +902,15 @@
+ } else {
+ con->http_status = 400;
+ con->keep_alive = 0;
+-
++
+ if (srv->srvconf.log_request_header_on_error) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "duplicate If-Modified-Since header -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
++ ds->free((data_unset *) ds);
+ return 0;
+ }
+ } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
+@@ -914,47 +920,49 @@
+ } else {
+ con->http_status = 400;
+ con->keep_alive = 0;
+-
++
+ if (srv->srvconf.log_request_header_on_error) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "duplicate If-None-Match-header -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
++ ds->free((data_unset *) ds);
+ return 0;
+ }
+ } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
+ if (!con->request.http_range) {
+ /* bytes=.*-.* */
+-
+
-+ xmlFreeDoc(xml);
-+ return HANDLER_FINISHED;
-+ } else {
-+ con->http_status = 400;
-+ return HANDLER_FINISHED;
-+ }
-+ } else {
+ if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
+ NULL != strchr(ds->value->ptr+6, '-')) {
+-
+
-+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
-+ buffer *locktoken = ds->value;
-+ sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
+ /* if dup, only the first one will survive */
+ con->request.http_range = ds->value->ptr + 6;
+ }
+ } else {
+ con->http_status = 400;
+ con->keep_alive = 0;
+-
++
+ if (srv->srvconf.log_request_header_on_error) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "duplicate Range-header -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
++ ds->free((data_unset *) ds);
+ return 0;
+ }
+ }
+-
+
-+ /* remove the < > around the token */
-+ if (locktoken->used < 6) {
-+ con->http_status = 400;
+ array_insert_unique(con->request.headers, (data_unset *)ds);
+ } else {
+ /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
+ }
+ }
+-
+
-+ return HANDLER_FINISHED;
-+ }
+ i++;
+ first = i+1;
+ is_key = 1;
+@@ -963,10 +971,10 @@
+ in_folding = 0;
+ } else {
+ if (srv->srvconf.log_request_header_on_error) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "CR without LF", con->request.request, "-> 400");
+ }
+-
+
-+ buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
+ con->http_status = 400;
+ con->keep_alive = 0;
+ con->response.keep_alive = 0;
+@@ -982,28 +990,28 @@
+ }
+ }
+ }
+-
+
-+ sqlite3_reset(stmt);
+ con->header_len = i;
+-
+
-+ sqlite3_bind_text(stmt, 1,
-+ CONST_BUF_LEN(p->tmp_buf),
-+ SQLITE_TRANSIENT);
+ /* do some post-processing */
+
+ if (con->request.http_version == HTTP_VERSION_1_1) {
+ if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
+ /* no Connection-Header sent */
+-
+
-+ if (SQLITE_DONE != sqlite3_step(stmt)) {
-+ log_error_write(srv, __FILE__, __LINE__, "ss",
-+ "refresh lock:", sqlite3_errmsg(p->conf.sql));
-+ }
+ /* HTTP/1.1 -> keep-alive default TRUE */
+ con->keep_alive = 1;
+ } else {
+ con->keep_alive = 0;
+ }
+-
+
-+ webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
+ /* RFC 2616, 14.23 */
+ if (con->request.http_host == NULL ||
+ buffer_is_empty(con->request.http_host)) {
+ con->http_status = 400;
+ con->response.keep_alive = 0;
+ con->keep_alive = 0;
+-
+
-+ con->http_status = 200;
-+ con->file_finished = 1;
-+ return HANDLER_FINISHED;
-+ } else {
-+ /* we need a lock-token to refresh */
-+ con->http_status = 400;
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+@@ -1015,18 +1023,18 @@
+ } else {
+ if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
+ /* no Connection-Header sent */
+-
+
-+ return HANDLER_FINISHED;
-+ }
-+ }
-+ break;
-+#else
-+ con->http_status = 501;
-+ return HANDLER_FINISHED;
-+#endif
-+ case HTTP_METHOD_UNLOCK:
-+#ifdef USE_LOCKS
-+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
-+ buffer *locktoken = ds->value;
-+ sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
+ /* HTTP/1.0 -> keep-alive default FALSE */
+ con->keep_alive = 1;
+ } else {
+ con->keep_alive = 0;
+ }
+ }
+-
+
-+ /* remove the < > around the token */
-+ if (locktoken->used < 4) {
-+ con->http_status = 400;
+ /* check hostname field if it is set */
+ if (NULL != con->request.http_host &&
+ 0 != request_check_hostname(srv, con, con->request.http_host)) {
+-
+
-+ return HANDLER_FINISHED;
-+ }
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "Invalid Hostname -> 400");
+@@ -1038,7 +1046,7 @@
+ con->http_status = 400;
+ con->response.keep_alive = 0;
+ con->keep_alive = 0;
+-
+
-+ /**
-+ * FIXME:
-+ *
-+ * if the resourse is locked:
-+ * - by us: unlock
-+ * - by someone else: 401
-+ * if the resource is not locked:
-+ * - 412
-+ * */
+ return 0;
+ }
+
+@@ -1048,7 +1056,7 @@
+ /* content-length is forbidden for those */
+ if (con_length_set && con->request.content_length != 0) {
+ /* content-length is missing */
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "GET/HEAD with content-length -> 400");
+
+ con->keep_alive = 0;
+@@ -1060,7 +1068,7 @@
+ /* content-length is required for them */
+ if (!con_length_set) {
+ /* content-length is missing */
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "POST-request, but content-length missing -> 411");
+
+ con->keep_alive = 0;
+@@ -1073,16 +1081,16 @@
+ /* the may have a content-length */
+ break;
+ }
+-
+-
++
++
+ /* check if we have read post data */
+ if (con_length_set) {
+ /* don't handle more the SSIZE_MAX bytes in content-length */
+ if (con->request.content_length > SSIZE_MAX) {
+- con->http_status = 413;
++ con->http_status = 413;
+ con->keep_alive = 0;
+
+- log_error_write(srv, __FILE__, __LINE__, "sds",
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "request-size too long:", con->request.content_length, "-> 413");
+ return 0;
+ }
+@@ -1090,25 +1098,25 @@
+ /* divide by 1024 as srvconf.max_request_size is in kBytes */
+ if (srv->srvconf.max_request_size != 0 &&
+ (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
+- /* the request body itself is larger then
++ /* the request body itself is larger then
+ * our our max_request_size
+ */
+-
+
-+ buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
+ con->http_status = 413;
+ con->keep_alive = 0;
+-
+- log_error_write(srv, __FILE__, __LINE__, "sds",
+
-+ sqlite3_reset(stmt);
++ log_error_write(srv, __FILE__, __LINE__, "sds",
+ "request-size too long:", con->request.content_length, "-> 413");
+ return 0;
+ }
+-
+-
+
-+ sqlite3_bind_text(stmt, 1,
-+ CONST_BUF_LEN(p->tmp_buf),
-+ SQLITE_TRANSIENT);
+
-+ sqlite3_bind_text(stmt, 2,
-+ CONST_BUF_LEN(con->uri.path),
-+ SQLITE_TRANSIENT);
+ /* we have content */
+ if (con->request.content_length != 0) {
+ return 1;
+ }
+ }
+-
+
-+ if (SQLITE_DONE != sqlite3_step(stmt)) {
-+ log_error_write(srv, __FILE__, __LINE__, "ss",
-+ "remove lock:", sqlite3_errmsg(p->conf.sql));
-+ }
+ return 0;
+ }
+
+@@ -1116,9 +1124,9 @@
+ UNUSED(srv);
+
+ if (con->request.request->used < 5) return 0;
+-
+
-+ if (0 == sqlite3_changes(p->conf.sql)) {
-+ con->http_status = 401;
-+ } else {
-+ con->http_status = 204;
-+ }
-+ return HANDLER_FINISHED;
-+ } else {
-+ /* we need a lock-token to unlock */
-+ con->http_status = 400;
+ if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
+ if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
+-
+
-+ return HANDLER_FINISHED;
-+ }
-+ break;
-+#else
-+ con->http_status = 501;
-+ return HANDLER_FINISHED;
-+#endif
- default:
- break;
- }
---- lighttpd-1.4.11/src/network.c 2006-03-04 16:45:46.000000000 +0200
-+++ lighttpd/src/network.c 2006-07-11 21:23:39.983848713 +0300
-@@ -1,14 +1,14 @@
- #include <sys/types.h>
- #include <sys/stat.h>
--#include <sys/time.h>
-
- #include <errno.h>
- #include <fcntl.h>
--#include <unistd.h>
- #include <string.h>
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/response.c lighttpd-1.4.12/src/response.c
+--- lighttpd-1.4.11/src/response.c 2006-03-04 16:41:39.000000000 +0200
++++ lighttpd-1.4.12/src/response.c 2006-07-11 21:23:40.000000000 +0300
+@@ -7,7 +7,6 @@
#include <stdlib.h>
+ #include <string.h>
+ #include <time.h>
+-#include <unistd.h>
+ #include <ctype.h>
#include <assert.h>
-+#include <stdio.h>
-+
- #include "network.h"
- #include "fdevent.h"
- #include "log.h"
-@@ -19,6 +19,7 @@
- #include "network_backends.h"
- #include "sys-mmap.h"
+@@ -24,15 +23,17 @@
+ #include "plugin.h"
+
#include "sys-socket.h"
+#include "sys-files.h"
++#include "sys-strings.h"
- #ifdef USE_OPENSSL
- # include <openssl/ssl.h>
-@@ -77,7 +78,7 @@
- struct accept_filter_arg afa;
- #endif
-
--#ifdef __WIN32
-+#ifdef _WIN32
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
-@@ -244,6 +245,7 @@
- addr_len = sizeof(struct sockaddr_in);
-
- break;
-+#ifndef _WIN32
- case AF_UNIX:
- srv_socket->addr.un.sun_family = AF_UNIX;
- strcpy(srv_socket->addr.un.sun_path, host);
-@@ -283,6 +285,7 @@
- }
-
- break;
-+#endif
- default:
- addr_len = 0;
-
-@@ -404,7 +407,6 @@
- }
-
- srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
+ int http_response_write_header(server *srv, connection *con) {
+ buffer *b;
+ size_t i;
+ int have_date = 0;
+ int have_server = 0;
-
- buffer_free(b);
-
- return 0;
-@@ -425,11 +427,20 @@
- close(srv_socket->fd);
- }
-
-+ if (srv_socket->is_ssl) {
-+#ifdef USE_OPENSSL
-+ SSL_CTX_free(srv_socket->ssl_ctx);
-+#endif
-+ }
-+
- buffer_free(srv_socket->srv_token);
-
- free(srv_socket);
- }
-
-+#ifdef USE_OPENSSL
-+ ERR_free_strings();
-+#endif
- free(srv->srv_sockets.ptr);
-
- return 0;
-@@ -437,11 +448,15 @@
-
- typedef enum {
- NETWORK_BACKEND_UNSET,
+
- NETWORK_BACKEND_WRITE,
- NETWORK_BACKEND_WRITEV,
- NETWORK_BACKEND_LINUX_SENDFILE,
- NETWORK_BACKEND_FREEBSD_SENDFILE,
-- NETWORK_BACKEND_SOLARIS_SENDFILEV
-+ NETWORK_BACKEND_SOLARIS_SENDFILEV,
+ b = chunkqueue_get_prepend_buffer(con->write_queue);
+-
+
-+ NETWORK_BACKEND_WIN32_SEND,
-+ NETWORK_BACKEND_WIN32_TRANSMITFILE,
- } network_backend_t;
-
- int network_init(server *srv) {
-@@ -466,7 +481,16 @@
- #if defined USE_WRITEV
- { NETWORK_BACKEND_WRITEV, "writev" },
- #endif
-+#if defined USE_WRITE
- { NETWORK_BACKEND_WRITE, "write" },
-+#endif
-+#if defined USE_WIN32_TRANSMITFILE
-+ { NETWORK_BACKEND_WIN32_TRANSMITFILE, "win32-transmitfile" },
-+#endif
-+#if defined USE_WIN32_SEND
-+ { NETWORK_BACKEND_WIN32_SEND, "win32-send" },
-+#endif
+ if (con->request.http_version == HTTP_VERSION_1_1) {
+ BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
+ } else {
+@@ -41,25 +42,26 @@
+ buffer_append_long(b, con->http_status);
+ BUFFER_APPEND_STRING_CONST(b, " ");
+ buffer_append_string(b, get_http_status_name(con->http_status));
+-
+
- { NETWORK_BACKEND_UNSET, NULL }
- };
-
-@@ -508,33 +532,59 @@
- }
+ if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
+ BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
+ buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
}
-
-+#define SET_NETWORK_BACKEND(read, write) \
-+ srv->network_backend_write = network_write_chunkqueue_##write;\
-+ srv->network_backend_read = network_read_chunkqueue_##read
+-
+
-+#define SET_NETWORK_BACKEND_SSL(read, write) \
-+ srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
-+ srv->network_ssl_backend_read = network_read_chunkqueue_##read
+ if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
+ BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
+ }
+-
+-
+
- switch(backend) {
+
-+#ifdef USE_WIN32_SEND
-+ case NETWORK_BACKEND_WIN32_SEND:
-+ SET_NETWORK_BACKEND(win32recv, win32send);
-+ break;
-+#ifdef USE_WIN32_TRANSMITFILE
-+ case NETWORK_BACKEND_WIN32_TRANSMITFILE:
-+ SET_NETWORK_BACKEND(win32recv, win32transmitfile);
-+ break;
-+#endif
-+#endif
+ /* add all headers */
+ for (i = 0; i < con->response.headers->used; i++) {
+ data_string *ds;
+-
+
-+#ifdef USE_WRITE
- case NETWORK_BACKEND_WRITE:
-- srv->network_backend_write = network_write_chunkqueue_write;
-+ SET_NETWORK_BACKEND(read, write);
- break;
+ ds = (data_string *)con->response.headers->data[i];
+-
+
- #ifdef USE_WRITEV
- case NETWORK_BACKEND_WRITEV:
-- srv->network_backend_write = network_write_chunkqueue_writev;
-+ SET_NETWORK_BACKEND(read, writev);
- break;
- #endif
- #ifdef USE_LINUX_SENDFILE
- case NETWORK_BACKEND_LINUX_SENDFILE:
-- srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
-+ SET_NETWORK_BACKEND(read, linuxsendfile);
- break;
- #endif
- #ifdef USE_FREEBSD_SENDFILE
- case NETWORK_BACKEND_FREEBSD_SENDFILE:
-- srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
-+ SET_NETWORK_BACKEND(read, freebsdsendfile);
- break;
- #endif
- #ifdef USE_SOLARIS_SENDFILEV
- case NETWORK_BACKEND_SOLARIS_SENDFILEV:
-- srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
-+ SET_NETWORK_BACKEND(read, solarissendfilev);
- break;
+ if (ds->value->used && ds->key->used &&
+- 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
++ 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
++ 0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
+ if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
+ if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
+
+@@ -68,28 +70,28 @@
+ BUFFER_APPEND_STRING_CONST(b, ": ");
+ buffer_append_string_buffer(b, ds->value);
+ #if 0
+- log_error_write(srv, __FILE__, __LINE__, "bb",
++ log_error_write(srv, __FILE__, __LINE__, "bb",
+ ds->key, ds->value);
#endif
-+#endif
- default:
- return -1;
+ }
}
-+#ifdef USE_OPENSSL
-+ SET_NETWORK_BACKEND_SSL(openssl, openssl);
-+#endif
-
- /* check for $SERVER["socket"] */
- for (i = 1; i < srv->config_context->used; i++) {
-@@ -569,23 +619,34 @@
-
- int network_register_fdevents(server *srv) {
- size_t i;
-
- if (-1 == fdevent_reset(srv->ev)) {
- return -1;
- }
++
+ if (!have_date) {
+ /* HTTP/1.1 requires a Date: header */
+ BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
-
- /* register fdevents after reset */
- for (i = 0; i < srv->srv_sockets.used; i++) {
- server_socket *srv_socket = srv->srv_sockets.ptr[i];
++
+ /* cache the generated timestamp */
+ if (srv->cur_ts != srv->last_generated_date_ts) {
+ buffer_prepare_copy(srv->ts_date_str, 255);
+-
+- strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
++
++ strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
+ "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
+-
++
+ srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
-
- fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
- fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
- }
- return 0;
- }
-
--int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
-- int ret = -1;
-+network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
-+ server_socket *srv_socket = con->srv_socket;
+
-+ if (srv_socket->is_ssl) {
-+#ifdef USE_OPENSSL
-+ return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
-+#else
-+ return NETWORK_STATUS_FATAL_ERROR;
-+#endif
-+ } else {
-+ return srv->network_backend_read(srv, con, con->fd, cq);
-+ }
-+}
+ srv->last_generated_date_ts = srv->cur_ts;
+ }
+-
+
-+network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
-+ network_status_t ret = NETWORK_STATUS_UNSET;
- off_t written = 0;
- #ifdef TCP_CORK
- int corked = 0;
-@@ -622,9 +683,14 @@
- ret = srv->network_backend_write(srv, con, con->fd, cq);
+ buffer_append_string_buffer(b, srv->ts_date_str);
}
-
-- if (ret >= 0) {
-+ switch (ret) {
-+ case NETWORK_STATUS_WAIT_FOR_EVENT:
-+ case NETWORK_STATUS_SUCCESS:
- chunkqueue_remove_finished_chunks(cq);
-- ret = chunkqueue_is_empty(cq) ? 0 : 1;
+
+@@ -101,16 +103,16 @@
+ buffer_append_string_buffer(b, con->conf.server_tag);
+ }
+ }
+-
+
-+ break;
-+ default:
-+ break;
+ BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
+-
+-
++
++
+ con->bytes_header = b->used - 1;
+-
++
+ if (con->conf.log_response_header) {
+ log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
}
-
- #ifdef TCP_CORK
---- lighttpd-1.4.11/src/network.h 2005-08-11 01:26:42.000000000 +0300
-+++ lighttpd/src/network.h 2006-07-11 21:23:39.983848713 +0300
-@@ -3,7 +3,8 @@
-
- #include "server.h"
-
--int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
-+network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
-+network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
+-
++
+ return 0;
+ }
- int network_init(server *srv);
- int network_close(server *srv);
---- lighttpd-1.4.11/src/network_backends.h 2005-10-24 15:13:51.000000000 +0300
-+++ lighttpd/src/network_backends.h 2006-07-11 21:23:40.035851970 +0300
-@@ -43,16 +43,52 @@
- # define USE_AIX_SENDFILE
- #endif
+@@ -118,71 +120,71 @@
-+/**
-+* unix can use read/write or recv/send on sockets
-+* win32 only recv/send
-+*/
-+#ifdef _WIN32
-+# define USE_WIN32_SEND
-+/* wait for async-io support
-+# define USE_WIN32_TRANSMITFILE
-+*/
-+#else
-+# define USE_WRITE
-+#endif
+ handler_t http_response_prepare(server *srv, connection *con) {
+ handler_t r;
+-
+- /* looks like someone has already done a decision */
+- if (con->mode == DIRECT &&
+
- #include "base.h"
-+#include "network.h"
++ /* looks like someone has already made a decision */
++ if (con->mode == DIRECT &&
+ (con->http_status != 0 && con->http_status != 200)) {
+ /* remove a packets in the queue */
+ if (con->file_finished == 0) {
+ chunkqueue_reset(con->write_queue);
+ }
+-
+
-+#define NETWORK_BACKEND_WRITE_CHUNK(x) \
-+ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c)
+ return HANDLER_FINISHED;
+ }
+-
+
-+#define NETWORK_BACKEND_WRITE(x) \
-+ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
-+#define NETWORK_BACKEND_READ(x) \
-+ network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
+ /* no decision yet, build conf->filename */
+ if (con->mode == DIRECT && con->physical.path->used == 0) {
+ char *qstr;
-+NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
+- /* we only come here when we have the parse the full request again
+- *
+- * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
++ /* we only come here when we have to parse the full request again
++ *
++ * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
+ * problem here as mod_setenv might get called multiple times
+ *
+ * fastcgi-auth might lead to a COMEBACK too
+ * fastcgi again dead server too
+ *
+ * mod_compress might add headers twice too
+- *
++ *
+ * */
+-
+
-+NETWORK_BACKEND_WRITE(write);
-+NETWORK_BACKEND_WRITE(writev);
-+NETWORK_BACKEND_WRITE(linuxsendfile);
-+NETWORK_BACKEND_WRITE(freebsdsendfile);
-+NETWORK_BACKEND_WRITE(solarissendfilev);
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
+ }
+ config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
+-
+
-+NETWORK_BACKEND_WRITE(win32transmitfile);
-+NETWORK_BACKEND_WRITE(win32send);
+ /**
+ * prepare strings
+- *
+- * - uri.path_raw
++ *
++ * - uri.path_raw
+ * - uri.path (secure)
+ * - uri.query
+- *
++ *
+ */
+-
+- /**
+
-+NETWORK_BACKEND_READ(read);
-+NETWORK_BACKEND_READ(win32recv);
-
--int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
--int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
--int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
--int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
--int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
- #ifdef USE_OPENSSL
--int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
-+#define NETWORK_BACKEND_WRITE_SSL(x) \
-+ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
-+#define NETWORK_BACKEND_READ_SSL(x) \
-+ network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
++ /**
+ * Name according to RFC 2396
+- *
++ *
+ * - scheme
+ * - authority
+ * - path
+ * - query
+- *
++ *
+ * (scheme)://(authority)(path)?(query)
+- *
+- *
++ *
++ *
+ */
+-
+
-+NETWORK_BACKEND_WRITE_SSL(openssl);
-+NETWORK_BACKEND_READ_SSL(openssl);
- #endif
-
- #endif
---- lighttpd-1.4.11/src/network_freebsd_sendfile.c 2005-10-22 12:28:18.000000000 +0300
-+++ lighttpd/src/network_freebsd_sendfile.c 2006-07-11 21:23:40.107856480 +0300
-@@ -31,106 +31,25 @@
- # endif
- #endif
-
--int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
-+NETWORK_BACKEND_WRITE(freebsdsendfile) {
- chunk *c;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- int chunk_finished = 0;
-+ network_status_t ret;
-
- switch(c->type) {
-- case MEM_CHUNK: {
-- char * offset;
-- size_t toSend;
-- ssize_t r;
--
-- size_t num_chunks, i;
-- struct iovec chunks[UIO_MAXIOV];
-- chunk *tc;
-- size_t num_bytes = 0;
--
-- /* we can't send more then SSIZE_MAX bytes in one chunk */
--
-- /* build writev list
-- *
-- * 1. limit: num_chunks < UIO_MAXIOV
-- * 2. limit: num_bytes < SSIZE_MAX
-- */
-- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
--
-- for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
-- if (tc->mem->used == 0) {
-- chunks[i].iov_base = tc->mem->ptr;
-- chunks[i].iov_len = 0;
-- } else {
-- offset = tc->mem->ptr + tc->offset;
-- toSend = tc->mem->used - 1 - tc->offset;
--
-- chunks[i].iov_base = offset;
--
-- /* protect the return value of writev() */
-- if (toSend > SSIZE_MAX ||
-- num_bytes + toSend > SSIZE_MAX) {
-- chunks[i].iov_len = SSIZE_MAX - num_bytes;
--
-- num_chunks = i + 1;
-- break;
-- } else {
-- chunks[i].iov_len = toSend;
-- }
--
-- num_bytes += toSend;
-- }
-- }
--
-- if ((r = writev(fd, chunks, num_chunks)) < 0) {
-- switch (errno) {
-- case EAGAIN:
-- case EINTR:
-- r = 0;
-- break;
-- case EPIPE:
-- case ECONNRESET:
-- return -2;
-- default:
-- log_error_write(srv, __FILE__, __LINE__, "ssd",
-- "writev failed:", strerror(errno), fd);
--
-- return -1;
-- }
--
-- r = 0;
-- }
-+ case MEM_CHUNK:
-+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
-
-- /* check which chunks have been written */
-- cq->bytes_out += r;
--
-- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
-- if (r >= (ssize_t)chunks[i].iov_len) {
-- /* written */
-- r -= chunks[i].iov_len;
-- tc->offset += chunks[i].iov_len;
--
-- if (chunk_finished) {
-- /* skip the chunks from further touches */
-- chunks_written++;
-- c = c->next;
-- } else {
-- /* chunks_written + c = c->next is done in the for()*/
-- chunk_finished++;
-+ if (ret != NETWORK_STATUS_SUCCESS) {
-+ return ret;
- }
-- } else {
-- /* partially written */
-
-- tc->offset += r;
-- chunk_finished = 0;
--
-- break;
-- }
-- }
-+ chunk_finished = 1;
-
+ buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
+ buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
+ buffer_to_lower(con->uri.authority);
+-
++
+ config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */
+ config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */
+ config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
+ config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */
+ config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */
+-
++
+ /** extract query string from request.uri */
+ if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
+ buffer_copy_string (con->uri.query, qstr + 1);
+@@ -200,22 +202,22 @@
+ log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path_raw);
+ log_error_write(srv, __FILE__, __LINE__, "sb", "URI-query : ", con->uri.query);
+ }
+-
++
+ /* disable keep-alive if requested */
+-
++
+ if (con->request_count > con->conf.max_keep_alive_requests) {
+ con->keep_alive = 0;
+ }
+-
+-
++
++
+ /**
+- *
+- * call plugins
+- *
++ *
++ * call plugins
++ *
+ * - based on the raw URL
+- *
++ *
+ */
+-
++
+ switch(r = plugins_call_handle_uri_raw(srv, con)) {
+ case HANDLER_GO_ON:
+ break;
+@@ -229,14 +231,14 @@
break;
-- }
- case FILE_CHUNK: {
- off_t offset, r;
- size_t toSend;
-@@ -140,7 +59,7 @@
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- strerror(errno), c->file.name);
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
-
- offset = c->file.start + c->offset;
-@@ -151,13 +70,13 @@
- if (offset > sce->st.st_size) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
-
- r = 0;
-@@ -169,11 +88,11 @@
- break;
- case ENOTCONN:
- close(ifd);
-- return -2;
-+ return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
- close(ifd);
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
- }
- close(ifd);
-@@ -201,7 +120,7 @@
}
- }
-
-- return chunks_written;
-+ return NETWORK_STATUS_SUCCESS;
- }
-
- #endif
---- lighttpd-1.4.11/src/network_linux_sendfile.c 2006-02-15 20:02:36.000000000 +0200
-+++ lighttpd/src/network_linux_sendfile.c 2006-07-11 21:23:40.271866752 +0300
-@@ -26,106 +26,38 @@
- /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
- #undef HAVE_POSIX_FADVISE
--int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
-- chunk *c;
-+NETWORK_BACKEND_WRITE(linuxsendfile) {
-+ chunk *c, *tc;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- int chunk_finished = 0;
-+ network_status_t ret;
-
- switch(c->type) {
-- case MEM_CHUNK: {
-- char * offset;
-- size_t toSend;
-- ssize_t r;
--
-- size_t num_chunks, i;
-- struct iovec chunks[UIO_MAXIOV];
-- chunk *tc;
-- size_t num_bytes = 0;
--
-- /* we can't send more then SSIZE_MAX bytes in one chunk */
--
-- /* build writev list
-- *
-- * 1. limit: num_chunks < UIO_MAXIOV
-- * 2. limit: num_bytes < SSIZE_MAX
-- */
-- for (num_chunks = 0, tc = c;
-- tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
-- tc = tc->next, num_chunks++);
--
-- for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
-- if (tc->mem->used == 0) {
-- chunks[i].iov_base = tc->mem->ptr;
-- chunks[i].iov_len = 0;
-- } else {
-- offset = tc->mem->ptr + tc->offset;
-- toSend = tc->mem->used - 1 - tc->offset;
--
-- chunks[i].iov_base = offset;
--
-- /* protect the return value of writev() */
-- if (toSend > SSIZE_MAX ||
-- num_bytes + toSend > SSIZE_MAX) {
-- chunks[i].iov_len = SSIZE_MAX - num_bytes;
--
-- num_chunks = i + 1;
-- break;
-- } else {
-- chunks[i].iov_len = toSend;
-- }
--
-- num_bytes += toSend;
-- }
-- }
--
-- if ((r = writev(fd, chunks, num_chunks)) < 0) {
-- switch (errno) {
-- case EAGAIN:
-- case EINTR:
-- r = 0;
-- break;
-- case EPIPE:
-- case ECONNRESET:
-- return -2;
-- default:
-- log_error_write(srv, __FILE__, __LINE__, "ssd",
-- "writev failed:", strerror(errno), fd);
--
-- return -1;
-- }
-- }
--
-- /* check which chunks have been written */
-- cq->bytes_out += r;
--
-- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
-- if (r >= (ssize_t)chunks[i].iov_len) {
-- /* written */
-- r -= chunks[i].iov_len;
-- tc->offset += chunks[i].iov_len;
-+ case MEM_CHUNK:
-+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
-
-+ /* check which chunks are finished now */
-+ for (tc = c; tc; tc = tc->next) {
-+ /* finished the chunk */
-+ if (tc->offset == tc->mem->used - 1) {
-+ /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
-- /* skip the chunks from further touches */
-- chunks_written++;
- c = c->next;
- } else {
-- /* chunks_written + c = c->next is done in the for()*/
-- chunk_finished++;
-+ chunk_finished = 1;
- }
- } else {
-- /* partially written */
--
-- tc->offset += r;
-- chunk_finished = 0;
--
- break;
- }
- }
-
-- break;
-+ if (ret != NETWORK_STATUS_SUCCESS) {
-+ return ret;
- }
+- /* build filename
++ /* build filename
+ *
+ * - decode url-encodings (e.g. %20 -> ' ')
+ * - remove path-modifiers (e.g. /../)
+ */
+-
+-
+-
+
-+ break;
- case FILE_CHUNK: {
- ssize_t r;
- off_t offset;
---- lighttpd-1.4.11/src/network_openssl.c 2005-11-17 14:53:29.000000000 +0200
-+++ lighttpd/src/network_openssl.c 2006-07-11 21:23:40.107856480 +0300
-@@ -26,7 +26,77 @@
- # include <openssl/ssl.h>
- # include <openssl/err.h>
++
++
+ if (con->request.http_method == HTTP_METHOD_OPTIONS &&
+ con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
+ /* OPTIONS * ... */
+@@ -253,15 +255,20 @@
+ }
--int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
-+NETWORK_BACKEND_READ_SSL(openssl) {
-+ buffer *b;
-+ off_t len;
+ /**
+- *
+- * call plugins
+- *
++ *
++ * call plugins
++ *
+ * - based on the clean URL
+- *
++ *
+ */
+-
+
-+ b = chunkqueue_get_append_buffer(cq);
-+ buffer_prepare_copy(b, 8192);
-+ len = SSL_read(ssl, b->ptr, b->size - 1);
+ config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
+-
+
-+ log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
++ /* do we have to downgrade to 1.0 ? */
++ if (!con->conf.allow_http11) {
++ con->request.http_version = HTTP_VERSION_1_0;
++ }
+
-+ if (len < 0) {
-+ int r, ssl_err;
+ switch(r = plugins_call_handle_uri_clean(srv, con)) {
+ case HANDLER_GO_ON:
+ break;
+@@ -274,11 +281,11 @@
+ log_error_write(srv, __FILE__, __LINE__, "");
+ break;
+ }
+-
+
-+ switch ((r = SSL_get_error(con->ssl, len))) {
-+ case SSL_ERROR_WANT_READ:
-+ return NETWORK_STATUS_WAIT_FOR_EVENT;
-+ case SSL_ERROR_SYSCALL:
-+ /**
-+ * man SSL_get_error()
-+ *
-+ * SSL_ERROR_SYSCALL
-+ * Some I/O error occurred. The OpenSSL error queue may contain more
-+ * information on the error. If the error queue is empty (i.e.
-+ * ERR_get_error() returns 0), ret can be used to find out more about
-+ * the error: If ret == 0, an EOF was observed that violates the
-+ * protocol. If ret == -1, the underlying BIO reported an I/O error
-+ * (for socket I/O on Unix systems, consult errno for details).
-+ *
-+ */
-+ while((ssl_err = ERR_get_error())) {
-+ /* get all errors from the error-queue */
-+ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
-+ r, ERR_error_string(ssl_err, NULL));
-+ }
+ if (con->request.http_method == HTTP_METHOD_OPTIONS &&
+ con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
+- /* option requests are handled directly without checking of the path */
+-
++ /* option requests are handled directly without checking the path */
++
+ response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
+
+ con->http_status = 200;
+@@ -288,46 +295,47 @@
+ }
+
+ /***
+- *
+- * border
+- *
++ *
++ * border
++ *
+ * logical filename (URI) becomes a physical filename here
+- *
+- *
+- *
++ *
++ *
++ *
+ */
+-
+-
+-
+-
+
-+ switch(errno) {
-+ default:
-+ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
-+ len, r, errno,
-+ strerror(errno));
-+ break;
-+ }
+
-+ break;
-+ case SSL_ERROR_ZERO_RETURN:
-+ /* clean shutdown on the remote side */
+
-+ if (r == 0) {
-+ /* FIXME: later */
-+ }
+
-+ /* fall thourgh */
-+ default:
-+ while((ssl_err = ERR_get_error())) {
-+ /* get all errors from the error-queue */
-+ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
-+ r, ERR_error_string(ssl_err, NULL));
-+ }
-+ break;
-+ }
-+ }
+ /* 1. stat()
+ * ... ISREG() -> ok, go on
+ * ... ISDIR() -> index-file -> redirect
+- *
+- * 2. pathinfo()
++ *
++ * 2. pathinfo()
+ * ... ISREG()
+- *
++ *
+ * 3. -> 404
+- *
++ *
+ */
+-
+
-+ assert(len > 0);
-+ b->used += len;
-+ b->ptr[b->used - 1] = '\0';
+ /*
+ * SEARCH DOCUMENT ROOT
+ */
+-
+
-+ return NETWORK_STATUS_SUCCESS;
-+}
+ /* set a default */
+-
+
+ buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
+ buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
+-
+-#if defined(__WIN32) || defined(__CYGWIN__)
+- /* strip dots from the end and spaces
+
-+NETWORK_BACKEND_WRITE_SSL(openssl) {
- int ssl_r;
- chunk *c;
- size_t chunks_written = 0;
-@@ -65,7 +135,7 @@
- case MEM_CHUNK: {
- char * offset;
- size_t toSend;
-- ssize_t r;
-+ ssize_t r = 0;
-
- if (c->mem->used == 0) {
- chunk_finished = 1;
-@@ -83,9 +153,11 @@
- * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
- * repeated with the same arguments.
- *
-+ * SSL_write(..., 0) return 0 which is handle as an error (Success)
-+ * checking toSend and not calling SSL_write() is simpler
- */
-
-- if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
-+ if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
- unsigned long err;
-
- switch ((ssl_r = SSL_get_error(ssl, r))) {
---- lighttpd-1.4.11/src/network_solaris_sendfilev.c 2005-10-22 12:28:27.000000000 +0300
-+++ lighttpd/src/network_solaris_sendfilev.c 2006-07-11 21:23:40.211862994 +0300
-@@ -38,105 +38,25 @@
- */
-
-
--int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
-+NETWORK_BACKEND_WRITE(solarissendfilev) {
- chunk *c;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- int chunk_finished = 0;
-+ network_status_t ret;
-
- switch(c->type) {
-- case MEM_CHUNK: {
-- char * offset;
-- size_t toSend;
-- ssize_t r;
--
-- size_t num_chunks, i;
-- struct iovec chunks[UIO_MAXIOV];
-- chunk *tc;
--
-- size_t num_bytes = 0;
--
-- /* we can't send more then SSIZE_MAX bytes in one chunk */
--
-- /* build writev list
-- *
-- * 1. limit: num_chunks < UIO_MAXIOV
-- * 2. limit: num_bytes < SSIZE_MAX
-- */
-- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
--
-- for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
-- if (tc->mem->used == 0) {
-- chunks[i].iov_base = tc->mem->ptr;
-- chunks[i].iov_len = 0;
-- } else {
-- offset = tc->mem->ptr + tc->offset;
-- toSend = tc->mem->used - 1 - tc->offset;
--
-- chunks[i].iov_base = offset;
--
-- /* protect the return value of writev() */
-- if (toSend > SSIZE_MAX ||
-- num_bytes + toSend > SSIZE_MAX) {
-- chunks[i].iov_len = SSIZE_MAX - num_bytes;
--
-- num_chunks = i + 1;
-- break;
-- } else {
-- chunks[i].iov_len = toSend;
-- }
--
-- num_bytes += toSend;
-- }
-- }
--
-- if ((r = writev(fd, chunks, num_chunks)) < 0) {
-- switch (errno) {
-- case EAGAIN:
-- case EINTR:
-- r = 0;
-- break;
-- case EPIPE:
-- case ECONNRESET:
-- return -2;
-- default:
-- log_error_write(srv, __FILE__, __LINE__, "ssd",
-- "writev failed:", strerror(errno), fd);
--
-- return -1;
-- }
-- }
-+ case MEM_CHUNK:
-+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
-
-- /* check which chunks have been written */
-- cq->bytes_out += r;
--
-- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
-- if (r >= (ssize_t)chunks[i].iov_len) {
-- /* written */
-- r -= chunks[i].iov_len;
-- tc->offset += chunks[i].iov_len;
--
-- if (chunk_finished) {
-- /* skip the chunks from further touches */
-- chunks_written++;
-- c = c->next;
-- } else {
-- /* chunks_written + c = c->next is done in the for()*/
-- chunk_finished++;
-+ if (ret != NETWORK_STATUS_SUCCESS) {
-+ return ret;
- }
-- } else {
-- /* partially written */
--
-- tc->offset += r;
-- chunk_finished = 0;
-
-- break;
-- }
-- }
-+ chunk_finished = 1;
-
- break;
-- }
- case FILE_CHUNK: {
- ssize_t r;
- off_t offset;
-@@ -177,7 +97,7 @@
- log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
-
- close(ifd);
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
-
- r = 0;
-@@ -194,10 +114,9 @@
++ filename_unix2local(con->physical.rel_path);
++#if defined(_WIN32) || defined(__CYGWIN__)
++ /* strip dots and spaces from the end
+ *
+ * windows/dos handle those filenames as the same file
+ *
+ * foo == foo. == foo..... == "foo... " == "foo.. ./"
+ *
+- * This will affect in some cases PATHINFO
++ * This will affect PATHINFO in some cases
+ *
+ * on native windows we could prepend the filename with \\?\ to circumvent
+ * this behaviour. I have no idea how to push this through cygwin
+@@ -377,36 +385,41 @@
+ log_error_write(srv, __FILE__, __LINE__, "");
break;
}
- default:
--
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
+-
+- /* MacOS X and Windows can't distiguish between upper and lower-case
+- *
+- * convert to lower-case
++
++ /* The default Mac OS X and Windows filesystems can't distiguish between
++ * upper- and lowercase, so convert to lowercase
+ */
+ if (con->conf.force_lowercase_filenames) {
+ buffer_to_lower(con->physical.rel_path);
+ }
+
+- /* the docroot plugins might set the servername, if they don't we take http-host */
++ /* the docroot plugins might set the servername; if they don't we take http-host */
+ if (buffer_is_empty(con->server_name)) {
+ buffer_copy_string_buffer(con->server_name, con->uri.authority);
+ }
+-
+- /**
+- * create physical filename
++
++ /**
++ * create physical filename
+ * -> physical.path = docroot + rel_path
+- *
++ *
+ */
+-
++
+ buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
+- BUFFER_APPEND_SLASH(con->physical.path);
++ PATHNAME_APPEND_SLASH(con->physical.path);
+ buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
+ if (con->physical.rel_path->used &&
+- con->physical.rel_path->ptr[0] == '/') {
++ con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
+ buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
+ } else {
+ buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
+ }
+
++ /* win32: directories can't have a trailing slash */
++ if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
++ con->physical.path->ptr[con->physical.path->used - 2] = '\0';
++ con->physical.path->used--;
++ }
++
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
+@@ -426,7 +439,7 @@
+ log_error_write(srv, __FILE__, __LINE__, "");
+ break;
}
-
- if (!chunk_finished) {
-@@ -207,7 +126,7 @@
+-
++
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- logical -> physical");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
+@@ -434,38 +447,38 @@
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
}
}
-
-- return chunks_written;
-+ return NETWORK_STATUS_SUCCESS;
- }
-
- #endif
---- lighttpd-1.4.11/src/network_write.c 2005-10-22 12:27:56.000000000 +0300
-+++ lighttpd/src/network_write.c 2006-07-11 21:23:39.887842700 +0300
-@@ -1,11 +1,11 @@
- #include <sys/types.h>
- #include <sys/stat.h>
--#include <sys/time.h>
+-
+- /*
+- * Noone catched away the file from normal path of execution yet (like mod_access)
+- *
+
- #include <errno.h>
- #include <fcntl.h>
--#include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
-+#include <assert.h>
-
- #include "network.h"
- #include "fdevent.h"
-@@ -13,9 +13,12 @@
- #include "stat_cache.h"
-
- #include "sys-socket.h"
-+#include "sys-files.h"
-
- #include "network_backends.h"
-
-+#ifdef USE_WRITE
++ /*
++ * No one took the file away from the normal path of execution yet (like mod_access)
++ *
+ * Go on and check of the file exists at all
+ */
+-
+
- #ifdef HAVE_SYS_FILIO_H
- # include <sys/filio.h>
- #endif
-@@ -24,7 +27,53 @@
- #include <sys/resource.h>
- #endif
-
--int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
-+/**
-+* fill the chunkqueue will all the data that we can get
-+*
-+* this might be optimized into a readv() which uses the chunks
-+* as vectors
-+*/
-+NETWORK_BACKEND_READ(read) {
-+ int toread;
-+ buffer *b;
-+ off_t r;
+ if (con->mode == DIRECT) {
+ char *slash = NULL;
+ char *pathinfo = NULL;
+ int found = 0;
+ stat_cache_entry *sce = NULL;
+-
+
-+ /* check how much we have to read */
-+ if (ioctl(fd, FIONREAD, &toread)) {
-+ log_error_write(srv, __FILE__, __LINE__, "sd",
-+ "ioctl failed: ",
-+ fd);
-+ return NETWORK_STATUS_FATAL_ERROR;
-+ }
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
+ }
+-
+
-+ if (toread == 0) return NETWORK_STATUS_WAIT_FOR_EVENT;
+ if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+ /* file exists */
+-
+
-+ /*
-+ * our chunk queue is quiet large already
-+ *
-+ * let's buffer it to disk
-+ */
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- file found");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
+ }
+-
+
-+ b = chunkqueue_get_append_buffer(cq);
+ if (S_ISDIR(sce->st.st_mode)) {
+- if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
++ if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
+ /* redirect to .../ */
+-
+
-+ buffer_prepare_copy(b, toread);
+ http_response_redirect_to_directory(srv, con);
+-
+
-+ if (-1 == (r = read(fd, b->ptr, toread))) {
-+ log_error_write(srv, __FILE__, __LINE__, "sds",
-+ "unexpected end-of-file (perhaps the proxy process died):",
-+ fd, strerror(errno));
-+ return NETWORK_STATUS_FATAL_ERROR;
-+ }
+ return HANDLER_FINISHED;
+ }
+ } else if (!S_ISREG(sce->st.st_mode)) {
+@@ -477,12 +490,12 @@
+ switch (errno) {
+ case EACCES:
+ con->http_status = 403;
+-
+
-+ /* this should be catched by the b > 0 above */
-+ assert(r);
-+ b->used += r + 1;
-+ b->ptr[b->used - 1] = '\0';
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
+ }
+-
+
-+ return NETWORK_STATUS_SUCCESS;
-+}
+ buffer_reset(con->physical.path);
+ return HANDLER_FINISHED;
+ case ENOENT:
+@@ -499,77 +512,77 @@
+ /* PATH_INFO ! :) */
+ break;
+ default:
+- /* we have no idea what happend. let's tell the user so. */
++ /* we have no idea what happened, so tell the user. */
+ con->http_status = 500;
+ buffer_reset(con->physical.path);
+-
+
-+NETWORK_BACKEND_WRITE(write) {
- chunk *c;
- size_t chunks_written = 0;
-
-@@ -44,19 +93,12 @@
-
- offset = c->mem->ptr + c->offset;
- toSend = c->mem->used - 1 - c->offset;
--#ifdef __WIN32
-- if ((r = send(fd, offset, toSend, 0)) < 0) {
-- log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
-
-- return -1;
-- }
--#else
- if ((r = write(fd, offset, toSend)) < 0) {
- log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
+ log_error_write(srv, __FILE__, __LINE__, "ssbsb",
+ "file not found ... or so: ", strerror(errno),
+ con->uri.path,
+ "->", con->physical.path);
+-
++
+ return HANDLER_FINISHED;
}
--#endif
-
- c->offset += r;
- cq->bytes_out += r;
-@@ -80,7 +122,7 @@
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- strerror(errno), c->file.name);
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
+-
++
+ /* not found, perhaps PATHINFO */
+-
++
+ buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
+-
++
+ do {
+ struct stat st;
+-
++
+ if (slash) {
+ buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
+ } else {
+ buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
+ }
+-
++
+ if (0 == stat(con->physical.path->ptr, &(st)) &&
+ S_ISREG(st.st_mode)) {
+ found = 1;
+ break;
+ }
+-
++
+ if (pathinfo != NULL) {
+ *pathinfo = '\0';
+ }
+ slash = strrchr(srv->tmp_buf->ptr, '/');
+-
++
+ if (pathinfo != NULL) {
+ /* restore '/' */
+ *pathinfo = '/';
+ }
+-
++
+ if (slash) pathinfo = slash;
+ } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
+-
++
+ if (found == 0) {
+- /* no it really doesn't exists */
++ /* no, it really doesn't exists */
+ con->http_status = 404;
+-
++
+ if (con->conf.log_file_not_found) {
+ log_error_write(srv, __FILE__, __LINE__, "sbsb",
+ "file not found:", con->uri.path,
+ "->", con->physical.path);
+ }
+-
++
+ buffer_reset(con->physical.path);
+-
++
+ return HANDLER_FINISHED;
}
-
- offset = c->file.start + c->offset;
-@@ -89,13 +131,13 @@
- if (offset > sce->st.st_size) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
+-
++
+ /* we have a PATHINFO */
+ if (pathinfo) {
+ buffer_copy_string(con->request.pathinfo, pathinfo);
+-
++
+ /*
+ * shorten uri.path
+ */
+-
++
+ con->uri.path->used -= strlen(pathinfo);
+ con->uri.path->ptr[con->uri.path->used - 1] = '\0';
}
-
- if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
+-
++
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- after pathinfo check");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
+@@ -577,12 +590,12 @@
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Pathinfo :", con->request.pathinfo);
}
-
- #if defined USE_MMAP
-@@ -104,14 +146,14 @@
-
- close(ifd);
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
+ }
+-
++
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- handling subrequest");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
+ }
+-
++
+ /* call the handlers */
+ switch(r = plugins_call_handle_subrequest_start(srv, con)) {
+ case HANDLER_GO_ON:
+@@ -593,32 +606,32 @@
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished");
}
- close(ifd);
+-
+- /* something strange happend */
++
++ /* something strange happened */
+ return r;
+ }
+-
+- /* if we are still here, no one wanted the file, status 403 is ok I think */
+-
++
++ /* if we are still here, no one wanted the file; status 403 is ok I think */
++
+ if (con->mode == DIRECT) {
+ con->http_status = 403;
+-
++
+ return HANDLER_FINISHED;
+ }
+-
++
+ }
+-
++
+ switch(r = plugins_call_handle_subrequest(srv, con)) {
+ case HANDLER_GO_ON:
+- /* request was not handled, looks like we are done */
++ /* request was not handled; looks like we are done */
+ return HANDLER_FINISHED;
+ case HANDLER_FINISHED:
+ /* request is finished */
+ default:
+- /* something strange happend */
++ /* something strange happened */
+ return r;
+ }
+-
++
+ /* can't happen */
+ return HANDLER_COMEBACK;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/server.c lighttpd-1.4.12/src/server.c
+--- lighttpd-1.4.11/src/server.c 2006-03-04 19:12:17.000000000 +0200
++++ lighttpd-1.4.12/src/server.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,11 +1,9 @@
+ #include <sys/types.h>
+-#include <sys/time.h>
+ #include <sys/stat.h>
- if ((r = write(fd, p + offset, toSend)) <= 0) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
- munmap(p, sce->st.st_size);
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
-
- munmap(p, sce->st.st_size);
-@@ -123,14 +165,14 @@
- log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
- close(ifd);
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
- close(ifd);
+ #include <string.h>
+ #include <errno.h>
+ #include <fcntl.h>
+-#include <unistd.h>
+ #include <stdlib.h>
+ #include <time.h>
+ #include <signal.h>
+@@ -29,9 +27,14 @@
+ #include "plugin.h"
+ #include "joblist.h"
+ #include "network_backends.h"
+-
++#ifdef _WIN32
++/* use local getopt implementation */
++# undef HAVE_GETOPT_H
++#endif
+ #ifdef HAVE_GETOPT_H
+ #include <getopt.h>
++#else
++#include "getopt.h"
+ #endif
- if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
+ #ifdef HAVE_VALGRIND_VALGRIND_H
+@@ -60,8 +63,16 @@
+ /* #define USE_ALARM */
#endif
- c->offset += r;
-@@ -146,7 +188,7 @@
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
-@@ -158,11 +200,7 @@
- chunks_written++;
- }
-- return chunks_written;
-+ return NETWORK_STATUS_SUCCESS;
- }
++#ifdef _WIN32
++#undef HAVE_SIGNAL
++#endif
++
++#include "sys-files.h"
++#include "sys-process.h"
++
+ static volatile sig_atomic_t srv_shutdown = 0;
+ static volatile sig_atomic_t graceful_shutdown = 0;
++static volatile sig_atomic_t graceful_restart = 0;
+ static volatile sig_atomic_t handle_sig_alarm = 1;
+ static volatile sig_atomic_t handle_sig_hup = 0;
--#if 0
--network_write_init(void) {
-- p->write = network_write_write_chunkset;
--}
+@@ -72,9 +83,9 @@
+
+ switch (sig) {
+ case SIGTERM: srv_shutdown = 1; break;
+- case SIGINT:
++ case SIGINT:
+ if (graceful_shutdown) srv_shutdown = 1;
+- else graceful_shutdown = 1;
++ else graceful_shutdown = 1;
+
+ break;
+ case SIGALRM: handle_sig_alarm = 1; break;
+@@ -86,9 +97,9 @@
+ static void signal_handler(int sig) {
+ switch (sig) {
+ case SIGTERM: srv_shutdown = 1; break;
+- case SIGINT:
++ case SIGINT:
+ if (graceful_shutdown) srv_shutdown = 1;
+- else graceful_shutdown = 1;
++ else graceful_shutdown = 1;
+
+ break;
+ case SIGALRM: handle_sig_alarm = 1; break;
+@@ -110,25 +121,26 @@
+ signal(SIGTSTP, SIG_IGN);
#endif
---- lighttpd-1.4.11/src/network_writev.c 2006-02-15 01:02:36.000000000 +0200
-+++ lighttpd/src/network_writev.c 2006-07-11 21:23:40.103856229 +0300
-@@ -51,22 +51,14 @@
- #define LOCAL_BUFFERING 1
+ if (0 != fork()) exit(0);
+-
++
+ if (-1 == setsid()) exit(0);
+
+ signal(SIGHUP, SIG_IGN);
+
+ if (0 != fork()) exit(0);
+-
++
+ if (0 != chdir("/")) exit(0);
+ }
#endif
--int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
-- chunk *c;
-- size_t chunks_written = 0;
+ static server *server_init(void) {
+ int i;
-
-- for(c = cq->first; c; c = c->next) {
-- int chunk_finished = 0;
--
-- switch(c->type) {
-- case MEM_CHUNK: {
-+NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
- char * offset;
- size_t toSend;
- ssize_t r;
-
- size_t num_chunks, i;
- struct iovec chunks[UIO_MAXIOV];
-- chunk *tc;
-+ chunk *tc; /* transfer chunks */
- size_t num_bytes = 0;
-
- /* we can't send more then SSIZE_MAX bytes in one chunk */
-@@ -111,12 +103,12 @@
- break;
- case EPIPE:
- case ECONNRESET:
-- return -2;
-+ return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "writev failed:", strerror(errno), fd);
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
-@@ -129,27 +121,49 @@
- /* written */
- r -= chunks[i].iov_len;
- tc->offset += chunks[i].iov_len;
-+ } else {
-+ /* partially written */
-
-+ tc->offset += r;
-+ break;
-+ }
-+ }
+
-+ return NETWORK_STATUS_SUCCESS;
-+}
+ server *srv = calloc(1, sizeof(*srv));
+ assert(srv);
++ srv->max_fds = 1024;
+ #define CLEAN(x) \
+ srv->x = buffer_init();
+-
+
-+NETWORK_BACKEND_WRITE(writev) {
-+ chunk *c, *tc;
-+ size_t chunks_written = 0;
+ CLEAN(response_header);
+ CLEAN(parse_full_path);
+ CLEAN(ts_debug_str);
+@@ -138,7 +150,7 @@
+ CLEAN(tmp_buf);
+ srv->empty_string = buffer_init_string("");
+ CLEAN(cond_check_buf);
+-
+
-+ for(c = cq->first; c; c = c->next) {
-+ int chunk_finished = 0;
-+ network_status_t ret;
+ CLEAN(srvconf.errorlog_file);
+ CLEAN(srvconf.groupname);
+ CLEAN(srvconf.username);
+@@ -146,58 +158,58 @@
+ CLEAN(srvconf.bindhost);
+ CLEAN(srvconf.event_handler);
+ CLEAN(srvconf.pid_file);
+-
+
-+ switch(c->type) {
-+ case MEM_CHUNK:
-+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
+ CLEAN(tmp_chunk_len);
+ #undef CLEAN
+-
+
-+ /* check which chunks are finished now */
-+ for (tc = c; tc; tc = tc->next) {
-+ /* finished the chunk */
-+ if (tc->offset == tc->mem->used - 1) {
-+ /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
-- /* skip the chunks from further touches */
-- chunks_written++;
- c = c->next;
- } else {
-- /* chunks_written + c = c->next is done in the for()*/
-- chunk_finished++;
-+ chunk_finished = 1;
- }
- } else {
-- /* partially written */
--
-- tc->offset += r;
-- chunk_finished = 0;
--
- break;
- }
- }
-
-- break;
-+ if (ret != NETWORK_STATUS_SUCCESS) {
-+ return ret;
- }
+ #define CLEAN(x) \
+ srv->x = array_init();
+-
+
-+ break;
- case FILE_CHUNK: {
- ssize_t r;
- off_t abs_offset;
-@@ -165,7 +179,7 @@
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- strerror(errno), c->file.name);
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
+ CLEAN(config_context);
+ CLEAN(config_touched);
+ CLEAN(status);
+ #undef CLEAN
+-
++
+ for (i = 0; i < FILE_CACHE_MAX; i++) {
+ srv->mtime_cache[i].str = buffer_init();
+ }
+-
++
+ srv->cur_ts = time(NULL);
+ srv->startup_ts = srv->cur_ts;
+-
++
+ srv->conns = calloc(1, sizeof(*srv->conns));
+ assert(srv->conns);
+-
++
+ srv->joblist = calloc(1, sizeof(*srv->joblist));
+ assert(srv->joblist);
+-
++
+ srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
+ assert(srv->fdwaitqueue);
+-
++
+ srv->srvconf.modules = array_init();
+ srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
+ srv->srvconf.network_backend = buffer_init();
+ srv->srvconf.upload_tempdirs = array_init();
+-
++
+ /* use syslog */
+ srv->errorlog_fd = -1;
+ srv->errorlog_mode = ERRORLOG_STDERR;
- abs_offset = c->file.start + c->offset;
-@@ -174,7 +188,7 @@
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "file was shrinked:", c->file.name);
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
+ srv->split_vals = array_init();
+-
++
+ return srv;
+ }
- /* mmap the buffer
-@@ -235,7 +249,7 @@
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
- #ifdef FD_CLOEXEC
- fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
-@@ -248,7 +262,7 @@
- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
- strerror(errno), c->file.name, c->file.fd);
+ static void server_free(server *srv) {
+ size_t i;
+-
++
+ for (i = 0; i < FILE_CACHE_MAX; i++) {
+ buffer_free(srv->mtime_cache[i].str);
+ }
+-
++
+ #define CLEAN(x) \
+ buffer_free(srv->x);
+-
++
+ CLEAN(response_header);
+ CLEAN(parse_full_path);
+ CLEAN(ts_debug_str);
+@@ -207,7 +219,7 @@
+ CLEAN(tmp_buf);
+ CLEAN(empty_string);
+ CLEAN(cond_check_buf);
+-
++
+ CLEAN(srvconf.errorlog_file);
+ CLEAN(srvconf.groupname);
+ CLEAN(srvconf.username);
+@@ -217,7 +229,7 @@
+ CLEAN(srvconf.pid_file);
+ CLEAN(srvconf.modules_dir);
+ CLEAN(srvconf.network_backend);
+-
++
+ CLEAN(tmp_chunk_len);
+ #undef CLEAN
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
+@@ -225,15 +237,15 @@
+ fdevent_unregister(srv->ev, srv->fd);
+ #endif
+ fdevent_free(srv->ev);
+-
++
+ free(srv->conns);
+-
++
+ if (srv->config_storage) {
+ for (i = 0; i < srv->config_context->used; i++) {
+ specific_config *s = srv->config_storage[i];
- c->file.mmap.length = to_mmap;
-@@ -297,12 +311,12 @@
- break;
- case EPIPE:
- case ECONNRESET:
-- return -2;
-+ return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "write failed:", strerror(errno), fd);
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
-@@ -325,7 +339,7 @@
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
-- return -1;
-+ return NETWORK_STATUS_FATAL_ERROR;
+ if (!s) continue;
+-
++
+ buffer_free(s->document_root);
+ buffer_free(s->server_name);
+ buffer_free(s->server_tag);
+@@ -242,32 +254,32 @@
+ buffer_free(s->error_handler);
+ buffer_free(s->errorfile_prefix);
+ array_free(s->mimetypes);
+-
++
+ free(s);
}
-
- if (!chunk_finished) {
-@@ -337,7 +351,7 @@
- chunks_written++;
+ free(srv->config_storage);
+ srv->config_storage = NULL;
+ }
+-
++
+ #define CLEAN(x) \
+ array_free(srv->x);
+-
++
+ CLEAN(config_context);
+ CLEAN(config_touched);
+ CLEAN(status);
+ CLEAN(srvconf.upload_tempdirs);
+ #undef CLEAN
+-
++
+ joblist_free(srv, srv->joblist);
+ fdwaitqueue_free(srv, srv->fdwaitqueue);
+-
++
+ if (srv->stat_cache) {
+ stat_cache_free(srv->stat_cache);
}
-- return chunks_written;
-+ return NETWORK_STATUS_SUCCESS;
+ array_free(srv->srvconf.modules);
+ array_free(srv->split_vals);
+-
++
+ free(srv);
+ }
+
+@@ -281,14 +293,12 @@
+ " - a light and fast webserver\n" \
+ "Build-Date: " __DATE__ " " __TIME__ "\n";
+ ;
+-#undef TEXT_SSL
++#undef TEXT_SSL
+ write(STDOUT_FILENO, b, strlen(b));
}
+ static void show_features (void) {
+- show_version();
+- printf("\nEvent Handlers:\n\n%s",
+-
++ const char *s = ""
+ #ifdef USE_SELECT
+ "\t+ select (generic)\n"
+ #else
+@@ -355,11 +365,6 @@
+ #else
+ "\t- crypt support\n"
#endif
---- lighttpd-1.4.11/src/plugin.c 2006-02-08 14:00:54.000000000 +0200
-+++ lighttpd/src/plugin.c 2006-07-11 21:23:40.067853974 +0300
-@@ -13,7 +13,7 @@
- #include <valgrind/valgrind.h>
+-#ifdef USE_PAM
+- "\t+ PAM support\n"
+-#else
+- "\t- PAM support\n"
+-#endif
+ #ifdef USE_OPENSSL
+ "\t+ SSL Support\n"
+ #else
+@@ -371,9 +376,9 @@
+ "\t- PCRE support\n"
#endif
-
--#ifndef __WIN32
-+#ifndef _WIN32
- #include <dlfcn.h>
+ #ifdef HAVE_MYSQL
+- "\t+ mySQL support\n"
++ "\t+ MySQL support\n"
+ #else
+- "\t- mySQL support\n"
++ "\t- MySQL support\n"
#endif
- /*
-@@ -56,19 +56,23 @@
-
- p = calloc(1, sizeof(*p));
-
-+ p->required_plugins = array_init();
+ #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
+ "\t+ LDAP support\n"
+@@ -410,8 +415,11 @@
+ #else
+ "\t- GDBM support\n"
+ #endif
+- "\n"
+- );
++ "\n";
+
- return p;
++ show_version();
++
++ printf("\nEvent Handlers:\n\n%s", s);
}
- static void plugin_free(plugin *p) {
- int use_dlclose = 1;
- if (p->name) buffer_free(p->name);
-+
-+ array_free(p->required_plugins);
- #ifdef HAVE_VALGRIND_VALGRIND_H
- /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
- #endif
+ static void show_help (void) {
+@@ -433,12 +441,12 @@
+ " -h show this help\n" \
+ "\n"
+ ;
+-#undef TEXT_SSL
++#undef TEXT_SSL
+ #undef TEXT_IPV6
+ write(STDOUT_FILENO, b, strlen(b));
+ }
- #ifndef LIGHTTPD_STATIC
- if (use_dlclose && p->lib) {
--#ifdef __WIN32
-+#ifdef _WIN32
- FreeLibrary(p->lib);
- #else
- dlclose(p->lib);
-@@ -121,9 +125,14 @@
- #else
- int plugins_load(server *srv) {
- plugin *p;
+-int main (int argc, char **argv) {
++int main (int argc, char **argv, char **envp) {
+ server *srv = NULL;
+ int print_config = 0;
+ int test_config = 0;
+@@ -447,33 +455,37 @@
+ int num_childs = 0;
+ int pid_fd = -1, fd;
+ size_t i;
+#ifdef _WIN32
-+ FARPROC init;
-+#else
- int (*init)(plugin *pl);
++ char *optarg = NULL;
+#endif
+
- const char *error;
-- size_t i;
-+ size_t i, j, k;
-
- for (i = 0; i < srv->srvconf.modules->used; i++) {
- data_string *d = (data_string *)srv->srvconf.modules->data[i];
-@@ -133,14 +142,14 @@
-
- buffer_append_string(srv->tmp_buf, "/");
- buffer_append_string(srv->tmp_buf, modules);
--#if defined(__WIN32) || defined(__CYGWIN__)
-+#if defined(_WIN32) || defined(__CYGWIN__)
- buffer_append_string(srv->tmp_buf, ".dll");
- #else
- buffer_append_string(srv->tmp_buf, ".so");
+ #ifdef HAVE_SIGACTION
+ struct sigaction act;
#endif
-
- p = plugin_init();
--#ifdef __WIN32
-+#ifdef _WIN32
- if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
- LPVOID lpMsgBuf;
- FormatMessage(
-@@ -175,7 +184,7 @@
- buffer_copy_string(srv->tmp_buf, modules);
- buffer_append_string(srv->tmp_buf, "_plugin_init");
-
--#ifdef __WIN32
-+#ifdef _WIN32
- init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
-
- if (init == NULL) {
-@@ -218,6 +227,25 @@
- #if 0
- log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
+ #ifdef HAVE_GETRLIMIT
+ struct rlimit rlim;
#endif
-+ /* check if the required plugin is loaded */
-+ for (k = 0; k < p->required_plugins->used; k++) {
-+ data_string *req = (data_string *)p->required_plugins->data[k];
+-
+
-+ for (j = 0; j < i; j++) {
-+ data_string *mod = (data_string *)srv->srvconf.modules->data[j];
+ #ifdef USE_ALARM
+ struct itimerval interval;
+-
+
-+ if (buffer_is_equal(req->value, mod->value)) break;
-+ }
+ interval.it_interval.tv_sec = 1;
+ interval.it_interval.tv_usec = 0;
+ interval.it_value.tv_sec = 1;
+ interval.it_value.tv_usec = 0;
+ #endif
+-
+-
+
-+ if (j == i) {
-+ /* not found */
-+ log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
+
-+ plugin_free(p);
-+
-+ return -1;
-+ }
-+ }
- plugins_register(srv, p);
+ /* for nice %b handling in strfime() */
+ setlocale(LC_TIME, "C");
+-
++
+ if (NULL == (srv = server_init())) {
+ fprintf(stderr, "did this really happen?\n");
+ return -1;
}
-
-@@ -426,6 +454,23 @@
- return HANDLER_GO_ON;
- }
-
-+/**
-+ * get the config-storage of the named plugin
-+ */
-+void *plugin_get_config(server *srv, const char *name) {
-+ size_t i;
+-
+
-+ for (i = 0; i < srv->plugins.used; i++) {
-+ plugin *p = ((plugin **)srv->plugins.ptr)[i];
+ /* init structs done */
+-
+
-+ if (buffer_is_equal_string(p->name, name, strlen(name))) {
-+ return p->data;
-+ }
-+ }
+ srv->srvconf.port = 0;
+ #ifdef HAVE_GETUID
+ i_am_root = (getuid() == 0);
+@@ -481,14 +493,19 @@
+ i_am_root = 0;
+ #endif
+ srv->srvconf.dont_daemonize = 0;
+-
+
-+ return NULL;
-+}
+ while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
+ switch(o) {
+- case 'f':
+- if (config_read(srv, optarg)) {
++ case 'f':
++#ifdef _WIN32
++ /* evil HACK for windows, optarg is not set */
++ optarg = argv[optind-1];
++#endif
++ if (config_read(srv, optarg)) {
+ server_free(srv);
+ return -1;
+ }
+
- void plugins_free(server *srv) {
- size_t i;
- plugins_call_cleanup(srv);
---- lighttpd-1.4.11/src/plugin.h 2005-08-15 12:28:56.000000000 +0300
-+++ lighttpd/src/plugin.h 2006-07-11 21:23:40.075854475 +0300
-@@ -12,6 +12,12 @@
-
- #define INIT_FUNC(x) \
- static void *x()
-+/*
-+ * The PATCH_OPTION() macro is used in the patch_connection() functions
-+ * of the modules to update the config object for the current request.
-+ */
-+#define PATCH_OPTION(x) \
-+ p->conf.x = s->x
-
- #define FREE_FUNC SERVER_FUNC
- #define TRIGGER_FUNC SERVER_FUNC
-@@ -59,6 +65,8 @@
-
- /* dlopen handle */
- void *lib;
+ break;
+ case 'm':
+ buffer_copy_string(srv->srvconf.modules_dir, optarg);
+@@ -497,23 +514,23 @@
+ case 't': test_config = 1; break;
+ case 'D': srv->srvconf.dont_daemonize = 1; break;
+ case 'v': show_version(); return 0;
+- case 'V': show_features(); return 0;
++ case 'V': show_features(); return 0;
+ case 'h': show_help(); return 0;
+- default:
++ default:
+ show_help();
+ server_free(srv);
+ return -1;
+ }
+ }
+-
+
-+ array *required_plugins;
- } plugin;
-
- int plugins_load(server *srv);
-@@ -88,5 +96,8 @@
- int config_patch_connection(server *srv, connection *con, comp_key_t comp);
- int config_check_cond(server *srv, connection *con, data_config *dc);
- int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
-+int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
+ if (!srv->config_storage) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "No configuration available. Try using -f option.");
+-
+
-+void *plugin_get_config(server *srv, const char *name);
-
- #endif
---- lighttpd-1.4.11/src/proc_open.c 2005-08-11 01:26:39.000000000 +0300
-+++ lighttpd/src/proc_open.c 2006-07-11 21:23:40.283867504 +0300
-@@ -13,13 +13,13 @@
- #endif
-
-
--#ifdef WIN32
-+#ifdef _WIN32
- /* {{{ win32 stuff */
- # define SHELLENV "ComSpec"
- # define SECURITY_DC , SECURITY_ATTRIBUTES *security
- # define SECURITY_CC , security
- # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
--static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
-+static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
- {
- HANDLE copy, self = GetCurrentProcess();
-
-@@ -148,11 +148,14 @@
- STARTUPINFO si;
- BOOL procok;
- SECURITY_ATTRIBUTES security;
-- const char *shell;
-+ const char *shell = NULL;
-+ const char *windir = NULL;
- buffer *cmdline;
-
-- if (NULL == (shell = getenv(SHELLENV))) {
-- fprintf(stderr, "env %s is required", SHELLENV);
-+ if (NULL == (shell = getenv(SHELLENV)) &&
-+ NULL == (windir = getenv("SystemRoot")) &&
-+ NULL == (windir = getenv("windir"))) {
-+ fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
+ server_free(srv);
+ return -1;
+ }
+-
++
+ if (print_config) {
+ data_unset *dc = srv->config_context->data[0];
+ if (dc) {
+@@ -533,7 +550,7 @@
+ server_free(srv);
+ return 0;
+ }
+-
++
+ /* close stdin and stdout, as they are not needed */
+ /* move stdin to /dev/null */
+ if (-1 != (fd = open("/dev/null", O_RDONLY))) {
+@@ -541,54 +558,55 @@
+ dup2(fd, STDIN_FILENO);
+ close(fd);
+ }
+-
++
+ /* move stdout to /dev/null */
+ if (-1 != (fd = open("/dev/null", O_WRONLY))) {
+ close(STDOUT_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+ }
+-
++
+ if (0 != config_set_defaults(srv)) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "setting default values failed");
+ server_free(srv);
return -1;
}
-
-@@ -177,17 +180,23 @@
- memset(&pi, 0, sizeof(pi));
-
- cmdline = buffer_init();
-+ if (shell) {
- buffer_append_string(cmdline, shell);
-+ } else {
-+ buffer_append_string(cmdline, windir);
-+ buffer_append_string(cmdline, "\\system32\\cmd.exe");
-+ }
- buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
- buffer_append_string(cmdline, command);
- procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
- NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
-- buffer_free(cmdline);
-
- if (FALSE == procok) {
-- fprintf(stderr, "failed to CreateProcess");
-+ fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
-+ buffer_free(cmdline);
+-
++
+ /* UID handling */
+ #ifdef HAVE_GETUID
+ if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
+ /* we are setuid-root */
+-
+- log_error_write(srv, __FILE__, __LINE__, "s",
++
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "Are you nuts ? Don't apply a SUID bit to this binary");
+-
++
+ server_free(srv);
return -1;
}
-+ buffer_free(cmdline);
-
- proc->child = pi.hProcess;
- CloseHandle(pi.hThread);
-@@ -226,8 +235,7 @@
- const char *shell;
-
- if (NULL == (shell = getenv(SHELLENV))) {
-- fprintf(stderr, "env %s is required", SHELLENV);
-- return -1;
-+ shell = "/bin/sh";
+ #endif
+-
++
+ /* check document-root */
+ if (srv->config_storage[0]->document_root->used <= 1) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "document-root is not set\n");
+-
++
+ server_free(srv);
+-
++
+ return -1;
}
-
- if (proc_open_pipes(proc) != 0) {
-@@ -262,11 +270,11 @@
+-
++
+ if (plugins_load(srv)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "loading plugins finally failed");
+-
++
+ plugins_free(srv);
+ server_free(srv);
+-
++
+ return -1;
}
- }
- /* }}} */
--#endif /* WIN32 */
-+#endif /* _WIN32 */
+-
++
++#ifndef _WIN32
+ /* open pid file BEFORE chroot */
+ if (srv->srvconf.pid_file->used) {
+ 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))) {
+@@ -598,18 +616,18 @@
+ "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
+ return -1;
+ }
+-
++
+ if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
+ }
+-
++
+ if (!S_ISREG(st.st_mode)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
+ return -1;
+ }
+-
++
+ if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
+ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
+@@ -617,13 +635,14 @@
+ }
+ }
+ }
+-
++#endif
+ if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
+ /* select limits itself
+ *
+ * as it is a hard limit and will lead to a segfault we add some safety
+ * */
+- srv->max_fds = FD_SETSIZE - 200;
++ fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
++ srv->max_fds = FD_SETSIZE - 4;
+ } else {
+ srv->max_fds = 4096;
+ }
+@@ -636,7 +655,7 @@
+ #ifdef HAVE_VALGRIND_VALGRIND_H
+ if (RUNNING_ON_VALGRIND) use_rlimit = 0;
+ #endif
+-
++
+ #ifdef HAVE_GETRLIMIT
+ if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
+ log_error_write(srv, __FILE__, __LINE__,
+@@ -644,13 +663,13 @@
+ strerror(errno));
+ return -1;
+ }
+-
++
+ if (use_rlimit && srv->srvconf.max_fds) {
+ /* set rlimits */
+-
++
+ rlim.rlim_cur = srv->srvconf.max_fds;
+ rlim.rlim_max = srv->srvconf.max_fds;
+-
++
+ if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
+ log_error_write(srv, __FILE__, __LINE__,
+ "ss", "couldn't set 'max filedescriptors'",
+@@ -659,7 +678,7 @@
+ }
+ }
- /* {{{ proc_read_fd_to_buffer */
- static void proc_read_fd_to_buffer(int fd, buffer *b) {
-- ssize_t s;
-+ int s; /* win32 has not ssize_t */
+- /* #372: solaris need some fds extra for devpoll */
++ /* #372: solaris need some fds extra for devpoll */
+ if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
- for (;;) {
- buffer_prepare_append(b, 512);
---- lighttpd-1.4.11/src/proc_open.h 2005-08-11 01:26:39.000000000 +0300
-+++ lighttpd/src/proc_open.h 2006-07-11 21:23:40.287867754 +0300
-@@ -1,7 +1,7 @@
+ if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
+@@ -677,33 +696,33 @@
+ if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
+ /* don't raise the limit above FD_SET_SIZE */
+ if (srv->max_fds > FD_SETSIZE - 200) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "can't raise max filedescriptors above", FD_SETSIZE - 200,
+ "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
+ return -1;
+ }
+ }
- #include "buffer.h"
+-
++
+ #ifdef HAVE_PWD_H
+ /* set user and group */
+ if (srv->srvconf.username->used) {
+ if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "can't find username", srv->srvconf.username);
+ return -1;
+ }
+-
++
+ if (pwd->pw_uid == 0) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "I will not set uid to 0\n");
+ return -1;
+ }
+ }
+-
++
+ if (srv->srvconf.groupname->used) {
+ if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
+- log_error_write(srv, __FILE__, __LINE__, "sb",
++ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "can't find groupname", srv->srvconf.groupname);
+ return -1;
+ }
+@@ -713,15 +732,15 @@
+ return -1;
+ }
+ }
+-#endif
++#endif
+ /* we need root-perms for port < 1024 */
+ if (0 != network_init(srv)) {
+ plugins_free(srv);
+ server_free(srv);
+-
++
+ return -1;
+ }
+-#ifdef HAVE_CHROOT
++#ifdef HAVE_CHROOT
+ if (srv->srvconf.changeroot->used) {
+ tzset();
--#ifdef WIN32
-+#ifdef _WIN32
- #include <windows.h>
- typedef HANDLE descriptor_t;
- typedef HANDLE proc_pid_t;
---- lighttpd-1.4.11/src/request.c 2006-03-05 11:58:09.000000000 +0200
-+++ lighttpd/src/request.c 2006-07-11 21:23:40.035851970 +0300
-@@ -10,6 +10,8 @@
- #include "keyvalue.h"
- #include "log.h"
+@@ -761,7 +780,7 @@
+ }
-+#include "sys-strings.h"
+ if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
+- srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
++ srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
+ } else {
+ srv->max_fds = rlim.rlim_cur;
+ }
+@@ -775,18 +794,18 @@
+ #endif
+ if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
+ /* don't raise the limit above FD_SET_SIZE */
+- if (srv->max_fds > FD_SETSIZE - 200) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
+- "can't raise max filedescriptors above", FD_SETSIZE - 200,
++ if (srv->max_fds > FD_SETSIZE - 4) {
++ log_error_write(srv, __FILE__, __LINE__, "sd",
++ "can't raise max filedescriptors above", FD_SETSIZE - 4,
+ "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
+ return -1;
+ }
+ }
+-
+
- static int request_check_hostname(server *srv, connection *con, buffer *host) {
- enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
- size_t i;
-@@ -413,7 +415,7 @@
- }
+ if (0 != network_init(srv)) {
+ plugins_free(srv);
+ server_free(srv);
+-
++
+ return -1;
+ }
+ }
+@@ -802,25 +821,27 @@
+ /* or use the default */
+ srv->max_conns = srv->max_fds;
+ }
+-
++
+ if (HANDLER_GO_ON != plugins_call_init(srv)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
+-
++
+ plugins_free(srv);
+ network_close(srv);
+ server_free(srv);
+-
++
+ return -1;
+ }
- if (major_num == 1 && minor_num == 1) {
-- con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
-+ con->request.http_version = HTTP_VERSION_1_1;
- } else if (major_num == 1 && minor_num == 0) {
- con->request.http_version = HTTP_VERSION_1_0;
- } else {
-@@ -797,6 +799,7 @@
- "request-header:\n",
- con->request.request);
- }
-+ ds->free((data_unset *) ds);
- return 0;
- }
-
-@@ -846,6 +849,7 @@
- "request-header:\n",
- con->request.request);
- }
-+ ds->free((data_unset *) ds);
- return 0;
- }
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
-@@ -883,6 +887,7 @@
- "request-header:\n",
- con->request.request);
- }
-+ ds->free((data_unset *) ds);
- return 0;
- }
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
-@@ -905,6 +910,7 @@
- "request-header:\n",
- con->request.request);
- }
-+ ds->free((data_unset *) ds);
- return 0;
- }
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
-@@ -922,6 +928,7 @@
- "request-header:\n",
- con->request.request);
- }
-+ ds->free((data_unset *) ds);
- return 0;
- }
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
-@@ -945,6 +952,7 @@
- "request-header:\n",
- con->request.request);
- }
-+ ds->free((data_unset *) ds);
- return 0;
- }
- }
---- lighttpd-1.4.11/src/response.c 2006-03-04 16:41:39.000000000 +0200
-+++ lighttpd/src/response.c 2006-07-11 21:23:40.067853974 +0300
-@@ -7,7 +7,6 @@
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
--#include <unistd.h>
- #include <ctype.h>
- #include <assert.h>
+-#ifdef HAVE_FORK
++#ifdef HAVE_FORK
+ /* network is up, let's deamonize ourself */
+ if (srv->srvconf.dont_daemonize == 0) daemonize();
+ #endif
-@@ -24,6 +23,8 @@
- #include "plugin.h"
++#ifdef HAVE_PWD_H
+ srv->gid = getgid();
+ srv->uid = getuid();
+-
++#endif
++
+ /* write pid file */
+ if (pid_fd != -1) {
+ buffer_copy_long(srv->tmp_buf, getpid());
+@@ -829,17 +850,17 @@
+ close(pid_fd);
+ pid_fd = -1;
+ }
+-
++
+ if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
+-
++
+ plugins_free(srv);
+ network_close(srv);
+ server_free(srv);
+-
++
+ return -1;
+ }
+-
++
+ /* dump unused config-keys */
+ for (i = 0; i < srv->config_context->used; i++) {
+ array *config = ((data_config *)srv->config_context->data[i])->value;
+@@ -847,43 +868,42 @@
- #include "sys-socket.h"
-+#include "sys-files.h"
-+#include "sys-strings.h"
+ for (j = 0; config && j < config->used; j++) {
+ data_unset *du = config->data[j];
+-
++
+ /* all var.* is known as user defined variable */
+ if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
+ continue;
+ }
- int http_response_write_header(server *srv, connection *con) {
- buffer *b;
-@@ -59,7 +60,8 @@
- ds = (data_string *)con->response.headers->data[i];
-
- if (ds->value->used && ds->key->used &&
-- 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
-+ 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
-+ 0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
- if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
- if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
+ if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "WARNING: unknown config-key:",
+ du->key,
+ "(ignored)");
+ }
+ }
+ }
+-
++
+ if (srv->config_deprecated) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "Configuration contains deprecated keys. Going down.");
+-
++
+ plugins_free(srv);
+ network_close(srv);
+ server_free(srv);
+-
++
+ return -1;
+ }
+-
++
+ if (-1 == log_error_open(srv)) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "opening errorlog failed, dying");
+-
++
+ plugins_free(srv);
+ network_close(srv);
+ server_free(srv);
+ return -1;
+ }
+-
+-
++
+ #ifdef HAVE_SIGACTION
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = SIG_IGN;
+@@ -903,7 +923,7 @@
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGALRM, &act, NULL);
+ sigaction(SIGCHLD, &act, NULL);
+-
++
+ #elif defined(HAVE_SIGNAL)
+ /* ignore the SIGPIPE from sendfile() */
+ signal(SIGPIPE, SIG_IGN);
+@@ -914,20 +934,20 @@
+ signal(SIGCHLD, signal_handler);
+ signal(SIGINT, signal_handler);
+ #endif
+-
++
+ #ifdef USE_ALARM
+ signal(SIGALRM, signal_handler);
+-
++
+ /* setup periodic timer (1 second) */
+ if (setitimer(ITIMER_REAL, &interval, NULL)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
+ return -1;
+ }
+-
++
+ getitimer(ITIMER_REAL, &interval);
+ #endif
-@@ -119,7 +121,7 @@
- handler_t http_response_prepare(server *srv, connection *con) {
- handler_t r;
-
-- /* looks like someone has already done a decision */
-+ /* looks like someone has already made a decision */
- if (con->mode == DIRECT &&
- (con->http_status != 0 && con->http_status != 200)) {
- /* remove a packets in the queue */
-@@ -134,7 +136,7 @@
- if (con->mode == DIRECT && con->physical.path->used == 0) {
- char *qstr;
+-#ifdef HAVE_FORK
++#ifdef HAVE_FORK
+ /* start watcher and workers */
+ num_childs = srv->srvconf.max_worker;
+ if (num_childs > 0) {
+@@ -957,13 +977,13 @@
+ }
+ #endif
-- /* we only come here when we have the parse the full request again
-+ /* we only come here when we have to parse the full request again
- *
- * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
- * problem here as mod_setenv might get called multiple times
-@@ -262,6 +264,11 @@
-
- config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
-
-+ /* do we have to downgrade to 1.0 ? */
-+ if (!con->conf.allow_http11) {
-+ con->request.http_version = HTTP_VERSION_1_0;
-+ }
+- if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
++ if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
+ log_error_write(srv, __FILE__, __LINE__,
+ "s", "fdevent_init failed");
+ return -1;
+ }
+- /*
+- * kqueue() is called here, select resets its internals,
++ /*
++ * kqueue() is called here, select resets its internals,
+ * all server sockets get their handlers
+ *
+ * */
+@@ -971,7 +991,7 @@
+ plugins_free(srv);
+ network_close(srv);
+ server_free(srv);
+-
+
- switch(r = plugins_call_handle_uri_clean(srv, con)) {
- case HANDLER_GO_ON:
- break;
-@@ -277,7 +284,7 @@
-
- if (con->request.http_method == HTTP_METHOD_OPTIONS &&
- con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
-- /* option requests are handled directly without checking of the path */
-+ /* option requests are handled directly without checking the path */
-
- response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
+ return -1;
+ }
-@@ -320,14 +327,15 @@
- buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
- buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
-
--#if defined(__WIN32) || defined(__CYGWIN__)
-- /* strip dots from the end and spaces
-+ filename_unix2local(con->physical.rel_path);
-+#if defined(_WIN32) || defined(__CYGWIN__)
-+ /* strip dots and spaces from the end
- *
- * windows/dos handle those filenames as the same file
- *
- * foo == foo. == foo..... == "foo... " == "foo.. ./"
- *
-- * This will affect in some cases PATHINFO
-+ * This will affect PATHINFO in some cases
- *
- * on native windows we could prepend the filename with \\?\ to circumvent
- * this behaviour. I have no idea how to push this through cygwin
-@@ -378,15 +386,14 @@
- break;
+@@ -986,7 +1006,7 @@
+ /* setup FAM */
+ if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
+ if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
+- log_error_write(srv, __FILE__, __LINE__, "s",
++ log_error_write(srv, __FILE__, __LINE__, "s",
+ "could not open a fam connection, dieing.");
+ return -1;
}
-
-- /* MacOS X and Windows can't distiguish between upper and lower-case
-- *
-- * convert to lower-case
-+ /* The default Mac OS X and Windows filesystems can't distiguish between
-+ * upper- and lowercase, so convert to lowercase
- */
- if (con->conf.force_lowercase_filenames) {
- buffer_to_lower(con->physical.rel_path);
+@@ -1018,16 +1038,40 @@
+ int n;
+ size_t ndx;
+ time_t min_ts;
+-
++
+ if (handle_sig_hup) {
+ handler_t r;
+-
++
+ /* reset notification */
+ handle_sig_hup = 0;
+-
+-
++
++#if 0
++ pid_t pid;
++
++ /* send the old process into a graceful-shutdown and start a
++ * new process right away
++ *
++ * BUGS:
++ * - if webserver is running on port < 1024 (e.g. 80, 433)
++ * we don't have the permissions to bind to that port anymore
++ *
++ *
++ * */
++ if (0 == (pid = fork())) {
++ execve(argv[0], argv, envp);
++
++ exit(-1);
++ } else if (pid == -1) {
++
++ } else {
++ /* parent */
++
++ graceful_shutdown = 1; /* shutdown without killing running connections */
++ graceful_restart = 1; /* don't delete pid file */
++ }
++#else
+ /* cycle logfiles */
+-
++
+ switch(r = plugins_call_handle_sighup(srv)) {
+ case HANDLER_GO_ON:
+ break;
+@@ -1035,30 +1079,31 @@
+ log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
+ break;
+ }
+-
++
+ if (-1 == log_error_cycle(srv)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
+-
++
+ return -1;
+ }
++#endif
+ }
+-
++
+ if (handle_sig_alarm) {
+ /* a new second */
+-
++
+ #ifdef USE_ALARM
+ /* reset notification */
+ handle_sig_alarm = 0;
+ #endif
+-
++
+ /* get current time */
+ min_ts = time(NULL);
+-
++
+ if (min_ts != srv->cur_ts) {
+ int cs = 0;
+ connections *conns = srv->conns;
+ handler_t r;
+-
++
+ switch(r = plugins_call_handle_trigger(srv)) {
+ case HANDLER_GO_ON:
+ break;
+@@ -1069,21 +1114,21 @@
+ log_error_write(srv, __FILE__, __LINE__, "d", r);
+ break;
+ }
+-
++
+ /* trigger waitpid */
+ srv->cur_ts = min_ts;
+-
+- /* cleanup stat-cache */
++
++ /* cleanup stat-cache */
+ stat_cache_trigger_cleanup(srv);
+ /**
+- * check all connections for timeouts
+- *
++ * check all connections for timeouts
++ *
+ */
+ for (ndx = 0; ndx < conns->used; ndx++) {
+ int changed = 0;
+ connection *con;
+ int t_diff;
+-
++
+ con = conns->ptr[ndx];
+
+ if (con->state == CON_STATE_READ ||
+@@ -1092,7 +1137,7 @@
+ if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
+ /* time - out */
+ #if 0
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connection closed - read-timeout:", con->fd);
+ #endif
+ connection_set_state(srv, con, CON_STATE_ERROR);
+@@ -1102,7 +1147,7 @@
+ if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
+ /* time - out */
+ #if 0
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "connection closed - read-timeout:", con->fd);
+ #endif
+ connection_set_state(srv, con, CON_STATE_ERROR);
+@@ -1110,20 +1155,20 @@
+ }
+ }
+ }
+-
++
+ if ((con->state == CON_STATE_WRITE) &&
+- (con->write_request_ts != 0)) {
++ (con->write_request_ts != 0)) {
+ #if 0
+ if (srv->cur_ts - con->write_request_ts > 60) {
+- log_error_write(srv, __FILE__, __LINE__, "sdd",
++ log_error_write(srv, __FILE__, __LINE__, "sdd",
+ "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
+ }
+ #endif
+-
++
+ if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
+ /* time - out */
+ #if 1
+- log_error_write(srv, __FILE__, __LINE__, "sbsosds",
++ log_error_write(srv, __FILE__, __LINE__, "sbsosds",
+ "NOTE: a request for",
+ con->request.uri,
+ "timed out after writing",
+@@ -1138,35 +1183,35 @@
+ }
+ /* we don't like div by zero */
+ if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
+-
+- if (con->traffic_limit_reached &&
+- (con->conf.kbytes_per_second == 0 ||
++
++ if (con->traffic_limit_reached &&
++ (con->conf.kbytes_per_second == 0 ||
+ ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
+ /* enable connection again */
+ con->traffic_limit_reached = 0;
+-
++
+ changed = 1;
+ }
+-
++
+ if (changed) {
+ connection_state_machine(srv, con);
+ }
+ con->bytes_written_cur_second = 0;
+ *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
+-
++
+ #if 0
+ if (cs == 0) {
+ fprintf(stderr, "connection-state: ");
+ cs = 1;
+ }
+-
++
+ fprintf(stderr, "c[%d,%d]: %s ",
+ con->fd,
+ con->fcgi.fd,
+ connection_get_state(con->state));
+ #endif
+ }
+-
++
+ if (cs == 1) fprintf(stderr, "\n");
+ }
}
+@@ -1181,18 +1226,18 @@
+ server_socket *srv_socket = srv->srv_sockets.ptr[i];
+ fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
+ }
+-
++
+ log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
+-
++
+ srv->sockets_disabled = 0;
+ }
+ } else {
+ if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
+ (srv->conns->used > srv->max_conns) || /* out of connections */
+- (graceful_shutdown)) { /* graceful_shutdown */
++ (graceful_shutdown)) { /* graceful_shutdown */
-- /* the docroot plugins might set the servername, if they don't we take http-host */
-+ /* the docroot plugins might set the servername; if they don't we take http-host */
- if (buffer_is_empty(con->server_name)) {
- buffer_copy_string_buffer(con->server_name, con->uri.authority);
+ /* disable server-fds */
+-
++
+ for (i = 0; i < srv->srv_sockets.used; i++) {
+ server_socket *srv_socket = srv->srv_sockets.ptr[i];
+ fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
+@@ -1211,7 +1256,7 @@
+ /* network_close() will cleanup after us */
+ }
+ }
+-
++
+ if (graceful_shutdown) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
+ } else if (srv->conns->used > srv->max_conns) {
+@@ -1219,7 +1264,7 @@
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
+ }
+-
++
+ srv->sockets_disabled = 1;
+ }
}
-@@ -398,15 +405,21 @@
- */
-
- buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
-- BUFFER_APPEND_SLASH(con->physical.path);
-+ PATHNAME_APPEND_SLASH(con->physical.path);
- buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
- if (con->physical.rel_path->used &&
-- con->physical.rel_path->ptr[0] == '/') {
-+ con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
- buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
- } else {
- buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
+@@ -1229,16 +1274,16 @@
+ * we are ready to terminate without harming anyone */
+ srv_shutdown = 1;
}
-
-+ /* win32: directories can't have a trailing slash */
-+ if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
-+ con->physical.path->ptr[con->physical.path->used - 2] = '\0';
-+ con->physical.path->used--;
-+ }
+-
+
- if (con->conf.log_request_handling) {
- log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root");
- log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
-@@ -436,7 +449,7 @@
- }
-
- /*
-- * Noone catched away the file from normal path of execution yet (like mod_access)
-+ * No one took the file away from the normal path of execution yet (like mod_access)
- *
- * Go on and check of the file exists at all
- */
-@@ -461,7 +474,7 @@
+ /* we still have some fds to share */
+- if (srv->want_fds) {
++ if (srv->want_fds) {
+ /* check the fdwaitqueue for waiting fds */
+ int free_fds = srv->max_fds - srv->cur_fds - 16;
+ connection *con;
+-
++
+ for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
+ connection_state_machine(srv, con);
+-
++
+ srv->want_fds--;
}
-
- if (S_ISDIR(sce->st.st_mode)) {
-- if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
-+ if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
- /* redirect to .../ */
-
- http_response_redirect_to_directory(srv, con);
-@@ -499,7 +512,7 @@
- /* PATH_INFO ! :) */
+ }
+@@ -1249,27 +1294,27 @@
+ int fd_ndx;
+ #if 0
+ if (n > 0) {
+- log_error_write(srv, __FILE__, __LINE__, "sd",
++ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "polls:", n);
+ }
+-#endif
++#endif
+ fd_ndx = -1;
+ do {
+ fdevent_handler handler;
+ void *context;
+ handler_t r;
+-
++
+ fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx);
+ revents = fdevent_event_get_revent (srv->ev, fd_ndx);
+ fd = fdevent_event_get_fd (srv->ev, fd_ndx);
+ handler = fdevent_get_handler(srv->ev, fd);
+ context = fdevent_get_context(srv->ev, fd);
+-
++
+ /* connection_handle_fdevent needs a joblist_append */
+ #if 0
+- log_error_write(srv, __FILE__, __LINE__, "sdd",
++ log_error_write(srv, __FILE__, __LINE__, "sdd",
+ "event for", fd, revents);
+-#endif
++#endif
+ switch (r = (*handler)(srv, context, revents)) {
+ case HANDLER_FINISHED:
+ case HANDLER_GO_ON:
+@@ -1286,17 +1331,17 @@
+ }
+ } while (--n > 0);
+ } else if (n < 0 && errno != EINTR) {
+- log_error_write(srv, __FILE__, __LINE__, "ss",
+- "fdevent_poll failed:",
++ log_error_write(srv, __FILE__, __LINE__, "ss",
++ "fdevent_poll failed:",
+ strerror(errno));
+ }
+-
++
+ for (ndx = 0; ndx < srv->joblist->used; ndx++) {
+ connection *con = srv->joblist->ptr[ndx];
+ handler_t r;
+-
++
+ connection_state_machine(srv, con);
+-
++
+ switch(r = plugins_call_handle_joblist(srv, con)) {
+ case HANDLER_FINISHED:
+ case HANDLER_GO_ON:
+@@ -1305,32 +1350,33 @@
+ log_error_write(srv, __FILE__, __LINE__, "d", r);
break;
- default:
-- /* we have no idea what happend. let's tell the user so. */
-+ /* we have no idea what happened, so tell the user. */
- con->http_status = 500;
- buffer_reset(con->physical.path);
-
-@@ -544,7 +557,7 @@
- } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
-
- if (found == 0) {
-- /* no it really doesn't exists */
-+ /* no, it really doesn't exists */
- con->http_status = 404;
-
- if (con->conf.log_file_not_found) {
-@@ -594,11 +607,11 @@
- log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished");
}
-
-- /* something strange happend */
-+ /* something strange happened */
- return r;
+-
++
+ con->in_joblist = 0;
}
-
-- /* if we are still here, no one wanted the file, status 403 is ok I think */
-+ /* if we are still here, no one wanted the file; status 403 is ok I think */
-
- if (con->mode == DIRECT) {
- con->http_status = 403;
-@@ -610,12 +623,12 @@
-
- switch(r = plugins_call_handle_subrequest(srv, con)) {
- case HANDLER_GO_ON:
-- /* request was not handled, looks like we are done */
-+ /* request was not handled; looks like we are done */
- return HANDLER_FINISHED;
- case HANDLER_FINISHED:
- /* request is finished */
- default:
-- /* something strange happend */
-+ /* something strange happened */
- return r;
+-
++
+ srv->joblist->used = 0;
}
-
---- lighttpd-1.4.11/src/server.c 2006-03-04 19:12:17.000000000 +0200
-+++ lighttpd/src/server.c 2006-07-11 21:23:40.247865249 +0300
-@@ -1,11 +1,9 @@
+-
+- if (srv->srvconf.pid_file->used &&
++
++ if (0 == graceful_restart &&
++ srv->srvconf.pid_file->used &&
+ srv->srvconf.changeroot->used == 0) {
+ if (0 != unlink(srv->srvconf.pid_file->ptr)) {
+ if (errno != EACCES && errno != EPERM) {
+- log_error_write(srv, __FILE__, __LINE__, "sbds",
+- "unlink failed for:",
++ log_error_write(srv, __FILE__, __LINE__, "sbds",
++ "unlink failed for:",
+ srv->srvconf.pid_file,
+ errno,
+ strerror(errno));
+ }
+ }
+ }
+-
++
+ /* clean-up */
+ log_error_close(srv);
+ network_close(srv);
+ connections_free(srv);
+ plugins_free(srv);
+ server_free(srv);
+-
++
+ return 0;
+ }
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/settings.h lighttpd-1.4.12/src/settings.h
+--- lighttpd-1.4.11/src/settings.h 2005-08-11 01:26:41.000000000 +0300
++++ lighttpd-1.4.12/src/settings.h 2006-07-11 21:23:40.000000000 +0300
+@@ -9,24 +9,24 @@
+ /**
+ * max size of a buffer which will just be reset
+ * to ->used = 0 instead of really freeing the buffer
+- *
++ *
+ * 64kB (no real reason, just a guess)
+ */
+ #define BUFFER_MAX_REUSE_SIZE (4 * 1024)
+
+ /**
+ * max size of the HTTP request header
+- *
++ *
+ * 32k should be enough for everything (just a guess)
+- *
++ *
+ */
+ #define MAX_HTTP_REQUEST_HEADER (32 * 1024)
+
+-typedef enum { HANDLER_UNSET,
+- HANDLER_GO_ON,
++typedef enum { HANDLER_UNSET,
++ HANDLER_GO_ON,
+ HANDLER_FINISHED,
+- HANDLER_COMEBACK,
+- HANDLER_WAIT_FOR_EVENT,
++ HANDLER_COMEBACK,
++ HANDLER_WAIT_FOR_EVENT,
+ HANDLER_ERROR,
+ HANDLER_WAIT_FOR_FD
+ } handler_t;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/spawn-fcgi.c lighttpd-1.4.12/src/spawn-fcgi.c
+--- lighttpd-1.4.11/src/spawn-fcgi.c 2006-03-07 14:18:10.000000000 +0200
++++ lighttpd-1.4.12/src/spawn-fcgi.c 2006-07-11 21:23:40.000000000 +0300
+@@ -1,19 +1,16 @@
#include <sys/types.h>
-#include <sys/time.h>
#include <sys/stat.h>
+ #include <stdlib.h>
#include <string.h>
#include <errno.h>
- #include <fcntl.h>
+ #include <stdio.h>
-#include <unistd.h>
- #include <stdlib.h>
- #include <time.h>
- #include <signal.h>
-@@ -29,9 +27,14 @@
- #include "plugin.h"
- #include "joblist.h"
- #include "network_backends.h"
+ #include <fcntl.h>
-
-+#ifdef _WIN32
-+/* use local getopt implementation */
-+# undef HAVE_GETOPT_H
-+#endif
- #ifdef HAVE_GETOPT_H
- #include <getopt.h>
-+#else
-+#include "getopt.h"
++#include <time.h>
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
#endif
- #ifdef HAVE_VALGRIND_VALGRIND_H
-@@ -60,8 +63,16 @@
- /* #define USE_ALARM */
+-
+ #ifdef HAVE_PWD_H
+ #include <grp.h>
+ #include <pwd.h>
+@@ -30,6 +27,7 @@
#endif
-+#ifdef _WIN32
-+#undef HAVE_SIGNAL
-+#endif
-+
+ #include "sys-socket.h"
+#include "sys-files.h"
-+#include "sys-process.h"
-+
- static volatile sig_atomic_t srv_shutdown = 0;
- static volatile sig_atomic_t graceful_shutdown = 0;
-+static volatile sig_atomic_t graceful_restart = 0;
- static volatile sig_atomic_t handle_sig_alarm = 1;
- static volatile sig_atomic_t handle_sig_hup = 0;
-
-@@ -126,6 +137,7 @@
-
- server *srv = calloc(1, sizeof(*srv));
- assert(srv);
-+ srv->max_fds = 1024;
- #define CLEAN(x) \
- srv->x = buffer_init();
-
-@@ -286,9 +298,7 @@
- }
- static void show_features (void) {
-- show_version();
-- printf("\nEvent Handlers:\n\n%s",
--
-+ const char *s = ""
- #ifdef USE_SELECT
- "\t+ select (generic)\n"
- #else
-@@ -355,11 +365,6 @@
- #else
- "\t- crypt support\n"
- #endif
--#ifdef USE_PAM
-- "\t+ PAM support\n"
--#else
-- "\t- PAM support\n"
--#endif
- #ifdef USE_OPENSSL
- "\t+ SSL Support\n"
- #else
-@@ -371,9 +376,9 @@
- "\t- PCRE support\n"
- #endif
- #ifdef HAVE_MYSQL
-- "\t+ mySQL support\n"
-+ "\t+ MySQL support\n"
- #else
-- "\t- mySQL support\n"
-+ "\t- MySQL support\n"
- #endif
- #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
- "\t+ LDAP support\n"
-@@ -410,8 +415,11 @@
+ #ifdef HAVE_SYS_WAIT_H
+ #include <sys/wait.h>
+@@ -45,28 +43,28 @@
+ int fcgi_fd;
+ int socket_type, status;
+ struct timeval tv = { 0, 100 * 1000 };
+-
++
+ struct sockaddr_un fcgi_addr_un;
+ struct sockaddr_in fcgi_addr_in;
+ struct sockaddr *fcgi_addr;
+-
++
+ socklen_t servlen;
+-
++
+ if (child_count < 2) {
+ child_count = 5;
+ }
+-
++
+ if (child_count > 256) {
+ child_count = 256;
+ }
+-
+-
++
++
+ if (unixsocket) {
+ memset(&fcgi_addr, 0, sizeof(fcgi_addr));
+-
++
+ fcgi_addr_un.sun_family = AF_UNIX;
+ strcpy(fcgi_addr_un.sun_path, unixsocket);
+-
++
+ #ifdef SUN_LEN
+ servlen = SUN_LEN(&fcgi_addr_un);
#else
- "\t- GDBM support\n"
- #endif
-- "\n"
-- );
-+ "\n";
+@@ -84,50 +82,50 @@
+ }
+ fcgi_addr_in.sin_port = htons(port);
+ servlen = sizeof(fcgi_addr_in);
+-
++
+ socket_type = AF_INET;
+ fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
+ }
+-
+
-+ show_version();
+ if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
+- fprintf(stderr, "%s.%d\n",
++ fprintf(stderr, "%s.%d\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+-
+
-+ printf("\nEvent Handlers:\n\n%s", s);
- }
+ if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
+ /* server is not up, spawn in */
+ pid_t child;
+ int val;
+-
++
+ if (unixsocket) unlink(unixsocket);
+-
++
+ close(fcgi_fd);
+-
++
+ /* reopen socket */
+ if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
+- fprintf(stderr, "%s.%d\n",
++ fprintf(stderr, "%s.%d\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
- static void show_help (void) {
-@@ -438,7 +446,7 @@
- write(STDOUT_FILENO, b, strlen(b));
- }
+ val = 1;
+ if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
+- fprintf(stderr, "%s.%d\n",
++ fprintf(stderr, "%s.%d\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
--int main (int argc, char **argv) {
-+int main (int argc, char **argv, char **envp) {
- server *srv = NULL;
- int print_config = 0;
- int test_config = 0;
-@@ -447,6 +455,10 @@
- int num_childs = 0;
- int pid_fd = -1, fd;
- size_t i;
-+#ifdef _WIN32
-+ char *optarg = NULL;
-+#endif
+ /* create socket */
+ if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
+- fprintf(stderr, "%s.%d: bind failed: %s\n",
++ fprintf(stderr, "%s.%d: bind failed: %s\n",
+ __FILE__, __LINE__,
+ strerror(errno));
+ return -1;
+ }
+-
+
- #ifdef HAVE_SIGACTION
- struct sigaction act;
- #endif
-@@ -485,10 +497,15 @@
- while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
- switch(o) {
- case 'f':
-+#ifdef _WIN32
-+ /* evil HACK for windows, optarg is not set */
-+ optarg = argv[optind-1];
-+#endif
- if (config_read(srv, optarg)) {
- server_free(srv);
- return -1;
+ if (-1 == listen(fcgi_fd, 1024)) {
+- fprintf(stderr, "%s.%d: fd = -1\n",
++ fprintf(stderr, "%s.%d: fd = -1\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+@@ -137,42 +135,45 @@
+ } else {
+ child = 0;
+ }
+-
++
+ switch (child) {
+ case 0: {
+ char cgi_childs[64];
+ char *b;
+-
++
+ int i = 0;
+-
++
++ /* loose control terminal */
++ setsid();
++
+ /* is save as we limit to 256 childs */
+ sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
+-
++
+ if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
+ close(FCGI_LISTENSOCK_FILENO);
+ dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
+ close(fcgi_fd);
+ }
+-
++
+ /* we don't need the client socket */
+ for (i = 3; i < 256; i++) {
+ close(i);
}
+-
++
+ /* create environment */
+-
++
+ putenv(cgi_childs);
+-
++
+ /* fork and replace shell */
+ b = malloc(strlen("exec ") + strlen(appPath) + 1);
+ strcpy(b, "exec ");
+ strcat(b, appPath);
+-
++
+ /* exec the cgi */
+ execl("/bin/sh", "sh", "-c", b, NULL);
+-
++
+ exit(errno);
+-
+
break;
- case 'm':
- buffer_copy_string(srv->srvconf.modules_dir, optarg);
-@@ -589,6 +606,7 @@
- return -1;
- }
-
-+#ifndef _WIN32
- /* open pid file BEFORE chroot */
- if (srv->srvconf.pid_file->used) {
- 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))) {
-@@ -617,13 +635,14 @@
+ }
+ case -1:
+@@ -180,47 +181,47 @@
+ break;
+ default:
+ /* father */
+-
++
+ /* wait */
+ select(0, NULL, NULL, NULL, &tv);
+-
++
+ switch (waitpid(child, &status, WNOHANG)) {
+ case 0:
+- fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
++ fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
+ __FILE__, __LINE__,
+ child);
+-
++
+ /* write pid file */
+ if (pid_fd != -1) {
+ /* assume a 32bit pid_t */
+ char pidbuf[12];
+-
++
+ snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
+-
++
+ write(pid_fd, pidbuf, strlen(pidbuf));
+ close(pid_fd);
+ pid_fd = -1;
+ }
+-
++
+ break;
+ case -1:
+ break;
+ default:
+ if (WIFEXITED(status)) {
+- fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
++ fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
+ __FILE__, __LINE__,
+ WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
+ } else if (WIFSIGNALED(status)) {
+- fprintf(stderr, "%s.%d: child signaled: %d\n",
++ fprintf(stderr, "%s.%d: child signaled: %d\n",
+ __FILE__, __LINE__,
+ WTERMSIG(status));
+ } else {
+- fprintf(stderr, "%s.%d: child died somehow: %d\n",
++ fprintf(stderr, "%s.%d: child died somehow: %d\n",
+ __FILE__, __LINE__,
+ status);
+ }
}
+-
++
+ break;
}
- }
--
-+#endif
- if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
- /* select limits itself
- *
- * as it is a hard limit and will lead to a segfault we add some safety
- * */
-- srv->max_fds = FD_SETSIZE - 200;
-+ fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
-+ srv->max_fds = FD_SETSIZE - 4;
} else {
- srv->max_fds = 4096;
+@@ -228,16 +229,16 @@
+ __FILE__, __LINE__);
+ return -1;
}
-@@ -761,7 +780,7 @@
- }
+-
++
+ close(fcgi_fd);
+-
++
+ return 0;
+ }
- if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
-- srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
-+ srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
- } else {
- srv->max_fds = rlim.rlim_cur;
- }
-@@ -775,9 +794,9 @@
- #endif
- if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
- /* don't raise the limit above FD_SET_SIZE */
-- if (srv->max_fds > FD_SETSIZE - 200) {
-+ if (srv->max_fds > FD_SETSIZE - 4) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
-- "can't raise max filedescriptors above", FD_SETSIZE - 200,
-+ "can't raise max filedescriptors above", FD_SETSIZE - 4,
- "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
- return -1;
- }
-@@ -818,8 +837,10 @@
- if (srv->srvconf.dont_daemonize == 0) daemonize();
- #endif
-+#ifdef HAVE_PWD_H
- srv->gid = getgid();
- srv->uid = getuid();
-+#endif
-
- /* write pid file */
- if (pid_fd != -1) {
-@@ -883,7 +904,6 @@
+ void show_version () {
+ char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
+-" - spawns fastcgi processes\n"
++" - spawns fastcgi processes\n"
+ ;
+ write(1, b, strlen(b));
+ }
+@@ -265,7 +266,7 @@
+
+
+ int main(int argc, char **argv) {
+- char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
++ char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
+ *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
+ *addr = NULL;
+ unsigned short port = 0;
+@@ -273,9 +274,9 @@
+ int i_am_root, o;
+ int pid_fd = -1;
+ int nofork = 0;
+-
++
+ i_am_root = (getuid() == 0);
+-
++
+ while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
+ switch(o) {
+ case 'f': fcgi_app = optarg; break;
+@@ -290,137 +291,137 @@
+ case 'P': pid_file = optarg; /* PID file */ break;
+ case 'v': show_version(); return 0;
+ case 'h': show_help(); return 0;
+- default:
++ default:
+ show_help();
+ return -1;
+ }
+ }
+-
++
+ if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
+ show_help();
+ return -1;
+ }
+-
++
+ if (unixsocket && port) {
+- fprintf(stderr, "%s.%d: %s\n",
++ fprintf(stderr, "%s.%d: %s\n",
+ __FILE__, __LINE__,
+ "either a unix domain socket or a tcp-port, but not both\n");
+-
++
return -1;
}
-
-
- #ifdef HAVE_SIGACTION
- memset(&act, 0, sizeof(act));
- act.sa_handler = SIG_IGN;
-@@ -957,7 +977,7 @@
++
+ if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) {
+- fprintf(stderr, "%s.%d: %s\n",
++ fprintf(stderr, "%s.%d: %s\n",
+ __FILE__, __LINE__,
+ "path of the unix socket is too long\n");
+-
++
+ return -1;
}
- #endif
-- if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
-+ if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
- log_error_write(srv, __FILE__, __LINE__,
- "s", "fdevent_init failed");
+ /* UID handling */
+ if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
+ /* we are setuid-root */
+-
+- fprintf(stderr, "%s.%d: %s\n",
++
++ fprintf(stderr, "%s.%d: %s\n",
+ __FILE__, __LINE__,
+ "Are you nuts ? Don't apply a SUID bit to this binary\n");
+-
++
return -1;
-@@ -1025,7 +1045,31 @@
- /* reset notification */
- handle_sig_hup = 0;
-
-+#if 0
-+ pid_t pid;
-
-+ /* send the old process into a graceful-shutdown and start a
-+ * new process right away
-+ *
-+ * BUGS:
-+ * - if webserver is running on port < 1024 (e.g. 80, 433)
-+ * we don't have the permissions to bind to that port anymore
-+ *
-+ *
-+ * */
-+ if (0 == (pid = fork())) {
-+ execve(argv[0], argv, envp);
+ }
+-
+- if (pid_file &&
++
++ if (pid_file &&
+ (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
+ struct stat st;
+ if (errno != EEXIST) {
+- fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
++ fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
+ __FILE__, __LINE__,
+ pid_file, strerror(errno));
+-
+
-+ exit(-1);
-+ } else if (pid == -1) {
+ return -1;
+ }
+-
+
-+ } else {
-+ /* parent */
+ /* ok, file exists */
+-
++
+ if (0 != stat(pid_file, &st)) {
+- fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
++ fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
+ __FILE__, __LINE__,
+ pid_file, strerror(errno));
+-
++
+ return -1;
+ }
+-
++
+ /* is it a regular file ? */
+-
++
+ if (!S_ISREG(st.st_mode)) {
+- fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
++ fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
+ __FILE__, __LINE__,
+ pid_file);
+-
++
+ return -1;
+ }
+-
++
+ if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
+- fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
++ fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
+ __FILE__, __LINE__,
+ pid_file, strerror(errno));
+-
++
+ return -1;
+ }
+ }
+-
++
+ if (i_am_root) {
+ struct group *grp = NULL;
+ struct passwd *pwd = NULL;
+-
++
+ /* set user and group */
+-
++
+ if (username) {
+ if (NULL == (pwd = getpwnam(username))) {
+- fprintf(stderr, "%s.%d: %s, %s\n",
++ fprintf(stderr, "%s.%d: %s, %s\n",
+ __FILE__, __LINE__,
+ "can't find username", username);
+ return -1;
+ }
+-
++
+ if (pwd->pw_uid == 0) {
+- fprintf(stderr, "%s.%d: %s\n",
++ fprintf(stderr, "%s.%d: %s\n",
+ __FILE__, __LINE__,
+ "I will not set uid to 0\n");
+ return -1;
+ }
+ }
+-
++
+ if (groupname) {
+ if (NULL == (grp = getgrnam(groupname))) {
+- fprintf(stderr, "%s.%d: %s %s\n",
++ fprintf(stderr, "%s.%d: %s %s\n",
+ __FILE__, __LINE__,
+- "can't find groupname",
++ "can't find groupname",
+ groupname);
+ return -1;
+ }
+ if (grp->gr_gid == 0) {
+- fprintf(stderr, "%s.%d: %s\n",
++ fprintf(stderr, "%s.%d: %s\n",
+ __FILE__, __LINE__,
+ "I will not set gid to 0\n");
+ return -1;
+ }
+ }
+-
+
-+ graceful_shutdown = 1; /* shutdown without killing running connections */
-+ graceful_restart = 1; /* don't delete pid file */
-+ }
-+#else
- /* cycle logfiles */
-
- switch(r = plugins_call_handle_sighup(srv)) {
-@@ -1041,6 +1085,7 @@
-
+ if (changeroot) {
+ if (-1 == chroot(changeroot)) {
+- fprintf(stderr, "%s.%d: %s %s\n",
++ fprintf(stderr, "%s.%d: %s %s\n",
+ __FILE__, __LINE__,
+ "chroot failed: ", strerror(errno));
+ return -1;
+ }
+ if (-1 == chdir("/")) {
+- fprintf(stderr, "%s.%d: %s %s\n",
++ fprintf(stderr, "%s.%d: %s %s\n",
+ __FILE__, __LINE__,
+ "chdir failed: ", strerror(errno));
return -1;
}
-+#endif
}
-
- if (handle_sig_alarm) {
-@@ -1312,7 +1357,8 @@
- srv->joblist->used = 0;
+-
++
+ /* drop root privs */
+ if (groupname) {
+ setgid(grp->gr_gid);
+@@ -428,7 +429,7 @@
+ }
+ if (username) setuid(pwd->pw_uid);
}
-
-- if (srv->srvconf.pid_file->used &&
-+ if (0 == graceful_restart &&
-+ srv->srvconf.pid_file->used &&
- srv->srvconf.changeroot->used == 0) {
- if (0 != unlink(srv->srvconf.pid_file->ptr)) {
- if (errno != EACCES && errno != EPERM) {
---- lighttpd-1.4.11/src/spawn-fcgi.c 2006-03-07 14:18:10.000000000 +0200
-+++ lighttpd/src/spawn-fcgi.c 2006-07-11 21:23:40.167860238 +0300
-@@ -1,19 +1,16 @@
- #include <sys/types.h>
--#include <sys/time.h>
- #include <sys/stat.h>
-
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <stdio.h>
--#include <unistd.h>
- #include <fcntl.h>
--
-+#include <time.h>
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
+-
++
+ return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
+ }
+ #else
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/splaytree.c lighttpd-1.4.12/src/splaytree.c
+--- lighttpd-1.4.11/src/splaytree.c 2005-09-12 21:51:28.000000000 +0300
++++ lighttpd-1.4.12/src/splaytree.c 2006-07-11 21:23:39.000000000 +0300
+@@ -56,19 +56,19 @@
+
+ #define node_size splaytree_size
+
+-/* Splay using the key i (which may or may not be in the tree.)
+- * The starting root is t, and the tree used is defined by rat
++/* Splay using the key i (which may or may not be in the tree.)
++ * The starting root is t, and the tree used is defined by rat
+ * size fields are maintained */
+ splay_tree * splaytree_splay (splay_tree *t, int i) {
+ splay_tree N, *l, *r, *y;
+ int comp, root_size, l_size, r_size;
+-
++
+ if (t == NULL) return t;
+ N.left = N.right = NULL;
+ l = r = &N;
+ root_size = node_size(t);
+ l_size = r_size = 0;
+-
++
+ for (;;) {
+ comp = compare(i, t->key);
+ if (comp < 0) {
+@@ -120,7 +120,7 @@
+ y->size = r_size;
+ r_size -= 1+node_size(y->right);
+ }
+-
++
+ l->right = t->left; /* assemble */
+ r->left = t->right;
+ t->left = N.right;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/splaytree.h lighttpd-1.4.12/src/splaytree.h
+--- lighttpd-1.4.11/src/splaytree.h 2005-09-12 21:51:13.000000000 +0300
++++ lighttpd-1.4.12/src/splaytree.h 2006-07-11 21:23:40.000000000 +0300
+@@ -19,6 +19,6 @@
+ /* This macro returns the size of a node. Unlike "x->size", */
+ /* it works even if x=NULL. The test could be avoided by using */
+ /* a special version of NULL which was a real node with size 0. */
+-
++
--
- #ifdef HAVE_PWD_H
- #include <grp.h>
- #include <pwd.h>
-@@ -30,6 +27,7 @@
#endif
-
- #include "sys-socket.h"
-+#include "sys-files.h"
-
- #ifdef HAVE_SYS_WAIT_H
- #include <sys/wait.h>
-@@ -145,6 +143,9 @@
-
- int i = 0;
-
-+ /* loose control terminal */
-+ setsid();
-+
- /* is save as we limit to 256 childs */
- sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
-
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/stat_cache.c lighttpd-1.4.12/src/stat_cache.c
--- lighttpd-1.4.11/src/stat_cache.c 2005-11-22 15:23:51.000000000 +0200
-+++ lighttpd/src/stat_cache.c 2006-07-11 21:23:40.067853974 +0300
++++ lighttpd-1.4.12/src/stat_cache.c 2006-07-11 21:23:40.000000000 +0300
@@ -6,7 +6,6 @@
#include <stdlib.h>
#include <string.h>
+#include "sys-files.h"
+#include "sys-strings.h"
- #if 0
- /* enables debug code for testing if all nodes in the stat-cache as accessable */
+ #if 0
+ /* enables debug code for testing if all nodes in the stat-cache as accessable */
+@@ -52,8 +40,8 @@
+ *
+ * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
+ *
+- * if the stat()-cache is queried we check if the version id for the directory is the
+- * same and return immediatly.
++ * if the stat()-cache is queried we check if the version id for the directory is the
++ * same and return immediatly.
+ *
+ *
+ * What we need:
+@@ -62,17 +50,17 @@
+ * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
+ *
+ * stat <<-> directory <-> FAMRequest
+- *
+- * if file is deleted, directory is dirty, file is rechecked ...
++ *
++ * if file is deleted, directory is dirty, file is rechecked ...
+ * if directory is deleted, directory mapping is removed
+- *
++ *
+ * */
+
+ #ifdef HAVE_FAM_H
+ typedef struct {
+ FAMRequest *req;
+ FAMConnection *fc;
+-
++
+ buffer *name;
+
+ int version;
+@@ -83,16 +71,16 @@
+ * - we need a hash
+ * - the hash-key is used as sorting criteria for a tree
+ * - a splay-tree is used as we can use the caching effect of it
+- */
++ */
+
+ /* we want to cleanup the stat-cache every few seconds, let's say 10
+ *
+ * - remove entries which are outdated since 30s
+ * - remove entries which are fresh but havn't been used since 60s
+ * - if we don't have a stat-cache entry for a directory, release it from the monitor
+- */
++ */
+
+-#ifdef DEBUG_STAT_CACHE
++#ifdef DEBUG_STAT_CACHE
+ typedef struct {
+ int *ptr;
+
+@@ -105,15 +93,15 @@
+
+ stat_cache *stat_cache_init(void) {
+ stat_cache *fc = NULL;
+-
++
+ fc = calloc(1, sizeof(*fc));
+-
++
+ fc->dir_name = buffer_init();
+ #ifdef HAVE_FAM_H
+ fc->fam = calloc(1, sizeof(*fc->fam));
+ #endif
+
+-#ifdef DEBUG_STAT_CACHE
++#ifdef DEBUG_STAT_CACHE
+ ctrl.size = 0;
+ #endif
+
+@@ -122,24 +110,24 @@
+
+ static stat_cache_entry * stat_cache_entry_init(void) {
+ stat_cache_entry *sce = NULL;
+-
++
+ sce = calloc(1, sizeof(*sce));
+-
++
+ sce->name = buffer_init();
+ sce->etag = buffer_init();
+ sce->content_type = buffer_init();
+-
++
+ return sce;
+ }
+
+ static void stat_cache_entry_free(void *data) {
+ stat_cache_entry *sce = data;
+ if (!sce) return;
+-
++
+ buffer_free(sce->etag);
+ buffer_free(sce->name);
+ buffer_free(sce->content_type);
+-
++
+ free(sce);
+ }
+
+@@ -148,22 +136,22 @@
+ fam_dir_entry *fam_dir = NULL;
+
+ fam_dir = calloc(1, sizeof(*fam_dir));
+-
++
+ fam_dir->name = buffer_init();
+-
++
+ return fam_dir;
+ }
+
+ static void fam_dir_entry_free(void *data) {
+ fam_dir_entry *fam_dir = data;
+-
++
+ if (!fam_dir) return;
+-
++
+ FAMCancelMonitor(fam_dir->fc, fam_dir->req);
+-
++
+ buffer_free(fam_dir->name);
+ free(fam_dir->req);
+-
++
+ free(fam_dir);
+ }
+ #endif
+@@ -174,7 +162,7 @@
+ splay_tree *node = sc->files;
+
+ osize = sc->files->size;
+-
++
+ stat_cache_entry_free(node->data);
+ sc->files = splaytree_delete(sc->files, node->key);
+
+@@ -187,12 +175,12 @@
+ while (sc->dirs) {
+ int osize;
+ splay_tree *node = sc->dirs;
+-
++
+ osize = sc->dirs->size;
+
+ fam_dir_entry_free(node->data);
+ sc->dirs = splaytree_delete(sc->dirs, node->key);
+-
++
+ if (osize == 1) {
+ assert(NULL == sc->dirs);
+ } else {
+@@ -212,7 +200,7 @@
+ static int stat_cache_attr_get(buffer *buf, char *name) {
+ int attrlen;
+ int ret;
+-
++
+ attrlen = 1024;
+ buffer_prepare_copy(buf, attrlen);
+ attrlen--;
+@@ -251,15 +239,15 @@
+ sc->fam) {
+
+ events = FAMPending(sc->fam);
+-
++
+ for (i = 0; i < events; i++) {
+ FAMEvent fe;
+ fam_dir_entry *fam_dir;
+ splay_tree *node;
+ int ndx;
+-
++
+ FAMNextEvent(sc->fam, &fe);
+-
++
+ /* handle event */
+
+ switch(fe.code) {
+@@ -280,7 +268,7 @@
+
+ sc->dirs = splaytree_splay(sc->dirs, ndx);
+ node = sc->dirs;
+-
++
+ if (node && (node->key == ndx)) {
+ int osize = splaytree_size(sc->dirs);
+
+@@ -308,7 +296,7 @@
+
+ sc->fam = NULL;
+ }
+-
++
+ return HANDLER_GO_ON;
+ }
+
+@@ -332,7 +320,7 @@
+ *
+ *
+ *
+- * returns:
++ * returns:
+ * - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
+ * - HANDLER_ERROR on stat() failed -> see errno for problem
+ */
+@@ -348,16 +336,16 @@
+ struct stat st;
+ size_t k;
+ int fd;
+-#ifdef DEBUG_STAT_CACHE
++#ifdef DEBUG_STAT_CACHE
+ size_t i;
+ #endif
+
+ int file_ndx;
+ splay_tree *file_node = NULL;
+
+- *ret_sce = NULL;
++ *ret_sce = NULL;
+
+- /*
++ /*
+ * check if the directory for this file has changed
+ */
+
+@@ -366,23 +354,23 @@
+ file_ndx = hashme(name);
+ sc->files = splaytree_splay(sc->files, file_ndx);
+
+-#ifdef DEBUG_STAT_CACHE
++#ifdef DEBUG_STAT_CACHE
+ for (i = 0; i < ctrl.used; i++) {
+ if (ctrl.ptr[i] == file_ndx) break;
+ }
+ #endif
+
+ if (sc->files && (sc->files->key == file_ndx)) {
+-#ifdef DEBUG_STAT_CACHE
++#ifdef DEBUG_STAT_CACHE
+ /* it was in the cache */
+ assert(i < ctrl.used);
+ #endif
+-
+- /* we have seen this file already and
++
++ /* we have seen this file already and
+ * don't stat() it again in the same second */
+
+ file_node = sc->files;
+-
++
+ sce = file_node->data;
+
+ /* check if the name is the same, we might have a collision */
+@@ -390,7 +378,7 @@
+ if (buffer_is_equal(name, sce->name)) {
+ if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
+ if (sce->stat_ts == srv->cur_ts) {
+- *ret_sce = sce;
++ *ret_sce = sce;
+ return HANDLER_GO_ON;
+ }
+ }
+@@ -400,15 +388,15 @@
+ * file_node is used by the FAM check below to see if we know this file
+ * and if we can save a stat().
+ *
+- * BUT, the sce is not reset here as the entry into the cache is ok, we
++ * BUT, the sce is not reset here as the entry into the cache is ok, we
+ * it is just not pointing to our requested file.
+- *
++ *
+ * */
+
+ file_node = NULL;
+ }
+ } else {
+-#ifdef DEBUG_STAT_CACHE
++#ifdef DEBUG_STAT_CACHE
+ if (i != ctrl.used) {
+ fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr);
+ }
+@@ -424,23 +412,23 @@
+ }
+
+ dir_ndx = hashme(sc->dir_name);
+-
++
+ sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
+-
++
+ if (sc->dirs && (sc->dirs->key == dir_ndx)) {
+ dir_node = sc->dirs;
+ }
+-
++
+ if (dir_node && file_node) {
+ /* we found a file */
+-
++
+ sce = file_node->data;
+ fam_dir = dir_node->data;
+-
++
+ if (fam_dir->version == sce->dir_version) {
+ /* the stat()-cache entry is still ok */
+-
+- *ret_sce = sce;
++
++ *ret_sce = sce;
+ return HANDLER_GO_ON;
+ }
+ }
+@@ -448,7 +436,7 @@
+ #endif
+
+ /*
+- * *lol*
++ * *lol*
+ * - open() + fstat() on a named-pipe results in a (intended) hang.
+ * - stat() if regualar file + open() to see if we can read from it is better
+ *
+@@ -469,16 +457,16 @@
+
+ if (NULL == sce) {
+ int osize = 0;
+-
++
+ if (sc->files) {
+ osize = sc->files->size;
+ }
+
+ sce = stat_cache_entry_init();
+ buffer_copy_string_buffer(sce->name, name);
+-
+- sc->files = splaytree_insert(sc->files, file_ndx, sce);
+-#ifdef DEBUG_STAT_CACHE
++
++ sc->files = splaytree_insert(sc->files, file_ndx, sce);
++#ifdef DEBUG_STAT_CACHE
+ if (ctrl.size == 0) {
+ ctrl.size = 16;
+ ctrl.used = 0;
+@@ -499,29 +487,29 @@
+ sce->st = st;
+ sce->stat_ts = srv->cur_ts;
+
+- /* catch the obvious symlinks
++ /* catch the obvious symlinks
+ *
+ * this is not a secure check as we still have a race-condition between
+- * the stat() and the open. We can only solve this by
++ * the stat() and the open. We can only solve this by
+ * 1. open() the file
+ * 2. fstat() the fd
+ *
+ * and keeping the file open for the rest of the time. But this can
+ * only be done at network level.
+- *
++ *
+ * */
+ if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
+ return HANDLER_ERROR;
+ }
+
+- if (S_ISREG(st.st_mode)) {
++ if (S_ISREG(st.st_mode)) {
+ /* determine mimetype */
+ buffer_reset(sce->content_type);
+-
++
+ for (k = 0; k < con->conf.mimetypes->used; k++) {
+ data_string *ds = (data_string *)con->conf.mimetypes->data[k];
+ buffer *type = ds->key;
+-
++
+ if (type->used == 0) continue;
+
+ /* check if the right side is the same */
+@@ -539,7 +527,7 @@
+ }
+ #endif
+ }
+-
++
+ #ifdef HAVE_FAM_H
+ if (sc->fam &&
+ (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
+@@ -549,19 +537,19 @@
+ fam_dir->fc = sc->fam;
+
+ buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
+-
++
+ fam_dir->version = 1;
+-
++
+ fam_dir->req = calloc(1, sizeof(FAMRequest));
+-
+- if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
++
++ if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
+ fam_dir->req, fam_dir)) {
+-
+- log_error_write(srv, __FILE__, __LINE__, "sbs",
+- "monitoring dir failed:",
+- fam_dir->name,
++
++ log_error_write(srv, __FILE__, __LINE__, "sbs",
++ "monitoring dir failed:",
++ fam_dir->name,
+ FamErrlist[FAMErrno]);
+-
++
+ fam_dir_entry_free(fam_dir);
+ } else {
+ int osize = 0;
+@@ -570,7 +558,7 @@
+ osize = sc->dirs->size;
+ }
+
+- sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
++ sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
+ assert(sc->dirs);
+ assert(sc->dirs->data == fam_dir);
+ assert(osize == (sc->dirs->size - 1));
+@@ -578,9 +566,9 @@
+ } else {
+ fam_dir = dir_node->data;
+ }
+-
++
+ /* bind the fam_fc to the stat() cache entry */
+-
++
+ if (fam_dir) {
+ sce->dir_version = fam_dir->version;
+ sce->dir_ndx = dir_ndx;
+@@ -594,11 +582,11 @@
+ }
+
+ /**
+- * remove stat() from cache which havn't been stat()ed for
++ * remove stat() from cache which havn't been stat()ed for
+ * more than 10 seconds
+- *
+ *
+- * walk though the stat-cache, collect the ids which are too old
++ *
++ * walk though the stat-cache, collect the ids which are too old
+ * and remove them in a second loop
+ */
+
+@@ -639,9 +627,9 @@
+ sc->files = splaytree_splay(sc->files, ndx);
+
+ node = sc->files;
+-
++
+ if (node && (node->key == ndx)) {
+-#ifdef DEBUG_STAT_CACHE
++#ifdef DEBUG_STAT_CACHE
+ size_t j;
+ int osize = splaytree_size(sc->files);
+ stat_cache_entry *sce = node->data;
+@@ -649,7 +637,7 @@
+ stat_cache_entry_free(node->data);
+ sc->files = splaytree_delete(sc->files, ndx);
+
+-#ifdef DEBUG_STAT_CACHE
++#ifdef DEBUG_STAT_CACHE
+ for (j = 0; j < ctrl.used; j++) {
+ if (ctrl.ptr[j] == ndx) {
+ ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/stream.c lighttpd-1.4.12/src/stream.c
--- lighttpd-1.4.11/src/stream.c 2005-09-23 21:50:15.000000000 +0300
-+++ lighttpd/src/stream.c 2006-07-11 21:23:40.215863244 +0300
++++ lighttpd-1.4.12/src/stream.c 2006-07-11 21:23:40.000000000 +0300
@@ -1,7 +1,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#ifndef O_BINARY
# define O_BINARY 0
-@@ -19,7 +19,7 @@
+@@ -19,39 +19,39 @@
struct stat st;
#ifdef HAVE_MMAP
int fd;
HANDLE *fh, *mh;
void *p;
#endif
-@@ -45,7 +45,7 @@
+
+ f->start = NULL;
+-
++
+ if (-1 == stat(fn->ptr, &st)) {
+ return -1;
+ }
+-
++
+ f->size = st.st_size;
+
+ #ifdef HAVE_MMAP
+ if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
+ return -1;
+ }
+-
++
+ f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
+-
++
+ close(fd);
+-
++
+ if (MAP_FAILED == f->start) {
return -1;
}
-#elif defined __WIN32
+- fh = CreateFile(fn->ptr,
+- GENERIC_READ,
+- FILE_SHARE_READ,
+- NULL,
+- OPEN_EXISTING,
+- FILE_ATTRIBUTE_READONLY,
+#elif defined _WIN32
- fh = CreateFile(fn->ptr,
- GENERIC_READ,
- FILE_SHARE_READ,
++ fh = CreateFile(fn->ptr,
++ GENERIC_READ,
++ FILE_SHARE_READ,
++ NULL,
++ OPEN_EXISTING,
++ FILE_ATTRIBUTE_READONLY,
+ NULL);
+
+ if (!fh) return -1;
+@@ -66,7 +66,7 @@
+ if (!mh) {
+ LPVOID lpMsgBuf;
+ FormatMessage(
+- FORMAT_MESSAGE_ALLOCATE_BUFFER |
++ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ GetLastError(),
+@@ -76,7 +76,7 @@
+
+ return -1;
+ }
+-
++
+ p = MapViewOfFile(mh,
+ FILE_MAP_READ,
+ 0,
+@@ -87,9 +87,9 @@
+
+ f->start = p;
+ #else
+-# error no mmap found
++# error no mmap found
+ #endif
+-
++
+ return 0;
+ }
+
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/sys-mmap.h lighttpd-1.4.12/src/sys-mmap.h
--- lighttpd-1.4.11/src/sys-mmap.h 2005-08-11 01:26:34.000000000 +0300
-+++ lighttpd/src/sys-mmap.h 2006-07-11 21:23:40.051852972 +0300
++++ lighttpd-1.4.12/src/sys-mmap.h 2006-07-11 21:23:40.000000000 +0300
@@ -1,7 +1,7 @@
#ifndef WIN32_MMAP_H
#define WIN32_MMAP_H
#define MAP_FAILED -1
#define PROT_SHARED 0
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/sys-socket.h lighttpd-1.4.12/src/sys-socket.h
--- lighttpd-1.4.11/src/sys-socket.h 2005-08-11 01:26:39.000000000 +0300
-+++ lighttpd/src/sys-socket.h 2006-07-11 21:23:40.051852972 +0300
++++ lighttpd-1.4.12/src/sys-socket.h 2006-07-11 21:23:40.000000000 +0300
@@ -1,15 +1,26 @@
#ifndef WIN32_SOCKET_H
#define WIN32_SOCKET_H
#include <netdb.h>
#endif
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/LightyTest.pm lighttpd-1.4.12/tests/LightyTest.pm
--- lighttpd-1.4.11/tests/LightyTest.pm 2006-01-14 20:32:31.000000000 +0200
-+++ lighttpd/tests/LightyTest.pm 2006-07-11 21:23:42.047977994 +0300
++++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-11 21:23:42.000000000 +0300
@@ -87,14 +87,14 @@
# pre-process configfile if necessary
#
# check length
if (defined $resp_hdr{"content-length"}) {
$resp_body = substr($lines, 0, $resp_hdr{"content-length"});
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/Makefile.am lighttpd-1.4.12/tests/Makefile.am
--- lighttpd-1.4.11/tests/Makefile.am 2005-09-16 15:48:40.000000000 +0300
-+++ lighttpd/tests/Makefile.am 2006-07-11 21:23:42.039977492 +0300
++++ lighttpd-1.4.12/tests/Makefile.am 2006-07-11 21:23:42.000000000 +0300
@@ -39,10 +39,15 @@
mod-redirect.t \
mod-userdir.t \
TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/Makefile.in lighttpd-1.4.12/tests/Makefile.in
+--- lighttpd-1.4.11/tests/Makefile.in 2006-03-07 14:21:03.000000000 +0200
++++ lighttpd-1.4.12/tests/Makefile.in 2006-07-11 21:48:14.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -13,8 +13,6 @@
+ # PARTICULAR PURPOSE.
+
+ @SET_MAKE@
+-SOURCES = $(fcgi_auth_SOURCES) $(fcgi_responder_SOURCES)
+-
+ srcdir = @srcdir@
+ top_srcdir = @top_srcdir@
+ VPATH = @srcdir@
+@@ -46,7 +44,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES =
+ am__fcgi_auth_SOURCES_DIST = fcgi-auth.c
+@@ -67,8 +65,8 @@
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+ CCLD = $(CC)
+-LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
++LINK = $(LIBTOOL) --tag=CC --mode=link "$(CCLD)" $(AM_CFLAGS) \
++ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+ SOURCES = $(fcgi_auth_SOURCES) $(fcgi_responder_SOURCES)
+ DIST_SOURCES = $(am__fcgi_auth_SOURCES_DIST) \
+ $(am__fcgi_responder_SOURCES_DIST)
+@@ -134,7 +132,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -177,6 +174,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+@@ -253,10 +251,15 @@
+ mod-redirect.t \
+ mod-userdir.t \
+ mod-rewrite.t \
++ mod-proxy.t \
+ request.t \
+ mod-ssi.t \
+ LightyTest.pm \
+- mod-setenv.t
++ mod-setenv.t \
++ lowercase.t \
++ lowercase.conf \
++ proxy.conf \
++ cachable.t
+
+ TESTS_ENVIRONMENT = $(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
+ EXTRA_DIST = wrapper.sh lighttpd.conf \
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/bug-06.conf lighttpd-1.4.12/tests/bug-06.conf
--- lighttpd-1.4.11/tests/bug-06.conf 2005-08-27 17:44:19.000000000 +0300
-+++ lighttpd/tests/bug-06.conf 2006-07-11 21:23:41.915969726 +0300
++++ lighttpd-1.4.12/tests/bug-06.conf 2006-07-11 21:23:41.000000000 +0300
@@ -1,5 +1,5 @@
-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
server.name = "zzz.example.org"
}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/bug-12.conf lighttpd-1.4.12/tests/bug-12.conf
--- lighttpd-1.4.11/tests/bug-12.conf 2005-08-27 17:44:19.000000000 +0300
-+++ lighttpd/tests/bug-12.conf 2006-07-11 21:23:41.907969224 +0300
++++ lighttpd-1.4.12/tests/bug-12.conf 2006-07-11 21:23:41.000000000 +0300
@@ -1,5 +1,5 @@
-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
server.name = "zzz.example.org"
}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/cachable.t lighttpd-1.4.12/tests/cachable.t
+--- lighttpd-1.4.11/tests/cachable.t 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/tests/cachable.t 2006-07-11 21:23:41.000000000 +0300
+@@ -0,0 +1,112 @@
++#!/usr/bin/env perl
++BEGIN {
++ # add current source dir to the include-path
++ # we need this for make distcheck
++ (my $srcdir = $0) =~ s#/[^/]+$#/#;
++ unshift @INC, $srcdir;
++}
++
++use strict;
++use IO::Socket;
++use Test::More tests => 12;
++use LightyTest;
++
++my $tf = LightyTest->new();
++my $t;
++
++$tf->{CONFIGFILE} = 'lighttpd.conf';
++
++ok($tf->start_proc == 0, "Starting lighttpd") or die();
++
++## check if If-Modified-Since, If-None-Match works
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
++
++my $now = $t->{date};
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-Modified-Since: $now
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-Modified-Since: $now; foo
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-None-Match: foo
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
++
++my $etag = $t->{etag};
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-None-Match: $etag
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-None-Match: $etag
++If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-None-Match: $etag
++If-Modified-Since: $now; foo
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-None-Match: Foo
++If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
++
++$t->{REQUEST} = ( <<EOF
++GET / HTTP/1.0
++If-None-Match: $etag
++If-Modified-Since: $now foo
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
++ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
++
++ok($tf->stop_proc == 0, "Stopping lighttpd");
++
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/condition.conf lighttpd-1.4.12/tests/condition.conf
--- lighttpd-1.4.11/tests/condition.conf 2005-08-27 17:44:19.000000000 +0300
-+++ lighttpd/tests/condition.conf 2006-07-11 21:23:41.951971980 +0300
++++ lighttpd-1.4.12/tests/condition.conf 2006-07-11 21:23:41.000000000 +0300
@@ -2,15 +2,15 @@
debug.log-request-handling = "enable"
debug.log-condition-handling = "enable"
server.name = "test3.example.org"
url.redirect = ("^" => "/match_4")
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/core-keepalive.t lighttpd-1.4.12/tests/core-keepalive.t
--- lighttpd-1.4.11/tests/core-keepalive.t 2005-11-17 15:54:19.000000000 +0200
-+++ lighttpd/tests/core-keepalive.t 2006-07-11 21:23:41.939971229 +0300
++++ lighttpd-1.4.12/tests/core-keepalive.t 2006-07-11 21:23:41.000000000 +0300
@@ -40,7 +40,7 @@
GET /12345.txt HTTP/1.0
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/123/Makefile.in lighttpd-1.4.12/tests/docroot/123/Makefile.in
+--- lighttpd-1.4.11/tests/docroot/123/Makefile.in 2006-03-07 14:21:03.000000000 +0200
++++ lighttpd-1.4.12/tests/docroot/123/Makefile.in 2006-07-11 21:48:15.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -42,7 +42,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES =
+ SOURCES =
+@@ -100,7 +100,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -143,6 +142,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/Makefile.in lighttpd-1.4.12/tests/docroot/Makefile.in
+--- lighttpd-1.4.11/tests/docroot/Makefile.in 2006-03-07 14:21:04.000000000 +0200
++++ lighttpd-1.4.12/tests/docroot/Makefile.in 2006-07-11 21:48:15.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -42,7 +42,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES =
+ SOURCES =
+@@ -109,7 +109,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -152,6 +151,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/Makefile.in lighttpd-1.4.12/tests/docroot/www/Makefile.in
+--- lighttpd-1.4.11/tests/docroot/www/Makefile.in 2006-03-07 14:21:05.000000000 +0200
++++ lighttpd-1.4.12/tests/docroot/www/Makefile.in 2006-07-11 21:48:15.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -42,7 +42,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES =
+ SOURCES =
+@@ -109,7 +109,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -152,6 +151,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries
--- lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries 2006-03-09 19:21:49.000000000 +0200
-+++ lighttpd/tests/docroot/www/dummydir/.svn/entries 2006-07-11 21:23:41.575948429 +0300
++++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries 2006-07-11 21:23:41.000000000 +0300
@@ -9,5 +9,6 @@
last-author="jan"
kind="dir"
+ repos="svn://svn.lighttpd.net/lighttpd"
+ revision="1159"/>
</wc-entries>
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/expire/Makefile.in lighttpd-1.4.12/tests/docroot/www/expire/Makefile.in
+--- lighttpd-1.4.11/tests/docroot/www/expire/Makefile.in 2006-03-07 14:21:05.000000000 +0200
++++ lighttpd-1.4.12/tests/docroot/www/expire/Makefile.in 2006-07-11 21:48:15.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -42,7 +42,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES =
+ SOURCES =
+@@ -100,7 +100,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -143,6 +142,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/go/Makefile.in lighttpd-1.4.12/tests/docroot/www/go/Makefile.in
+--- lighttpd-1.4.11/tests/docroot/www/go/Makefile.in 2006-03-07 14:21:06.000000000 +0200
++++ lighttpd-1.4.12/tests/docroot/www/go/Makefile.in 2006-07-11 21:48:16.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -42,7 +42,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES =
+ SOURCES =
+@@ -100,7 +100,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -143,6 +142,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/indexfile/Makefile.in lighttpd-1.4.12/tests/docroot/www/indexfile/Makefile.in
+--- lighttpd-1.4.11/tests/docroot/www/indexfile/Makefile.in 2006-03-07 14:21:07.000000000 +0200
++++ lighttpd-1.4.12/tests/docroot/www/indexfile/Makefile.in 2006-07-11 21:48:16.000000000 +0300
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.9.5 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+@@ -42,7 +42,7 @@
+ am__aclocal_m4_deps = $(top_srcdir)/configure.in
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
++mkinstalldirs = $(install_sh) -d
+ CONFIG_HEADER = $(top_builddir)/config.h
+ CONFIG_CLEAN_FILES =
+ SOURCES =
+@@ -100,7 +100,6 @@
+ LIBTOOL = @LIBTOOL@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LUACONFIG = @LUACONFIG@
+ LUA_CFLAGS = @LUA_CFLAGS@
+ LUA_LIBS = @LUA_LIBS@
+ MAINT = @MAINT@
+@@ -143,6 +142,7 @@
+ ac_ct_F77 = @ac_ct_F77@
+ ac_ct_RANLIB = @ac_ct_RANLIB@
+ ac_ct_STRIP = @ac_ct_STRIP@
++ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fastcgi-10.conf lighttpd-1.4.12/tests/fastcgi-10.conf
--- lighttpd-1.4.11/tests/fastcgi-10.conf 2005-08-31 23:36:34.000000000 +0300
-+++ lighttpd/tests/fastcgi-10.conf 2006-07-11 21:23:41.911969475 +0300
++++ lighttpd-1.4.12/tests/fastcgi-10.conf 2006-07-11 21:23:41.000000000 +0300
@@ -1,12 +1,12 @@
-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
server.name = "zzz.example.org"
}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fastcgi-13.conf lighttpd-1.4.12/tests/fastcgi-13.conf
--- lighttpd-1.4.11/tests/fastcgi-13.conf 2006-01-03 12:38:17.000000000 +0200
-+++ lighttpd/tests/fastcgi-13.conf 2006-07-11 21:23:41.971973233 +0300
++++ lighttpd-1.4.12/tests/fastcgi-13.conf 2006-07-11 21:23:41.000000000 +0300
@@ -1,5 +1,5 @@
-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
server.name = "zzz.example.org"
}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fastcgi-auth.conf lighttpd-1.4.12/tests/fastcgi-auth.conf
--- lighttpd-1.4.11/tests/fastcgi-auth.conf 2005-08-27 17:44:19.000000000 +0300
-+++ lighttpd/tests/fastcgi-auth.conf 2006-07-11 21:23:42.003975238 +0300
++++ lighttpd-1.4.12/tests/fastcgi-auth.conf 2006-07-11 21:23:42.000000000 +0300
@@ -1,5 +1,5 @@
-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
server.name = "zzz.example.org"
}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fastcgi-responder.conf lighttpd-1.4.12/tests/fastcgi-responder.conf
--- lighttpd-1.4.11/tests/fastcgi-responder.conf 2005-08-27 17:44:19.000000000 +0300
-+++ lighttpd/tests/fastcgi-responder.conf 2006-07-11 21:23:41.999974987 +0300
++++ lighttpd-1.4.12/tests/fastcgi-responder.conf 2006-07-11 21:23:41.000000000 +0300
@@ -1,5 +1,5 @@
-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
server.name = "zzz.example.org"
}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fcgi-responder.c lighttpd-1.4.12/tests/fcgi-responder.c
--- lighttpd-1.4.11/tests/fcgi-responder.c 2005-08-11 01:26:55.000000000 +0300
-+++ lighttpd/tests/fcgi-responder.c 2006-07-11 21:23:41.979973734 +0300
++++ lighttpd-1.4.12/tests/fcgi-responder.c 2006-07-11 21:23:41.000000000 +0300
@@ -6,11 +6,17 @@
int main () {
int num_requests = 2;
- while (num_requests > 0 &&
- FCGI_Accept() >= 0) {
- char* p;
+-
+- if (NULL != (p = getenv("QUERY_STRING"))) {
+ while (num_requests > 0 && FCGI_Accept() >= 0) {
+ char* p = NULL;
+ char* doc_root = NULL;
+ char fname[4096];
+ char* pfname = (char *)fname;
-
-- if (NULL != (p = getenv("QUERY_STRING"))) {
++
+ doc_root = getenv("DOCUMENT_ROOT");
+ p = getenv("QUERY_STRING");
+
} else if (0 == strcmp(p, "die-at-end")) {
printf("Status: 200 OK\r\n\r\n");
num_requests--;
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/lighttpd.conf lighttpd-1.4.12/tests/lighttpd.conf
--- lighttpd-1.4.11/tests/lighttpd.conf 2006-03-09 15:26:58.000000000 +0200
-+++ lighttpd/tests/lighttpd.conf 2006-07-11 21:23:41.999974987 +0300
++++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-11 21:23:41.000000000 +0300
@@ -1,80 +1,18 @@
-debug.log-request-handling = "enable"
-debug.log-condition-handling = "enable"
-## bind to port (default: 80)
-server.port = 2048
--
++include "default.conf"
+
-## bind to localhost (default: all interfaces)
-server.bind = "localhost"
-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
-server.tag = "Apache 1.3.29"
-
-server.dir-listing = "enable"
-+include "default.conf"
-
+-
-#server.event-handler = "linux-sysepoll"
-#server.event-handler = "linux-rtsig"
-
simple-vhost.default-host = "www.example.org"
}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/lowercase.conf lighttpd-1.4.12/tests/lowercase.conf
+--- lighttpd-1.4.11/tests/lowercase.conf 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/tests/lowercase.conf 2006-07-11 21:23:41.000000000 +0300
+@@ -0,0 +1,80 @@
++server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
++server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
++
++## bind to port (default: 80)
++server.port = 2048
++
++## bind to localhost (default: all interfaces)
++server.bind = "localhost"
++server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
++
++server.force-lowercase-filenames = "enable"
++
++server.dir-listing = "enable"
++
++server.modules = (
++ "mod_rewrite",
++ "mod_setenv",
++ "mod_secdownload",
++ "mod_access",
++ "mod_auth",
++ "mod_status",
++ "mod_expire",
++ "mod_redirect",
++ "mod_fastcgi",
++ "mod_cgi" )
++
++server.indexfiles = ( "index.php", "index.html",
++ "index.htm", "default.htm" )
++
++
++######################## MODULE CONFIG ############################
++
++mimetype.assign = ( ".png" => "image/png",
++ ".jpg" => "image/jpeg",
++ ".jpeg" => "image/jpeg",
++ ".gif" => "image/gif",
++ ".html" => "text/html",
++ ".htm" => "text/html",
++ ".pdf" => "application/pdf",
++ ".swf" => "application/x-shockwave-flash",
++ ".spl" => "application/futuresplash",
++ ".txt" => "text/plain",
++ ".tar.gz" => "application/x-tgz",
++ ".tgz" => "application/x-tgz",
++ ".gz" => "application/x-gzip",
++ ".c" => "text/plain",
++ ".conf" => "text/plain" )
++
++fastcgi.debug = 0
++fastcgi.server = ( ".php" => ( ( "host" => "127.0.0.1", "port" => 1026, "broken-scriptfilename" => "enable" ) ),
++ "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
++ )
++
++
++cgi.assign = ( ".pl" => "/usr/bin/perl",
++ ".cgi" => "/usr/bin/perl",
++ ".py" => "/usr/bin/python" )
++
++auth.backend = "plain"
++auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
++
++auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
++
++$HTTP["host"] == "lowercase-auth" {
++ auth.require = ( "/image.jpg" =>
++ (
++ "method" => "digest",
++ "realm" => "download archiv",
++ "require" => "valid-user"
++ )
++ )
++}
++
++$HTTP["host"] == "lowercase-deny" {
++ url.access-deny = ( ".jpg")
++}
++
++$HTTP["host"] == "lowercase-exclude" {
++ static-file.exclude-extensions = ( ".jpg" )
++}
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/lowercase.t lighttpd-1.4.12/tests/lowercase.t
+--- lighttpd-1.4.11/tests/lowercase.t 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/tests/lowercase.t 2006-07-11 21:23:41.000000000 +0300
+@@ -0,0 +1,94 @@
++#!/usr/bin/env perl
++BEGIN {
++ # add current source dir to the include-path
++ # we need this for make distcheck
++ (my $srcdir = $0) =~ s#/[^/]+$#/#;
++ unshift @INC, $srcdir;
++}
++
++use strict;
++use IO::Socket;
++use Test::More tests => 10;
++use LightyTest;
++
++my $tf = LightyTest->new();
++my $t;
++
++$tf->{CONFIGFILE} = 'lowercase.conf';
++
++ok($tf->start_proc == 0, "Starting lighttpd") or die();
++
++## check if lower-casing works
++
++$t->{REQUEST} = ( <<EOF
++GET /image.JPG HTTP/1.0
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
++ok($tf->handle_http($t) == 0, 'uppercase access');
++
++$t->{REQUEST} = ( <<EOF
++GET /image.jpg HTTP/1.0
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
++ok($tf->handle_http($t) == 0, 'lowercase access');
++
++## check that mod-auth works
++
++$t->{REQUEST} = ( <<EOF
++GET /image.JPG HTTP/1.0
++Host: lowercase-auth
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
++ok($tf->handle_http($t) == 0, 'uppercase access');
++
++$t->{REQUEST} = ( <<EOF
++GET /image.jpg HTTP/1.0
++Host: lowercase-auth
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
++ok($tf->handle_http($t) == 0, 'lowercase access');
++
++
++## check that mod-staticfile exclude works
++$t->{REQUEST} = ( <<EOF
++GET /image.JPG HTTP/1.0
++Host: lowercase-exclude
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
++ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
++
++$t->{REQUEST} = ( <<EOF
++GET /image.jpg HTTP/1.0
++Host: lowercase-exclude
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
++ok($tf->handle_http($t) == 0, 'lowercase access');
++
++
++## check that mod-access exclude works
++$t->{REQUEST} = ( <<EOF
++GET /image.JPG HTTP/1.0
++Host: lowercase-deny
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
++ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
++
++$t->{REQUEST} = ( <<EOF
++GET /image.jpg HTTP/1.0
++Host: lowercase-deny
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
++ok($tf->handle_http($t) == 0, 'lowercase access');
++
++
++
++ok($tf->stop_proc == 0, "Stopping lighttpd");
++
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/mod-fastcgi.t lighttpd-1.4.12/tests/mod-fastcgi.t
--- lighttpd-1.4.11/tests/mod-fastcgi.t 2006-03-09 15:30:45.000000000 +0200
-+++ lighttpd/tests/mod-fastcgi.t 2006-07-11 21:23:41.995974736 +0300
++++ lighttpd-1.4.12/tests/mod-fastcgi.t 2006-07-11 21:23:41.000000000 +0300
@@ -7,7 +7,7 @@
}
ok($tf->start_proc == 0, "Starting lighttpd") or die();
+@@ -223,7 +223,7 @@
+ }
+
+ SKIP: {
+- skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
++ skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
+ $tf->{CONFIGFILE} = 'fastcgi-13.conf';
+ ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
+ $t->{REQUEST} = ( <<EOF
@@ -285,6 +285,34 @@
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
$t->{REQUEST} = ( <<EOF
GET /index.fcgi?die-at-end HTTP/1.0
Host: www.example.org
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/mod-proxy.t lighttpd-1.4.12/tests/mod-proxy.t
+--- lighttpd-1.4.11/tests/mod-proxy.t 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/tests/mod-proxy.t 2006-07-11 21:23:41.000000000 +0300
+@@ -0,0 +1,173 @@
++#!/usr/bin/env perl
++BEGIN {
++ # add current source dir to the include-path
++ # we need this for make distcheck
++ (my $srcdir = $0) =~ s#/[^/]+$#/#;
++ unshift @INC, $srcdir;
++}
++
++use strict;
++use IO::Socket;
++use Test::More tests => 21;
++use LightyTest;
++
++my $tf_proxy = LightyTest->new();
++my $tf_backend1 = LightyTest->new();
++my $tf_backend2 = LightyTest->new();
++
++my $t;
++
++## we need two procs
++## 1. the real webserver
++## 2. the proxy server
++
++$tf_proxy->{PORT} = 2048;
++$tf_proxy->{CONFIGFILE} = 'proxy.conf';
++$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
++
++$tf_backend1->{PORT} = 2050;
++$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
++$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
++
++$tf_backend2->{PORT} = 2051;
++$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
++$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
++
++
++ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
++
++ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
++
++sleep(1);
++
++$t->{REQUEST} = ( <<EOF
++GET /index.html HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
++ok($tf_proxy->handle_http($t) == 0, 'valid request');
++
++$t->{REQUEST} = ( <<EOF
++GET /index.html HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'proxy-backend-1' } ];
++ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-rr/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-rr/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-fair/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
++
++## backend 2 starting
++ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-rr/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-rr/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-hash/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-hash/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-hash/bar HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-hash/bar HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
++
++## backend 1 stopping, failover
++ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-hash/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-hash/bar HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-rr/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
++
++$t->{REQUEST} = ( <<EOF
++GET /balance-fair/foo HTTP/1.0
++Host: www.example.org
++EOF
++ );
++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
++ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
++
++
++ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
++
++ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
++
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/proxy.conf lighttpd-1.4.12/tests/proxy.conf
+--- lighttpd-1.4.11/tests/proxy.conf 1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-1.4.12/tests/proxy.conf 2006-07-11 21:23:42.000000000 +0300
+@@ -0,0 +1,26 @@
++server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
++server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
++server.tag = "proxy"
++
++include "default.conf"
++
++## 127.0.0.1 and 127.0.0.2 are the same host
++proxy.server = (
++ "" => (( "host" => "127.0.0.1",
++ "port" => 2050 ),
++ ( "host" => "127.0.0.2",
++ "port" => 2051 )
++ ))
++
++$HTTP["url"] =~ "^/balance-rr/" {
++ proxy.balance = "round-robin"
++}
++
++$HTTP["url"] =~ "^/balance-hash/" {
++ proxy.balance = "hash"
++}
++
++$HTTP["url"] =~ "^/balance-fair/" {
++ proxy.balance = "fair"
++}
++
+diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/var-include.conf lighttpd-1.4.12/tests/var-include.conf
--- lighttpd-1.4.11/tests/var-include.conf 2005-08-27 17:44:19.000000000 +0300
-+++ lighttpd/tests/var-include.conf 2006-07-11 21:23:41.943971479 +0300
++++ lighttpd-1.4.12/tests/var-include.conf 2006-07-11 21:23:41.000000000 +0300
@@ -2,15 +2,15 @@
debug.log-request-handling = "enable"
debug.log-condition-handling = "enable"