]> git.pld-linux.org Git - packages/lighttpd.git/blame - lighttpd-branch.diff
- svn 1173
[packages/lighttpd.git] / lighttpd-branch.diff
CommitLineData
1175ccec 1--- ../lighttpd-1.4.11/NEWS 2006-03-09 19:34:33.000000000 +0200
36e2a29e 2+++ lighttpd-1.4.12/NEWS 2006-07-11 22:07:54.000000000 +0300
f26f9fd5
ER
3@@ -3,6 +3,23 @@
4 NEWS
5 ====
6
7+- 1.4.12 - 2006-..-..
8+
9+ * added handling of Content-Range to PUT requests in mod_webdav
10+ * added handling of ETag and If-Modified-Since to mod_compress if
11+ cache-dir is not set
12+ * added experimental LOCK support for mod_webdav
13+ * added support for X-Sendfile as addition to X-LIGHTTPD-send-file.
14+ This allows compatibility with mod_xsendfile for apache
15+ (http://celebnamer.celebworld.ws/stuff/mod_xsendfile/)
16+ * fixed handling of If-Modified-Since if Etag is not set
17+ * fixed hanging fastcgi connections
18+ * fixed stalling SSL POST requests
19+ * fixed round-robin load-balancing in mod_proxy
20+ * TODO: add fail-over to mod-proxy
21+ * TODO: fix CACHE_HIT/MISS in mod_cml
22+ * TODO: finish LOCK/UNLOCK in mod_webdav
23+
24 - 1.4.11 - 2006-03-09
25
26 * added ability to specify which ip address spawn-fci listens on
1175ccec
ER
27--- ../lighttpd-1.4.11/configure.in 2006-03-04 16:32:38.000000000 +0200
28+++ lighttpd-1.4.12/configure.in 2006-07-15 22:43:22.000000000 +0300
f673a614
ER
29@@ -1,7 +1,7 @@
30 # -*- Autoconf -*-
31 # Process this file with autoconf to produce a configure script.
32 AC_PREREQ(2.57)
33-AC_INIT(lighttpd, 1.4.11, jan@kneschke.de)
34+AC_INIT(lighttpd, 1.4.12, jan@kneschke.de)
35 AC_CONFIG_SRCDIR([src/server.c])
36
37 AC_CANONICAL_TARGET
38@@ -66,7 +66,7 @@
39 AC_TYPE_PID_T
40 AC_TYPE_SIZE_T
41
42-AC_CHECK_MEMBER(struct tm.tm_gmtoff,AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm]),,[#include <time.h>])
43+AC_CHECK_MEMBER(struct tm.tm_gmtoff,[AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm])],,[#include <time.h>])
44 AC_CHECK_TYPES(struct sockaddr_storage,,,[#include <sys/socket.h>])
45 AC_CHECK_TYPES(socklen_t,,,[#include <sys/types.h>
46 #include <sys/socket.h>])
47@@ -339,6 +339,22 @@
48 AC_DEFINE([HAVE_SQLITE3], [1], [libsqlite3])
49 AC_DEFINE([HAVE_SQLITE3_H], [1], [sqlite3.h])
50 ])
51+
52+ AC_MSG_CHECKING(for locks in mod_webdav)
53+ AC_ARG_WITH(webdav-locks, AC_HELP_STRING([--with-webdav-locks],[locks in mod_webdav]),
54+ [WITH_WEBDAV_LOCKS=$withval],[WITH_WEBDAV_LOCKS=no])
55+ AC_MSG_RESULT([$WITH_WEBDAV_LOCKS])
56+
57+ if test "$WITH_WEBDAV_LOCKS" != "no"; then
58+ AC_CHECK_LIB(uuid, uuid_unparse, [
59+ AC_CHECK_HEADERS([uuid/uuid.h],[
60+ UUID_LIB=-luuid
61+ AC_DEFINE([HAVE_UUID], [1], [libuuid])
62+ AC_DEFINE([HAVE_UUID_H], [1], [uuid/uuid.h is available])
63+ ])
64+ ])
65+
66+ fi
67 fi
68
69 dnl Check for gdbm
1175ccec
ER
70@@ -381,30 +397,11 @@
71
72 AC_MSG_RESULT($WITH_LUA)
73 if test "$WITH_LUA" != "no"; then
74- AC_PATH_PROG(LUACONFIG, lua-config)
75-
76- if test x"$LUACONFIG" != x; then
77- LUA_CFLAGS=`$LUACONFIG --include`
78- LUA_LIBS=`$LUACONFIG --libs --extralibs`
79+ # try pkgconfig
80+ PKG_CHECK_MODULES(LUA, lua >= 5.1, [
81 AC_DEFINE([HAVE_LUA], [1], [liblua])
82 AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
83- else
84- AC_CHECK_LIB(lua, lua_open, [
85- AC_CHECK_HEADERS([lua.h],[
86- LUA_LIBS="-llua -llualib"
87- AC_DEFINE([HAVE_LUA], [1], [liblua])
88- AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
89- ])
90- ])
91- fi
92-
93- if test x"$LUA_LIBS" = x; then
94- # try pkgconfig
95- PKG_CHECK_MODULES(LUA, lua, [
96- AC_DEFINE([HAVE_LUA], [1], [liblua])
97- AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
98- ])
99- fi
100+ ])
101
102 AC_SUBST(LUA_CFLAGS)
103 AC_SUBST(LUA_LIBS)
104@@ -440,7 +437,7 @@
f673a614
ER
105 esac
106
107 AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
108- strdup strerror strstr strtol sendfile getopt socket \
109+ strdup strerror strstr strtol sendfile getopt socket lstat \
110 gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
111 getuid select signal pathconf madvise posix_fadvise posix_madvise \
112 writev sigaction sendfile64 send_file kqueue port_create localtime_r])
1175ccec 113@@ -538,7 +535,7 @@
f673a614
ER
114 AC_OUTPUT
115
116
117-do_build="mod_cgi mod_fastcgi mod_proxy mod_evhost mod_simple_vhost mod_access mod_alias mod_setenv mod_usertrack mod_auth mod_status mod_accesslog mod_rrdtool mod_secdownload mod_expire mod_compress mod_dirlisting mod_indexfiles mod_userdir mod_webdav mod_staticfile mod_scgi"
118+do_build="mod_cgi mod_fastcgi mod_proxy mod_evhost mod_simple_vhost mod_access mod_alias mod_setenv mod_usertrack mod_auth mod_status mod_accesslog mod_rrdtool mod_secdownload mod_expire mod_compress mod_dirlisting mod_indexfiles mod_userdir mod_webdav mod_staticfile mod_scgi mod_flv_streaming"
119
120 plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
121 features="regex-conditionals"
1175ccec 122@@ -642,6 +639,14 @@
f673a614
ER
123 disable_feature="$disable_feature $features"
124 fi
125
126+features="webdav-locks"
127+if test "x$UUID_LIB" \!= x; then
128+ enable_feature="$enable_feature $features"
129+else
130+ disable_feature="$disable_feature $features"
131+fi
132+
133+
134 ## output
135
136 $ECHO
1175ccec 137--- ../lighttpd-1.4.11/cygwin/lighttpd.README 2006-03-07 14:22:19.000000000 +0200
36e2a29e 138+++ lighttpd-1.4.12/cygwin/lighttpd.README 2006-07-11 22:08:04.000000000 +0300
2519e6e5
ER
139@@ -1,114 +1,114 @@
140-lighttpd\r
141-------------------------------------------\r
142-A fast, secure and flexible webserver\r
143-\r
144-Runtime requirements:\r
145- cygwin-1.5.10 or newer\r
146- crypt-1.1 or newer\r
147- libbz2_1-1.0.2 or newer\r
148- libpcre0-4.5 or newer\r
149- openssl-0.9.7d or newer\r
150- zlib-1.2.1 or newer\r
151-\r
152-Build requirements:\r
153- cygwin-1.5.10 or newer\r
154- gcc-3.3.1-3 or newer\r
155- binutils-20030901-1 or newer\r
156- crypt\r
157- openssl-devel\r
158- openssl\r
159- openldap\r
160- openldap-devel\r
161- zlib\r
162- bzip2\r
163-\r
164-Canonical homepage:\r
165- http://jan.kneschke.de/projects/lighttpd/\r
166-\r
167-Canonical download:\r
168- http://jan.kneschke.de/projects/lighttpd/download\r
169-\r
170-------------------------------------\r
171-\r
172-Build instructions:\r
173- unpack lighttpd-1.4.11-<REL>-src.tar.bz2\r
174- if you use setup to install this src package, it will be\r
175- unpacked under /usr/src automatically\r
176- cd /usr/src\r
177- ./lighttpd-1.4.11-<REL>.sh all\r
178-\r
179-This will create:\r
180- /usr/src/lighttpd-1.4.11-<REL>.tar.bz2\r
181- /usr/src/lighttpd-1.4.11-<REL>-src.tar.bz2\r
182-\r
183-Or use './lighttpd-1.4.11-<REL>.sh prep' to get a patched source directory\r
184-\r
185--------------------------------------------\r
186-\r
187-Files included in the binary distribution:\r
188-\r
189- /etc/lighttpd/lighttpd.conf.default\r
190- /usr/lib/cyglightcomp.dll\r
191- /usr/lib/lighttpd/mod_access.dll\r
192- /usr/lib/lighttpd/mod_accesslog.dll\r
193- /usr/lib/lighttpd/mod_auth.dll\r
194- /usr/lib/lighttpd/mod_cgi.dll\r
195- /usr/lib/lighttpd/mod_compress.dll\r
196- /usr/lib/lighttpd/mod_evhost.dll\r
197- /usr/lib/lighttpd/mod_expire.dll\r
198- /usr/lib/lighttpd/mod_fastcgi.dll\r
199- /usr/lib/lighttpd/mod_httptls.dll\r
200- /usr/lib/lighttpd/mod_maps.dll\r
201- /usr/lib/lighttpd/mod_proxy.dll\r
202- /usr/lib/lighttpd/mod_redirect.dll\r
203- /usr/lib/lighttpd/mod_rewrite.dll\r
204- /usr/lib/lighttpd/mod_rrdtool.dll\r
205- /usr/lib/lighttpd/mod_secdownload.dll\r
206- /usr/lib/lighttpd/mod_simple_vhost.dll\r
207- /usr/lib/lighttpd/mod_ssi.dll\r
208- /usr/lib/lighttpd/mod_status.dll\r
209- /usr/lib/lighttpd/mod_usertrack.dll\r
210- /usr/sbin/lighttpd.exe\r
211- /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
212- /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
213- /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
214- /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
215- /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
216- /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
217- /usr/share/doc/lighttpd-1.3.0/compress.txt\r
218- /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
219- /usr/share/doc/lighttpd-1.3.0/COPYING\r
220- /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
221- /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
222- /usr/share/doc/lighttpd-1.3.0/features.txt\r
223- /usr/share/doc/lighttpd-1.3.0/INSTALL\r
224- /usr/share/doc/lighttpd-1.3.0/NEWS\r
225- /usr/share/doc/lighttpd-1.3.0/performance.txt\r
226- /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
227- /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
228- /usr/share/doc/lighttpd-1.3.0/README\r
229- /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
230- /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
231- /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
232- /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
233- /usr/share/doc/lighttpd-1.3.0/security.txt\r
234- /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
235- /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
236- /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
237- /usr/share/doc/lighttpd-1.3.0/state.txt\r
238- /usr/share/man/man1/lighttpd.1.gz\r
239-\r
240-------------------\r
241-\r
242-Port Notes:\r
243-\r
244----------- lighttpd-1.3.1-1 -----------\r
245-\r
246-Updated to 1.3.1\r
247-\r
248----------- lighttpd-1.3.0-1 -----------\r
249-Initial release\r
250-\r
251-Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
252-Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
253-\r
254+lighttpd
255+------------------------------------------
256+A fast, secure and flexible webserver
257+
258+Runtime requirements:
259+ cygwin-1.5.10 or newer
260+ crypt-1.1 or newer
261+ libbz2_1-1.0.2 or newer
262+ libpcre0-4.5 or newer
263+ openssl-0.9.7d or newer
264+ zlib-1.2.1 or newer
265+
266+Build requirements:
267+ cygwin-1.5.10 or newer
268+ gcc-3.3.1-3 or newer
269+ binutils-20030901-1 or newer
270+ crypt
271+ openssl-devel
272+ openssl
273+ openldap
274+ openldap-devel
275+ zlib
276+ bzip2
277+
278+Canonical homepage:
279+ http://jan.kneschke.de/projects/lighttpd/
280+
281+Canonical download:
282+ http://jan.kneschke.de/projects/lighttpd/download
283+
284+------------------------------------
285+
286+Build instructions:
287+ unpack lighttpd-1.4.12-<REL>-src.tar.bz2
288+ if you use setup to install this src package, it will be
289+ unpacked under /usr/src automatically
290+ cd /usr/src
291+ ./lighttpd-1.4.12-<REL>.sh all
292+
293+This will create:
294+ /usr/src/lighttpd-1.4.12-<REL>.tar.bz2
295+ /usr/src/lighttpd-1.4.12-<REL>-src.tar.bz2
296+
297+Or use './lighttpd-1.4.12-<REL>.sh prep' to get a patched source directory
298+
299+-------------------------------------------
300+
301+Files included in the binary distribution:
302+
303+ /etc/lighttpd/lighttpd.conf.default
304+ /usr/lib/cyglightcomp.dll
305+ /usr/lib/lighttpd/mod_access.dll
306+ /usr/lib/lighttpd/mod_accesslog.dll
307+ /usr/lib/lighttpd/mod_auth.dll
308+ /usr/lib/lighttpd/mod_cgi.dll
309+ /usr/lib/lighttpd/mod_compress.dll
310+ /usr/lib/lighttpd/mod_evhost.dll
311+ /usr/lib/lighttpd/mod_expire.dll
312+ /usr/lib/lighttpd/mod_fastcgi.dll
313+ /usr/lib/lighttpd/mod_httptls.dll
314+ /usr/lib/lighttpd/mod_maps.dll
315+ /usr/lib/lighttpd/mod_proxy.dll
316+ /usr/lib/lighttpd/mod_redirect.dll
317+ /usr/lib/lighttpd/mod_rewrite.dll
318+ /usr/lib/lighttpd/mod_rrdtool.dll
319+ /usr/lib/lighttpd/mod_secdownload.dll
320+ /usr/lib/lighttpd/mod_simple_vhost.dll
321+ /usr/lib/lighttpd/mod_ssi.dll
322+ /usr/lib/lighttpd/mod_status.dll
323+ /usr/lib/lighttpd/mod_usertrack.dll
324+ /usr/sbin/lighttpd.exe
325+ /usr/share/doc/Cygwin/lighttpd-1.3.0.README
326+ /usr/share/doc/lighttpd-1.3.0/accesslog.txt
327+ /usr/share/doc/lighttpd-1.3.0/authentification.txt
328+ /usr/share/doc/lighttpd-1.3.0/AUTHORS
329+ /usr/share/doc/lighttpd-1.3.0/cgi.txt
330+ /usr/share/doc/lighttpd-1.3.0/ChangeLog
331+ /usr/share/doc/lighttpd-1.3.0/compress.txt
332+ /usr/share/doc/lighttpd-1.3.0/configuration.txt
333+ /usr/share/doc/lighttpd-1.3.0/COPYING
334+ /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
335+ /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
336+ /usr/share/doc/lighttpd-1.3.0/features.txt
337+ /usr/share/doc/lighttpd-1.3.0/INSTALL
338+ /usr/share/doc/lighttpd-1.3.0/NEWS
339+ /usr/share/doc/lighttpd-1.3.0/performance.txt
340+ /usr/share/doc/lighttpd-1.3.0/plugins.txt
341+ /usr/share/doc/lighttpd-1.3.0/proxy.txt
342+ /usr/share/doc/lighttpd-1.3.0/README
343+ /usr/share/doc/lighttpd-1.3.0/redirect.txt
344+ /usr/share/doc/lighttpd-1.3.0/rewrite.txt
345+ /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
346+ /usr/share/doc/lighttpd-1.3.0/secdownload.txt
347+ /usr/share/doc/lighttpd-1.3.0/security.txt
348+ /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
349+ /usr/share/doc/lighttpd-1.3.0/skeleton.txt
350+ /usr/share/doc/lighttpd-1.3.0/ssi.txt
351+ /usr/share/doc/lighttpd-1.3.0/state.txt
352+ /usr/share/man/man1/lighttpd.1.gz
353+
354+------------------
355+
356+Port Notes:
357+
358+---------- lighttpd-1.3.1-1 -----------
359+
360+Updated to 1.3.1
361+
362+---------- lighttpd-1.3.0-1 -----------
363+Initial release
364+
365+Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
366+Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
367+
1175ccec 368--- ../lighttpd-1.4.11/cygwin/lighttpd.README.in 2005-08-11 01:26:59.000000000 +0300
36e2a29e 369+++ lighttpd-1.4.12/cygwin/lighttpd.README.in 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
370@@ -1,114 +1,114 @@
371-lighttpd\r
372-------------------------------------------\r
373-A fast, secure and flexible webserver\r
374-\r
375-Runtime requirements:\r
376- cygwin-1.5.10 or newer\r
377- crypt-1.1 or newer\r
378- libbz2_1-1.0.2 or newer\r
379- libpcre0-4.5 or newer\r
380- openssl-0.9.7d or newer\r
381- zlib-1.2.1 or newer\r
382-\r
383-Build requirements:\r
384- cygwin-1.5.10 or newer\r
385- gcc-3.3.1-3 or newer\r
386- binutils-20030901-1 or newer\r
387- crypt\r
388- openssl-devel\r
389- openssl\r
390- openldap\r
391- openldap-devel\r
392- zlib\r
393- bzip2\r
394-\r
395-Canonical homepage:\r
396- http://jan.kneschke.de/projects/lighttpd/\r
397-\r
398-Canonical download:\r
399- http://jan.kneschke.de/projects/lighttpd/download\r
400-\r
401-------------------------------------\r
402-\r
403-Build instructions:\r
404- unpack lighttpd-@VERSION@-<REL>-src.tar.bz2\r
405- if you use setup to install this src package, it will be\r
406- unpacked under /usr/src automatically\r
407- cd /usr/src\r
408- ./lighttpd-@VERSION@-<REL>.sh all\r
409-\r
410-This will create:\r
411- /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2\r
412- /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2\r
413-\r
414-Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory\r
415-\r
416--------------------------------------------\r
417-\r
418-Files included in the binary distribution:\r
419-\r
420- /etc/lighttpd/lighttpd.conf.default\r
421- /usr/lib/cyglightcomp.dll\r
422- /usr/lib/lighttpd/mod_access.dll\r
423- /usr/lib/lighttpd/mod_accesslog.dll\r
424- /usr/lib/lighttpd/mod_auth.dll\r
425- /usr/lib/lighttpd/mod_cgi.dll\r
426- /usr/lib/lighttpd/mod_compress.dll\r
427- /usr/lib/lighttpd/mod_evhost.dll\r
428- /usr/lib/lighttpd/mod_expire.dll\r
429- /usr/lib/lighttpd/mod_fastcgi.dll\r
430- /usr/lib/lighttpd/mod_httptls.dll\r
431- /usr/lib/lighttpd/mod_maps.dll\r
432- /usr/lib/lighttpd/mod_proxy.dll\r
433- /usr/lib/lighttpd/mod_redirect.dll\r
434- /usr/lib/lighttpd/mod_rewrite.dll\r
435- /usr/lib/lighttpd/mod_rrdtool.dll\r
436- /usr/lib/lighttpd/mod_secdownload.dll\r
437- /usr/lib/lighttpd/mod_simple_vhost.dll\r
438- /usr/lib/lighttpd/mod_ssi.dll\r
439- /usr/lib/lighttpd/mod_status.dll\r
440- /usr/lib/lighttpd/mod_usertrack.dll\r
441- /usr/sbin/lighttpd.exe\r
442- /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
443- /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
444- /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
445- /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
446- /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
447- /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
448- /usr/share/doc/lighttpd-1.3.0/compress.txt\r
449- /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
450- /usr/share/doc/lighttpd-1.3.0/COPYING\r
451- /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
452- /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
453- /usr/share/doc/lighttpd-1.3.0/features.txt\r
454- /usr/share/doc/lighttpd-1.3.0/INSTALL\r
455- /usr/share/doc/lighttpd-1.3.0/NEWS\r
456- /usr/share/doc/lighttpd-1.3.0/performance.txt\r
457- /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
458- /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
459- /usr/share/doc/lighttpd-1.3.0/README\r
460- /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
461- /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
462- /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
463- /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
464- /usr/share/doc/lighttpd-1.3.0/security.txt\r
465- /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
466- /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
467- /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
468- /usr/share/doc/lighttpd-1.3.0/state.txt\r
469- /usr/share/man/man1/lighttpd.1.gz\r
470-\r
471-------------------\r
472-\r
473-Port Notes:\r
474-\r
475----------- lighttpd-1.3.1-1 -----------\r
476-\r
477-Updated to 1.3.1\r
478-\r
479----------- lighttpd-1.3.0-1 -----------\r
480-Initial release\r
481-\r
482-Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
483-Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
484-\r
485+lighttpd
486+------------------------------------------
487+A fast, secure and flexible webserver
488+
489+Runtime requirements:
490+ cygwin-1.5.10 or newer
491+ crypt-1.1 or newer
492+ libbz2_1-1.0.2 or newer
493+ libpcre0-4.5 or newer
494+ openssl-0.9.7d or newer
495+ zlib-1.2.1 or newer
496+
497+Build requirements:
498+ cygwin-1.5.10 or newer
499+ gcc-3.3.1-3 or newer
500+ binutils-20030901-1 or newer
501+ crypt
502+ openssl-devel
503+ openssl
504+ openldap
505+ openldap-devel
506+ zlib
507+ bzip2
508+
509+Canonical homepage:
510+ http://jan.kneschke.de/projects/lighttpd/
511+
512+Canonical download:
513+ http://jan.kneschke.de/projects/lighttpd/download
514+
515+------------------------------------
516+
517+Build instructions:
518+ unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
519+ if you use setup to install this src package, it will be
520+ unpacked under /usr/src automatically
521+ cd /usr/src
522+ ./lighttpd-@VERSION@-<REL>.sh all
523+
524+This will create:
525+ /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
526+ /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
527+
528+Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
529+
530+-------------------------------------------
531+
532+Files included in the binary distribution:
533+
534+ /etc/lighttpd/lighttpd.conf.default
535+ /usr/lib/cyglightcomp.dll
536+ /usr/lib/lighttpd/mod_access.dll
537+ /usr/lib/lighttpd/mod_accesslog.dll
538+ /usr/lib/lighttpd/mod_auth.dll
539+ /usr/lib/lighttpd/mod_cgi.dll
540+ /usr/lib/lighttpd/mod_compress.dll
541+ /usr/lib/lighttpd/mod_evhost.dll
542+ /usr/lib/lighttpd/mod_expire.dll
543+ /usr/lib/lighttpd/mod_fastcgi.dll
544+ /usr/lib/lighttpd/mod_httptls.dll
545+ /usr/lib/lighttpd/mod_maps.dll
546+ /usr/lib/lighttpd/mod_proxy.dll
547+ /usr/lib/lighttpd/mod_redirect.dll
548+ /usr/lib/lighttpd/mod_rewrite.dll
549+ /usr/lib/lighttpd/mod_rrdtool.dll
550+ /usr/lib/lighttpd/mod_secdownload.dll
551+ /usr/lib/lighttpd/mod_simple_vhost.dll
552+ /usr/lib/lighttpd/mod_ssi.dll
553+ /usr/lib/lighttpd/mod_status.dll
554+ /usr/lib/lighttpd/mod_usertrack.dll
555+ /usr/sbin/lighttpd.exe
556+ /usr/share/doc/Cygwin/lighttpd-1.3.0.README
557+ /usr/share/doc/lighttpd-1.3.0/accesslog.txt
558+ /usr/share/doc/lighttpd-1.3.0/authentification.txt
559+ /usr/share/doc/lighttpd-1.3.0/AUTHORS
560+ /usr/share/doc/lighttpd-1.3.0/cgi.txt
561+ /usr/share/doc/lighttpd-1.3.0/ChangeLog
562+ /usr/share/doc/lighttpd-1.3.0/compress.txt
563+ /usr/share/doc/lighttpd-1.3.0/configuration.txt
564+ /usr/share/doc/lighttpd-1.3.0/COPYING
565+ /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
566+ /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
567+ /usr/share/doc/lighttpd-1.3.0/features.txt
568+ /usr/share/doc/lighttpd-1.3.0/INSTALL
569+ /usr/share/doc/lighttpd-1.3.0/NEWS
570+ /usr/share/doc/lighttpd-1.3.0/performance.txt
571+ /usr/share/doc/lighttpd-1.3.0/plugins.txt
572+ /usr/share/doc/lighttpd-1.3.0/proxy.txt
573+ /usr/share/doc/lighttpd-1.3.0/README
574+ /usr/share/doc/lighttpd-1.3.0/redirect.txt
575+ /usr/share/doc/lighttpd-1.3.0/rewrite.txt
576+ /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
577+ /usr/share/doc/lighttpd-1.3.0/secdownload.txt
578+ /usr/share/doc/lighttpd-1.3.0/security.txt
579+ /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
580+ /usr/share/doc/lighttpd-1.3.0/skeleton.txt
581+ /usr/share/doc/lighttpd-1.3.0/ssi.txt
582+ /usr/share/doc/lighttpd-1.3.0/state.txt
583+ /usr/share/man/man1/lighttpd.1.gz
584+
585+------------------
586+
587+Port Notes:
588+
589+---------- lighttpd-1.3.1-1 -----------
590+
591+Updated to 1.3.1
592+
593+---------- lighttpd-1.3.0-1 -----------
594+Initial release
595+
596+Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
597+Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
598+
1175ccec 599--- ../lighttpd-1.4.11/doc/authentication.txt 2006-01-12 20:34:26.000000000 +0200
36e2a29e 600+++ lighttpd-1.4.12/doc/authentication.txt 2006-07-11 22:07:54.000000000 +0300
f26f9fd5
ER
601@@ -7,8 +7,8 @@
602 ----------------
603
604 :Author: Jan Kneschke
605-:Date: $Date$
606-:Revision: $Revision$
607+:Date: $Date$
608+:Revision: $Revision$
f673a614 609
f26f9fd5
ER
610 :abstract:
611 The auth module provides ...
1175ccec 612--- ../lighttpd-1.4.11/doc/compress.txt 2005-08-11 01:26:16.000000000 +0300
36e2a29e 613+++ lighttpd-1.4.12/doc/compress.txt 2006-07-11 22:07:54.000000000 +0300
f26f9fd5
ER
614@@ -22,12 +22,38 @@
615 ===========
f673a614 616
f26f9fd5
ER
617 Output compression reduces the network load and can improve the overall
618-throughput of the webserver.
619+throughput of the webserver. All major http-clients support compression by
620+announcing it in the Accept-Encoding header. This is used to negotiate the
621+most suitable compression method. We support deflate, gzip and bzip2.
622
623-Only static content is supported up to now.
624+deflate (RFC1950, RFC1951) and gzip (RFC1952) depend on zlib while bzip2
625+depends on libbzip2. bzip2 is only supported by lynx and some other console
626+text-browsers.
627
628-The server negotiates automaticly which compression method is used.
629-Supported are gzip, deflate, bzip.
630+Currently we limit to compression support to static files.
f673a614 631+
f26f9fd5
ER
632+Caching
633+-------
f673a614 634+
f26f9fd5
ER
635+mod_compress can stored compressed files on disk to optimized the compression
636+on a second request away. As soon as compress.cache-dir is set the files are
637+compressed.
f673a614 638+
f26f9fd5
ER
639+The names of the cache files are made of the filename, the compression method
640+and the etag associated to the file.
f673a614 641+
f26f9fd5
ER
642+Cleaning the cache is left to the user. A cron job deleting files older than
643+10 days should do fine.
f673a614 644+
f26f9fd5
ER
645+Limitations
646+-----------
f673a614 647+
f26f9fd5
ER
648+The module limits the compression of files to files larger than 128 Byte and
649+smaller than 128 MByte.
f673a614 650+
f26f9fd5
ER
651+The lower limit is set as small files tend to become larger by compressing due
652+to the compression headers, the upper limit is set to work sensable with
653+memory and cpu-time.
f673a614 654
f26f9fd5
ER
655 Options
656 =======
2519e6e5 657@@ -47,15 +73,28 @@
f26f9fd5 658 Default: not set, compress the file for every request
f673a614 659
f26f9fd5
ER
660 compress.filetype
661- mimetypes where might get compressed
662+ mimetypes which might get compressed
663
664 e.g.: ::
665
666 compress.filetype = ("text/plain", "text/html")
f673a614 667
f26f9fd5
ER
668+ Keep in mind that compressed JavaScript and CSS files are broken in some
669+ browsers.
f673a614 670+
f26f9fd5
ER
671 Default: not set
672
673+compress.max-file-size
674+ maximum size of the original file to be compressed kBytes.
f673a614 675+
f26f9fd5
ER
676+ This is meant to protect the server against DoSing as compressing large
677+ (let's say 1Gbyte) takes a lot of time and would delay the whole operation
678+ of the server.
2519e6e5 679
f26f9fd5 680+ There is a hard upper limit of 128Mbyte.
f673a614 681+
f26f9fd5 682+ Default: unlimited (== hard-limit of 128MByte)
2519e6e5 683+
f26f9fd5
ER
684 Compressing Dynamic Content
685 ===========================
2519e6e5 686
1175ccec 687--- ../lighttpd-1.4.11/doc/configuration.txt 2006-03-09 02:10:40.000000000 +0200
36e2a29e 688+++ lighttpd-1.4.12/doc/configuration.txt 2006-07-11 22:07:54.000000000 +0300
f26f9fd5
ER
689@@ -7,8 +7,8 @@
690 ------------
691
692 :Author: Jan Kneschke
693-:Date: $Date$
694-:Revision: $Revision$
695+:Date: $Date$
696+:Revision: $Revision$
f673a614 697
f26f9fd5
ER
698 :abstract:
699 the layout of the configuration file
700@@ -511,3 +511,10 @@
701
702 debug.log-request-handling
703 default: disabled
f673a614 704+
f26f9fd5
ER
705+debug.log-condition-handling
706+ default: disabled
f673a614 707+
f26f9fd5
ER
708+debug.log-condition-cache-handling
709+ for developers only
710+ default: disabled
1175ccec 711--- ../lighttpd-1.4.11/doc/fastcgi.txt 2006-02-16 17:03:52.000000000 +0200
36e2a29e 712+++ lighttpd-1.4.12/doc/fastcgi.txt 2006-07-11 22:07:54.000000000 +0300
f26f9fd5
ER
713@@ -144,8 +144,8 @@
714 PHP can extract PATH_INFO from it (default: disabled)
715 :"disable-time": time to wait before a disabled backend is checked
716 again
717- :"allow-x-send-file": controls if X-LIGHTTPD-send-file headers
718- are allowed
719+ :"allow-x-send-file": controls if X-LIGHTTPD-send-file and X-Sendfile
720+ headers are allowed
f673a614 721
f26f9fd5 722 If bin-path is set:
f673a614 723
1175ccec 724--- ../lighttpd-1.4.11/doc/lighttpd.conf 2006-03-04 14:41:12.000000000 +0200
36e2a29e 725+++ lighttpd-1.4.12/doc/lighttpd.conf 2006-07-11 22:07:54.000000000 +0300
2519e6e5
ER
726@@ -172,10 +172,11 @@
727 #dir-listing.activate = "enable"
728
729 ## enable debugging
730-#debug.log-request-header = "enable"
731-#debug.log-response-header = "enable"
732-#debug.log-request-handling = "enable"
733-#debug.log-file-not-found = "enable"
734+#debug.log-request-header = "enable"
735+#debug.log-response-header = "enable"
736+#debug.log-request-handling = "enable"
737+#debug.log-file-not-found = "enable"
f26f9fd5
ER
738+#debug.log-condition-handling = "enable"
739
740 ### only root can use these options
741 #
1175ccec 742--- ../lighttpd-1.4.11/doc/performance.txt 2006-02-02 13:01:08.000000000 +0200
36e2a29e 743+++ lighttpd-1.4.12/doc/performance.txt 2006-07-11 22:07:54.000000000 +0300
f26f9fd5
ER
744@@ -183,6 +183,8 @@
745
746 server.stat-cache-engine = "fam" # either fam, simple or disabled
747
748+See http://oss.sgi.com/projects/fam/faq.html for information about FAM.
749+See http://www.gnome.org/~veillard/gamin/overview.html for information about gamin.
750
751 Platform-Specific Notes
752 =======================
1175ccec 753--- ../lighttpd-1.4.11/doc/secdownload.txt 2005-12-20 15:58:58.000000000 +0200
36e2a29e 754+++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-11 22:07:54.000000000 +0300
f26f9fd5
ER
755@@ -118,7 +118,7 @@
756 $secret = "verysecret";
757 $uri_prefix = "/dl/";
758
759- # filename
760+ # filename, make sure it's started with a "/" or you'll get 404 in the browser
761 $f = "/secret-file.txt";
762
763 # current timestamp
1175ccec 764--- ../lighttpd-1.4.11/lighttpd.spec 2006-03-07 14:22:18.000000000 +0200
36e2a29e 765+++ lighttpd-1.4.12/lighttpd.spec 2006-07-11 22:07:58.000000000 +0300
2519e6e5
ER
766@@ -1,6 +1,6 @@
767 Summary: A fast webserver with minimal memory-footprint (lighttpd)
768 Name: lighttpd
769-Version: 1.4.11
770+Version: 1.4.12
771 Release: 1
772 Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
773 Packager: Jan Kneschke <jan@kneschke.de>
1175ccec 774--- ../lighttpd-1.4.11/openwrt/control 2006-03-07 14:22:19.000000000 +0200
36e2a29e 775+++ lighttpd-1.4.12/openwrt/control 2006-07-11 22:08:05.000000000 +0300
2519e6e5
ER
776@@ -1,8 +1,8 @@
777 Package: lighttpd
778-Version: 1.4.11
779+Version: 1.4.12
780 Architecture: mipsel
781 Maintainer: Jan Kneschke <jan@kneschke.de>
782-Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.11.tar.gz
783+Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.12.tar.gz
784 Section: net
785 Priority: optional
786 Depends:
1175ccec 787--- ../lighttpd-1.4.11/openwrt/lighttpd.mk 2006-03-07 14:22:19.000000000 +0200
36e2a29e 788+++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-11 22:08:05.000000000 +0300
2519e6e5
ER
789@@ -10,7 +10,7 @@
790
791 # For this example we'll use a fairly simple package that compiles easily
792 # and has sources available for download at sourceforge
793-LIGHTTPD=lighttpd-1.4.11
794+LIGHTTPD=lighttpd-1.4.12
795 LIGHTTPD_TARGET=.built
796 LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
797 LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
1175ccec
ER
798--- ../lighttpd-1.4.11/src/Makefile.am 2006-03-07 14:20:20.000000000 +0200
799+++ lighttpd-1.4.12/src/Makefile.am 2006-07-15 22:43:21.000000000 +0300
800@@ -16,18 +16,24 @@
801 else
802 configparser.y: lemon
803 mod_ssi_exprparser.y: lemon
804+http_resp_parser.y: lemon
805
806 configparser.c configparser.h: configparser.y
807 rm -f configparser.h
808- $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
809+ $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
810+
811+http_resp_parser.c http_resp_parser.h: http_resp_parser.y
812+ rm -f http_resp_parser.h
813+ $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
814
815 mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y
816 rm -f mod_ssi_exprparser.h
817- $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
818+ $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
819 endif
2519e6e5 820
1175ccec
ER
821 configfile.c: configparser.h
822 mod_ssi_expr.c: mod_ssi_exprparser.h
823+http_resp.c: http_resp_parser.h
2519e6e5 824
1175ccec
ER
825 common_src=buffer.c log.c \
826 keyvalue.c chunk.c \
827@@ -46,7 +52,7 @@
2519e6e5
ER
828 network_write.c network_linux_sendfile.c \
829 network_freebsd_sendfile.c network_writev.c \
830 network_solaris_sendfilev.c network_openssl.c \
831- splaytree.c
832+ splaytree.c http_resp.c http_resp_parser.c
1175ccec
ER
833
834 src = server.c response.c connections.c network.c \
835 configfile.c configparser.c request.c proc_open.c
836@@ -82,9 +88,9 @@
2519e6e5 837
1175ccec 838 lib_LTLIBRARIES += mod_webdav.la
2519e6e5
ER
839 mod_webdav_la_SOURCES = mod_webdav.c
840-mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
841+mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
842 mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
843-mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
844+mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
1175ccec
ER
845
846 lib_LTLIBRARIES += mod_cml.la
2519e6e5 847 mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
1175ccec 848@@ -103,6 +109,11 @@
2519e6e5
ER
849 mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
850 mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
1175ccec
ER
851
852+lib_LTLIBRARIES += mod_sql_vhost_core.la
2519e6e5
ER
853+mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
854+mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
855+mod_sql_vhost_core_la_LIBADD = $(common_libadd)
1175ccec
ER
856+
857 lib_LTLIBRARIES += mod_cgi.la
2519e6e5
ER
858 mod_cgi_la_SOURCES = mod_cgi.c
859 mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1175ccec 860@@ -240,7 +251,8 @@
2519e6e5
ER
861 mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
862 configparser.h mod_ssi_exprparser.h \
863 sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
864- splaytree.h proc_open.h
36e2a29e 865+ splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h \
1175ccec 866+ sys-files.h sys-process.h sys-strings.h http_resp_parser.h
2519e6e5 867
1175ccec
ER
868 DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
869
870@@ -267,4 +279,4 @@
871 #ajp_SOURCES = ajp.c
872
873 noinst_HEADERS = $(hdr)
874-EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c
875+EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c http_resp_parser.y
876--- ../lighttpd-1.4.11/src/array.c 2005-11-18 13:58:32.000000000 +0200
36e2a29e 877+++ lighttpd-1.4.12/src/array.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
878@@ -11,12 +11,12 @@
879
880 array *array_init(void) {
881 array *a;
882-
883+
884 a = calloc(1, sizeof(*a));
885 assert(a);
886-
887+
888 a->next_power_of_2 = 1;
889-
890+
891 return a;
892 }
893
894@@ -43,29 +43,29 @@
895 void array_free(array *a) {
896 size_t i;
897 if (!a) return;
898-
899+
900 if (!a->is_weakref) {
901 for (i = 0; i < a->size; i++) {
902 if (a->data[i]) a->data[i]->free(a->data[i]);
903 }
904 }
905-
906+
907 if (a->data) free(a->data);
908 if (a->sorted) free(a->sorted);
909-
910+
911 free(a);
912 }
913
914 void array_reset(array *a) {
915 size_t i;
916 if (!a) return;
917-
918+
919 if (!a->is_weakref) {
920 for (i = 0; i < a->used; i++) {
921 a->data[i]->reset(a->data[i]);
922 }
923 }
924-
925+
926 a->used = 0;
927 }
928
929@@ -84,20 +84,20 @@
930 static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
931 int ndx = -1;
932 int i, pos = 0;
933-
934+
935 if (key == NULL) return -1;
936-
937+
938 /* try to find the string */
939 for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
940 int cmp;
941-
942+
943 if (pos < 0) {
944 pos += i;
945 } else if (pos >= (int)a->used) {
946 pos -= i;
947 } else {
948 cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
949-
950+
951 if (cmp == 0) {
952 /* found */
953 ndx = a->sorted[pos];
954@@ -110,46 +110,46 @@
955 }
956 if (i == 0) break;
957 }
958-
959+
960 if (rndx) *rndx = pos;
961-
962+
963 return ndx;
964 }
965
966 data_unset *array_get_element(array *a, const char *key) {
967 int ndx;
968-
969+
970 if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
971 /* found, leave here */
972-
973+
974 return a->data[ndx];
975- }
976-
977+ }
978+
979 return NULL;
980 }
981
982 data_unset *array_get_unused_element(array *a, data_type_t t) {
983 data_unset *ds = NULL;
984-
985+
986 UNUSED(t);
987
988 if (a->size == 0) return NULL;
989-
990+
991 if (a->used == a->size) return NULL;
992
993 if (a->data[a->used]) {
994 ds = a->data[a->used];
995-
996+
997 a->data[a->used] = NULL;
998 }
999-
1000+
1001 return ds;
1002 }
1003
1004 /* replace or insert data, return the old one with the same key */
1005 data_unset *array_replace(array *a, data_unset *du) {
1006 int ndx;
1007-
1008+
1009 if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
1010 array_insert_unique(a, du);
1011 return NULL;
1012@@ -164,13 +164,13 @@
1013 int ndx = -1;
f26f9fd5
ER
1014 int pos = 0;
1015 size_t j;
2519e6e5 1016-
f26f9fd5 1017- /* generate unique index if neccesary */
2519e6e5 1018+
f26f9fd5
ER
1019+ /* generate unique index if necessary */
1020 if (str->key->used == 0 || str->is_index_key) {
1021 buffer_copy_long(str->key, a->unique_ndx++);
1022 str->is_index_key = 1;
2519e6e5
ER
1023 }
1024-
1025+
1026 /* try to find the string */
1027 if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
1028 /* found, leave here */
1029@@ -181,14 +181,14 @@
1030 }
1031 return 0;
1032 }
1033-
1034+
1035 /* insert */
1036-
1037+
1038 if (a->used+1 > INT_MAX) {
1039 /* we can't handle more then INT_MAX entries: see array_get_index() */
1040 return -1;
1041 }
1042-
1043+
1044 if (a->size == 0) {
1045 a->size = 16;
1046 a->data = malloc(sizeof(*a->data) * a->size);
1047@@ -204,27 +204,27 @@
1048 assert(a->sorted);
1049 for (j = a->used; j < a->size; j++) a->data[j] = NULL;
1050 }
1051-
1052+
1053 ndx = (int) a->used;
1054-
1055+
1056 a->data[a->used++] = str;
1057-
1058+
1059 if (pos != ndx &&
1060- ((pos < 0) ||
1061+ ((pos < 0) ||
1062 buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
f26f9fd5 1063 pos++;
2519e6e5
ER
1064- }
1065-
f26f9fd5 1066- /* move everything on step to the right */
2519e6e5
ER
1067+ }
1068+
f26f9fd5
ER
1069+ /* move everything one step to the right */
1070 if (pos != ndx) {
1071 memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
f673a614 1072 }
2519e6e5
ER
1073-
1074+
1075 /* insert */
1076 a->sorted[pos] = ndx;
1077-
1078+
1079 if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
1080-
1081+
1082 return 0;
1083 }
1084
1085@@ -254,7 +254,7 @@
1086 size_t i;
1087 size_t maxlen;
1088 int oneline = 1;
1089-
1090+
1091 if (a->used > 5) {
1092 oneline = 0;
1093 }
1094@@ -314,7 +314,7 @@
1095 }
1096 array_print_indent(depth);
1097 fprintf(stderr, ")");
1098-
1099+
1100 return 0;
1101 }
1102
1103@@ -323,47 +323,47 @@
1104 array *a;
1105 data_string *ds;
1106 data_count *dc;
1107-
1108+
1109 UNUSED(argc);
1110 UNUSED(argv);
1111
1112 a = array_init();
1113-
1114+
1115 ds = data_string_init();
1116 buffer_copy_string(ds->key, "abc");
1117 buffer_copy_string(ds->value, "alfrag");
1118-
1119+
1120 array_insert_unique(a, (data_unset *)ds);
1121-
1122+
1123 ds = data_string_init();
1124 buffer_copy_string(ds->key, "abc");
1125 buffer_copy_string(ds->value, "hameplman");
1126-
1127+
1128 array_insert_unique(a, (data_unset *)ds);
1129-
1130+
1131 ds = data_string_init();
1132 buffer_copy_string(ds->key, "123");
1133 buffer_copy_string(ds->value, "alfrag");
1134-
1135+
1136 array_insert_unique(a, (data_unset *)ds);
1137-
1138+
1139 dc = data_count_init();
1140 buffer_copy_string(dc->key, "def");
1141-
1142+
1143 array_insert_unique(a, (data_unset *)dc);
1144-
1145+
1146 dc = data_count_init();
1147 buffer_copy_string(dc->key, "def");
1148-
1149+
1150 array_insert_unique(a, (data_unset *)dc);
1151-
1152+
1153 array_print(a, 0);
1154-
1155+
1156 array_free(a);
1157-
1158+
1159 fprintf(stderr, "%d\n",
1160 buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
1161-
1162+
1163 return 0;
1164 }
1165 #endif
1175ccec 1166--- ../lighttpd-1.4.11/src/array.h 2005-09-23 21:24:18.000000000 +0300
36e2a29e 1167+++ lighttpd-1.4.12/src/array.h 2006-07-11 22:07:51.000000000 +0300
f26f9fd5
ER
1168@@ -16,7 +16,7 @@
1169 #define DATA_UNSET \
1170 data_type_t type; \
1171 buffer *key; \
1172- int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
1173+ int is_index_key; /* 1 if key is an array index (auto-generated keys) */ \
1174 struct data_unset *(*copy)(const struct data_unset *src); \
1175 void (* free)(struct data_unset *p); \
1176 void (* reset)(struct data_unset *p); \
2519e6e5
ER
1177@@ -29,21 +29,21 @@
1178
1179 typedef struct {
1180 data_unset **data;
1181-
1182+
1183 size_t *sorted;
1184-
1185+
1186 size_t used;
1187 size_t size;
1188-
1189+
1190 size_t unique_ndx;
1191-
1192+
1193 size_t next_power_of_2;
1194 int is_weakref; /* data is weakref, don't bother the data */
1195 } array;
1196
1197 typedef struct {
1198 DATA_UNSET;
1199-
1200+
1201 int count;
1202 } data_count;
1203
1204@@ -51,7 +51,7 @@
1205
1206 typedef struct {
1207 DATA_UNSET;
1208-
1209+
1210 buffer *value;
1211 } data_string;
1212
1213@@ -60,7 +60,7 @@
1214
1215 typedef struct {
1216 DATA_UNSET;
1217-
1218+
1219 array *value;
1220 } data_array;
1221
1222@@ -74,7 +74,7 @@
1223 COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP
1224 } comp_key_t;
1225
1226-/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
1227+/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
1228 * for print: comp_key op string
1229 * for compare: comp cond string/regex
1230 */
1231@@ -82,15 +82,15 @@
1232 typedef struct _data_config data_config;
1233 struct _data_config {
1234 DATA_UNSET;
1235-
1236+
1237 array *value;
1238-
1239+
1240 buffer *comp_key;
1241 comp_key_t comp;
1242-
1243+
1244 config_cond_t cond;
1245 buffer *op;
1246-
1247+
1248 int context_ndx; /* more or less like an id */
1249 array *childs;
1250 /* nested */
1251@@ -98,7 +98,7 @@
1252 /* for chaining only */
1253 data_config *prev;
1254 data_config *next;
1255-
1256+
1257 buffer *string;
1258 #ifdef HAVE_PCRE_H
1259 pcre *regex;
1260@@ -110,7 +110,7 @@
1261
1262 typedef struct {
1263 DATA_UNSET;
1264-
1265+
1266 int value;
1267 } data_integer;
1268
1269@@ -120,13 +120,13 @@
1270 DATA_UNSET;
1271
1272 buffer *host;
1273-
1274+
1275 unsigned short port;
1276
1277 time_t disable_ts;
1278 int is_disabled;
1279 size_t balance;
1280-
1281+
1282 int usage; /* fair-balancing needs the no. of connections active on this host */
1283 int last_used_ndx; /* round robin */
1284 } data_fastcgi;
1175ccec
ER
1285--- ../lighttpd-1.4.11/src/base.h 2006-01-11 16:51:04.000000000 +0200
1286+++ lighttpd-1.4.12/src/base.h 2006-07-15 22:43:21.000000000 +0300
f26f9fd5
ER
1287@@ -2,7 +2,6 @@
1288 #define _BASE_H_
1289
1290 #include <sys/types.h>
1291-#include <sys/time.h>
1292 #include <sys/stat.h>
1293
1294 #ifdef HAVE_CONFIG_H
2519e6e5 1295@@ -26,10 +25,9 @@
f26f9fd5
ER
1296 #include "sys-socket.h"
1297 #include "splaytree.h"
1298
1299-
1300 #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
1301 # define USE_OPENSSL
2519e6e5
ER
1302-# include <openssl/ssl.h>
1303+# include <openssl/ssl.h>
1304 #endif
1305
1306 #ifdef HAVE_FAM_H
f26f9fd5
ER
1307@@ -40,10 +38,6 @@
1308 # define O_BINARY 0
f673a614 1309 #endif
f673a614 1310
f26f9fd5
ER
1311-#ifndef O_LARGEFILE
1312-# define O_LARGEFILE 0
1313-#endif
1314-
1315 #ifndef SIZE_MAX
1316 # ifdef SIZE_T_MAX
1317 # define SIZE_MAX SIZE_T_MAX
1318@@ -70,7 +64,8 @@
f673a614 1319
f26f9fd5
ER
1320 /* solaris and NetBSD 1.3.x again */
1321 #if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t))
1322-# define uint32_t u_int32_t
1175ccec 1323+/* # define uint32_t u_int32_t */
f26f9fd5
ER
1324+typedef unsigned __int32 uint32_t;
1325 #endif
f673a614 1326
f673a614 1327
2519e6e5
ER
1328@@ -80,24 +75,24 @@
1329
1330 #include "settings.h"
1331
1332-typedef enum { T_CONFIG_UNSET,
1333- T_CONFIG_STRING,
1334- T_CONFIG_SHORT,
1335- T_CONFIG_BOOLEAN,
1336- T_CONFIG_ARRAY,
1337- T_CONFIG_LOCAL,
1338+typedef enum { T_CONFIG_UNSET,
1339+ T_CONFIG_STRING,
1340+ T_CONFIG_SHORT,
1341+ T_CONFIG_BOOLEAN,
1342+ T_CONFIG_ARRAY,
1343+ T_CONFIG_LOCAL,
1344 T_CONFIG_DEPRECATED
1345 } config_values_type_t;
1346
1347-typedef enum { T_CONFIG_SCOPE_UNSET,
1348- T_CONFIG_SCOPE_SERVER,
1349+typedef enum { T_CONFIG_SCOPE_UNSET,
1350+ T_CONFIG_SCOPE_SERVER,
1351 T_CONFIG_SCOPE_CONNECTION
1352 } config_scope_type_t;
f673a614 1353
f26f9fd5 1354 typedef struct {
2519e6e5
ER
1355 const char *key;
1356 void *destination;
1357-
1358+
1359 config_values_type_t type;
1360 config_scope_type_t scope;
1361 } config_values_t;
1175ccec
ER
1362@@ -118,18 +113,6 @@
1363 short factor;
1364 } fcgi_connections;
1365
1366-
1367-typedef union {
1368-#ifdef HAVE_IPV6
1369- struct sockaddr_in6 ipv6;
1370-#endif
1371- struct sockaddr_in ipv4;
1372-#ifdef HAVE_SYS_UN_H
1373- struct sockaddr_un un;
1374-#endif
1375- struct sockaddr plain;
1376-} sock_addr;
1377-
1378 /* fcgi_response_header contains ... */
1379 #define HTTP_STATUS BV(0)
1380 #define HTTP_CONNECTION BV(1)
1381@@ -142,40 +125,40 @@
2519e6e5
ER
1382 /* the request-line */
1383 buffer *request;
1384 buffer *uri;
1385-
1386+
1387 buffer *orig_uri;
1388-
1389+
1390 http_method_t http_method;
1391 http_version_t http_version;
1392-
1393+
1394 buffer *request_line;
1395-
1396+
1397 /* strings to the header */
1398 buffer *http_host; /* not alloced */
1399 const char *http_range;
1400 const char *http_content_type;
1401 const char *http_if_modified_since;
1402 const char *http_if_none_match;
1403-
1404+
f26f9fd5 1405 array *headers;
2519e6e5
ER
1406-
1407+
1408 /* CONTENT */
1409 size_t content_length; /* returned by strtoul() */
1410-
1411+
1412 /* internal representation */
1413 int accept_encoding;
1414-
1415+
1416 /* internal */
1417 buffer *pathinfo;
1418 } request;
1419
1420 typedef struct {
1421 off_t content_length;
1422- int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */
1423-
1424+ int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
1425+
1426 array *headers;
1427-
1428- enum {
1429+
1430+ enum {
1431 HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
1432 } transfer_encoding;
1433 } response;
1175ccec 1434@@ -191,21 +174,21 @@
2519e6e5
ER
1435 typedef struct {
1436 buffer *path;
1437 buffer *basedir; /* path = "(basedir)(.*)" */
1438-
1439+
1440 buffer *doc_root; /* path = doc_root + rel_path */
1441 buffer *rel_path;
1442-
1443+
1444 buffer *etag;
1445 } physical;
1446
1447 typedef struct {
1448 buffer *name;
1449 buffer *etag;
1450-
1451+
1452 struct stat st;
1453-
1454+
1455 time_t stat_ts;
1456-
1457+
1458 #ifdef HAVE_FAM_H
1459 int dir_version;
1460 int dir_ndx;
1175ccec 1461@@ -215,8 +198,8 @@
f26f9fd5
ER
1462 } stat_cache_entry;
1463
1464 typedef struct {
1465- splay_tree *files; /* the nodes of the tree are stat_cache_entry's */
2519e6e5 1466-
f26f9fd5 1467+ splay_tree *files; /* the nodes of the tree are stat_cache_entries */
2519e6e5 1468+
f26f9fd5
ER
1469 buffer *dir_name; /* for building the dirname from the filename */
1470 #ifdef HAVE_FAM_H
2519e6e5 1471 splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */
1175ccec 1472@@ -228,7 +211,7 @@
2519e6e5
ER
1473
1474 typedef struct {
1475 array *mimetypes;
1476-
1477+
1478 /* virtual-servers */
1479 buffer *document_root;
1480 buffer *server_name;
1175ccec 1481@@ -236,7 +219,7 @@
2519e6e5
ER
1482 buffer *server_tag;
1483 buffer *dirlist_encoding;
1484 buffer *errorfile_prefix;
1485-
1486+
1487 unsigned short max_keep_alive_requests;
1488 unsigned short max_keep_alive_idle;
1489 unsigned short max_read_idle;
1175ccec 1490@@ -244,16 +227,17 @@
2519e6e5
ER
1491 unsigned short use_xattr;
1492 unsigned short follow_symlink;
1493 unsigned short range_requests;
1494-
1495+
1496 /* debug */
1497-
1498+
1499 unsigned short log_file_not_found;
1500 unsigned short log_request_header;
f26f9fd5
ER
1501 unsigned short log_request_handling;
1502 unsigned short log_response_header;
1503 unsigned short log_condition_handling;
2519e6e5
ER
1504-
1505-
f26f9fd5 1506+ unsigned short log_condition_cache_handling;
2519e6e5
ER
1507+
1508+
f26f9fd5 1509 /* server wide */
2519e6e5
ER
1510 buffer *ssl_pemfile;
1511 buffer *ssl_ca_file;
1175ccec 1512@@ -268,22 +252,22 @@
2519e6e5
ER
1513 /* configside */
1514 unsigned short global_kbytes_per_second; /* */
1515
1516- off_t global_bytes_per_second_cnt;
1517+ off_t global_bytes_per_second_cnt;
f26f9fd5 1518 /* server-wide traffic-shaper
2519e6e5
ER
1519- *
1520+ *
f26f9fd5
ER
1521 * each context has the counter which is inited once
1522- * a second by the global_kbytes_per_second config-var
1523+ * per second by the global_kbytes_per_second config-var
1524 *
1525 * as soon as global_kbytes_per_second gets below 0
1526 * the connected conns are "offline" a little bit
1527 *
1528 * the problem:
1529- * we somehow have to loose our "we are writable" signal
1530+ * we somehow have to lose our "we are writable" signal
1531 * on the way.
2519e6e5
ER
1532- *
1533+ *
f26f9fd5 1534 */
2519e6e5
ER
1535 off_t *global_bytes_per_second_cnt_ptr; /* */
1536-
1537+
1538 #ifdef USE_OPENSSL
1539 SSL_CTX *ssl_ctx;
1540 #endif
1175ccec 1541@@ -291,18 +275,18 @@
2519e6e5
ER
1542
1543 /* the order of the items should be the same as they are processed
1544 * read before write as we use this later */
1545-typedef enum {
1546- CON_STATE_CONNECT,
1547- CON_STATE_REQUEST_START,
1548- CON_STATE_READ,
1549- CON_STATE_REQUEST_END,
1550- CON_STATE_READ_POST,
1551- CON_STATE_HANDLE_REQUEST,
1552- CON_STATE_RESPONSE_START,
1553- CON_STATE_WRITE,
1554- CON_STATE_RESPONSE_END,
1555- CON_STATE_ERROR,
1556- CON_STATE_CLOSE
1557+typedef enum {
1558+ CON_STATE_CONNECT,
1559+ CON_STATE_REQUEST_START,
1560+ CON_STATE_READ,
1561+ CON_STATE_REQUEST_END,
1562+ CON_STATE_READ_POST,
1563+ CON_STATE_HANDLE_REQUEST,
1564+ CON_STATE_RESPONSE_START,
1565+ CON_STATE_WRITE,
1566+ CON_STATE_RESPONSE_END,
1567+ CON_STATE_ERROR,
1568+ CON_STATE_CLOSE
1569 } connection_state_t;
1570
1571 typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
1175ccec 1572@@ -315,88 +299,88 @@
2519e6e5
ER
1573
1574 typedef struct {
1575 connection_state_t state;
1576-
1577+
1578 /* timestamps */
1579 time_t read_idle_ts;
1580 time_t close_timeout_ts;
1581 time_t write_request_ts;
1582-
1583+
1584 time_t connection_start;
1585 time_t request_start;
1586-
1587+
1588 struct timeval start_tv;
1589-
1590+
1591 size_t request_count; /* number of requests handled in this connection */
1592 size_t loops_per_request; /* to catch endless loops in a single request
1593- *
1594+ *
1595 * used by mod_rewrite, mod_fastcgi, ... and others
1596 * this is self-protection
1597 */
1598-
1599+
1600 int fd; /* the FD for this connection */
1601 int fde_ndx; /* index for the fdevent-handler */
1602 int ndx; /* reverse mapping to server->connection[ndx] */
1603-
1604+
1605 /* fd states */
f26f9fd5
ER
1606 int is_readable;
1607 int is_writable;
2519e6e5 1608-
f26f9fd5 1609- int keep_alive; /* only request.c can enable it, all other just disable */
2519e6e5
ER
1610-
1611+
f26f9fd5 1612+ int keep_alive; /* only request.c can enable it, all others just disable */
2519e6e5 1613+
f26f9fd5
ER
1614 int file_started;
1615 int file_finished;
2519e6e5
ER
1616-
1617+
1618 chunkqueue *write_queue; /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
1619 chunkqueue *read_queue; /* a small queue for low-level read ( HTTP request ) [ mem ] */
1620 chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/
1621-
1622+
1623 int traffic_limit_reached;
1624-
1625+
1626 off_t bytes_written; /* used by mod_accesslog, mod_rrd */
1627 off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */
1628 off_t bytes_read; /* used by mod_accesslog, mod_rrd */
1629 off_t bytes_header;
1630-
1631+
1632 int http_status;
1633-
1634+
1635 sock_addr dst_addr;
1636 buffer *dst_addr_buf;
1637
1638 /* request */
1639 buffer *parse_request;
1640 unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */
1641-
1642+
1643 request request;
1644 request_uri uri;
1645- physical physical;
1646+ physical physical;
1647 response response;
1648-
1649+
1650 size_t header_len;
1651-
1652+
1653 buffer *authed_user;
1654 array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
1655-
1656+
1657 /* response */
1658 int got_response;
1659-
1660+
1661 int in_joblist;
1662-
1663+
1664 connection_type mode;
1665-
1666+
1667 void **plugin_ctx; /* plugin connection specific config */
1668-
1669+
1670 specific_config conf; /* global connection specific config */
1671 cond_cache_t *cond_cache;
1672-
1673+
1674 buffer *server_name;
1675-
1676+
1677 /* error-handler */
1678 buffer *error_handler;
1679 int error_handler_saved_status;
1680 int in_error_handler;
1681-
1682+
1683 void *srv_socket; /* reference to the server-socket (typecast to server_socket) */
1684-
1685+
1686 #ifdef USE_OPENSSL
1687 SSL *ssl;
1688 #endif
1175ccec 1689@@ -439,39 +423,48 @@
f26f9fd5
ER
1690 size_t size;
1691 } buffer_plugin;
1692
1693+typedef enum {
1694+ NETWORK_STATUS_UNSET,
1695+ NETWORK_STATUS_SUCCESS,
1696+ NETWORK_STATUS_FATAL_ERROR,
1697+ NETWORK_STATUS_CONNECTION_CLOSE,
1698+ NETWORK_STATUS_WAIT_FOR_EVENT,
1699+ NETWORK_STATUS_INTERRUPTED
1700+} network_status_t;
f673a614 1701+
f26f9fd5
ER
1702 typedef struct {
1703 unsigned short port;
1704 buffer *bindhost;
2519e6e5
ER
1705-
1706+
1707 buffer *errorlog_file;
1708 unsigned short errorlog_use_syslog;
1709-
1710+
1711 unsigned short dont_daemonize;
1712 buffer *changeroot;
1713 buffer *username;
1714 buffer *groupname;
1715-
1716+
1717 buffer *pid_file;
1718-
1719+
1720 buffer *event_handler;
1721-
1722+
1723 buffer *modules_dir;
1724 buffer *network_backend;
1725 array *modules;
1726 array *upload_tempdirs;
1727-
1728+
1729 unsigned short max_worker;
1730 unsigned short max_fds;
1731 unsigned short max_conns;
1732 unsigned short max_request_size;
1733-
1734+
1735 unsigned short log_request_header_on_error;
1736 unsigned short log_state_handling;
1737-
1738- enum { STAT_CACHE_ENGINE_UNSET,
1739- STAT_CACHE_ENGINE_NONE,
1740- STAT_CACHE_ENGINE_SIMPLE,
1741- STAT_CACHE_ENGINE_FAM
1742+
1743+ enum { STAT_CACHE_ENGINE_UNSET,
1744+ STAT_CACHE_ENGINE_NONE,
1745+ STAT_CACHE_ENGINE_SIMPLE,
1746+ STAT_CACHE_ENGINE_FAM
1747 } stat_cache_engine;
1748 unsigned short enable_cores;
1749 } server_config;
1175ccec 1750@@ -480,14 +473,14 @@
2519e6e5
ER
1751 sock_addr addr;
1752 int fd;
1753 int fde_ndx;
1754-
1755+
1756 buffer *ssl_pemfile;
1757 buffer *ssl_ca_file;
1758 unsigned short use_ipv6;
1759 unsigned short is_ssl;
1760-
1761+
1762 buffer *srv_token;
1763-
1764+
1765 #ifdef USE_OPENSSL
1766 SSL_CTX *ssl_ctx;
1767 #endif
1175ccec 1768@@ -495,37 +488,37 @@
2519e6e5
ER
1769
1770 typedef struct {
1771 server_socket **ptr;
1772-
1773+
1774 size_t size;
1775 size_t used;
1776 } server_socket_array;
1777
1778 typedef struct server {
1779 server_socket_array srv_sockets;
1780-
1781+
1782 /* the errorlog */
1783 int errorlog_fd;
1784 enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
1785 buffer *errorlog_buf;
1786-
1787+
1788 fdevents *ev, *ev_ins;
1789-
1790+
1791 buffer_plugin plugins;
1792 void *plugin_slots;
1793-
1794+
1795 /* counters */
1796 int con_opened;
1797 int con_read;
1798 int con_written;
1799 int con_closed;
1800-
1801+
1802 int ssl_is_init;
1803-
1804+
1805 int max_fds; /* max possible fds */
1806 int cur_fds; /* currently used fds */
1807 int want_fds; /* waiting fds */
1808 int sockets_disabled;
1809-
1810+
1811 size_t max_conns;
1812
1813 /* buffers */
1175ccec 1814@@ -533,13 +526,13 @@
2519e6e5
ER
1815 buffer *response_header;
1816 buffer *response_range;
1817 buffer *tmp_buf;
1818-
1819+
1820 buffer *tmp_chunk_len;
1821-
1822+
1823 buffer *empty_string; /* is necessary for cond_match */
1824
1825 buffer *cond_check_buf;
1826-
1827+
1828 /* caches */
1829 #ifdef HAVE_IPV6
1830 inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
1175ccec 1831@@ -547,31 +540,31 @@
2519e6e5
ER
1832 mtime_cache_type mtime_cache[FILE_CACHE_MAX];
1833
1834 array *split_vals;
1835-
1836+
1837 /* Timestamps */
1838 time_t cur_ts;
1839 time_t last_generated_date_ts;
1840 time_t last_generated_debug_ts;
1841 time_t startup_ts;
1842-
1843+
1844 buffer *ts_debug_str;
1845 buffer *ts_date_str;
1846-
1847+
1848 /* config-file */
1849 array *config;
1850 array *config_touched;
1851-
1852+
1853 array *config_context;
1854 specific_config **config_storage;
1855-
1856+
1857 server_config srvconf;
1858-
1859+
1860 int config_deprecated;
1861-
1862+
1863 connections *conns;
1864 connections *joblist;
1865 connections *fdwaitqueue;
1866-
1867+
1868 stat_cache *stat_cache;
1869
1870 /**
1175ccec 1871@@ -588,18 +581,20 @@
2519e6e5
ER
1872 * fastcgi.backend.<key>.disconnects = ...
1873 */
1874 array *status;
1875-
1876+
f26f9fd5 1877 fdevent_handler_t event_handler;
f673a614 1878
f26f9fd5
ER
1879- int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1880- int (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1881+ network_status_t (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1882+ network_status_t (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1883 #ifdef USE_OPENSSL
1884- int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
1885- int (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
1886+ network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
1887+ network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
f673a614 1888 #endif
f26f9fd5
ER
1889
1890+#ifdef HAVE_PWD_H
1891 uid_t uid;
1892 gid_t gid;
f673a614 1893+#endif
f26f9fd5 1894 } server;
f673a614 1895
f673a614 1896
1175ccec 1897--- ../lighttpd-1.4.11/src/buffer.c 2006-01-13 00:00:45.000000000 +0200
36e2a29e 1898+++ lighttpd-1.4.12/src/buffer.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
1899@@ -12,20 +12,20 @@
1900
1901
1902 /**
1903- * init the buffer
1904- *
1905+ * init the buffer
1906+ *
1907 */
1908
1909 buffer* buffer_init(void) {
1910 buffer *b;
1911-
1912+
1913 b = malloc(sizeof(*b));
1914 assert(b);
1915-
1916+
1917 b->ptr = NULL;
1918 b->size = 0;
1919 b->used = 0;
1920-
1921+
1922 return b;
1923 }
1924
1925@@ -36,8 +36,8 @@
1926 }
1927
1928 /**
1929- * free the buffer
1930- *
1931+ * free the buffer
1932+ *
1933 */
1934
1935 void buffer_free(buffer *b) {
1936@@ -49,39 +49,39 @@
1937
1938 void buffer_reset(buffer *b) {
1939 if (!b) return;
1940-
1941+
1942 /* limit don't reuse buffer larger than ... bytes */
1943 if (b->size > BUFFER_MAX_REUSE_SIZE) {
1944 free(b->ptr);
1945 b->ptr = NULL;
1946 b->size = 0;
1947 }
1948-
1949+
1950 b->used = 0;
1951 }
1952
f673a614
ER
1953
1954 /**
2519e6e5 1955- *
f26f9fd5 1956- * allocate (if neccessary) enough space for 'size' bytes and
2519e6e5 1957+ *
f26f9fd5
ER
1958+ * allocate (if necessary) enough space for 'size' bytes and
1959 * set the 'used' counter to 0
2519e6e5
ER
1960- *
1961+ *
f673a614 1962 */
2519e6e5
ER
1963
1964 #define BUFFER_PIECE_SIZE 64
1965
1966 int buffer_prepare_copy(buffer *b, size_t size) {
1967 if (!b) return -1;
1968-
1969- if ((0 == b->size) ||
1970+
1971+ if ((0 == b->size) ||
1972 (size > b->size)) {
1973 if (b->size) free(b->ptr);
1974-
1975+
f26f9fd5 1976 b->size = size;
2519e6e5 1977-
f26f9fd5 1978- /* always allocate a multiply of BUFFER_PIECE_SIZE */
2519e6e5 1979+
f26f9fd5
ER
1980+ /* always allocate a multiple of BUFFER_PIECE_SIZE */
1981 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2519e6e5
ER
1982-
1983+
f26f9fd5 1984 b->ptr = malloc(b->size);
2519e6e5
ER
1985 assert(b->ptr);
1986 }
1987@@ -90,30 +90,30 @@
1988 }
f673a614 1989
f26f9fd5 1990 /**
2519e6e5 1991- *
f26f9fd5 1992- * increase the internal buffer (if neccessary) to append another 'size' byte
2519e6e5 1993+ *
f26f9fd5
ER
1994+ * increase the internal buffer (if necessary) to append another 'size' byte
1995 * ->used isn't changed
2519e6e5
ER
1996- *
1997+ *
f26f9fd5 1998 */
2519e6e5
ER
1999
2000 int buffer_prepare_append(buffer *b, size_t size) {
2001 if (!b) return -1;
2002-
2003+
f26f9fd5
ER
2004 if (0 == b->size) {
2005 b->size = size;
2519e6e5 2006-
f26f9fd5 2007- /* always allocate a multiply of BUFFER_PIECE_SIZE */
2519e6e5 2008+
f26f9fd5
ER
2009+ /* always allocate a multiple of BUFFER_PIECE_SIZE */
2010 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2519e6e5
ER
2011-
2012+
f26f9fd5 2013 b->ptr = malloc(b->size);
2519e6e5
ER
2014 b->used = 0;
2015 assert(b->ptr);
f26f9fd5
ER
2016 } else if (b->used + size > b->size) {
2017 b->size += size;
2519e6e5 2018-
f26f9fd5 2019- /* always allocate a multiply of BUFFER_PIECE_SIZE */
2519e6e5 2020+
f26f9fd5
ER
2021+ /* always allocate a multiple of BUFFER_PIECE_SIZE */
2022 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2519e6e5
ER
2023-
2024+
f26f9fd5 2025 b->ptr = realloc(b->ptr, b->size);
2519e6e5
ER
2026 assert(b->ptr);
2027 }
2028@@ -122,7 +122,7 @@
2029
2030 int buffer_copy_string(buffer *b, const char *s) {
2031 size_t s_len;
2032-
2033+
2034 if (!s || !b) return -1;
2035
2036 s_len = strlen(s) + 1;
2037@@ -136,26 +136,26 @@
2038
2039 int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
2040 if (!s || !b) return -1;
2041-#if 0
2042- /* removed optimization as we have to keep the empty string
2043+#if 0
2044+ /* removed optimization as we have to keep the empty string
2045 * in some cases for the config handling
2046- *
2047+ *
2048 * url.access-deny = ( "" )
2049 */
2050 if (s_len == 0) return 0;
2051-#endif
2052+#endif
2053 buffer_prepare_copy(b, s_len + 1);
2054-
2055+
2056 memcpy(b->ptr, s, s_len);
2057 b->ptr[s_len] = '\0';
2058 b->used = s_len + 1;
2059-
2060+
2061 return 0;
2062 }
2063
2064 int buffer_copy_string_buffer(buffer *b, const buffer *src) {
2065 if (!src) return -1;
2066-
2067+
2068 if (src->used == 0) {
2069 b->used = 0;
2070 return 0;
2071@@ -201,10 +201,10 @@
2072
2073 /**
f26f9fd5 2074 * append a string to the end of the buffer
2519e6e5
ER
2075- *
2076- * the resulting buffer is terminated with a '\0'
f26f9fd5 2077- * s is treated as a un-terminated string (a \0 is handled a normal character)
2519e6e5
ER
2078- *
2079+ *
2080+ * the resulting buffer is terminated with a '\0'
f26f9fd5 2081+ * s is treated as an un-terminated string (a \0 is handled as a normal character)
2519e6e5 2082+ *
f26f9fd5
ER
2083 * @param b a buffer
2084 * @param s the string
2519e6e5
ER
2085 * @param s_len size of the string (without the terminating \0)
2086@@ -228,7 +228,7 @@
2087 int buffer_append_string_buffer(buffer *b, const buffer *src) {
2088 if (!src) return -1;
2089 if (src->used == 0) return 0;
2090-
2091+
2092 return buffer_append_string_len(b, src->ptr, src->used - 1);
2093 }
2094
2095@@ -245,9 +245,9 @@
2096
2097 int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
2098 if (!s || !b) return -1;
2099-
2100+
2101 b->used = 0;
2102-
2103+
2104 return buffer_append_memory(b, s, s_len);
2105 }
2106
2107@@ -402,46 +402,115 @@
f673a614 2108
f673a614
ER
2109
2110 /**
2519e6e5
ER
2111- * init the buffer
2112- *
f26f9fd5 2113+ * init the ptr buffer
f673a614 2114+ *
f26f9fd5
ER
2115+ */
2116+buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer)
2117+{
2118+ buffer_ptr *l = calloc(1, sizeof(buffer_ptr));
2119+ l->free = freer;
f673a614 2120+
f26f9fd5
ER
2121+ return l;
2122+}
f673a614 2123+
f26f9fd5
ER
2124+/**
2125+ * free the buffer_array
2126+ *
2127+ */
2128+void buffer_ptr_free(buffer_ptr *l)
2129+{
2130+ if (NULL != l) {
2131+ buffer_ptr_clear(l);
2132+ free(l);
2133+ }
2134+}
f673a614 2135+
f26f9fd5
ER
2136+void buffer_ptr_clear(buffer_ptr *l)
2137+{
2138+ assert(NULL != l);
f673a614 2139+
f26f9fd5
ER
2140+ if (l->free && l->used) {
2141+ size_t i;
2142+ for (i = 0; i < l->used; i ++) {
2143+ l->free(l->ptr[i]);
2144+ }
2145+ }
f673a614 2146+
f26f9fd5
ER
2147+ if (l->ptr) {
2148+ free(l->ptr);
2149+ l->ptr = NULL;
2150+ }
2151+ l->used = 0;
2152+ l->size = 0;
2153+}
f673a614 2154+
f26f9fd5
ER
2155+void buffer_ptr_append(buffer_ptr* l, void *item)
2156+{
2157+ assert(NULL != l);
2158+ if (l->ptr == NULL) {
2159+ l->size = 16;
2160+ l->ptr = (void **)malloc(sizeof(void *) * l->size);
2161+ }
2162+ else if (l->used == l->size) {
2163+ l->size += 16;
2164+ l->ptr = realloc(l->ptr, sizeof(void *) * l->size);
2165+ }
2166+ l->ptr[l->used++] = item;
2167+}
f673a614 2168+
f26f9fd5
ER
2169+void *buffer_ptr_pop(buffer_ptr* l)
2170+{
2171+ assert(NULL != l && l->used > 0);
2172+ return l->ptr[--l->used];
2173+}
f673a614 2174+
f26f9fd5
ER
2175+void *buffer_ptr_top(buffer_ptr* l)
2176+{
2177+ assert(NULL != l && l->used > 0);
2178+ return l->ptr[l->used-1];
2179+}
f673a614 2180+
f26f9fd5 2181+/**
2519e6e5
ER
2182+ * init the buffer
2183+ *
2184 */
2185
2186 buffer_array* buffer_array_init(void) {
2187 buffer_array *b;
2188-
2189+
2190 b = malloc(sizeof(*b));
2191-
2192+
2193 assert(b);
2194 b->ptr = NULL;
2195 b->size = 0;
2196 b->used = 0;
2197-
2198+
2199 return b;
2200 }
2201
2202 void buffer_array_reset(buffer_array *b) {
2203 size_t i;
2204-
2205+
2206 if (!b) return;
2207-
2208+
2209 /* if they are too large, reduce them */
2210 for (i = 0; i < b->used; i++) {
2211 buffer_reset(b->ptr[i]);
2212 }
2213-
2214+
2215 b->used = 0;
2216 }
2217
2218
2219 /**
2220- * free the buffer_array
2221- *
2222+ * free the buffer_array
2223+ *
f26f9fd5 2224 */
2519e6e5
ER
2225
2226 void buffer_array_free(buffer_array *b) {
2227 size_t i;
2228 if (!b) return;
2229-
2230+
2231 for (i = 0; i < b->size; i++) {
2232 if (b->ptr[i]) buffer_free(b->ptr[i]);
2233 }
2234@@ -451,7 +520,7 @@
2235
2236 buffer *buffer_array_append_get_buffer(buffer_array *b) {
2237 size_t i;
2238-
2239+
2240 if (b->size == 0) {
2241 b->size = 16;
2242 b->ptr = malloc(sizeof(*b->ptr) * b->size);
2243@@ -467,13 +536,13 @@
2244 b->ptr[i] = NULL;
2245 }
2246 }
2247-
2248+
2249 if (b->ptr[b->used] == NULL) {
2250 b->ptr[b->used] = buffer_init();
2251 }
2252-
2253+
2254 b->ptr[b->used]->used = 0;
2255-
2256+
2257 return b->ptr[b->used++];
2258 }
2259
2260@@ -482,23 +551,23 @@
2261 size_t i;
2262 if (len == 0) return NULL;
2263 if (needle == NULL) return NULL;
2264-
2265+
2266 if (b->used < len) return NULL;
2267-
2268+
2269 for(i = 0; i < b->used - len; i++) {
2270 if (0 == memcmp(b->ptr + i, needle, len)) {
2271 return b->ptr + i;
2272 }
2273 }
2274-
2275+
2276 return NULL;
2277 }
2278
2279 buffer *buffer_init_string(const char *str) {
2280 buffer *b = buffer_init();
2281-
2282+
2283 buffer_copy_string(b, str);
2284-
2285+
2286 return b;
2287 }
2288
2289@@ -507,8 +576,8 @@
f26f9fd5 2290 }
f673a614 2291
f26f9fd5
ER
2292 /**
2293- * check if two buffer contain the same data
2519e6e5 2294- *
f26f9fd5 2295+ * check if two buffers contain the same data
2519e6e5 2296+ *
f26f9fd5
ER
2297 * HISTORY: this function was pretty much optimized, but didn't handled
2298 * alignment properly.
2519e6e5
ER
2299 */
2300@@ -522,100 +591,100 @@
2301
2302 int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
2303 buffer b;
2304-
2305+
2306 b.ptr = (char *)s;
2307 b.used = b_len + 1;
2308-
2309+
2310 return buffer_is_equal(a, &b);
2311 }
f673a614 2312
f26f9fd5 2313 /* simple-assumption:
2519e6e5 2314- *
f26f9fd5 2315- * most parts are equal and doing a case conversion needs time
2519e6e5
ER
2316- *
2317+ *
f26f9fd5 2318+ * most parts are equal and doing a case conversion takes time
2519e6e5 2319+ *
f26f9fd5
ER
2320 */
2321 int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
2519e6e5
ER
2322 size_t ndx = 0, max_ndx;
2323 size_t *al, *bl;
2324 size_t mask = sizeof(*al) - 1;
2325-
2326+
2327 al = (size_t *)a;
2328 bl = (size_t *)b;
2329-
2330- /* is the alignment correct ? */
2331+
2332+ /* is the alignment correct? */
2333 if ( ((size_t)al & mask) == 0 &&
2334 ((size_t)bl & mask) == 0 ) {
2335-
2336+
2337 max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
2338-
2339+
2340 for (; ndx < max_ndx; ndx += sizeof(*al)) {
2341 if (*al != *bl) break;
2342 al++; bl++;
2343-
2344+
2345 }
2346-
2347+
2348 }
2349-
2350+
2351 a = (char *)al;
2352 b = (char *)bl;
2353-
2354+
2355 max_ndx = ((a_len < b_len) ? a_len : b_len);
2356-
2357+
2358 for (; ndx < max_ndx; ndx++) {
2359 char a1 = *a++, b1 = *b++;
2360-
2361+
2362 if (a1 != b1) {
2363 if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z'))
2364 a1 |= 32;
2365 else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z'))
2366 b1 |= 32;
2367 if ((a1 - b1) != 0) return (a1 - b1);
2368-
2369+
2370 }
2371 }
2372-
2373+
2374 return 0;
2375 }
2376
2377
2378 /**
2379 * check if the rightmost bytes of the string are equal.
2380- *
2381- *
2382+ *
2383+ *
2384 */
2385
2386 int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
2387 /* no, len -> equal */
2388 if (len == 0) return 1;
2389-
2390+
2391 /* len > 0, but empty buffers -> not equal */
f26f9fd5 2392 if (b1->used == 0 || b2->used == 0) return 0;
2519e6e5
ER
2393-
2394+
f26f9fd5
ER
2395 /* buffers too small -> not equal */
2396- if (b1->used - 1 < len || b1->used - 1 < len) return 0;
2519e6e5
ER
2397-
2398- if (0 == strncmp(b1->ptr + b1->used - 1 - len,
f26f9fd5 2399+ if (b1->used - 1 < len || b2->used - 1 < len) return 0;
2519e6e5
ER
2400+
2401+ if (0 == strncmp(b1->ptr + b1->used - 1 - len,
f26f9fd5 2402 b2->ptr + b2->used - 1 - len, len)) {
2519e6e5
ER
2403 return 1;
2404 }
2405-
2406+
2407 return 0;
2408 }
2409
2410 int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
2411 size_t i;
2412-
2413+
2414 /* BO protection */
2415 if (in_len * 2 < in_len) return -1;
2416-
2417+
2418 buffer_prepare_copy(b, in_len * 2 + 1);
2419-
2420+
2421 for (i = 0; i < in_len; i++) {
2422 b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
2423 b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
2424 }
2425 b->ptr[b->used++] = '\0';
2426-
2427+
2428 return 0;
2429 }
2430
2431@@ -624,7 +693,7 @@
2432 0 1 2 3 4 5 6 7 8 9 A B C D E F
2433 */
2434 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2435- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2436+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2437 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, /* 20 - 2F space " # $ % & ' + , / */
2438 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
2439 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2440@@ -646,7 +715,7 @@
2441 0 1 2 3 4 5 6 7 8 9 A B C D E F
2442 */
2443 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2444- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2445+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2446 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, /* 20 - 2F space " # $ % & ' + , / */
2447 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
2448 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2449@@ -668,7 +737,7 @@
2450 0 1 2 3 4 5 6 7 8 9 A B C D E F
2451 */
2452 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2453- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2454+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2455 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
2456 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
2457 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2458@@ -690,7 +759,7 @@
2459 0 1 2 3 4 5 6 7 8 9 A B C D E F
2460 */
2461 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2462- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2463+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2464 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
2465 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
2466 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2467@@ -712,12 +781,12 @@
2468 0 1 2 3 4 5 6 7 8 9 A B C D E F
2469 */
2470 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2471- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2472- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
2473- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
2474- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
2475- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
2476- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
2477+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2478+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
2479+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
2480+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
2481+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
2482+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
2483 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */
2484 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
2485 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
2486@@ -734,13 +803,13 @@
2487 unsigned char *ds, *d;
2488 size_t d_len, ndx;
2489 const char *map = NULL;
2490-
2491+
2492 if (!s || !b) return -1;
2493-
2494+
2495 if (b->ptr[b->used - 1] != '\0') {
2496 SEGFAULT();
2497 }
2498-
2499+
2500 if (s_len == 0) return 0;
2501
2502 switch(encoding) {
f26f9fd5
ER
2503@@ -760,12 +829,12 @@
2504 map = encoded_chars_hex;
2505 break;
2506 case ENCODING_UNSET:
2507- break;
2508+ return buffer_append_string_len(b, s, s_len);
2509 }
f673a614 2510
f26f9fd5 2511 assert(map != NULL);
2519e6e5 2512-
f26f9fd5 2513- /* count to-be-encoded-characters */
2519e6e5 2514+
f26f9fd5
ER
2515+ /* count to-be-encoded characters */
2516 for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2517 if (map[*ds]) {
2518 switch(encoding) {
2519e6e5
ER
2519@@ -787,9 +856,9 @@
2520 d_len ++;
2521 }
2522 }
2523-
2524+
2525 buffer_prepare_append(b, d_len);
2526-
2527+
2528 for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2529 if (map[*ds]) {
2530 switch(encoding) {
2531@@ -820,16 +889,16 @@
2532 }
2533 }
2534
2535- /* terminate buffer and calculate new length */
2536+ /* terminate buffer and calculate new length */
2537 b->ptr[b->used + d_len - 1] = '\0';
2538-
2539+
2540 b->used += d_len;
2541
2542 return 0;
f673a614
ER
2543 }
2544
f673a614 2545
f26f9fd5
ER
2546-/* decodes url-special-chars inplace.
2547+/* decodes url-special chars in-place.
2548 * replaces non-printable characters with '_'
2549 */
f673a614 2550
2519e6e5
ER
2551@@ -854,10 +923,10 @@
2552 low = hex2int(*(src + 2));
f26f9fd5
ER
2553 if (low != 0xFF) {
2554 high = (high << 4) | low;
2519e6e5 2555-
f26f9fd5 2556- /* map control-characters out */
2519e6e5 2557+
f26f9fd5
ER
2558+ /* map out control characters */
2559 if (high < 32 || high == 127) high = '_';
2519e6e5
ER
2560-
2561+
f26f9fd5 2562 *dst = high;
2519e6e5
ER
2563 src += 2;
2564 }
f26f9fd5
ER
2565@@ -891,7 +960,7 @@
2566 * /abc/./xyz gets /abc/xyz
2567 * /abc//xyz gets /abc/xyz
2568 *
2569- * NOTE: src and dest can point to the same buffer, in which case,
2570+ * NOTE: src and dest can point to the same buffer, in which case
2571 * the operation is performed in-place.
2572 */
f673a614 2573
2519e6e5
ER
2574@@ -979,7 +1048,7 @@
2575
2576 int light_isxdigit(int c) {
2577 if (light_isdigit(c)) return 1;
2578-
2579+
2580 c |= 32;
2581 return (c >= 'a' && c <= 'f');
2582 }
2583@@ -993,31 +1062,56 @@
f26f9fd5 2584 return light_isdigit(c) || light_isalpha(c);
f673a614
ER
2585 }
2586
f26f9fd5
ER
2587+#undef BUFFER_CTYPE_FUNC
2588+#define BUFFER_CTYPE_FUNC(type) \
2589+ int buffer_is##type(buffer *b) { \
2590+ size_t i, len; \
2591+ if (b->used < 2) return 0; \
2592+ /* strlen */ \
2593+ len = b->used - 1; \
2594+ /* c-string only */ \
2595+ if (b->ptr[len] != '\0') { \
2596+ return 0; \
2597+ } \
2598+ /* check on the whole string */ \
2599+ for (i = 0; i < len; i ++) { \
2600+ if (!light_is##type(b->ptr[i])) { \
2601+ return 0; \
2602+ } \
2603+ } \
2604+ return 1; \
2605+ }
f673a614 2606+
f26f9fd5
ER
2607+BUFFER_CTYPE_FUNC(digit)
2608+BUFFER_CTYPE_FUNC(xdigit)
2609+BUFFER_CTYPE_FUNC(alpha)
2610+BUFFER_CTYPE_FUNC(alnum)
f673a614 2611+
f26f9fd5
ER
2612 int buffer_to_lower(buffer *b) {
2613 char *c;
2519e6e5
ER
2614-
2615+
2616 if (b->used == 0) return 0;
2617-
2618+
2619 for (c = b->ptr; *c; c++) {
2620 if (*c >= 'A' && *c <= 'Z') {
2621 *c |= 32;
2622 }
2623 }
2624-
2625+
2626 return 0;
2627 }
2628
2629
2630 int buffer_to_upper(buffer *b) {
2631 char *c;
2632-
2633+
2634 if (b->used == 0) return 0;
2635-
2636+
2637 for (c = b->ptr; *c; c++) {
2638 if (*c >= 'a' && *c <= 'z') {
2639 *c &= ~32;
2640 }
2641 }
2642-
2643+
2644 return 0;
2645 }
1175ccec 2646--- ../lighttpd-1.4.11/src/buffer.h 2006-01-13 00:00:45.000000000 +0200
36e2a29e 2647+++ lighttpd-1.4.12/src/buffer.h 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
2648@@ -12,27 +12,44 @@
2649
2650 typedef struct {
2651 char *ptr;
2652-
2653+
2654 size_t used;
f26f9fd5
ER
2655 size_t size;
2656 } buffer;
f673a614
ER
2657
2658+
f26f9fd5 2659+typedef void (*buffer_ptr_free_t)(void *p);
f673a614 2660+
f26f9fd5
ER
2661+typedef struct {
2662+ void **ptr;
2663+ size_t size;
2664+ size_t used;
2665+ buffer_ptr_free_t free;
2666+} buffer_ptr;
f673a614 2667+
f26f9fd5
ER
2668 typedef struct {
2669 buffer **ptr;
2519e6e5
ER
2670-
2671+
2672 size_t used;
2673 size_t size;
2674 } buffer_array;
2675
2676 typedef struct {
2677 char *ptr;
2678-
f26f9fd5 2679- size_t offset; /* input-pointer */
2519e6e5 2680-
f26f9fd5 2681- size_t used; /* output-pointer */
2519e6e5
ER
2682+
2683+ size_t offset; /* input pointer */
2684+
f26f9fd5
ER
2685+ size_t used; /* output pointer */
2686 size_t size;
2687 } read_buffer;
f673a614 2688
f26f9fd5
ER
2689+buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer);
2690+void buffer_ptr_free(buffer_ptr *b);
2691+void buffer_ptr_clear(buffer_ptr *b);
2692+void buffer_ptr_append(buffer_ptr *b, void *item);
2693+void *buffer_ptr_pop(buffer_ptr *b);
2694+void *buffer_ptr_top(buffer_ptr *b);
f673a614 2695+
f26f9fd5
ER
2696 buffer_array* buffer_array_init(void);
2697 void buffer_array_free(buffer_array *b);
2698 void buffer_array_reset(buffer_array *b);
2519e6e5
ER
2699@@ -43,7 +60,7 @@
2700 buffer* buffer_init_string(const char *str);
2701 void buffer_free(buffer *b);
2702 void buffer_reset(buffer *b);
2703-
2704+
2705 int buffer_prepare_copy(buffer *b, size_t size);
2706 int buffer_prepare_append(buffer *b, size_t size);
2707
f26f9fd5 2708@@ -85,9 +102,9 @@
f673a614 2709
f26f9fd5
ER
2710 typedef enum {
2711 ENCODING_UNSET,
2712- ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of a href */
2713- ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus coding / too as %2F */
2714- ENCODING_HTML, /* & becomes &amp; and so on */
2715+ ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of an href */
2716+ ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus encoding "/" as "%2F" */
2717+ ENCODING_HTML, /* "&" becomes "&amp;" and so on */
2718 ENCODING_MINIMAL_XML, /* minimal encoding for xml */
2719 ENCODING_HEX /* encode string as hex */
2720 } buffer_encoding_t;
2721@@ -111,19 +128,21 @@
2722 int light_isalpha(int c);
2723 int light_isalnum(int c);
2724
2725+#define BUFFER_CTYPE_FUNC(type) int buffer_is##type(buffer *b);
2726+BUFFER_CTYPE_FUNC(digit)
2727+BUFFER_CTYPE_FUNC(xdigit)
2728+BUFFER_CTYPE_FUNC(alpha)
2729+BUFFER_CTYPE_FUNC(alnum)
f673a614 2730+
f26f9fd5
ER
2731 #define BUFFER_APPEND_STRING_CONST(x, y) \
2732 buffer_append_string_len(x, y, sizeof(y) - 1)
2733
2734 #define BUFFER_COPY_STRING_CONST(x, y) \
2735 buffer_copy_string_len(x, y, sizeof(y) - 1)
2736
2737-#define BUFFER_APPEND_SLASH(x) \
2738- if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); }
2739-
2740 #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
2741 #define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0
2742
2743-
2744 #define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0)
2745 #define UNUSED(x) ( (void)(x) )
2746
1175ccec 2747--- ../lighttpd-1.4.11/src/chunk.c 2005-11-18 15:18:19.000000000 +0200
36e2a29e 2748+++ lighttpd-1.4.12/src/chunk.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
2749@@ -1,16 +1,14 @@
2750 /**
2751 * the network chunk-API
2752- *
2753- *
2754+ *
2755+ *
2756 */
f26f9fd5
ER
2757
2758 #include <sys/types.h>
2759 #include <sys/stat.h>
2760-#include <sys/mman.h>
2761
2762 #include <stdlib.h>
2763 #include <fcntl.h>
2764-#include <unistd.h>
2765
2766 #include <stdio.h>
2767 #include <errno.h>
2519e6e5 2768@@ -18,36 +16,39 @@
f26f9fd5
ER
2769
2770 #include "chunk.h"
2771
2772+#include "sys-mmap.h"
2773+#include "sys-files.h"
f673a614 2774+
f26f9fd5
ER
2775 chunkqueue *chunkqueue_init(void) {
2776 chunkqueue *cq;
2519e6e5
ER
2777-
2778+
2779 cq = calloc(1, sizeof(*cq));
2780-
2781+
2782 cq->first = NULL;
2783 cq->last = NULL;
2784-
2785+
2786 cq->unused = NULL;
2787-
2788+
2789 return cq;
2790 }
2791
2792 static chunk *chunk_init(void) {
2793 chunk *c;
2794-
2795+
2796 c = calloc(1, sizeof(*c));
2797-
2798+
2799 c->mem = buffer_init();
2800 c->file.name = buffer_init();
2801 c->file.fd = -1;
2802 c->file.mmap.start = MAP_FAILED;
2803 c->next = NULL;
2804-
2805+
2806 return c;
2807 }
2808
2809 static void chunk_free(chunk *c) {
2810 if (!c) return;
2811-
2812+
2813 buffer_free(c->mem);
2814 buffer_free(c->file.name);
2815
2816@@ -56,13 +57,13 @@
2817
2818 static void chunk_reset(chunk *c) {
2819 if (!c) return;
2820-
2821+
2822 buffer_reset(c->mem);
2823
2824 if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
2825 unlink(c->file.name->ptr);
2826 }
2827-
2828+
2829 buffer_reset(c->file.name);
2830
2831 if (c->file.fd != -1) {
2832@@ -78,28 +79,28 @@
2833
2834 void chunkqueue_free(chunkqueue *cq) {
2835 chunk *c, *pc;
2836-
2837+
2838 if (!cq) return;
2839-
2840+
2841 for (c = cq->first; c; ) {
2842 pc = c;
2843 c = c->next;
2844 chunk_free(pc);
2845 }
2846-
2847+
2848 for (c = cq->unused; c; ) {
2849 pc = c;
2850 c = c->next;
2851 chunk_free(pc);
2852 }
2853-
2854+
2855 free(cq);
2856 }
2857
f26f9fd5
ER
2858 static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) {
2859 chunk *c;
2519e6e5 2860-
f26f9fd5 2861- /* check if we have a unused chunk */
2519e6e5 2862+
f26f9fd5
ER
2863+ /* check if we have an unused chunk */
2864 if (!cq->unused) {
2865 c = chunk_init();
2866 } else {
2519e6e5
ER
2867@@ -109,18 +110,18 @@
2868 c->next = NULL;
2869 cq->unused_chunks--;
2870 }
2871-
2872+
2873 return c;
2874 }
2875
2876 static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
2877 c->next = cq->first;
2878 cq->first = c;
2879-
2880+
2881 if (cq->last == NULL) {
2882 cq->last = c;
2883 }
2884-
2885+
2886 return 0;
2887 }
2888
2889@@ -129,19 +130,19 @@
2890 cq->last->next = c;
2891 }
2892 cq->last = c;
2893-
2894+
2895 if (cq->first == NULL) {
2896 cq->first = c;
2897 }
2898-
2899+
2900 return 0;
2901 }
2902
2903 void chunkqueue_reset(chunkqueue *cq) {
2904 chunk *c;
2905 /* move everything to the unused queue */
2906-
2907- /* mark all read written */
2908+
2909+ /* mark all read written */
2910 for (c = cq->first; c; c = c->next) {
2911 switch(c->type) {
2912 case MEM_CHUNK:
2913@@ -150,7 +151,7 @@
2914 case FILE_CHUNK:
2915 c->offset = c->file.length;
2916 break;
2917- default:
2918+ default:
2919 break;
2920 }
2921 }
2922@@ -162,93 +163,93 @@
2923
2924 int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
2925 chunk *c;
2926-
2927+
2928 if (len == 0) return 0;
2929-
2930+
2931 c = chunkqueue_get_unused_chunk(cq);
2932-
2933+
2934 c->type = FILE_CHUNK;
2935-
2936+
2937 buffer_copy_string_buffer(c->file.name, fn);
2938 c->file.start = offset;
2939 c->file.length = len;
2940 c->offset = 0;
2941-
2942+
2943 chunkqueue_append_chunk(cq, c);
2944-
2945+
2946 return 0;
2947 }
2948
2949 int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
2950 chunk *c;
2951-
2952+
2953 if (mem->used == 0) return 0;
2954-
2955+
2956 c = chunkqueue_get_unused_chunk(cq);
2957 c->type = MEM_CHUNK;
2958 c->offset = 0;
2959 buffer_copy_string_buffer(c->mem, mem);
2960-
2961+
2962 chunkqueue_append_chunk(cq, c);
2963-
2964+
2965 return 0;
2966 }
2967
2968 int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
2969 chunk *c;
2970-
2971+
2972 if (mem->used == 0) return 0;
2973-
2974+
2975 c = chunkqueue_get_unused_chunk(cq);
2976 c->type = MEM_CHUNK;
2977 c->offset = 0;
2978 buffer_copy_string_buffer(c->mem, mem);
2979-
2980+
2981 chunkqueue_prepend_chunk(cq, c);
2982-
2983+
2984 return 0;
2985 }
2986
2987 int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
2988 chunk *c;
2989-
2990+
2991 if (len == 0) return 0;
2992-
2993+
2994 c = chunkqueue_get_unused_chunk(cq);
2995 c->type = MEM_CHUNK;
2996 c->offset = 0;
2997 buffer_copy_string_len(c->mem, mem, len - 1);
2998-
2999+
3000 chunkqueue_append_chunk(cq, c);
3001-
3002+
3003 return 0;
3004 }
3005
3006 buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
3007 chunk *c;
3008-
3009+
3010 c = chunkqueue_get_unused_chunk(cq);
3011-
3012+
3013 c->type = MEM_CHUNK;
3014 c->offset = 0;
3015 buffer_reset(c->mem);
3016-
3017+
3018 chunkqueue_prepend_chunk(cq, c);
3019-
3020+
3021 return c->mem;
3022 }
3023
3024 buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
3025 chunk *c;
3026-
3027+
3028 c = chunkqueue_get_unused_chunk(cq);
3029-
3030+
3031 c->type = MEM_CHUNK;
3032 c->offset = 0;
3033 buffer_reset(c->mem);
3034-
3035+
3036 chunkqueue_append_chunk(cq, c);
3037-
3038+
3039 return c->mem;
3040 }
3041
3042@@ -263,7 +264,7 @@
3043 chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
3044 chunk *c;
3045 buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
3046-
3047+
3048 c = chunkqueue_get_unused_chunk(cq);
3049
3050 c->type = FILE_CHUNK;
3051@@ -273,12 +274,12 @@
3052 size_t i;
3053
3054 /* we have several tempdirs, only if all of them fail we jump out */
3055-
3056+
3057 for (i = 0; i < cq->tempdirs->used; i++) {
f26f9fd5
ER
3058 data_string *ds = (data_string *)cq->tempdirs->data[i];
3059
3060 buffer_copy_string_buffer(template, ds->value);
3061- BUFFER_APPEND_SLASH(template);
3062+ PATHNAME_APPEND_SLASH(template);
3063 BUFFER_APPEND_STRING_CONST(template, "lighttpd-upload-XXXXXX");
3064
3065 if (-1 != (c->file.fd = mkstemp(template->ptr))) {
2519e6e5
ER
3066@@ -300,7 +301,7 @@
3067 chunkqueue_append_chunk(cq, c);
3068
3069 buffer_free(template);
3070-
3071+
3072 return c;
3073 }
3074
3075@@ -308,7 +309,7 @@
3076 off_t chunkqueue_length(chunkqueue *cq) {
3077 off_t len = 0;
3078 chunk *c;
3079-
3080+
3081 for (c = cq->first; c; c = c->next) {
3082 switch (c->type) {
3083 case MEM_CHUNK:
3084@@ -321,14 +322,14 @@
3085 break;
3086 }
3087 }
3088-
3089+
3090 return len;
3091 }
3092
3093 off_t chunkqueue_written(chunkqueue *cq) {
3094 off_t len = 0;
3095 chunk *c;
3096-
3097+
3098 for (c = cq->first; c; c = c->next) {
3099 switch (c->type) {
3100 case MEM_CHUNK:
3101@@ -339,7 +340,7 @@
3102 break;
3103 }
3104 }
3105-
3106+
3107 return len;
3108 }
3109
3110@@ -358,9 +359,9 @@
3111 if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
3112 break;
3113 case FILE_CHUNK:
3114- if (c->offset == c->file.length) is_finished = 1;
3115+ if (c->offset == c->file.length) is_finished = 1;
3116 break;
3117- default:
3118+ default:
3119 break;
3120 }
3121
1175ccec 3122--- ../lighttpd-1.4.11/src/chunk.h 2005-11-01 09:32:21.000000000 +0200
36e2a29e 3123+++ lighttpd-1.4.12/src/chunk.h 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
3124@@ -6,7 +6,7 @@
3125
3126 typedef struct chunk {
3127 enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
3128-
3129+
3130 buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
3131
3132 struct {
3133@@ -16,28 +16,28 @@
3134 off_t length; /* octets to send from the starting offset */
3135
3136 int fd;
3137- struct {
3138+ struct {
f26f9fd5
ER
3139 char *start; /* the start pointer of the mmap'ed area */
3140 size_t length; /* size of the mmap'ed area */
3141- off_t offset; /* start is <n> octet away from the start of the file */
3142+ off_t offset; /* start is <n> octets away from the start of the file */
3143 } mmap;
3144
3145- int is_temp; /* file is temporary and will be deleted if on cleanup */
3146+ int is_temp; /* file is temporary and will be deleted on cleanup */
3147 } file;
2519e6e5
ER
3148-
3149- off_t offset; /* octets sent from this chunk
3150- the size of the chunk is either
3151+
3152+ off_t offset; /* octets sent from this chunk
3153+ the size of the chunk is either
3154 - mem-chunk: mem->used - 1
3155 - file-chunk: file.length
3156 */
3157-
3158+
3159 struct chunk *next;
3160 } chunk;
3161
3162 typedef struct {
3163 chunk *first;
3164 chunk *last;
3165-
3166+
3167 chunk *unused;
3168 size_t unused_chunks;
3169
1175ccec 3170--- ../lighttpd-1.4.11/src/configfile-glue.c 2006-03-03 20:14:56.000000000 +0200
36e2a29e 3171+++ lighttpd-1.4.12/src/configfile-glue.c 2006-07-11 22:07:51.000000000 +0300
f26f9fd5
ER
3172@@ -1,4 +1,5 @@
3173 #include <string.h>
3174+#include <ctype.h>
3175
3176 #include "base.h"
3177 #include "buffer.h"
2519e6e5
ER
3178@@ -11,10 +12,10 @@
3179 * are the external interface of lighttpd. The functions
3180 * are used by the server itself and the plugins.
3181 *
3182- * The main-goal is to have a small library in the end
3183- * which is linked against both and which will define
3184+ * The main-goal is to have a small library in the end
3185+ * which is linked against both and which will define
3186 * the interface itself in the end.
3187- *
3188+ *
3189 */
3190
3191
3192@@ -24,56 +25,60 @@
3193 int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
3194 size_t i;
3195 data_unset *du;
3196-
f673a614 3197+
2519e6e5
ER
3198 for (i = 0; cv[i].key; i++) {
3199-
f673a614 3200+
2519e6e5
ER
3201 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3202 /* no found */
3203-
3204+
3205 continue;
3206 }
3207-
3208+
3209 switch (cv[i].type) {
3210 case T_CONFIG_ARRAY:
3211 if (du->type == TYPE_ARRAY) {
3212 size_t j;
3213 data_array *da = (data_array *)du;
3214-
3215+
3216 for (j = 0; j < da->value->used; j++) {
3217 if (da->value->data[j]->type == TYPE_STRING) {
3218 data_string *ds = data_string_init();
3219-
3220+
3221 buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
3222 if (!da->is_index_key) {
3223 /* the id's were generated automaticly, as we copy now we might have to renumber them
3224- * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
3225+ * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
3226 * before mod_fastcgi and friends */
3227 buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
3228 }
3229-
3230+
3231 array_insert_unique(cv[i].destination, (data_unset *)ds);
3232 } else {
3233- log_error_write(srv, __FILE__, __LINE__, "sssd",
3234- "the key of and array can only be a string or a integer, variable:",
3235- cv[i].key, "type:", da->value->data[j]->type);
3236-
3237+ log_error_write(srv, __FILE__, __LINE__, "sssd",
3238+ "the key of and array can only be a string or a integer, variable:",
3239+ cv[i].key, "type:", da->value->data[j]->type);
3240+
3241 return -1;
3242 }
3243 }
3244 } else {
3245 log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
3246-
3247+
3248 return -1;
3249 }
3250 break;
3251 case T_CONFIG_STRING:
3252 if (du->type == TYPE_STRING) {
3253 data_string *ds = (data_string *)du;
3254-
3255+
3256 buffer_copy_string_buffer(cv[i].destination, ds->value);
3257+ } else if (du->type == TYPE_INTEGER) {
3258+ data_integer *di = (data_integer *)du;
3259+
3260+ buffer_copy_long(cv[i].destination, di->value);
3261 } else {
3262 log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
3263-
3264+
3265 return -1;
3266 }
3267 break;
3268@@ -81,15 +86,20 @@
3269 switch(du->type) {
3270 case TYPE_INTEGER: {
3271 data_integer *di = (data_integer *)du;
3272-
3273+
3274 *((unsigned short *)(cv[i].destination)) = di->value;
3275 break;
3276 }
3277 case TYPE_STRING: {
3278 data_string *ds = (data_string *)du;
3279-
3280+
3281+ if (buffer_isdigit(ds->value)) {
3282+ *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
3283+ break;
3284+ }
3285+
3286 log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
3287-
3288+
3289 return -1;
3290 }
3291 default:
3292@@ -100,19 +110,19 @@
3293 case T_CONFIG_BOOLEAN:
3294 if (du->type == TYPE_STRING) {
3295 data_string *ds = (data_string *)du;
3296-
3297+
3298 if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
3299 *((unsigned short *)(cv[i].destination)) = 1;
3300 } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
3301 *((unsigned short *)(cv[i].destination)) = 0;
3302 } else {
3303 log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
3304-
3305+
3306 return -1;
3307 }
3308 } else {
3309 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
3310-
3311+
3312 return -1;
3313 }
3314 break;
3315@@ -121,9 +131,9 @@
3316 break;
3317 case T_CONFIG_DEPRECATED:
3318 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
3319-
3320+
3321 srv->config_deprecated = 1;
3322-
3323+
3324 break;
3325 }
3326 }
3327@@ -133,25 +143,25 @@
3328 int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
3329 size_t i;
3330 data_unset *du;
3331-
3332+
3333 for (i = 0; cv[i].key; i++) {
3334 data_string *touched;
3335-
3336+
3337 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3338 /* no found */
3339-
3340+
3341 continue;
3342 }
3343-
3344+
3345 /* touched */
3346 touched = data_string_init();
3347-
3348+
3349 buffer_copy_string(touched->value, "");
3350 buffer_copy_string_buffer(touched->key, du->key);
3351-
3352+
3353 array_insert_unique(srv->config_touched, (data_unset *)touched);
3354 }
3355-
3356+
3357 return config_insert_values_internal(srv, ca, cv);
3358 }
3359
3360@@ -191,25 +201,25 @@
3361 }
3362
3363 /* pass the rules */
3364-
3365+
3366 switch (dc->comp) {
3367 case COMP_HTTP_HOST: {
3368 char *ck_colon = NULL, *val_colon = NULL;
3369-
3370+
3371 if (!buffer_is_empty(con->uri.authority)) {
3372-
3373- /*
3374+
3375+ /*
3376 * append server-port to the HTTP_POST if necessary
3377 */
3378-
3379+
3380 l = con->uri.authority;
3381-
3382+
3383 switch(dc->cond) {
3384 case CONFIG_COND_NE:
3385 case CONFIG_COND_EQ:
3386 ck_colon = strchr(dc->string->ptr, ':');
3387 val_colon = strchr(l->ptr, ':');
3388-
3389+
3390 if (ck_colon == val_colon) {
3391 /* nothing to do with it */
3392 break;
3393@@ -230,21 +240,21 @@
3394 break;
3395 }
3396 } else {
3397- l = NULL;
f26f9fd5 3398+ l = srv->empty_string;
f673a614 3399 }
f26f9fd5 3400 break;
f673a614 3401 }
2519e6e5
ER
3402 case COMP_HTTP_REMOTEIP: {
3403 char *nm_slash;
3404- /* handle remoteip limitations
3405- *
3406+ /* handle remoteip limitations
3407+ *
3408 * "10.0.0.1" is provided for all comparisions
3409- *
3410+ *
3411 * only for == and != we support
3412- *
3413+ *
3414 * "10.0.0.1/24"
3415 */
3416-
3417+
3418 if ((dc->cond == CONFIG_COND_EQ ||
3419 dc->cond == CONFIG_COND_NE) &&
3420 (con->dst_addr.plain.sa_family == AF_INET) &&
3421@@ -253,41 +263,48 @@
3422 long nm;
f26f9fd5
ER
3423 char *err;
3424 struct in_addr val_inp;
2519e6e5
ER
3425-
3426+
f26f9fd5
ER
3427+ if (con->conf.log_condition_handling) {
3428+ l = srv->empty_string;
f673a614 3429+
f26f9fd5
ER
3430+ log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
3431+ "(", l, ") compare to", dc->string);
3432+ }
f673a614 3433+
f26f9fd5
ER
3434 if (*(nm_slash+1) == '\0') {
3435 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
2519e6e5
ER
3436-
3437+
3438 return COND_RESULT_FALSE;
3439 }
3440-
3441+
3442 nm_bits = strtol(nm_slash + 1, &err, 10);
3443-
3444+
3445 if (*err) {
3446 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
3447-
3448+
3449 return COND_RESULT_FALSE;
3450 }
3451-
3452+
f26f9fd5
ER
3453 /* take IP convert to the native */
3454 buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
3455-#ifdef __WIN32
3456+#ifdef _WIN32
3457 if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
3458 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
2519e6e5
ER
3459-
3460+
3461 return COND_RESULT_FALSE;
3462 }
3463
3464 #else
3465 if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
3466 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3467-
3468+
3469 return COND_RESULT_FALSE;
3470 }
3471 #endif
3472-
3473+
3474 /* build netmask */
3475 nm = htonl(~((1 << (32 - nm_bits)) - 1));
3476-
3477+
3478 if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
3479 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
3480 } else {
3481@@ -308,7 +325,7 @@
3482
3483 case COMP_HTTP_REFERER: {
3484 data_string *ds;
3485-
3486+
3487 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
3488 l = ds->value;
3489 } else {
3490@@ -338,7 +355,7 @@
3491 default:
3492 return COND_RESULT_FALSE;
3493 }
3494-
3495+
3496 if (NULL == l) {
3497 if (con->conf.log_condition_handling) {
3498 log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key,
3499@@ -346,10 +363,10 @@
3500 }
3501 return COND_RESULT_FALSE;
3502 }
3503-
3504+
3505 if (con->conf.log_condition_handling) {
3506 log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
3507- "(", l, ") compare to ", dc->string);
3508+ "(", l, ") compare to", dc->string);
3509 }
3510 switch(dc->cond) {
3511 case CONFIG_COND_NE:
3512@@ -365,13 +382,13 @@
3513 case CONFIG_COND_MATCH: {
3514 cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
3515 int n;
3516-
3517+
3518 #ifndef elementsof
3519 #define elementsof(x) (sizeof(x) / sizeof(x[0]))
3520 #endif
3521 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
3522 cache->matches, elementsof(cache->matches));
3523-
3524+
3525 cache->patterncount = n;
3526 if (n > 0) {
3527 cache->comp_value = l;
3528@@ -387,7 +404,7 @@
3529 /* no way */
3530 break;
3531 }
3532-
3533+
3534 return COND_RESULT_FALSE;
3535 }
3536
f26f9fd5
ER
3537@@ -395,6 +412,9 @@
3538 cond_cache_t *caches = con->cond_cache;
f673a614 3539
f26f9fd5
ER
3540 if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
3541+ if (con->conf.log_condition_handling) {
3542+ log_error_write(srv, __FILE__, __LINE__, "sds", "=== start of", dc->context_ndx, "condition block ===");
3543+ }
3544 if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
3545 if (dc->next) {
3546 data_config *c;
3547@@ -409,11 +429,11 @@
3548 }
3549 if (con->conf.log_condition_handling) {
3550 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3551- "(uncached) result:",
3552+ "result:",
3553 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3554 }
3555 } else {
3556- if (con->conf.log_condition_handling) {
3557+ if (con->conf.log_condition_cache_handling) {
3558 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3559 "(cached) result:",
3560 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3561@@ -423,9 +443,6 @@
f673a614
ER
3562 }
3563
f26f9fd5
ER
3564 int config_check_cond(server *srv, connection *con, data_config *dc) {
3565- if (con->conf.log_condition_handling) {
3566- log_error_write(srv, __FILE__, __LINE__, "s", "=== start of condition block ===");
3567- }
3568 return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
3569 }
f673a614 3570
f26f9fd5
ER
3571@@ -443,3 +460,85 @@
3572 return 1;
f673a614
ER
3573 }
3574
f26f9fd5
ER
3575+/* return <0 on error
3576+ * return 0-x if matched (and replaced)
3577+ */
3578+int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result)
3579+{
3580+#ifdef HAVE_PCRE_H
3581+ pcre *match;
3582+ pcre_extra *extra;
3583+ const char *pattern;
3584+ size_t pattern_len;
3585+ int n;
3586+ size_t i;
3587+ pcre_keyvalue *kv;
3588+# define N 10
3589+ int ovec[N * 3];
f673a614 3590+
f26f9fd5
ER
3591+ for (i = 0; i < kvb->used; i++) {
3592+ kv = kvb->kv[i];
f673a614 3593+
f26f9fd5
ER
3594+ match = kv->key;
3595+ extra = kv->key_extra;
3596+ pattern = kv->value->ptr;
3597+ pattern_len = kv->value->used - 1;
f673a614 3598+
f26f9fd5
ER
3599+ if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
3600+ if (n != PCRE_ERROR_NOMATCH) {
3601+ return n;
3602+ }
3603+ } else {
3604+ const char **list;
3605+ size_t start, end;
3606+ size_t k;
f673a614 3607+
f26f9fd5
ER
3608+ /* it matched */
3609+ pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
f673a614 3610+
f26f9fd5 3611+ /* search for $[0-9] */
f673a614 3612+
f26f9fd5 3613+ buffer_reset(result);
f673a614 3614+
f26f9fd5
ER
3615+ start = 0; end = pattern_len;
3616+ for (k = 0; k < pattern_len; k++) {
3617+ if ((pattern[k] == '$' || pattern[k] == '%') &&
3618+ isdigit((unsigned char)pattern[k + 1])) {
3619+ /* got one */
f673a614 3620+
f26f9fd5 3621+ size_t num = pattern[k + 1] - '0';
f673a614 3622+
f26f9fd5 3623+ end = k;
f673a614 3624+
f26f9fd5 3625+ buffer_append_string_len(result, pattern + start, end - start);
f673a614 3626+
f26f9fd5
ER
3627+ if (pattern[k] == '$') {
3628+ /* n is always > 0 */
3629+ if (num < (size_t)n) {
3630+ buffer_append_string(result, list[num]);
3631+ }
3632+ } else {
3633+ config_append_cond_match_buffer(con, context, result, num);
3634+ }
f673a614 3635+
f26f9fd5
ER
3636+ k++;
3637+ start = k + 1;
3638+ }
3639+ }
f673a614 3640+
f26f9fd5 3641+ buffer_append_string_len(result, pattern + start, pattern_len - start);
f673a614 3642+
f26f9fd5 3643+ pcre_free(list);
f673a614 3644+
f26f9fd5
ER
3645+ return i;
3646+ }
3647+ }
f673a614 3648+
f26f9fd5
ER
3649+ return PCRE_ERROR_NOMATCH;
3650+#undef N
3651+#else
3652+ UNUSED(kvb);
3653+ return -2;
3654+#endif
3655+}
f673a614 3656+
1175ccec
ER
3657--- ../lighttpd-1.4.11/src/configfile.c 2006-02-15 14:26:42.000000000 +0200
3658+++ lighttpd-1.4.12/src/configfile.c 2006-07-15 22:43:21.000000000 +0300
f26f9fd5
ER
3659@@ -2,7 +2,6 @@
3660
3661 #include <stdlib.h>
3662 #include <fcntl.h>
3663-#include <unistd.h>
3664 #include <errno.h>
3665 #include <string.h>
3666 #include <stdio.h>
1175ccec 3667@@ -13,21 +12,24 @@
f26f9fd5
ER
3668 #include "log.h"
3669 #include "stream.h"
3670 #include "plugin.h"
3671-#ifdef USE_LICENSE
3672-#include "license.h"
3673-#endif
3674-
3675 #include "configparser.h"
3676 #include "configfile.h"
3677 #include "proc_open.h"
3678
3679+#include "sys-files.h"
1175ccec 3680+#include "sys-process.h"
f673a614 3681+
f26f9fd5
ER
3682+#ifndef PATH_MAX
3683+/* win32 */
3684+#define PATH_MAX 64
3685+#endif
3686
3687 static int config_insert(server *srv) {
3688 size_t i;
2519e6e5
ER
3689 int ret = 0;
3690 buffer *stat_cache_string;
3691-
3692- config_values_t cv[] = {
3693+
3694+ config_values_t cv[] = {
3695 { "server.bind", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 */
3696 { "server.errorlog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 */
3697 { "server.errorfile-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 */
1175ccec 3698@@ -38,7 +40,7 @@
2519e6e5
ER
3699 { "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
3700 { "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
3701 { "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */
3702-
3703+
3704 { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */
3705 { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */
3706 { "server.max-request-size", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
1175ccec 3707@@ -49,7 +51,7 @@
2519e6e5
ER
3708 { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
3709 { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */
3710 { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */
3711-
3712+
3713 { "server.max-read-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 20 */
3714 { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */
3715 { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */
1175ccec 3716@@ -60,19 +62,19 @@
2519e6e5
ER
3717 { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
3718 { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */
3719 { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 29 */
3720-
3721+
3722 { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */
3723-
3724+
3725 { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 31 */
3726 { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 32 */
3727 { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 33 */
3728 { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 34 */
3729-
3730+
3731 { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 35 */
3732 { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
3733 { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */
3734 { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 38 */
3735-
3736+
3737 { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 39 */
3738 { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
3739 { "server.stat-cache-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
1175ccec 3740@@ -80,7 +82,8 @@
f26f9fd5
ER
3741 { "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 43 */
3742 { "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 44 */
3743 { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
2519e6e5 3744-
f26f9fd5 3745+ { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 46 */
2519e6e5 3746+
f26f9fd5
ER
3747 { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3748 { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
2519e6e5 3749 { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
1175ccec 3750@@ -90,11 +93,11 @@
2519e6e5
ER
3751 { "server.groupid", "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3752 { "server.use-keep-alive", "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3753 { "server.force-lower-case-files", "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3754-
3755+
3756 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
3757 };
3758
3759-
3760+
3761 /* 0 */
3762 cv[0].destination = srv->srvconf.bindhost;
3763 cv[1].destination = srv->srvconf.errorlog_file;
1175ccec 3764@@ -102,33 +105,33 @@
2519e6e5
ER
3765 cv[4].destination = srv->srvconf.username;
3766 cv[5].destination = srv->srvconf.groupname;
3767 cv[6].destination = &(srv->srvconf.port);
3768-
3769+
3770 cv[9].destination = srv->srvconf.modules;
3771 cv[10].destination = srv->srvconf.event_handler;
3772 cv[11].destination = srv->srvconf.pid_file;
3773-
3774+
3775 cv[13].destination = &(srv->srvconf.max_worker);
3776 cv[23].destination = &(srv->srvconf.max_fds);
3777 cv[36].destination = &(srv->srvconf.log_request_header_on_error);
3778 cv[37].destination = &(srv->srvconf.log_state_handling);
3779-
3780+
3781 cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
3782-
3783+
3784 stat_cache_string = buffer_init();
3785 cv[41].destination = stat_cache_string;
3786 cv[43].destination = srv->srvconf.network_backend;
3787 cv[44].destination = srv->srvconf.upload_tempdirs;
3788 cv[45].destination = &(srv->srvconf.enable_cores);
3789-
3790+
3791 cv[42].destination = &(srv->srvconf.max_conns);
3792 cv[12].destination = &(srv->srvconf.max_request_size);
3793 srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
3794
3795 assert(srv->config_storage);
3796-
3797+
3798 for (i = 0; i < srv->config_context->used; i++) {
3799 specific_config *s;
3800-
3801+
3802 s = calloc(1, sizeof(specific_config));
3803 assert(s);
3804 s->document_root = buffer_init();
1175ccec 3805@@ -154,17 +157,18 @@
2519e6e5
ER
3806 s->global_kbytes_per_second = 0;
3807 s->global_bytes_per_second_cnt = 0;
3808 s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
3809-
3810+
3811 cv[2].destination = s->errorfile_prefix;
3812-
3813+
3814 cv[7].destination = s->server_tag;
3815 cv[8].destination = &(s->use_ipv6);
3816-
3817-
3818+
3819+
3820 /* 13 max-worker */
f26f9fd5
ER
3821 cv[14].destination = s->document_root;
3822 cv[15].destination = &(s->force_lowercase_filenames);
3823 cv[16].destination = &(s->log_condition_handling);
3824+ cv[46].destination = &(s->log_condition_cache_handling);
3825 cv[17].destination = &(s->max_keep_alive_requests);
3826 cv[18].destination = s->server_name;
3827 cv[19].destination = &(s->max_keep_alive_idle);
1175ccec 3828@@ -179,23 +183,23 @@
2519e6e5
ER
3829 cv[28].destination = s->mimetypes;
3830 cv[29].destination = s->ssl_pemfile;
3831 cv[30].destination = &(s->is_ssl);
3832-
3833+
3834 cv[31].destination = &(s->log_file_not_found);
3835 cv[32].destination = &(s->log_request_handling);
3836 cv[33].destination = &(s->log_response_header);
3837 cv[34].destination = &(s->log_request_header);
3838-
3839+
3840 cv[35].destination = &(s->allow_http11);
3841 cv[38].destination = s->ssl_ca_file;
3842 cv[40].destination = &(s->range_requests);
3843-
3844+
3845 srv->config_storage[i] = s;
3846-
3847+
3848 if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
3849 break;
3850 }
3851 }
3852-
3853+
3854 if (buffer_is_empty(stat_cache_string)) {
3855 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
3856 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
1175ccec 3857@@ -205,22 +209,22 @@
2519e6e5
ER
3858 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
3859 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
3860 } else {
3861- log_error_write(srv, __FILE__, __LINE__, "sb",
3862+ log_error_write(srv, __FILE__, __LINE__, "sb",
3863 "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string);
3864 ret = HANDLER_ERROR;
3865 }
3866-
3867+
3868 buffer_free(stat_cache_string);
3869-
3870+
3871 return ret;
3872-
3873-}
3874
3875+}
f26f9fd5 3876
f26f9fd5
ER
3877-#define PATCH(x) con->conf.x = s->x
3878+#define PATCH(x) \
3879+ con->conf.x = s->x
3880 int config_setup_connection(server *srv, connection *con) {
3881 specific_config *s = srv->config_storage[0];
2519e6e5
ER
3882-
3883+
3884 PATCH(allow_http11);
3885 PATCH(mimetypes);
3886 PATCH(document_root);
1175ccec 3887@@ -236,20 +240,21 @@
2519e6e5
ER
3888 PATCH(kbytes_per_second);
3889 PATCH(global_kbytes_per_second);
3890 PATCH(global_bytes_per_second_cnt);
3891-
3892+
3893 con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
3894 buffer_copy_string_buffer(con->server_name, s->server_name);
3895-
3896+
3897 PATCH(log_request_header);
3898 PATCH(log_response_header);
3899 PATCH(log_request_handling);
3900 PATCH(log_condition_handling);
3901+ PATCH(log_condition_cache_handling);
f26f9fd5 3902 PATCH(log_file_not_found);
2519e6e5
ER
3903-
3904+
f26f9fd5 3905 PATCH(range_requests);
2519e6e5
ER
3906 PATCH(force_lowercase_filenames);
3907 PATCH(is_ssl);
3908-
3909+
3910 PATCH(ssl_pemfile);
3911 PATCH(ssl_ca_file);
3912 return 0;
1175ccec 3913@@ -257,22 +262,22 @@
2519e6e5
ER
3914
3915 int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
3916 size_t i, j;
3917-
3918+
3919 /* skip the first, the global context */
3920 for (i = 1; i < srv->config_context->used; i++) {
3921 data_config *dc = (data_config *)srv->config_context->data[i];
3922 specific_config *s = srv->config_storage[i];
3923-
3924+
3925 /* not our stage */
3926 if (comp != dc->comp) continue;
3927-
3928+
3929 /* condition didn't match */
3930 if (!config_check_cond(srv, con, dc)) continue;
3931-
3932+
3933 /* merge config */
3934 for (j = 0; j < dc->value->used; j++) {
3935 data_unset *du = dc->value->data[j];
3936-
3937+
3938 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
3939 PATCH(document_root);
3940 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
1175ccec 3941@@ -315,11 +320,13 @@
f26f9fd5
ER
3942 PATCH(log_response_header);
3943 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
3944 PATCH(log_condition_handling);
3945+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-cache-handling"))) {
3946+ PATCH(log_condition_cache_handling);
3947 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
3948 PATCH(log_file_not_found);
3949 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
2519e6e5
ER
3950 PATCH(allow_http11);
3951- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
3952+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
3953 PATCH(force_lowercase_filenames);
3954 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
3955 PATCH(global_kbytes_per_second);
1175ccec 3956@@ -328,7 +335,7 @@
2519e6e5
ER
3957 }
3958 }
3959 }
3960-
3961+
3962 return 0;
3963 }
3964 #undef PATCH
1175ccec 3965@@ -336,15 +343,15 @@
2519e6e5
ER
3966 typedef struct {
3967 int foo;
3968 int bar;
3969-
3970+
3971 const buffer *source;
3972 const char *input;
3973 size_t offset;
3974 size_t size;
3975-
3976+
3977 int line_pos;
3978 int line;
3979-
3980+
3981 int in_key;
3982 int in_brace;
3983 int in_cond;
1175ccec 3984@@ -362,7 +369,7 @@
2519e6e5
ER
3985 }
3986
3987 if (0 != stream_open(&(t->s), t->file)) {
3988- log_error_write(srv, __FILE__, __LINE__, "sbss",
3989+ log_error_write(srv, __FILE__, __LINE__, "sbss",
3990 "opening configfile ", t->file, "failed:", strerror(errno));
3991 buffer_free(t->file);
3992 return -1;
1175ccec 3993@@ -373,7 +380,7 @@
2519e6e5
ER
3994 t->size = t->s.size;
3995 t->line = 1;
3996 t->line_pos = 1;
3997-
3998+
3999 t->in_key = 1;
4000 t->in_brace = 0;
4001 t->in_cond = 0;
1175ccec 4002@@ -401,7 +408,7 @@
2519e6e5
ER
4003 static int config_skip_comment(tokenizer_t *t) {
4004 int i;
4005 assert(t->input[t->offset] == '#');
4006- for (i = 1; t->input[t->offset + i] &&
4007+ for (i = 1; t->input[t->offset + i] &&
4008 (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
4009 i++);
4010 t->offset += i;
1175ccec 4011@@ -411,44 +418,44 @@
2519e6e5
ER
4012 static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
4013 int tid = 0;
4014 size_t i;
4015-
4016+
4017 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
4018 char c = t->input[t->offset];
4019 const char *start = NULL;
4020-
4021+
4022 switch (c) {
4023- case '=':
4024+ case '=':
4025 if (t->in_brace) {
4026 if (t->input[t->offset + 1] == '>') {
4027 t->offset += 2;
4028-
4029+
4030 buffer_copy_string(token, "=>");
4031-
4032+
4033 tid = TK_ARRAY_ASSIGN;
4034 } else {
4035- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4036+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4037 "source:", t->source,
4038- "line:", t->line, "pos:", t->line_pos,
4039+ "line:", t->line, "pos:", t->line_pos,
4040 "use => for assignments in arrays");
4041 return -1;
4042 }
4043 } else if (t->in_cond) {
4044 if (t->input[t->offset + 1] == '=') {
4045 t->offset += 2;
4046-
4047+
4048 buffer_copy_string(token, "==");
4049-
4050+
4051 tid = TK_EQ;
4052 } else if (t->input[t->offset + 1] == '~') {
4053 t->offset += 2;
4054-
4055+
4056 buffer_copy_string(token, "=~");
4057-
4058+
4059 tid = TK_MATCH;
4060 } else {
4061- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4062+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4063 "source:", t->source,
4064- "line:", t->line, "pos:", t->line_pos,
4065+ "line:", t->line, "pos:", t->line_pos,
4066 "only =~ and == are allowed in the condition");
4067 return -1;
4068 }
1175ccec 4069@@ -456,51 +463,51 @@
2519e6e5
ER
4070 t->in_cond = 0;
4071 } else if (t->in_key) {
4072 tid = TK_ASSIGN;
4073-
4074+
4075 buffer_copy_string_len(token, t->input + t->offset, 1);
4076-
4077+
4078 t->offset++;
4079 t->line_pos++;
4080 } else {
4081- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4082+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4083 "source:", t->source,
4084- "line:", t->line, "pos:", t->line_pos,
4085+ "line:", t->line, "pos:", t->line_pos,
4086 "unexpected equal-sign: =");
4087 return -1;
4088 }
4089-
4090+
4091 break;
4092- case '!':
4093+ case '!':
4094 if (t->in_cond) {
4095 if (t->input[t->offset + 1] == '=') {
4096 t->offset += 2;
4097-
4098+
4099 buffer_copy_string(token, "!=");
4100-
4101+
4102 tid = TK_NE;
4103 } else if (t->input[t->offset + 1] == '~') {
4104 t->offset += 2;
4105-
4106+
4107 buffer_copy_string(token, "!~");
4108-
4109+
4110 tid = TK_NOMATCH;
4111 } else {
4112- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4113+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4114 "source:", t->source,
4115- "line:", t->line, "pos:", t->line_pos,
4116+ "line:", t->line, "pos:", t->line_pos,
4117 "only !~ and != are allowed in the condition");
4118 return -1;
4119 }
4120 t->in_key = 1;
4121 t->in_cond = 0;
4122 } else {
4123- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4124+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4125 "source:", t->source,
4126- "line:", t->line, "pos:", t->line_pos,
4127+ "line:", t->line, "pos:", t->line_pos,
4128 "unexpected exclamation-marks: !");
4129 return -1;
4130 }
4131-
4132+
4133 break;
4134 case '\t':
4135 case ' ':
1175ccec 4136@@ -546,10 +553,10 @@
2519e6e5
ER
4137 case ',':
4138 if (t->in_brace > 0) {
4139 tid = TK_COMMA;
4140-
4141+
4142 buffer_copy_string(token, "(COMMA)");
4143 }
4144-
4145+
4146 t->offset++;
4147 t->line_pos++;
4148 break;
1175ccec 4149@@ -557,70 +564,70 @@
2519e6e5
ER
4150 /* search for the terminating " */
4151 start = t->input + t->offset + 1;
4152 buffer_copy_string(token, "");
4153-
4154+
4155 for (i = 1; t->input[t->offset + i]; i++) {
4156 if (t->input[t->offset + i] == '\\' &&
4157 t->input[t->offset + i + 1] == '"') {
4158-
4159+
4160 buffer_append_string_len(token, start, t->input + t->offset + i - start);
4161-
4162+
4163 start = t->input + t->offset + i + 1;
4164-
4165+
4166 /* skip the " */
4167 i++;
4168 continue;
4169 }
4170-
4171-
4172+
4173+
4174 if (t->input[t->offset + i] == '"') {
4175 tid = TK_STRING;
4176-
4177+
4178 buffer_append_string_len(token, start, t->input + t->offset + i - start);
4179-
4180+
4181 break;
4182 }
4183 }
4184
4185 if (t->input[t->offset + i] == '\0') {
4186 /* ERROR */
4187-
4188- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4189+
4190+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4191 "source:", t->source,
4192- "line:", t->line, "pos:", t->line_pos,
4193+ "line:", t->line, "pos:", t->line_pos,
4194 "missing closing quote");
4195-
4196+
4197 return -1;
4198 }
4199-
4200+
4201 t->offset += i + 1;
4202 t->line_pos += i + 1;
4203-
4204+
4205 break;
4206 case '(':
4207 t->offset++;
4208 t->in_brace++;
4209-
4210+
4211 tid = TK_LPARAN;
4212-
4213+
4214 buffer_copy_string(token, "(");
4215 break;
4216 case ')':
4217 t->offset++;
4218 t->in_brace--;
4219-
4220+
4221 tid = TK_RPARAN;
4222-
4223+
4224 buffer_copy_string(token, ")");
4225 break;
4226 case '$':
4227 t->offset++;
4228-
4229+
4230 tid = TK_DOLLAR;
4231 t->in_cond = 1;
4232 t->in_key = 0;
4233-
4234+
4235 buffer_copy_string(token, "$");
4236-
4237+
4238 break;
4239
4240 case '+':
1175ccec 4241@@ -637,96 +644,88 @@
2519e6e5
ER
4242
4243 case '{':
4244 t->offset++;
4245-
4246+
4247 tid = TK_LCURLY;
4248-
4249+
4250 buffer_copy_string(token, "{");
4251-
4252+
4253 break;
4254-
4255+
4256 case '}':
4257 t->offset++;
4258-
4259+
4260 tid = TK_RCURLY;
4261-
4262+
4263 buffer_copy_string(token, "}");
4264-
4265+
4266 break;
4267
4268 case '[':
4269 t->offset++;
4270-
4271+
4272 tid = TK_LBRACKET;
4273-
4274+
4275 buffer_copy_string(token, "[");
4276-
4277+
4278 break;
4279-
4280+
4281 case ']':
4282 t->offset++;
4283-
4284+
4285 tid = TK_RBRACKET;
4286-
4287+
4288 buffer_copy_string(token, "]");
4289-
4290+
4291 break;
4292 case '#':
4293 t->line_pos += config_skip_comment(t);
4294-
4295+
4296 break;
4297 default:
4298 if (t->in_cond) {
4299- for (i = 0; t->input[t->offset + i] &&
4300+ for (i = 0; t->input[t->offset + i] &&
4301 (isalpha((unsigned char)t->input[t->offset + i])
4302 ); i++);
4303-
4304+
4305 if (i && t->input[t->offset + i]) {
4306 tid = TK_SRVVARNAME;
4307 buffer_copy_string_len(token, t->input + t->offset, i);
4308-
4309+
4310 t->offset += i;
4311 t->line_pos += i;
4312 } else {
4313 /* ERROR */
4314- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4315+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4316 "source:", t->source,
4317- "line:", t->line, "pos:", t->line_pos,
4318+ "line:", t->line, "pos:", t->line_pos,
4319 "invalid character in condition");
4320 return -1;
4321 }
4322 } else if (isdigit((unsigned char)c)) {
4323 /* take all digits */
f26f9fd5 4324 for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
2519e6e5
ER
4325-
4326+
f26f9fd5
ER
4327 /* was there it least a digit ? */
4328- if (i && t->input[t->offset + i]) {
4329+ if (i) {
4330 tid = TK_INTEGER;
2519e6e5
ER
4331-
4332+
f26f9fd5 4333 buffer_copy_string_len(token, t->input + t->offset, i);
2519e6e5
ER
4334-
4335+
f26f9fd5
ER
4336 t->offset += i;
4337 t->line_pos += i;
4338- } else {
4339- /* ERROR */
4340- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4341- "source:", t->source,
4342- "line:", t->line, "pos:", t->line_pos,
4343- "unexpected EOF");
f673a614 4344-
f26f9fd5 4345- return -1;
f673a614 4346 }
f26f9fd5
ER
4347 } else {
4348 /* the key might consist of [-.0-9a-z] */
2519e6e5
ER
4349- for (i = 0; t->input[t->offset + i] &&
4350- (isalnum((unsigned char)t->input[t->offset + i]) ||
4351+ for (i = 0; t->input[t->offset + i] &&
4352+ (isalnum((unsigned char)t->input[t->offset + i]) ||
4353 t->input[t->offset + i] == '.' ||
4354 t->input[t->offset + i] == '_' || /* for env.* */
4355 t->input[t->offset + i] == '-'
4356 ); i++);
4357-
4358+
4359 if (i && t->input[t->offset + i]) {
4360 buffer_copy_string_len(token, t->input + t->offset, i);
4361-
4362+
4363 if (strcmp(token->ptr, "include") == 0) {
4364 tid = TK_INCLUDE;
4365 } else if (strcmp(token->ptr, "include_shell") == 0) {
1175ccec 4366@@ -738,14 +737,14 @@
2519e6e5
ER
4367 } else {
4368 tid = TK_LKEY;
4369 }
4370-
4371+
4372 t->offset += i;
4373 t->line_pos += i;
4374 } else {
4375 /* ERROR */
4376- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4377+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4378 "source:", t->source,
4379- "line:", t->line, "pos:", t->line_pos,
4380+ "line:", t->line, "pos:", t->line_pos,
4381 "invalid character in variable name");
4382 return -1;
4383 }
1175ccec 4384@@ -753,16 +752,16 @@
2519e6e5
ER
4385 break;
4386 }
4387 }
4388-
4389+
4390 if (tid) {
4391 *token_id = tid;
4392 #if 0
4393- log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
4394+ log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
4395 "source:", t->source,
4396 "line:", t->line, "pos:", t->line_pos,
4397 token, token->used - 1, tid);
4398 #endif
4399-
4400+
4401 return 1;
4402 } else if (t->offset < t->size) {
4403 fprintf(stderr, "%s.%d: %d, %s\n",
1175ccec 4404@@ -781,10 +780,11 @@
f26f9fd5
ER
4405 pParser = configparserAlloc( malloc );
4406 lasttoken = buffer_init();
4407 token = buffer_init();
f673a614 4408+
f26f9fd5
ER
4409 while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
4410 buffer_copy_string_buffer(lasttoken, token);
4411 configparser(pParser, token_id, token, context);
2519e6e5
ER
4412-
4413+
4414 token = buffer_init();
4415 }
4416 buffer_free(token);
1175ccec 4417@@ -797,14 +797,14 @@
2519e6e5
ER
4418 }
4419 }
4420 configparserFree(pParser, free);
4421-
4422+
4423 if (ret == -1) {
4424- log_error_write(srv, __FILE__, __LINE__, "sb",
4425+ log_error_write(srv, __FILE__, __LINE__, "sb",
4426 "configfile parser failed:", lasttoken);
4427 } else if (context->ok == 0) {
4428- log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
4429+ log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
4430 "source:", t->source,
4431- "line:", t->line, "pos:", t->line_pos,
4432+ "line:", t->line, "pos:", t->line_pos,
4433 "parser failed somehow near here:", lasttoken);
4434 ret = -1;
4435 }
1175ccec 4436@@ -821,7 +821,7 @@
2519e6e5
ER
4437 t->offset = 0;
4438 t->line = 1;
4439 t->line_pos = 1;
4440-
4441+
4442 t->in_key = 1;
4443 t->in_brace = 0;
4444 t->in_cond = 0;
1175ccec 4445@@ -844,7 +844,7 @@
2519e6e5
ER
4446 }
4447
4448 if (0 != stream_open(&s, filename)) {
4449- log_error_write(srv, __FILE__, __LINE__, "sbss",
4450+ log_error_write(srv, __FILE__, __LINE__, "sbss",
4451 "opening configfile ", filename, "failed:", strerror(errno));
4452 ret = -1;
4453 } else {
1175ccec 4454@@ -866,7 +866,7 @@
2519e6e5
ER
4455 char oldpwd[PATH_MAX];
4456
4457 if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
4458- log_error_write(srv, __FILE__, __LINE__, "s",
4459+ log_error_write(srv, __FILE__, __LINE__, "s",
4460 "cannot get cwd", strerror(errno));
4461 return -1;
4462 }
1175ccec 4463@@ -879,7 +879,7 @@
2519e6e5
ER
4464 }
4465
4466 if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
4467- log_error_write(srv, __FILE__, __LINE__, "sbss",
4468+ log_error_write(srv, __FILE__, __LINE__, "sbss",
4469 "opening", source, "failed:", strerror(errno));
4470 ret = -1;
4471 } else {
1175ccec 4472@@ -896,13 +896,12 @@
2519e6e5
ER
4473 static void context_init(server *srv, config_t *context) {
4474 context->srv = srv;
4475 context->ok = 1;
4476- context->configs_stack = array_init();
4477- context->configs_stack->is_weakref = 1;
4478+ context->configs_stack = buffer_ptr_init(NULL);
4479 context->basedir = buffer_init();
4480 }
4481
4482 static void context_free(config_t *context) {
4483- array_free(context->configs_stack);
4484+ buffer_ptr_free(context->configs_stack);
4485 buffer_free(context->basedir);
f26f9fd5 4486 }
f673a614 4487
1175ccec 4488@@ -918,18 +917,15 @@
f26f9fd5
ER
4489 context_init(srv, &context);
4490 context.all_configs = srv->config_context;
f673a614 4491
f26f9fd5
ER
4492- pos = strrchr(fn,
4493-#ifdef __WIN32
4494- '\\'
4495-#else
4496- '/'
4497-#endif
4498- );
4499+ /* use the current dir as basedir for all other includes
4500+ */
4501+ pos = strrchr(fn, DIR_SEPERATOR);
f673a614 4502+
f26f9fd5
ER
4503 if (pos) {
4504 buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
4505 fn = pos + 1;
2519e6e5
ER
4506 }
4507-
4508+
4509 dc = data_config_init();
4510 buffer_copy_string(dc->key, "global");
4511
1175ccec
ER
4512@@ -944,7 +940,7 @@
4513 dpid->value = getpid();
2519e6e5
ER
4514 buffer_copy_string(dpid->key, "var.PID");
4515 array_insert_unique(srv->config, (data_unset *)dpid);
4516-
4517+
4518 dcwd = data_string_init();
4519 buffer_prepare_copy(dcwd->value, 1024);
4520 if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
1175ccec 4521@@ -968,7 +964,7 @@
2519e6e5
ER
4522 } else {
4523 return -1;
4524 }
4525-
4526+
4527 if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
4528 data_string *ds;
4529 data_array *prepends;
1175ccec 4530@@ -1026,22 +1022,23 @@
2519e6e5
ER
4531 buffer_copy_string(modules->key, "server.modules");
4532 array_insert_unique(srv->config, (data_unset *)modules);
4533 }
4534-
4535+
4536
4537 if (0 != config_insert(srv)) {
4538 return -1;
4539 }
4540-
4541+
f26f9fd5 4542 return 0;
f673a614
ER
4543 }
4544
f673a614 4545+
f26f9fd5
ER
4546 int config_set_defaults(server *srv) {
4547 size_t i;
4548 specific_config *s = srv->config_storage[0];
2519e6e5
ER
4549 struct stat st1, st2;
4550-
4551- struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4552- {
4553+
4554+ struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4555+ {
4556 /* - poll is most reliable
4557 * - select works everywhere
4558 * - linux-* are experimental
1175ccec 4559@@ -1067,20 +1064,21 @@
2519e6e5
ER
4560 #endif
4561 { FDEVENT_HANDLER_UNSET, NULL }
4562 };
4563-
4564
4565- if (buffer_is_empty(s->document_root)) {
4566- log_error_write(srv, __FILE__, __LINE__, "s",
4567- "a default document-root has to be set");
4568-
4569- return -1;
4570- }
4571-
4572+
4573+ if (buffer_is_empty(s->document_root)) {
4574+ log_error_write(srv, __FILE__, __LINE__, "s",
4575+ "a default document-root has to be set");
4576+
4577+ return -1;
4578+ }
4579+
f26f9fd5 4580 if (buffer_is_empty(srv->srvconf.changeroot)) {
2519e6e5 4581- if (-1 == stat(s->document_root->ptr, &st1)) {
f26f9fd5 4582- log_error_write(srv, __FILE__, __LINE__, "sb",
2519e6e5
ER
4583+ pathname_unix2local(s->document_root);
4584+ if (-1 == stat(s->document_root->ptr, &st1)) {
f26f9fd5
ER
4585+ log_error_write(srv, __FILE__, __LINE__, "sbs",
4586 "base-docroot doesn't exist:",
4587- s->document_root);
4588+ s->document_root, strerror(errno));
4589 return -1;
f673a614 4590 }
f673a614 4591
1175ccec 4592@@ -1088,18 +1086,18 @@
2519e6e5
ER
4593 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
4594 buffer_append_string_buffer(srv->tmp_buf, s->document_root);
4595
4596- if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
4597- log_error_write(srv, __FILE__, __LINE__, "sb",
4598+ if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
4599+ log_error_write(srv, __FILE__, __LINE__, "sb",
4600 "base-docroot doesn't exist:",
4601- srv->tmp_buf);
4602+ srv->tmp_buf);
4603 return -1;
4604 }
4605-
4606+
4607 }
4608-
4609- buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4610
4611- buffer_to_lower(srv->tmp_buf);
4612+ buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4613+
4614+ buffer_to_lower(srv->tmp_buf);
4615
4616 if (0 == stat(srv->tmp_buf->ptr, &st1)) {
4617 int is_lower = 0;
1175ccec 4618@@ -1107,68 +1105,68 @@
2519e6e5
ER
4619 is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
4620
4621 /* lower-case existed, check upper-case */
4622- buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4623+ buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4624
4625- buffer_to_upper(srv->tmp_buf);
4626+ buffer_to_upper(srv->tmp_buf);
4627
4628 /* we have to handle the special case that upper and lower-casing results in the same filename
4629 * as in server.document-root = "/" or "/12345/" */
4630
4631 if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
4632- /* lower-casing and upper-casing didn't result in
4633- * an other filename, no need to stat(),
4634+ /* lower-casing and upper-casing didn't result in
4635+ * an other filename, no need to stat(),
4636 * just assume it is case-sensitive. */
4637
4638 s->force_lowercase_filenames = 0;
4639- } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
4640+ } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
4641+
4642+ /* upper case exists too, doesn't the FS handle this ? */
4643+
4644+ /* upper and lower have the same inode -> case-insensitve FS */
4645+
4646+ if (st1.st_ino == st2.st_ino) {
4647+ /* upper and lower have the same inode -> case-insensitve FS */
4648+
4649+ s->force_lowercase_filenames = 1;
4650+ }
4651+ }
4652+ }
4653
4654- /* upper case exists too, doesn't the FS handle this ? */
4655-
4656- /* upper and lower have the same inode -> case-insensitve FS */
4657-
4658- if (st1.st_ino == st2.st_ino) {
4659- /* upper and lower have the same inode -> case-insensitve FS */
4660-
4661- s->force_lowercase_filenames = 1;
4662- }
4663- }
4664- }
4665-
4666 if (srv->srvconf.port == 0) {
4667 srv->srvconf.port = s->is_ssl ? 443 : 80;
4668 }
4669-
4670+
4671 if (srv->srvconf.event_handler->used == 0) {
4672 /* choose a good default
4673- *
4674- * the event_handler list is sorted by 'goodness'
4675+ *
4676+ * the event_handler list is sorted by 'goodness'
4677 * taking the first available should be the best solution
4678 */
4679 srv->event_handler = event_handlers[0].et;
4680-
4681+
4682 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4683- log_error_write(srv, __FILE__, __LINE__, "s",
4684+ log_error_write(srv, __FILE__, __LINE__, "s",
4685 "sorry, there is no event handler for this system");
4686-
4687+
4688 return -1;
4689 }
4690 } else {
4691 /*
4692 * User override
4693 */
4694-
4695+
4696 for (i = 0; event_handlers[i].name; i++) {
4697 if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
4698 srv->event_handler = event_handlers[i].et;
4699 break;
4700 }
4701 }
4702-
4703+
4704 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4705- log_error_write(srv, __FILE__, __LINE__, "sb",
4706- "the selected event-handler in unknown or not supported:",
4707+ log_error_write(srv, __FILE__, __LINE__, "sb",
4708+ "the selected event-handler in unknown or not supported:",
4709 srv->srvconf.event_handler );
4710-
4711+
4712 return -1;
4713 }
4714 }
1175ccec 4715@@ -1176,19 +1174,19 @@
2519e6e5
ER
4716 if (s->is_ssl) {
4717 if (buffer_is_empty(s->ssl_pemfile)) {
4718 /* PEM file is require */
4719-
4720- log_error_write(srv, __FILE__, __LINE__, "s",
4721+
4722+ log_error_write(srv, __FILE__, __LINE__, "s",
4723 "ssl.pemfile has to be set");
4724 return -1;
4725 }
4726-
4727+
4728 #ifndef USE_OPENSSL
4729- log_error_write(srv, __FILE__, __LINE__, "s",
4730+ log_error_write(srv, __FILE__, __LINE__, "s",
4731 "ssl support is missing, recompile with --with-openssl");
4732-
4733+
4734 return -1;
4735 #endif
4736 }
4737-
4738+
4739 return 0;
4740 }
1175ccec 4741--- ../lighttpd-1.4.11/src/configfile.h 2005-08-23 17:36:12.000000000 +0300
36e2a29e 4742+++ lighttpd-1.4.12/src/configfile.h 2006-07-11 22:07:51.000000000 +0300
f26f9fd5
ER
4743@@ -9,7 +9,7 @@
4744 server *srv;
4745 int ok;
4746 array *all_configs;
4747- array *configs_stack; /* to parse nested block */
4748+ buffer_ptr *configs_stack; /* to parse nested block */
4749 data_config *current; /* current started with { */
4750 buffer *basedir;
4751 } config_t;
1175ccec 4752--- ../lighttpd-1.4.11/src/configparser.c 2006-02-01 19:51:15.000000000 +0200
36e2a29e 4753+++ lighttpd-1.4.12/src/configparser.c 2006-07-11 22:08:02.000000000 +0300
2519e6e5 4754@@ -24,52 +24,34 @@
f26f9fd5
ER
4755 dc->parent = ctx->current;
4756 array_insert_unique(dc->parent->childs, (data_unset *)dc);
4757 }
4758- array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
4759+ buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
4760 ctx->current = dc;
4761 }
f673a614 4762
f26f9fd5
ER
4763 static data_config *configparser_pop(config_t *ctx) {
4764 data_config *old = ctx->current;
4765- ctx->current = (data_config *) array_pop(ctx->configs_stack);
4766+ ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
4767 return old;
f673a614
ER
4768 }
4769
f26f9fd5
ER
4770 /* return a copied variable */
4771 static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
4772- if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
4773- char *env;
4774-
4775- if (NULL != (env = getenv(key->ptr + 4))) {
4776- data_string *ds;
4777- ds = data_string_init();
4778- buffer_append_string(ds->value, env);
4779- return (data_unset *)ds;
4780- }
4781-
4782- fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
4783- ctx->ok = 0;
4784-
4785- return NULL;
4786- } else {
2519e6e5
ER
4787- data_unset *du;
4788- data_config *dc;
4789+ data_unset *du;
4790+ data_config *dc;
f673a614 4791
2519e6e5
ER
4792 #if 0
4793- fprintf(stderr, "get var %s\n", key->ptr);
4794+ fprintf(stderr, "get var %s\n", key->ptr);
4795 #endif
4796- for (dc = ctx->current; dc; dc = dc->parent) {
4797+ for (dc = ctx->current; dc; dc = dc->parent) {
4798 #if 0
4799- fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
4800- array_print(dc->value, 0);
4801+ fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
4802+ array_print(dc->value, 0);
4803 #endif
4804- if (NULL != (du = array_get_element(dc->value, key->ptr))) {
4805- return du->copy(du);
4806- }
4807+ if (NULL != (du = array_get_element(dc->value, key->ptr))) {
4808+ return du->copy(du);
f26f9fd5
ER
4809 }
4810- fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
4811- ctx->ok = 0;
2519e6e5 4812- return NULL;
f26f9fd5 4813 }
2519e6e5
ER
4814+ return NULL;
4815 }
f673a614 4816
f26f9fd5 4817 /* op1 is to be eat/return by this function, op1->key is not cared
2519e6e5
ER
4818@@ -124,14 +106,14 @@
4819 }
f673a614 4820
2519e6e5
ER
4821
4822-#line 128 "configparser.c"
4823+#line 110 "configparser.c"
4824 /* Next is all token values, in a form suitable for use by makeheaders.
4825 ** This section will be null unless lemon is run with the -m switch.
4826 */
4827-/*
4828+/*
4829 ** These constants (all generated automatically by the parser generator)
4830 ** specify the various kinds of tokens (terminals) that the parser
4831-** understands.
4832+** understands.
4833 **
4834 ** Each symbol here is a terminal symbol in the grammar.
4835 */
4836@@ -148,7 +130,7 @@
4837 ** and nonterminals. "int" is used otherwise.
4838 ** YYNOCODE is a number of type YYCODETYPE which corresponds
4839 ** to no legal terminal or nonterminal number. This
4840-** number is used to fill in empty slots of the hash
4841+** number is used to fill in empty slots of the hash
4842 ** table.
4843 ** YYFALLBACK If defined, this indicates that one or more tokens
4844 ** have fall-back values which should be used if the
4845@@ -157,7 +139,7 @@
4846 ** and nonterminal numbers. "unsigned char" is
4847 ** used if there are fewer than 250 rules and
4848 ** states combined. "int" is used otherwise.
4849-** configparserTOKENTYPE is the data type used for minor tokens given
4850+** configparserTOKENTYPE is the data type used for minor tokens given
4851 ** directly to the parser from the tokenizer.
4852 ** YYMINORTYPE is the data type used for all minor tokens.
4853 ** This is typically a union of many types, one of
4854@@ -192,8 +174,8 @@
4855 #define configparserARG_PDECL ,config_t *ctx
4856 #define configparserARG_FETCH config_t *ctx = yypParser->ctx
4857 #define configparserARG_STORE yypParser->ctx = ctx
4858-#define YYNSTATE 62
4859-#define YYNRULE 39
4860+#define YYNSTATE 63
4861+#define YYNRULE 40
4862 #define YYERRORSYMBOL 26
4863 #define YYERRSYMDT yy95
4864 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
4865@@ -203,7 +185,7 @@
4866 /* Next are that tables used to determine what action to take based on the
4867 ** current state and lookahead token. These tables are used to implement
4868 ** functions that take a state number and lookahead value and return an
4869-** action integer.
4870+** action integer.
4871 **
4872 ** Suppose the action integer is N. Then the action is determined as
4873 ** follows
4874@@ -228,7 +210,7 @@
4875 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
4876 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
4877 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
4878-** and that yy_default[S] should be used instead.
4879+** and that yy_default[S] should be used instead.
4880 **
4881 ** The formula above is for computing the action when the lookahead is
4882 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
4883@@ -248,67 +230,69 @@
4884 ** yy_default[] Default action for each state.
4885 */
4886 static YYACTIONTYPE yy_action[] = {
4887- /* 0 */ 2, 3, 4, 5, 13, 14, 62, 15, 7, 44,
4888- /* 10 */ 20, 86, 16, 45, 28, 48, 40, 10, 39, 25,
4889- /* 20 */ 22, 49, 45, 8, 15, 102, 1, 20, 28, 18,
4890- /* 30 */ 57, 59, 19, 25, 22, 39, 19, 61, 98, 45,
4891- /* 40 */ 20, 6, 23, 24, 26, 28, 35, 57, 59, 12,
4892- /* 50 */ 25, 22, 28, 27, 36, 87, 29, 25, 22, 33,
4893- /* 60 */ 15, 30, 31, 20, 28, 38, 9, 17, 37, 25,
4894- /* 70 */ 22, 39, 42, 43, 10, 45, 11, 53, 54, 55,
4895- /* 80 */ 56, 28, 52, 57, 59, 34, 25, 22, 28, 27,
4896- /* 90 */ 32, 88, 41, 25, 22, 33, 28, 48, 46, 28,
4897- /* 100 */ 48, 25, 22, 58, 25, 22, 60, 21, 19, 47,
4898- /* 110 */ 51, 50, 25, 22, 88, 88, 93,
4899+ /* 0 */ 2, 3, 4, 5, 13, 14, 63, 15, 7, 45,
4900+ /* 10 */ 20, 88, 16, 46, 28, 49, 41, 10, 40, 25,
4901+ /* 20 */ 22, 50, 46, 8, 15, 104, 1, 20, 28, 18,
4902+ /* 30 */ 58, 60, 6, 25, 22, 40, 47, 62, 11, 46,
4903+ /* 40 */ 20, 9, 23, 24, 26, 29, 89, 58, 60, 10,
4904+ /* 50 */ 17, 38, 28, 27, 37, 19, 30, 25, 22, 34,
4905+ /* 60 */ 15, 100, 20, 20, 23, 24, 26, 12, 19, 31,
4906+ /* 70 */ 32, 40, 19, 44, 43, 46, 95, 35, 90, 89,
4907+ /* 80 */ 28, 49, 42, 58, 60, 25, 22, 59, 28, 27,
4908+ /* 90 */ 33, 48, 52, 25, 22, 34, 28, 49, 51, 28,
4909+ /* 100 */ 36, 25, 22, 61, 25, 22, 89, 28, 39, 89,
4910+ /* 110 */ 89, 89, 25, 22, 54, 55, 56, 57, 89, 28,
4911+ /* 120 */ 53, 21, 89, 89, 25, 22, 25, 22,
4912 };
4913 static YYCODETYPE yy_lookahead[] = {
4914 /* 0 */ 29, 30, 31, 32, 33, 34, 0, 1, 44, 38,
4915 /* 10 */ 4, 15, 41, 16, 35, 36, 45, 46, 12, 40,
4916 /* 20 */ 41, 42, 16, 15, 1, 27, 28, 4, 35, 36,
4917- /* 30 */ 24, 25, 5, 40, 41, 12, 5, 14, 11, 16,
4918- /* 40 */ 4, 1, 6, 7, 8, 35, 36, 24, 25, 28,
4919- /* 50 */ 40, 41, 35, 36, 37, 15, 39, 40, 41, 42,
4920- /* 60 */ 1, 9, 10, 4, 35, 36, 38, 2, 3, 40,
4921- /* 70 */ 41, 12, 28, 14, 46, 16, 13, 20, 21, 22,
4922- /* 80 */ 23, 35, 36, 24, 25, 11, 40, 41, 35, 36,
4923- /* 90 */ 37, 13, 13, 40, 41, 42, 35, 36, 17, 35,
4924- /* 100 */ 36, 40, 41, 42, 40, 41, 42, 35, 5, 18,
4925- /* 110 */ 43, 19, 40, 41, 47, 47, 13,
4926+ /* 30 */ 24, 25, 1, 40, 41, 12, 17, 14, 13, 16,
4927+ /* 40 */ 4, 38, 6, 7, 8, 9, 15, 24, 25, 46,
4928+ /* 50 */ 2, 3, 35, 36, 37, 5, 39, 40, 41, 42,
4929+ /* 60 */ 1, 11, 4, 4, 6, 7, 8, 28, 5, 9,
4930+ /* 70 */ 10, 12, 5, 14, 28, 16, 13, 11, 13, 47,
4931+ /* 80 */ 35, 36, 13, 24, 25, 40, 41, 42, 35, 36,
4932+ /* 90 */ 37, 18, 43, 40, 41, 42, 35, 36, 19, 35,
4933+ /* 100 */ 36, 40, 41, 42, 40, 41, 47, 35, 36, 47,
4934+ /* 110 */ 47, 47, 40, 41, 20, 21, 22, 23, 47, 35,
4935+ /* 120 */ 36, 35, 47, 47, 40, 41, 40, 41,
4936 };
4937 #define YY_SHIFT_USE_DFLT (-5)
4938 static signed char yy_shift_ofst[] = {
4939- /* 0 */ -5, 6, -5, -5, -5, 40, -4, 8, -3, -5,
4940- /* 10 */ 63, -5, 23, -5, -5, -5, 65, 36, 31, 36,
4941- /* 20 */ -5, -5, -5, -5, -5, -5, 36, 27, -5, 52,
4942- /* 30 */ -5, 36, -5, 74, 36, 31, -5, 36, 31, 78,
4943- /* 40 */ 79, -5, 59, -5, -5, 81, 91, 36, 31, 92,
4944- /* 50 */ 57, 36, 103, -5, -5, -5, -5, 36, -5, 36,
4945- /* 60 */ -5, -5,
4946+ /* 0 */ -5, 6, -5, -5, -5, 31, -4, 8, -3, -5,
4947+ /* 10 */ 25, -5, 23, -5, -5, -5, 48, 58, 67, 58,
4948+ /* 20 */ -5, -5, -5, -5, -5, -5, 36, 50, -5, -5,
4949+ /* 30 */ 60, -5, 58, -5, 66, 58, 67, -5, 58, 67,
4950+ /* 40 */ 65, 69, -5, 59, -5, -5, 19, 73, 58, 67,
4951+ /* 50 */ 79, 94, 58, 63, -5, -5, -5, -5, 58, -5,
4952+ /* 60 */ 58, -5, -5,
4953 };
4954 #define YY_REDUCE_USE_DFLT (-37)
4955 static signed char yy_reduce_ofst[] = {
4956- /* 0 */ -2, -29, -37, -37, -37, -36, -37, -37, 28, -37,
4957- /* 10 */ -37, 21, -29, -37, -37, -37, -37, -7, -37, 72,
4958+ /* 0 */ -2, -29, -37, -37, -37, -36, -37, -37, 3, -37,
4959+ /* 10 */ -37, 39, -29, -37, -37, -37, -37, -7, -37, 86,
4960 /* 20 */ -37, -37, -37, -37, -37, -37, 17, -37, -37, -37,
4961- /* 30 */ -37, 53, -37, -37, 10, -37, -37, 29, -37, -37,
4962- /* 40 */ -37, 44, -29, -37, -37, -37, -37, -21, -37, -37,
4963- /* 50 */ 67, 46, -37, -37, -37, -37, -37, 61, -37, 64,
4964- /* 60 */ -37, -37,
4965+ /* 30 */ -37, -37, 53, -37, -37, 64, -37, -37, 72, -37,
4966+ /* 40 */ -37, -37, 46, -29, -37, -37, -37, -37, -21, -37,
4967+ /* 50 */ -37, 49, 84, -37, -37, -37, -37, -37, 45, -37,
4968+ /* 60 */ 61, -37, -37,
4969 };
4970 static YYACTIONTYPE yy_default[] = {
4971- /* 0 */ 64, 101, 63, 65, 66, 101, 67, 101, 101, 90,
4972- /* 10 */ 101, 64, 101, 68, 69, 70, 101, 101, 71, 101,
4973- /* 20 */ 73, 74, 76, 77, 78, 79, 101, 84, 75, 101,
4974- /* 30 */ 80, 82, 81, 101, 101, 85, 83, 101, 72, 101,
4975- /* 40 */ 101, 64, 101, 89, 91, 101, 101, 101, 98, 101,
4976- /* 50 */ 101, 101, 101, 94, 95, 96, 97, 101, 99, 101,
4977- /* 60 */ 100, 92,
4978+ /* 0 */ 65, 103, 64, 66, 67, 103, 68, 103, 103, 92,
4979+ /* 10 */ 103, 65, 103, 69, 70, 71, 103, 103, 72, 103,
4980+ /* 20 */ 74, 75, 77, 78, 79, 80, 103, 86, 76, 81,
4981+ /* 30 */ 103, 82, 84, 83, 103, 103, 87, 85, 103, 73,
4982+ /* 40 */ 103, 103, 65, 103, 91, 93, 103, 103, 103, 100,
4983+ /* 50 */ 103, 103, 103, 103, 96, 97, 98, 99, 103, 101,
4984+ /* 60 */ 103, 102, 94,
4985 };
4986 #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
4987
4988 /* The next table maps tokens into fallback tokens. If a construct
4989 ** like the following:
4990-**
4991+**
4992 ** %fallback ID X Y Z.
4993 **
4994 ** appears in the grammer, then ID becomes a fallback token for X, Y,
4995@@ -359,10 +343,10 @@
4996 #endif /* NDEBUG */
4997
4998 #ifndef NDEBUG
4999-/*
5000+/*
5001 ** Turn parser tracing on by giving a stream to which to write the trace
5002 ** and a prompt to preface each trace message. Tracing is turned off
5003-** by making either argument NULL
5004+** by making either argument NULL
5005 **
5006 ** Inputs:
5007 ** <ul>
5008@@ -387,7 +371,7 @@
5009 #ifndef NDEBUG
5010 /* For tracing shifts, the names of all terminals and nonterminals
5011 ** are required. The following table supplies these names */
5012-static const char *yyTokenName[] = {
5013+static const char *yyTokenName[] = {
5014 "$", "EOL", "ASSIGN", "APPEND",
5015 "LKEY", "PLUS", "STRING", "INTEGER",
5016 "LPARAN", "RPARAN", "COMMA", "ARRAY_ASSIGN",
5017@@ -425,27 +409,28 @@
5018 /* 15 */ "value ::= STRING",
5019 /* 16 */ "value ::= INTEGER",
5020 /* 17 */ "value ::= array",
5021- /* 18 */ "array ::= LPARAN aelements RPARAN",
5022- /* 19 */ "aelements ::= aelements COMMA aelement",
5023- /* 20 */ "aelements ::= aelements COMMA",
5024- /* 21 */ "aelements ::= aelement",
5025- /* 22 */ "aelement ::= expression",
5026- /* 23 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5027- /* 24 */ "eols ::= EOL",
5028- /* 25 */ "eols ::=",
5029- /* 26 */ "globalstart ::= GLOBAL",
5030- /* 27 */ "global ::= globalstart LCURLY metalines RCURLY",
5031- /* 28 */ "condlines ::= condlines eols ELSE condline",
5032- /* 29 */ "condlines ::= condline",
5033- /* 30 */ "condline ::= context LCURLY metalines RCURLY",
5034- /* 31 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5035- /* 32 */ "cond ::= EQ",
5036- /* 33 */ "cond ::= MATCH",
5037- /* 34 */ "cond ::= NE",
5038- /* 35 */ "cond ::= NOMATCH",
5039- /* 36 */ "stringop ::= expression",
5040- /* 37 */ "include ::= INCLUDE stringop",
5041- /* 38 */ "include_shell ::= INCLUDE_SHELL stringop",
5042+ /* 18 */ "array ::= LPARAN RPARAN",
5043+ /* 19 */ "array ::= LPARAN aelements RPARAN",
5044+ /* 20 */ "aelements ::= aelements COMMA aelement",
5045+ /* 21 */ "aelements ::= aelements COMMA",
5046+ /* 22 */ "aelements ::= aelement",
5047+ /* 23 */ "aelement ::= expression",
5048+ /* 24 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5049+ /* 25 */ "eols ::= EOL",
5050+ /* 26 */ "eols ::=",
5051+ /* 27 */ "globalstart ::= GLOBAL",
5052+ /* 28 */ "global ::= globalstart LCURLY metalines RCURLY",
5053+ /* 29 */ "condlines ::= condlines eols ELSE condline",
5054+ /* 30 */ "condlines ::= condline",
5055+ /* 31 */ "condline ::= context LCURLY metalines RCURLY",
5056+ /* 32 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5057+ /* 33 */ "cond ::= EQ",
5058+ /* 34 */ "cond ::= MATCH",
5059+ /* 35 */ "cond ::= NE",
5060+ /* 36 */ "cond ::= NOMATCH",
5061+ /* 37 */ "stringop ::= expression",
5062+ /* 38 */ "include ::= INCLUDE stringop",
5063+ /* 39 */ "include_shell ::= INCLUDE_SHELL stringop",
5064 };
5065 #endif /* NDEBUG */
5066
5067@@ -465,7 +450,7 @@
5068 #endif
5069 }
5070
5071-/*
5072+/*
5073 ** This function allocates a new parser.
5074 ** The only argument is a pointer to a function which works like
5075 ** malloc.
5076@@ -496,7 +481,7 @@
5077 /* Here is inserted the actions which take place when a
5078 ** terminal or non-terminal is destroyed. This can happen
5079 ** when the symbol is popped from the stack during a
5080- ** reduce or during error processing or when a parser is
5081+ ** reduce or during error processing or when a parser is
5082 ** being destroyed before it is finished parsing.
5083 **
5084 ** Note: during a reduce, the only symbols destroyed are those
5085@@ -528,44 +513,44 @@
5086 case 23:
5087 case 24:
5088 case 25:
5089-#line 160 "./configparser.y"
5090+#line 143 "./configparser.y"
5091 { buffer_free((yypminor->yy0)); }
5092-#line 533 "configparser.c"
5093+#line 518 "configparser.c"
5094 break;
5095 case 35:
5096-#line 151 "./configparser.y"
5097+#line 134 "./configparser.y"
5098 { (yypminor->yy41)->free((yypminor->yy41)); }
5099-#line 538 "configparser.c"
5100+#line 523 "configparser.c"
5101 break;
5102 case 36:
5103-#line 152 "./configparser.y"
5104+#line 135 "./configparser.y"
5105 { (yypminor->yy41)->free((yypminor->yy41)); }
5106-#line 543 "configparser.c"
5107+#line 528 "configparser.c"
5108 break;
5109 case 37:
5110-#line 153 "./configparser.y"
5111+#line 136 "./configparser.y"
5112 { (yypminor->yy41)->free((yypminor->yy41)); }
5113-#line 548 "configparser.c"
5114+#line 533 "configparser.c"
5115 break;
5116 case 39:
5117-#line 154 "./configparser.y"
5118+#line 137 "./configparser.y"
5119 { array_free((yypminor->yy40)); }
5120-#line 553 "configparser.c"
5121+#line 538 "configparser.c"
5122 break;
5123 case 40:
5124-#line 155 "./configparser.y"
5125+#line 138 "./configparser.y"
5126 { array_free((yypminor->yy40)); }
5127-#line 558 "configparser.c"
5128+#line 543 "configparser.c"
5129 break;
5130 case 41:
5131-#line 156 "./configparser.y"
5132+#line 139 "./configparser.y"
5133 { buffer_free((yypminor->yy43)); }
5134-#line 563 "configparser.c"
5135+#line 548 "configparser.c"
5136 break;
5137 case 42:
5138-#line 157 "./configparser.y"
5139+#line 140 "./configparser.y"
5140 { buffer_free((yypminor->yy43)); }
5141-#line 568 "configparser.c"
5142+#line 553 "configparser.c"
5143 break;
5144 default: break; /* If no destructor action specified: do nothing */
5145 }
5146@@ -597,7 +582,7 @@
5147 return yymajor;
5148 }
5149
5150-/*
5151+/*
5152 ** Deallocate and destroy a parser. Destructors are all called for
5153 ** all stack elements before shutting the parser down.
5154 **
5155@@ -633,7 +618,7 @@
5156 ){
5157 int i;
5158 int stateno = pParser->yystack[pParser->yyidx].stateno;
5159-
5160+
5161 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
5162 i = yy_shift_ofst[stateno];
5163 if( i==YY_SHIFT_USE_DFLT ){
5164@@ -677,7 +662,7 @@
5165 ){
5166 int i;
5167 int stateno = pParser->yystack[pParser->yyidx].stateno;
5168-
5169+
5170 i = yy_reduce_ofst[stateno];
5171 if( i==YY_REDUCE_USE_DFLT ){
5172 return yy_default[stateno];
5173@@ -759,6 +744,7 @@
5174 { 35, 1 },
5175 { 35, 1 },
5176 { 35, 1 },
5177+ { 40, 2 },
5178 { 40, 3 },
5179 { 39, 3 },
5180 { 39, 2 },
5181@@ -800,7 +786,7 @@
5182 configparserARG_FETCH;
5183 yymsp = &yypParser->yystack[yypParser->yyidx];
5184 #ifndef NDEBUG
5185- if( yyTraceFILE && yyruleno>=0
5186+ if( yyTraceFILE && yyruleno>=0
5187 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
5188 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
5189 yyRuleName[yyruleno]);
5190@@ -832,9 +818,9 @@
5191 /* No destructor defined for global */
5192 break;
5193 case 5:
5194-#line 134 "./configparser.y"
5195+#line 116 "./configparser.y"
5196 { yymsp[-1].minor.yy78 = NULL; }
5197-#line 837 "configparser.c"
5198+#line 823 "configparser.c"
5199 yy_destructor(1,&yymsp[0].minor);
5200 break;
5201 case 6:
5202@@ -847,10 +833,15 @@
5203 yy_destructor(1,&yymsp[0].minor);
5204 break;
5205 case 9:
5206-#line 162 "./configparser.y"
5207+#line 145 "./configparser.y"
5208 {
5209 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5210- if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5211+ if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
f26f9fd5
ER
5212+ fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5213+ ctx->current->context_ndx,
2519e6e5 5214+ ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
f26f9fd5 5215+ ctx->ok = 0;
2519e6e5
ER
5216+ } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5217 array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5218 yymsp[0].minor.yy41 = NULL;
f26f9fd5 5219 } else {
2519e6e5
ER
5220@@ -864,16 +855,21 @@
5221 buffer_free(yymsp[-2].minor.yy43);
5222 yymsp[-2].minor.yy43 = NULL;
5223 }
5224-#line 867 "configparser.c"
5225+#line 858 "configparser.c"
5226 yy_destructor(2,&yymsp[-1].minor);
5227 break;
5228 case 10:
5229-#line 179 "./configparser.y"
5230+#line 167 "./configparser.y"
5231 {
f26f9fd5
ER
5232 array *vars = ctx->current->value;
5233 data_unset *du;
f673a614 5234
2519e6e5
ER
5235- if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5236+ if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
f26f9fd5
ER
5237+ fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5238+ ctx->current->context_ndx,
2519e6e5 5239+ ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
f26f9fd5 5240+ ctx->ok = 0;
2519e6e5 5241+ } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
f26f9fd5 5242 /* exists in current block */
2519e6e5 5243 du = configparser_merge_data(du, yymsp[0].minor.yy41);
f26f9fd5 5244 if (NULL == du) {
2519e6e5
ER
5245@@ -883,6 +879,7 @@
5246 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
f26f9fd5
ER
5247 array_replace(vars, du);
5248 }
2519e6e5
ER
5249+ yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5250 } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) {
5251 du = configparser_merge_data(du, yymsp[0].minor.yy41);
f26f9fd5 5252 if (NULL == du) {
2519e6e5
ER
5253@@ -892,22 +889,20 @@
5254 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
f26f9fd5
ER
5255 array_insert_unique(ctx->current->value, du);
5256 }
2519e6e5 5257+ yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
f26f9fd5
ER
5258 } else {
5259- fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
5260- ctx->current->context_ndx,
2519e6e5 5261- ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
f26f9fd5 5262- ctx->ok = 0;
2519e6e5
ER
5263+ buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5264+ array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
f26f9fd5 5265 }
2519e6e5
ER
5266 buffer_free(yymsp[-2].minor.yy43);
5267 yymsp[-2].minor.yy43 = NULL;
5268- yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5269 yymsp[0].minor.yy41 = NULL;
f673a614 5270 }
2519e6e5
ER
5271-#line 906 "configparser.c"
5272+#line 901 "configparser.c"
5273 yy_destructor(3,&yymsp[-1].minor);
5274 break;
5275 case 11:
5276-#line 214 "./configparser.y"
5277+#line 206 "./configparser.y"
5278 {
5279 if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) {
5280 yygotominor.yy43 = buffer_init_string("var.");
5281@@ -919,10 +914,10 @@
5282 yymsp[0].minor.yy0 = NULL;
5283 }
f26f9fd5 5284 }
2519e6e5
ER
5285-#line 922 "configparser.c"
5286+#line 917 "configparser.c"
5287 break;
5288 case 12:
5289-#line 226 "./configparser.y"
5290+#line 218 "./configparser.y"
5291 {
5292 yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41);
5293 if (NULL == yygotominor.yy41) {
5294@@ -932,21 +927,38 @@
5295 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5296 yymsp[0].minor.yy41 = NULL;
5297 }
5298-#line 935 "configparser.c"
5299+#line 930 "configparser.c"
5300 yy_destructor(5,&yymsp[-1].minor);
5301 break;
5302 case 13:
5303-#line 236 "./configparser.y"
5304+#line 228 "./configparser.y"
5305 {
5306 yygotominor.yy41 = yymsp[0].minor.yy41;
5307 yymsp[0].minor.yy41 = NULL;
5308 }
5309-#line 944 "configparser.c"
5310+#line 939 "configparser.c"
5311 break;
5312 case 14:
5313-#line 241 "./configparser.y"
5314+#line 233 "./configparser.y"
5315 {
5316- yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43);
5317+ if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
f26f9fd5 5318+ char *env;
f673a614 5319+
2519e6e5 5320+ if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) {
f26f9fd5
ER
5321+ data_string *ds;
5322+ ds = data_string_init();
5323+ buffer_append_string(ds->value, env);
2519e6e5 5324+ yygotominor.yy41 = (data_unset *)ds;
f26f9fd5
ER
5325+ }
5326+ else {
2519e6e5
ER
5327+ yygotominor.yy41 = NULL;
5328+ fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4);
f26f9fd5
ER
5329+ ctx->ok = 0;
5330+ }
2519e6e5
ER
5331+ } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) {
5332+ fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr);
f26f9fd5
ER
5333+ ctx->ok = 0;
5334+ }
2519e6e5 5335 if (!yygotominor.yy41) {
f26f9fd5 5336 /* make a dummy so it won't crash */
2519e6e5
ER
5337 yygotominor.yy41 = (data_unset *)data_string_init();
5338@@ -954,50 +966,59 @@
5339 buffer_free(yymsp[0].minor.yy43);
5340 yymsp[0].minor.yy43 = NULL;
f26f9fd5 5341 }
2519e6e5
ER
5342-#line 957 "configparser.c"
5343+#line 969 "configparser.c"
5344 break;
5345 case 15:
5346-#line 251 "./configparser.y"
5347+#line 260 "./configparser.y"
5348 {
5349 yygotominor.yy41 = (data_unset *)data_string_init();
5350 buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
5351 buffer_free(yymsp[0].minor.yy0);
5352 yymsp[0].minor.yy0 = NULL;
5353 }
5354-#line 967 "configparser.c"
5355+#line 979 "configparser.c"
5356 break;
5357 case 16:
5358-#line 258 "./configparser.y"
5359+#line 267 "./configparser.y"
5360 {
5361 yygotominor.yy41 = (data_unset *)data_integer_init();
5362 ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
5363 buffer_free(yymsp[0].minor.yy0);
5364 yymsp[0].minor.yy0 = NULL;
5365 }
5366-#line 977 "configparser.c"
5367+#line 989 "configparser.c"
5368 break;
5369 case 17:
5370-#line 264 "./configparser.y"
5371+#line 273 "./configparser.y"
5372 {
5373 yygotominor.yy41 = (data_unset *)data_array_init();
5374 array_free(((data_array *)(yygotominor.yy41))->value);
5375 ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
5376 yymsp[0].minor.yy40 = NULL;
5377 }
5378-#line 987 "configparser.c"
5379+#line 999 "configparser.c"
5380 break;
5381 case 18:
5382-#line 270 "./configparser.y"
5383+#line 279 "./configparser.y"
5384+{
5385+ yygotominor.yy40 = array_init();
f26f9fd5 5386+}
2519e6e5
ER
5387+#line 1006 "configparser.c"
5388+ yy_destructor(8,&yymsp[-1].minor);
5389+ yy_destructor(9,&yymsp[0].minor);
5390+ break;
5391+ case 19:
5392+#line 282 "./configparser.y"
5393 {
5394 yygotominor.yy40 = yymsp[-1].minor.yy40;
5395 yymsp[-1].minor.yy40 = NULL;
5396 }
5397-#line 995 "configparser.c"
5398+#line 1016 "configparser.c"
5399 yy_destructor(8,&yymsp[-2].minor);
5400 yy_destructor(9,&yymsp[0].minor);
5401 break;
5402- case 19:
5403-#line 275 "./configparser.y"
5404+ case 20:
5405+#line 287 "./configparser.y"
5406 {
5407 if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
5408 NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
5409@@ -1014,37 +1035,37 @@
5410 yygotominor.yy40 = yymsp[-2].minor.yy40;
5411 yymsp[-2].minor.yy40 = NULL;
5412 }
5413-#line 1017 "configparser.c"
5414+#line 1038 "configparser.c"
5415 yy_destructor(10,&yymsp[-1].minor);
5416 break;
5417- case 20:
5418-#line 292 "./configparser.y"
5419+ case 21:
5420+#line 304 "./configparser.y"
5421 {
5422 yygotominor.yy40 = yymsp[-1].minor.yy40;
5423 yymsp[-1].minor.yy40 = NULL;
5424 }
5425-#line 1026 "configparser.c"
5426+#line 1047 "configparser.c"
5427 yy_destructor(10,&yymsp[0].minor);
5428 break;
5429- case 21:
5430-#line 297 "./configparser.y"
5431+ case 22:
5432+#line 309 "./configparser.y"
5433 {
5434 yygotominor.yy40 = array_init();
5435 array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
5436 yymsp[0].minor.yy41 = NULL;
5437 }
5438-#line 1036 "configparser.c"
5439+#line 1057 "configparser.c"
5440 break;
5441- case 22:
5442-#line 303 "./configparser.y"
5443+ case 23:
5444+#line 315 "./configparser.y"
5445 {
5446 yygotominor.yy41 = yymsp[0].minor.yy41;
5447 yymsp[0].minor.yy41 = NULL;
5448 }
5449-#line 1044 "configparser.c"
5450+#line 1065 "configparser.c"
5451 break;
5452- case 23:
5453-#line 307 "./configparser.y"
5454+ case 24:
5455+#line 319 "./configparser.y"
5456 {
5457 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5458 buffer_free(yymsp[-2].minor.yy43);
5459@@ -1053,27 +1074,27 @@
5460 yygotominor.yy41 = yymsp[0].minor.yy41;
5461 yymsp[0].minor.yy41 = NULL;
5462 }
5463-#line 1056 "configparser.c"
5464+#line 1077 "configparser.c"
5465 yy_destructor(11,&yymsp[-1].minor);
5466 break;
5467- case 24:
5468- yy_destructor(1,&yymsp[0].minor);
5469- break;
5470 case 25:
5471+ yy_destructor(1,&yymsp[0].minor);
5472 break;
5473 case 26:
5474-#line 319 "./configparser.y"
5475+ break;
5476+ case 27:
5477+#line 331 "./configparser.y"
5478 {
5479 data_config *dc;
5480 dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
5481 assert(dc);
5482 configparser_push(ctx, dc, 0);
5483 }
5484-#line 1072 "configparser.c"
5485+#line 1093 "configparser.c"
5486 yy_destructor(12,&yymsp[0].minor);
5487 break;
5488- case 27:
5489-#line 326 "./configparser.y"
5490+ case 28:
5491+#line 338 "./configparser.y"
5492 {
5493 data_config *cur;
5494
5495@@ -1082,16 +1103,16 @@
5496
5497 assert(cur && ctx->current);
5498
5499- yygotominor.yy0 = cur;
5500+ yygotominor.yy78 = cur;
5501 }
5502-#line 1087 "configparser.c"
5503+#line 1108 "configparser.c"
5504 /* No destructor defined for globalstart */
5505 yy_destructor(13,&yymsp[-2].minor);
5506 /* No destructor defined for metalines */
5507 yy_destructor(14,&yymsp[0].minor);
5508 break;
5509- case 28:
5510-#line 337 "./configparser.y"
5511+ case 29:
5512+#line 349 "./configparser.y"
5513 {
5514 assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx);
5515 yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
5516@@ -1100,20 +1121,20 @@
5517 yymsp[-3].minor.yy78 = NULL;
5518 yymsp[0].minor.yy78 = NULL;
5519 }
5520-#line 1103 "configparser.c"
5521+#line 1124 "configparser.c"
5522 /* No destructor defined for eols */
5523 yy_destructor(15,&yymsp[-1].minor);
5524 break;
5525- case 29:
5526-#line 346 "./configparser.y"
5527+ case 30:
5528+#line 358 "./configparser.y"
5529 {
5530 yygotominor.yy78 = yymsp[0].minor.yy78;
5531 yymsp[0].minor.yy78 = NULL;
5532 }
5533-#line 1113 "configparser.c"
5534+#line 1134 "configparser.c"
5535 break;
5536- case 30:
5537-#line 351 "./configparser.y"
5538+ case 31:
5539+#line 363 "./configparser.y"
5540 {
5541 data_config *cur;
5542
5543@@ -1124,14 +1145,14 @@
5544
5545 yygotominor.yy78 = cur;
5546 }
5547-#line 1127 "configparser.c"
5548+#line 1148 "configparser.c"
5549 /* No destructor defined for context */
5550 yy_destructor(13,&yymsp[-2].minor);
5551 /* No destructor defined for metalines */
5552 yy_destructor(14,&yymsp[0].minor);
5553 break;
5554- case 31:
5555-#line 362 "./configparser.y"
5556+ case 32:
5557+#line 374 "./configparser.y"
5558 {
5559 data_config *dc;
5560 buffer *b, *rvalue, *op;
5561@@ -1266,45 +1287,45 @@
5562 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5563 yymsp[0].minor.yy41 = NULL;
5564 }
5565-#line 1269 "configparser.c"
5566+#line 1290 "configparser.c"
5567 yy_destructor(16,&yymsp[-6].minor);
5568 yy_destructor(18,&yymsp[-4].minor);
5569 yy_destructor(19,&yymsp[-2].minor);
5570 break;
5571- case 32:
5572-#line 496 "./configparser.y"
5573+ case 33:
5574+#line 508 "./configparser.y"
5575 {
5576 yygotominor.yy27 = CONFIG_COND_EQ;
5577 }
5578-#line 1279 "configparser.c"
5579+#line 1300 "configparser.c"
5580 yy_destructor(20,&yymsp[0].minor);
5581 break;
5582- case 33:
5583-#line 499 "./configparser.y"
5584+ case 34:
5585+#line 511 "./configparser.y"
5586 {
5587 yygotominor.yy27 = CONFIG_COND_MATCH;
5588 }
5589-#line 1287 "configparser.c"
5590+#line 1308 "configparser.c"
5591 yy_destructor(21,&yymsp[0].minor);
5592 break;
5593- case 34:
5594-#line 502 "./configparser.y"
5595+ case 35:
5596+#line 514 "./configparser.y"
5597 {
5598 yygotominor.yy27 = CONFIG_COND_NE;
5599 }
5600-#line 1295 "configparser.c"
5601+#line 1316 "configparser.c"
5602 yy_destructor(22,&yymsp[0].minor);
5603 break;
5604- case 35:
5605-#line 505 "./configparser.y"
5606+ case 36:
5607+#line 517 "./configparser.y"
5608 {
5609 yygotominor.yy27 = CONFIG_COND_NOMATCH;
5610 }
5611-#line 1303 "configparser.c"
5612+#line 1324 "configparser.c"
5613 yy_destructor(23,&yymsp[0].minor);
5614 break;
5615- case 36:
5616-#line 509 "./configparser.y"
5617+ case 37:
5618+#line 521 "./configparser.y"
5619 {
5620 yygotominor.yy43 = NULL;
5621 if (ctx->ok) {
5622@@ -1321,10 +1342,10 @@
5623 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5624 yymsp[0].minor.yy41 = NULL;
5625 }
5626-#line 1324 "configparser.c"
5627+#line 1345 "configparser.c"
5628 break;
5629- case 37:
5630-#line 526 "./configparser.y"
5631+ case 38:
5632+#line 538 "./configparser.y"
5633 {
5634 if (ctx->ok) {
5635 if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5636@@ -1334,11 +1355,11 @@
5637 yymsp[0].minor.yy43 = NULL;
5638 }
5639 }
5640-#line 1337 "configparser.c"
5641+#line 1358 "configparser.c"
5642 yy_destructor(24,&yymsp[-1].minor);
5643 break;
5644- case 38:
5645-#line 536 "./configparser.y"
5646+ case 39:
5647+#line 548 "./configparser.y"
5648 {
5649 if (ctx->ok) {
5650 if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5651@@ -1348,7 +1369,7 @@
5652 yymsp[0].minor.yy43 = NULL;
5653 }
5654 }
5655-#line 1351 "configparser.c"
5656+#line 1372 "configparser.c"
5657 yy_destructor(25,&yymsp[-1].minor);
5658 break;
5659 };
5660@@ -1378,11 +1399,11 @@
5661 while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
5662 /* Here code is inserted which will be executed whenever the
5663 ** parser fails */
5664-#line 125 "./configparser.y"
5665+#line 107 "./configparser.y"
5666
5667 ctx->ok = 0;
5668
5669-#line 1385 "configparser.c"
5670+#line 1406 "configparser.c"
5671 configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
5672 }
5673
5674@@ -1489,7 +1510,7 @@
5675 #ifdef YYERRORSYMBOL
5676 /* A syntax error has occurred.
5677 ** The response to an error depends upon whether or not the
5678- ** grammar defines an error token "ERROR".
5679+ ** grammar defines an error token "ERROR".
5680 **
5681 ** This is what we do if the grammar does define ERROR:
5682 **
1175ccec 5683--- ../lighttpd-1.4.11/src/configparser.y 2006-01-26 18:46:25.000000000 +0200
36e2a29e 5684+++ lighttpd-1.4.12/src/configparser.y 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
5685@@ -21,52 +21,34 @@
5686 dc->parent = ctx->current;
5687 array_insert_unique(dc->parent->childs, (data_unset *)dc);
5688 }
5689- array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
5690+ buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
5691 ctx->current = dc;
5692 }
5693
5694 static data_config *configparser_pop(config_t *ctx) {
5695 data_config *old = ctx->current;
5696- ctx->current = (data_config *) array_pop(ctx->configs_stack);
5697+ ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
5698 return old;
5699 }
5700
5701 /* return a copied variable */
5702 static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
5703- if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
5704- char *env;
5705-
5706- if (NULL != (env = getenv(key->ptr + 4))) {
5707- data_string *ds;
5708- ds = data_string_init();
5709- buffer_append_string(ds->value, env);
5710- return (data_unset *)ds;
5711- }
5712-
5713- fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
5714- ctx->ok = 0;
5715-
5716- return NULL;
5717- } else {
5718- data_unset *du;
5719- data_config *dc;
5720+ data_unset *du;
5721+ data_config *dc;
5722
5723 #if 0
5724- fprintf(stderr, "get var %s\n", key->ptr);
5725+ fprintf(stderr, "get var %s\n", key->ptr);
5726 #endif
5727- for (dc = ctx->current; dc; dc = dc->parent) {
5728+ for (dc = ctx->current; dc; dc = dc->parent) {
5729 #if 0
5730- fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5731- array_print(dc->value, 0);
5732+ fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5733+ array_print(dc->value, 0);
5734 #endif
5735- if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5736- return du->copy(du);
5737- }
5738+ if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5739+ return du->copy(du);
5740 }
5741- fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
5742- ctx->ok = 0;
5743- return NULL;
5744 }
5745+ return NULL;
5746 }
5747
5748 /* op1 is to be eat/return by this function, op1->key is not cared
5749@@ -141,6 +123,7 @@
5750 %type aelement {data_unset *}
5751 %type condline {data_config *}
5752 %type condlines {data_config *}
5753+%type global {data_config *}
5754 %type aelements {array *}
5755 %type array {array *}
5756 %type key {buffer *}
5757@@ -161,7 +144,12 @@
5758
5759 varline ::= key(A) ASSIGN expression(B). {
5760 buffer_copy_string_buffer(B->key, A);
5761- if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
5762+ if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
5763+ fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5764+ ctx->current->context_ndx,
5765+ ctx->current->key->ptr, A->ptr);
5766+ ctx->ok = 0;
5767+ } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
5768 array_insert_unique(ctx->current->value, B);
5769 B = NULL;
5770 } else {
5771@@ -180,7 +168,12 @@
5772 array *vars = ctx->current->value;
5773 data_unset *du;
5774
5775- if (NULL != (du = array_get_element(vars, A->ptr))) {
5776+ if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
5777+ fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5778+ ctx->current->context_ndx,
5779+ ctx->current->key->ptr, A->ptr);
5780+ ctx->ok = 0;
5781+ } else if (NULL != (du = array_get_element(vars, A->ptr))) {
5782 /* exists in current block */
5783 du = configparser_merge_data(du, B);
5784 if (NULL == du) {
5785@@ -190,6 +183,7 @@
5786 buffer_copy_string_buffer(du->key, A);
5787 array_replace(vars, du);
5788 }
5789+ B->free(B);
5790 } else if (NULL != (du = configparser_get_variable(ctx, A))) {
5791 du = configparser_merge_data(du, B);
5792 if (NULL == du) {
5793@@ -199,15 +193,13 @@
5794 buffer_copy_string_buffer(du->key, A);
5795 array_insert_unique(ctx->current->value, du);
5796 }
5797+ B->free(B);
5798 } else {
5799- fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
5800- ctx->current->context_ndx,
5801- ctx->current->key->ptr, A->ptr);
5802- ctx->ok = 0;
5803+ buffer_copy_string_buffer(B->key, A);
5804+ array_insert_unique(ctx->current->value, B);
5805 }
5806 buffer_free(A);
5807 A = NULL;
5808- B->free(B);
5809 B = NULL;
5810 }
5811
5812@@ -239,7 +231,24 @@
5813 }
5814
5815 value(A) ::= key(B). {
5816- A = configparser_get_variable(ctx, B);
5817+ if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
5818+ char *env;
5819+
5820+ if (NULL != (env = getenv(B->ptr + 4))) {
5821+ data_string *ds;
5822+ ds = data_string_init();
5823+ buffer_append_string(ds->value, env);
5824+ A = (data_unset *)ds;
5825+ }
5826+ else {
5827+ A = NULL;
5828+ fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
5829+ ctx->ok = 0;
5830+ }
5831+ } else if (NULL == (A = configparser_get_variable(ctx, B))) {
5832+ fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
5833+ ctx->ok = 0;
5834+ }
5835 if (!A) {
5836 /* make a dummy so it won't crash */
5837 A = (data_unset *)data_string_init();
5838@@ -267,6 +276,9 @@
5839 ((data_array *)(A))->value = B;
5840 B = NULL;
5841 }
5842+array(A) ::= LPARAN RPARAN. {
5843+ A = array_init();
5844+}
5845 array(A) ::= LPARAN aelements(B) RPARAN. {
5846 A = B;
5847 B = NULL;
1175ccec 5848--- ../lighttpd-1.4.11/src/connections-glue.c 2005-09-12 10:04:23.000000000 +0300
36e2a29e 5849+++ lighttpd-1.4.12/src/connections-glue.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
5850@@ -13,7 +13,7 @@
5851 case CON_STATE_REQUEST_END: return "req-end";
5852 case CON_STATE_RESPONSE_START: return "resp-start";
5853 case CON_STATE_RESPONSE_END: return "resp-end";
5854- default: return "(unknown)";
5855+ default: return "(unknown)";
5856 }
5857 }
5858
5859@@ -30,15 +30,15 @@
5860 case CON_STATE_REQUEST_END: return "Q";
5861 case CON_STATE_RESPONSE_START: return "s";
5862 case CON_STATE_RESPONSE_END: return "S";
5863- default: return "x";
5864+ default: return "x";
5865 }
5866 }
5867
5868 int connection_set_state(server *srv, connection *con, connection_state_t state) {
5869 UNUSED(srv);
5870-
5871+
5872 con->state = state;
5873-
5874+
5875 return 0;
5876 }
5877
1175ccec
ER
5878--- ../lighttpd-1.4.11/src/connections.c 2006-03-05 22:14:53.000000000 +0200
5879+++ lighttpd-1.4.12/src/connections.c 2006-07-15 22:43:21.000000000 +0300
2519e6e5
ER
5880@@ -2,7 +2,6 @@
5881
5882 #include <stdlib.h>
5883 #include <stdio.h>
5884-#include <unistd.h>
5885 #include <errno.h>
5886 #include <string.h>
5887 #include <fcntl.h>
5888@@ -26,8 +25,8 @@
5889 #include "inet_ntop_cache.h"
5890
5891 #ifdef USE_OPENSSL
5892-# include <openssl/ssl.h>
5893-# include <openssl/err.h>
5894+# include <openssl/ssl.h>
5895+# include <openssl/err.h>
5896 #endif
5897
5898 #ifdef HAVE_SYS_FILIO_H
1175ccec 5899@@ -35,15 +34,16 @@
f26f9fd5 5900 #endif
f673a614 5901
f26f9fd5
ER
5902 #include "sys-socket.h"
5903+#include "sys-files.h"
f673a614 5904
f26f9fd5 5905 typedef struct {
1175ccec
ER
5906- PLUGIN_DATA;
5907+ PLUGIN_DATA;
5908 } plugin_data;
5909
2519e6e5
ER
5910 static connection *connections_get_new_connection(server *srv) {
5911 connections *conns = srv->conns;
5912 size_t i;
5913-
5914+
5915 if (conns->size == 0) {
5916 conns->size = 128;
5917 conns->ptr = NULL;
5918@@ -54,21 +54,21 @@
5919 } else if (conns->size == conns->used) {
5920 conns->size += 128;
5921 conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
5922-
5923+
5924 for (i = conns->used; i < conns->size; i++) {
5925 conns->ptr[i] = connection_init(srv);
5926 }
5927 }
f673a614 5928
2519e6e5
ER
5929 connection_reset(srv, conns->ptr[conns->used]);
5930-#if 0
5931+#if 0
5932 fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
5933 for (i = 0; i < conns->used + 1; i++) {
5934 fprintf(stderr, "%d ", conns->ptr[i]->fd);
5935 }
5936 fprintf(stderr, "\n");
5937-#endif
5938-
5939+#endif
5940+
5941 conns->ptr[conns->used]->ndx = conns->used;
5942 return conns->ptr[conns->used++];
5943 }
5944@@ -77,26 +77,26 @@
5945 size_t i;
5946 connections *conns = srv->conns;
5947 connection *temp;
5948-
5949+
5950 if (con == NULL) return -1;
5951-
5952+
5953 if (-1 == con->ndx) return -1;
5954-
5955+
5956 i = con->ndx;
5957-
5958+
5959 /* not last element */
5960-
5961+
5962 if (i != conns->used - 1) {
5963 temp = conns->ptr[i];
5964 conns->ptr[i] = conns->ptr[conns->used - 1];
5965 conns->ptr[conns->used - 1] = temp;
5966-
5967+
5968 conns->ptr[i]->ndx = i;
5969 conns->ptr[conns->used - 1]->ndx = -1;
5970 }
5971-
5972+
5973 conns->used--;
5974-
5975+
5976 con->ndx = -1;
5977 #if 0
5978 fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
5979@@ -104,25 +104,23 @@
5980 fprintf(stderr, "%d ", conns->ptr[i]->fd);
5981 }
5982 fprintf(stderr, "\n");
5983-#endif
5984+#endif
5985 return 0;
5986 }
5987
5988 int connection_close(server *srv, connection *con) {
5989 #ifdef USE_OPENSSL
5990 server_socket *srv_sock = con->srv_socket;
5991-#endif
5992-
5993-#ifdef USE_OPENSSL
5994+
5995 if (srv_sock->is_ssl) {
5996 if (con->ssl) SSL_free(con->ssl);
5997 con->ssl = NULL;
5998 }
5999 #endif
6000-
6001+
6002 fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
6003 fdevent_unregister(srv->ev, con->fd);
6004-#ifdef __WIN32
6005+#ifdef _WIN32
6006 if (closesocket(con->fd)) {
6007 log_error_write(srv, __FILE__, __LINE__, "sds",
6008 "(warning) close:", con->fd, strerror(errno));
6009@@ -133,207 +131,96 @@
6010 "(warning) close:", con->fd, strerror(errno));
6011 }
6012 #endif
6013-
6014+
6015 srv->cur_fds--;
6016 #if 0
6017 log_error_write(srv, __FILE__, __LINE__, "sd",
6018 "closed()", con->fd);
6019 #endif
6020-
6021+
6022 connection_del(srv, con);
6023 connection_set_state(srv, con, CON_STATE_CONNECT);
6024-
6025+
6026 return 0;
6027 }
6028
6029 #if 0
6030 static void dump_packet(const unsigned char *data, size_t len) {
6031 size_t i, j;
6032-
6033+
6034 if (len == 0) return;
6035-
6036+
6037 for (i = 0; i < len; i++) {
6038 if (i % 16 == 0) fprintf(stderr, " ");
6039-
6040+
6041 fprintf(stderr, "%02x ", data[i]);
6042-
6043+
6044 if ((i + 1) % 16 == 0) {
6045 fprintf(stderr, " ");
6046 for (j = 0; j <= i % 16; j++) {
6047 unsigned char c;
6048-
6049+
6050 if (i-15+j >= len) break;
6051-
6052+
6053 c = data[i-15+j];
6054-
6055+
6056 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6057 }
6058-
6059+
6060 fprintf(stderr, "\n");
6061 }
6062 }
6063-
6064+
6065 if (len % 16 != 0) {
6066 for (j = i % 16; j < 16; j++) {
6067 fprintf(stderr, " ");
6068 }
6069-
6070+
6071 fprintf(stderr, " ");
6072 for (j = i & ~0xf; j < len; j++) {
6073 unsigned char c;
6074-
6075+
6076 c = data[j];
6077 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6078 }
6079 fprintf(stderr, "\n");
6080 }
6081 }
6082-#endif
f26f9fd5 6083-
2519e6e5
ER
6084-static int connection_handle_read(server *srv, connection *con) {
6085- int len;
6086- buffer *b;
6087- int toread;
6088-#ifdef USE_OPENSSL
6089- server_socket *srv_sock = con->srv_socket;
6090 #endif
6091
f26f9fd5
ER
6092- b = chunkqueue_get_append_buffer(con->read_queue);
6093- buffer_prepare_copy(b, 4096);
2519e6e5
ER
6094+static network_status_t connection_handle_read(server *srv, connection *con) {
6095+ off_t oldlen, newlen;
6096
f26f9fd5
ER
6097-#ifdef USE_OPENSSL
6098- if (srv_sock->is_ssl) {
6099- len = SSL_read(con->ssl, b->ptr, b->size - 1);
6100- } else {
6101- if (ioctl(con->fd, FIONREAD, &toread)) {
6102- log_error_write(srv, __FILE__, __LINE__, "sd",
6103- "unexpected end-of-file:",
6104- con->fd);
6105- return -1;
6106- }
6107- buffer_prepare_copy(b, toread);
1175ccec 6108+ oldlen = chunkqueue_length(con->read_queue);
2519e6e5 6109
f26f9fd5
ER
6110- len = read(con->fd, b->ptr, b->size - 1);
6111- }
6112-#elif defined(__WIN32)
6113- len = recv(con->fd, b->ptr, b->size - 1, 0);
6114-#else
6115- if (ioctl(con->fd, FIONREAD, &toread)) {
6116- log_error_write(srv, __FILE__, __LINE__, "sd",
6117- "unexpected end-of-file:",
6118- con->fd);
6119- return -1;
6120- }
6121- buffer_prepare_copy(b, toread);
6122-
6123- len = read(con->fd, b->ptr, b->size - 1);
6124-#endif
6125-
6126- if (len < 0) {
1175ccec
ER
6127+ switch(network_read_chunkqueue(srv, con, con->read_queue)) {
6128+ case NETWORK_STATUS_SUCCESS:
6129+ break;
6130+ case NETWORK_STATUS_WAIT_FOR_EVENT:
6131+ con->is_readable = 0;
6132+ return NETWORK_STATUS_WAIT_FOR_EVENT;
6133+ case NETWORK_STATUS_INTERRUPTED:
6134+ con->is_readable = 1;
6135+ return NETWORK_STATUS_WAIT_FOR_EVENT;
6136+ case NETWORK_STATUS_CONNECTION_CLOSE:
6137+ /* pipelining */
6138+ con->is_readable = 0;
6139+ return NETWORK_STATUS_CONNECTION_CLOSE;
6140+ case NETWORK_STATUS_FATAL_ERROR:
6141 con->is_readable = 0;
f673a614 6142-
f26f9fd5
ER
6143-#ifdef USE_OPENSSL
6144- if (srv_sock->is_ssl) {
6145- int r, ssl_err;
6146-
6147- switch ((r = SSL_get_error(con->ssl, len))) {
6148- case SSL_ERROR_WANT_READ:
6149- return 0;
6150- case SSL_ERROR_SYSCALL:
6151- /**
6152- * man SSL_get_error()
6153- *
6154- * SSL_ERROR_SYSCALL
6155- * Some I/O error occurred. The OpenSSL error queue may contain more
6156- * information on the error. If the error queue is empty (i.e.
6157- * ERR_get_error() returns 0), ret can be used to find out more about
6158- * the error: If ret == 0, an EOF was observed that violates the
6159- * protocol. If ret == -1, the underlying BIO reported an I/O error
6160- * (for socket I/O on Unix systems, consult errno for details).
6161- *
6162- */
6163- while((ssl_err = ERR_get_error())) {
6164- /* get all errors from the error-queue */
6165- log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
6166- r, ERR_error_string(ssl_err, NULL));
6167- }
2519e6e5 6168
f26f9fd5
ER
6169- switch(errno) {
6170- default:
6171- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
6172- len, r, errno,
6173- strerror(errno));
6174- break;
6175- }
6176-
6177- break;
6178- case SSL_ERROR_ZERO_RETURN:
6179- /* clean shutdown on the remote side */
2519e6e5 6180-
f26f9fd5
ER
6181- if (r == 0) {
6182- /* FIXME: later */
6183- }
2519e6e5 6184-
f26f9fd5
ER
6185- /* fall thourgh */
6186- default:
6187- while((ssl_err = ERR_get_error())) {
6188- /* get all errors from the error-queue */
6189- log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
6190- r, ERR_error_string(ssl_err, NULL));
6191- }
2519e6e5 6192- break;
f26f9fd5
ER
6193- }
6194- } else {
6195- if (errno == EAGAIN) return 0;
6196- if (errno == EINTR) {
6197- /* we have been interrupted before we could read */
6198- con->is_readable = 1;
6199- return 0;
6200- }
f673a614 6201-
f26f9fd5
ER
6202- if (errno != ECONNRESET) {
6203- /* expected for keep-alive */
6204- log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6205- }
6206- }
6207-#else
6208- if (errno == EAGAIN) return 0;
6209- if (errno == EINTR) {
6210- /* we have been interrupted before we could read */
6211- con->is_readable = 1;
6212- return 0;
6213- }
f673a614 6214-
f26f9fd5
ER
6215- if (errno != ECONNRESET) {
6216- /* expected for keep-alive */
6217- log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6218- }
6219-#endif
1175ccec 6220 connection_set_state(srv, con, CON_STATE_ERROR);
f673a614 6221-
f26f9fd5
ER
6222- return -1;
6223- } else if (len == 0) {
2519e6e5 6224- con->is_readable = 0;
f26f9fd5 6225- /* the other end close the connection -> KEEP-ALIVE */
1175ccec
ER
6226+ return NETWORK_STATUS_FATAL_ERROR;
6227+ default:
6228+ SEGFAULT();
6229+ break;
6230+ }
6231
2519e6e5 6232- /* pipelining */
1175ccec
ER
6233+ newlen = chunkqueue_length(con->read_queue);
6234
f26f9fd5
ER
6235- return -2;
6236- } else if ((size_t)len < b->size - 1) {
6237- /* we got less then expected, wait for the next fd-event */
f673a614 6238-
2519e6e5
ER
6239- con->is_readable = 0;
6240- }
6241-
f26f9fd5
ER
6242- b->used = len;
6243- b->ptr[b->used++] = '\0';
2519e6e5 6244-
f26f9fd5
ER
6245- con->bytes_read += len;
6246-#if 0
6247- dump_packet(b->ptr, len);
6248-#endif
2519e6e5 6249-
f26f9fd5 6250- return 0;
2519e6e5
ER
6251+ con->bytes_read += (newlen - oldlen);
6252+
f26f9fd5 6253+ return NETWORK_STATUS_SUCCESS;
f673a614
ER
6254 }
6255
f26f9fd5
ER
6256 static int connection_handle_write_prepare(server *srv, connection *con) {
6257@@ -343,6 +230,7 @@
6258 case HTTP_METHOD_GET:
6259 case HTTP_METHOD_POST:
6260 case HTTP_METHOD_HEAD:
6261+ /* webdav */
6262 case HTTP_METHOD_PUT:
6263 case HTTP_METHOD_MKCOL:
6264 case HTTP_METHOD_DELETE:
2519e6e5 6265@@ -350,12 +238,14 @@
f26f9fd5
ER
6266 case HTTP_METHOD_MOVE:
6267 case HTTP_METHOD_PROPFIND:
6268 case HTTP_METHOD_PROPPATCH:
6269+ case HTTP_METHOD_LOCK:
6270+ case HTTP_METHOD_UNLOCK:
6271 break;
6272 case HTTP_METHOD_OPTIONS:
6273 /*
2519e6e5
ER
6274 * 400 is coming from the request-parser BEFORE uri.path is set
6275- * 403 is from the response handler when noone else catched it
6276- *
6277+ * 403 is from the response handler when noone else catched it
6278+ *
6279 * */
6280 if (con->uri.path->used &&
6281 con->uri.path->ptr[0] != '*') {
6282@@ -381,55 +271,58 @@
6283 break;
6284 }
6285 }
6286-
6287+
6288 if (con->http_status == 0) {
6289 con->http_status = 403;
6290 }
6291-
6292+
6293 switch(con->http_status) {
6294 case 400: /* class: header + custom body */
6295 case 401:
f26f9fd5
ER
6296 case 403:
6297 case 404:
6298 case 408:
6299+ case 409:
6300+ case 410:
6301 case 411:
6302 case 416:
6303 case 423:
2519e6e5 6304 case 500:
f26f9fd5
ER
6305 case 501:
6306 case 503:
2519e6e5
ER
6307- case 505:
6308+ case 505:
f26f9fd5
ER
6309+ case 509:
6310 if (con->mode != DIRECT) break;
2519e6e5
ER
6311-
6312+
f26f9fd5 6313 con->file_finished = 0;
2519e6e5
ER
6314-
6315+
6316 buffer_reset(con->physical.path);
6317-
6318+
6319 /* try to send static errorfile */
6320 if (!buffer_is_empty(con->conf.errorfile_prefix)) {
6321 stat_cache_entry *sce = NULL;
6322-
6323+
6324 buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
6325 buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
6326-
6327+
6328 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
6329 con->file_finished = 1;
6330-
6331+
6332 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
6333 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
6334 }
f26f9fd5 6335 }
2519e6e5
ER
6336-
6337- if (!con->file_finished) {
6338+
6339+ if (!con->file_finished) {
6340 buffer *b;
6341-
6342+
6343 buffer_reset(con->physical.path);
6344-
6345+
6346 con->file_finished = 1;
6347 b = chunkqueue_get_append_buffer(con->write_queue);
6348-
6349+
6350 /* build default error-page */
6351- buffer_copy_string(b,
6352+ buffer_copy_string(b,
6353 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
6354 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
6355 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
6356@@ -439,7 +332,7 @@
6357 buffer_append_long(b, con->http_status);
6358 buffer_append_string(b, " - ");
6359 buffer_append_string(b, get_http_status_name(con->http_status));
6360-
6361+
6362 buffer_append_string(b,
6363 "</title>\n"
6364 " </head>\n"
6365@@ -448,12 +341,12 @@
6366 buffer_append_long(b, con->http_status);
6367 buffer_append_string(b, " - ");
6368 buffer_append_string(b, get_http_status_name(con->http_status));
6369-
6370- buffer_append_string(b,"</h1>\n"
6371+
6372+ buffer_append_string(b,"</h1>\n"
6373 " </body>\n"
6374 "</html>\n"
6375 );
6376-
6377+
6378 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
6379 }
6380 /* fall through */
6381@@ -463,10 +356,10 @@
6382 case 301:
6383 case 302:
f26f9fd5 6384 break;
2519e6e5
ER
6385-
6386+
6387 case 206: /* write_queue is already prepared */
6388 con->file_finished = 1;
6389-
6390+
f26f9fd5 6391 break;
2519e6e5
ER
6392 case 205: /* class: header only */
6393 case 304:
6394@@ -474,19 +367,19 @@
6395 /* disable chunked encoding again as we have no body */
6396 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
6397 chunkqueue_reset(con->write_queue);
6398-
6399+
6400 con->file_finished = 1;
f26f9fd5 6401 break;
f26f9fd5 6402 }
2519e6e5
ER
6403-
6404+
f673a614 6405
2519e6e5
ER
6406 if (con->file_finished) {
6407- /* we have all the content and chunked encoding is not used, set a content-length */
6408-
6409- if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6410+ /* we have all the content and chunked encoding is not used, set a content-length */
6411+
6412+ if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6413 (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
6414 buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
6415-
6416+
6417 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
6418 }
6419 } else {
6420@@ -495,74 +388,77 @@
6421 ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
6422 con->keep_alive = 0;
6423 }
6424-
6425+
6426 if (0 == (con->parsed_response & HTTP_CONNECTION)) {
6427 /* (f)cgi did'nt send Connection: header
6428- *
6429+ *
6430 * shall we ?
6431 */
6432 if (((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) &&
6433 (con->parsed_response & HTTP_CONTENT_LENGTH) == 0) {
6434 /* without content_length, no keep-alive */
6435-
6436+
6437 con->keep_alive = 0;
6438 }
6439 } else {
6440 /* a subrequest disable keep-alive although the client wanted it */
6441 if (con->keep_alive && !con->response.keep_alive) {
6442 con->keep_alive = 0;
6443-
6444+
6445 /* FIXME: we have to drop the Connection: Header from the subrequest */
6446 }
6447 }
6448 }
6449-
6450+
6451 if (con->request.http_method == HTTP_METHOD_HEAD) {
6452 chunkqueue_reset(con->write_queue);
6453 }
6454
6455 http_response_write_header(srv, con);
6456-
6457+
6458 return 0;
6459 }
6460
6461 static int connection_handle_write(server *srv, connection *con) {
1175ccec 6462 switch(network_write_chunkqueue(srv, con, con->write_queue)) {
2519e6e5 6463- case 0:
2519e6e5
ER
6464+ case NETWORK_STATUS_SUCCESS:
6465 if (con->file_finished) {
6466 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
6467 joblist_append(srv, con);
6468 }
6469 break;
6470- case -1: /* error on our side */
6471+ case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
6472 log_error_write(srv, __FILE__, __LINE__, "sd",
6473 "connection closed: write failed on fd", con->fd);
6474 connection_set_state(srv, con, CON_STATE_ERROR);
6475 joblist_append(srv, con);
6476 break;
6477- case -2: /* remote close */
6478+ case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
6479 connection_set_state(srv, con, CON_STATE_ERROR);
6480 joblist_append(srv, con);
6481 break;
6482- case 1:
6483+ case NETWORK_STATUS_WAIT_FOR_EVENT:
6484 con->is_writable = 0;
6485-
6486+
6487 /* not finished yet -> WRITE */
6488 break;
6489+ case NETWORK_STATUS_INTERRUPTED:
6490+ con->is_writable = 1;
6491+ break;
6492+ case NETWORK_STATUS_UNSET:
6493+ break;
6494 }
6495-
6496+
6497 return 0;
6498 }
6499
6500-
f26f9fd5
ER
6501-
6502 connection *connection_init(server *srv) {
6503 connection *con;
2519e6e5
ER
6504-
6505+
6506 UNUSED(srv);
6507
6508 con = calloc(1, sizeof(*con));
6509-
6510+
6511 con->fd = 0;
6512 con->ndx = -1;
6513 con->fde_ndx = -1;
6514@@ -573,32 +469,32 @@
6515
6516 #define CLEAN(x) \
6517 con->x = buffer_init();
6518-
6519+
6520 CLEAN(request.uri);
6521 CLEAN(request.request_line);
6522 CLEAN(request.request);
6523 CLEAN(request.pathinfo);
6524-
6525+
6526 CLEAN(request.orig_uri);
6527-
6528+
6529 CLEAN(uri.scheme);
6530 CLEAN(uri.authority);
6531 CLEAN(uri.path);
6532 CLEAN(uri.path_raw);
6533 CLEAN(uri.query);
6534-
6535+
6536 CLEAN(physical.doc_root);
6537 CLEAN(physical.path);
6538 CLEAN(physical.basedir);
6539 CLEAN(physical.rel_path);
6540 CLEAN(physical.etag);
6541 CLEAN(parse_request);
6542-
6543+
6544 CLEAN(authed_user);
6545 CLEAN(server_name);
6546 CLEAN(error_handler);
6547 CLEAN(dst_addr_buf);
6548-
6549+
6550 #undef CLEAN
6551 con->write_queue = chunkqueue_init();
6552 con->read_queue = chunkqueue_init();
6553@@ -608,26 +504,26 @@
6554 con->request.headers = array_init();
6555 con->response.headers = array_init();
6556 con->environment = array_init();
6557-
6558+
6559 /* init plugin specific connection structures */
6560-
6561+
6562 con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
6563-
6564+
6565 con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
6566 config_setup_connection(srv, con);
6567-
6568+
6569 return con;
6570 }
6571
6572 void connections_free(server *srv) {
6573 connections *conns = srv->conns;
6574- size_t i;
6575-
6576+ size_t i;
6577+
6578 for (i = 0; i < conns->size; i++) {
6579 connection *con = conns->ptr[i];
6580-
6581+
6582 connection_reset(srv, con);
6583-
6584+
6585 chunkqueue_free(con->write_queue);
6586 chunkqueue_free(con->read_queue);
6587 chunkqueue_free(con->request_content_queue);
6588@@ -637,27 +533,27 @@
6589
6590 #define CLEAN(x) \
6591 buffer_free(con->x);
6592-
6593+
6594 CLEAN(request.uri);
6595 CLEAN(request.request_line);
6596 CLEAN(request.request);
6597 CLEAN(request.pathinfo);
6598-
6599+
6600 CLEAN(request.orig_uri);
6601-
6602+
6603 CLEAN(uri.scheme);
6604 CLEAN(uri.authority);
6605 CLEAN(uri.path);
6606 CLEAN(uri.path_raw);
6607 CLEAN(uri.query);
6608-
6609+
6610 CLEAN(physical.doc_root);
6611 CLEAN(physical.path);
6612 CLEAN(physical.basedir);
6613 CLEAN(physical.etag);
6614 CLEAN(physical.rel_path);
6615 CLEAN(parse_request);
6616-
6617+
6618 CLEAN(authed_user);
6619 CLEAN(server_name);
6620 CLEAN(error_handler);
6621@@ -665,97 +561,97 @@
6622 #undef CLEAN
6623 free(con->plugin_ctx);
6624 free(con->cond_cache);
6625-
6626+
6627 free(con);
6628 }
6629-
6630+
6631 free(conns->ptr);
6632 }
6633
6634
6635 int connection_reset(server *srv, connection *con) {
6636 size_t i;
6637-
6638+
6639 plugins_call_connection_reset(srv, con);
6640-
6641+
6642 con->is_readable = 1;
6643 con->is_writable = 1;
6644 con->http_status = 0;
6645 con->file_finished = 0;
6646 con->file_started = 0;
6647 con->got_response = 0;
6648-
6649+
6650 con->parsed_response = 0;
6651-
6652+
6653 con->bytes_written = 0;
6654 con->bytes_written_cur_second = 0;
6655 con->bytes_read = 0;
6656 con->bytes_header = 0;
6657 con->loops_per_request = 0;
6658-
6659+
6660 con->request.http_method = HTTP_METHOD_UNSET;
6661 con->request.http_version = HTTP_VERSION_UNSET;
6662-
6663+
6664 con->request.http_if_modified_since = NULL;
6665 con->request.http_if_none_match = NULL;
6666-
6667+
6668 con->response.keep_alive = 0;
6669 con->response.content_length = -1;
6670 con->response.transfer_encoding = 0;
6671-
6672+
6673 con->mode = DIRECT;
6674-
6675+
6676 #define CLEAN(x) \
6677 if (con->x) buffer_reset(con->x);
6678-
6679+
6680 CLEAN(request.uri);
6681 CLEAN(request.request_line);
6682 CLEAN(request.pathinfo);
6683 CLEAN(request.request);
6684-
6685+
6686 CLEAN(request.orig_uri);
6687-
6688+
6689 CLEAN(uri.scheme);
6690 CLEAN(uri.authority);
6691 CLEAN(uri.path);
6692 CLEAN(uri.path_raw);
6693 CLEAN(uri.query);
6694-
6695+
6696 CLEAN(physical.doc_root);
6697 CLEAN(physical.path);
6698 CLEAN(physical.basedir);
6699 CLEAN(physical.rel_path);
6700 CLEAN(physical.etag);
6701-
6702+
6703 CLEAN(parse_request);
6704-
6705+
6706 CLEAN(authed_user);
6707 CLEAN(server_name);
6708 CLEAN(error_handler);
6709-#undef CLEAN
6710-
6711+#undef CLEAN
6712+
6713 #define CLEAN(x) \
6714- if (con->x) con->x->used = 0;
6715-
6716+ if (con->x) con->x->used = 0;
6717+
6718 #undef CLEAN
6719-
6720+
6721 #define CLEAN(x) \
6722 con->request.x = NULL;
6723-
6724+
6725 CLEAN(http_host);
6726 CLEAN(http_range);
6727 CLEAN(http_content_type);
6728 #undef CLEAN
6729 con->request.content_length = 0;
6730-
6731+
6732 array_reset(con->request.headers);
6733 array_reset(con->response.headers);
6734 array_reset(con->environment);
6735-
6736+
6737 chunkqueue_reset(con->write_queue);
6738 chunkqueue_reset(con->request_content_queue);
6739
6740- /* the plugins should cleanup themself */
6741+ /* the plugins should cleanup themself */
6742 for (i = 0; i < srv->plugins.used; i++) {
6743 plugin *p = ((plugin **)(srv->plugins.ptr))[i];
6744 plugin_data *pd = p->data;
6745@@ -768,7 +664,7 @@
6746
6747 con->plugin_ctx[pd->id] = NULL;
6748 }
6749-
6750+
6751 #if COND_RESULT_UNSET
6752 for (i = srv->config_context->used - 1; i >= 0; i --) {
6753 con->cond_cache[i].result = COND_RESULT_UNSET;
6754@@ -777,56 +673,56 @@
6755 #else
6756 memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
6757 #endif
6758-
6759+
6760 con->header_len = 0;
6761 con->in_error_handler = 0;
6762-
6763+
6764 config_setup_connection(srv, con);
6765-
6766+
6767 return 0;
6768 }
6769
6770 /**
6771- *
6772- * search for \r\n\r\n
6773- *
6774+ *
6775+ * search for \r\n\r\n
6776+ *
6777 * this is a special 32bit version which is using a sliding window for
6778- * the comparisions
6779- *
6780+ * the comparisions
6781+ *
6782 * how it works:
6783- *
6784+ *
6785 * b: 'abcdefg'
6786 * rnrn: 'cdef'
6787- *
6788+ *
6789 * cmpbuf: abcd != cdef
6790 * cmpbuf: bcde != cdef
6791 * cmpbuf: cdef == cdef -> return &c
6792- *
6793- * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
6794+ *
6795+ * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
6796 * maintain cmpbuf and rnrn
6797- *
6798+ *
6799 */
6800
6801 char *buffer_search_rnrn(buffer *b) {
6802 uint32_t cmpbuf, rnrn;
6803 char *cp;
6804 size_t i;
6805-
6806+
6807 if (b->used < 4) return NULL;
6808-
6809+
6810 rnrn = ('\r' << 24) | ('\n' << 16) |
6811 ('\r' << 8) | ('\n' << 0);
6812-
6813+
6814 cmpbuf = (b->ptr[0] << 24) | (b->ptr[1] << 16) |
6815 (b->ptr[2] << 8) | (b->ptr[3] << 0);
6816-
6817+
6818 cp = b->ptr + 4;
6819 for (i = 0; i < b->used - 4; i++) {
6820 if (cmpbuf == rnrn) return cp - 4;
6821-
6822+
6823 cmpbuf = (cmpbuf << 8 | *(cp++)) & 0xffffffff;
6824 }
6825-
6826+
6827 return NULL;
6828 }
6829 /**
6830@@ -840,22 +736,25 @@
6831 chunk *c;
6832 chunkqueue *cq = con->read_queue;
6833 chunkqueue *dst_cq = con->request_content_queue;
6834-
6835+
6836 if (con->is_readable) {
f26f9fd5 6837 con->read_idle_ts = srv->cur_ts;
2519e6e5
ER
6838-
6839+
f26f9fd5
ER
6840 switch(connection_handle_read(srv, con)) {
6841- case -1:
6842+ case NETWORK_STATUS_FATAL_ERROR:
6843 return -1;
6844- case -2:
6845+ case NETWORK_STATUS_CONNECTION_CLOSE:
6846 /* remote side closed the connection
6847 * if we still have content, handle it, if not leave here */
6848
6849 if (cq->first == cq->last &&
6850- cq->first->mem->used == 0) {
1175ccec 6851+ (NULL == cq->first ||
f26f9fd5
ER
6852+ cq->first->mem->used == 0)) {
6853
6854 /* conn-closed, leave here */
6855 connection_set_state(srv, con, CON_STATE_ERROR);
f673a614 6856+
1175ccec 6857+ return 0;
f26f9fd5
ER
6858 }
6859 default:
6860 break;
2519e6e5
ER
6861@@ -891,14 +790,14 @@
6862 /* the last node was empty */
6863 if (c->next == NULL) {
6864 cq->last = c;
6865- }
6866+ }
6867
6868 c = c->next;
6869 } else {
6870 c = c->next;
6871 }
6872 }
6873-
6874+
6875 /* nothing to handle */
6876 if (cq->first == NULL) return 0;
6877
6878@@ -906,25 +805,26 @@
6879 case CON_STATE_READ:
6880 /* prepare con->request.request */
6881 c = cq->first;
6882-
6883+
6884 /* check if we need the full package */
6885 if (con->request.request->used == 0) {
6886 buffer b;
6887-
6888+
6889 b.ptr = c->mem->ptr + c->offset;
6890 b.used = c->mem->used - c->offset;
6891-
6892+
6893 if (NULL != (h_term = buffer_search_rnrn(&b))) {
6894 /* \r\n\r\n found
6895 * - copy everything incl. the terminator to request.request
6896 */
6897-
6898- buffer_copy_string_len(con->request.request,
6899- b.ptr,
6900+
6901+ buffer_copy_string_len(con->request.request,
6902+ b.ptr,
6903 h_term - b.ptr + 4);
6904-
6905+
f26f9fd5
ER
6906 /* the buffer has been read up to the terminator */
6907 c->offset += h_term - b.ptr + 4;
f673a614 6908+
f26f9fd5
ER
6909 } else {
6910 /* not found, copy everything */
6911 buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
2519e6e5
ER
6912@@ -932,14 +832,14 @@
6913 }
6914 } else {
6915 /* have to take care of overlapping header terminators */
6916-
6917+
6918 size_t l = con->request.request->used - 2;
6919 char *s = con->request.request->ptr;
6920 buffer b;
6921-
6922+
6923 b.ptr = c->mem->ptr + c->offset;
6924 b.used = c->mem->used - c->offset;
6925-
6926+
6927 if (con->request.request->used - 1 > 3 &&
6928 c->mem->used > 1 &&
6929 s[l-2] == '\r' &&
6930@@ -948,7 +848,7 @@
6931 c->mem->ptr[0] == '\n') {
6932 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
6933 c->offset += 1;
6934-
6935+
6936 h_term = con->request.request->ptr;
6937 } else if (con->request.request->used - 1 > 2 &&
6938 c->mem->used > 2 &&
6939@@ -958,7 +858,7 @@
6940 c->mem->ptr[1] == '\n') {
6941 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
6942 c->offset += 2;
6943-
6944+
6945 h_term = con->request.request->ptr;
6946 } else if (con->request.request->used - 1 > 1 &&
6947 c->mem->used > 3 &&
6948@@ -968,17 +868,17 @@
6949 c->mem->ptr[2] == '\n') {
6950 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3);
6951 c->offset += 3;
6952-
6953+
6954 h_term = con->request.request->ptr;
6955 } else if (NULL != (h_term = buffer_search_string_len(&b, "\r\n\r\n", 4))) {
6956 /* \r\n\r\n found
6957 * - copy everything incl. the terminator to request.request
6958 */
6959-
6960- buffer_append_string_len(con->request.request,
6961- c->mem->ptr + c->offset,
6962+
6963+ buffer_append_string_len(con->request.request,
6964+ c->mem->ptr + c->offset,
6965 c->offset + h_term - b.ptr + 4);
6966-
6967+
6968 /* the buffer has been read up to the terminator */
6969 c->offset += h_term - b.ptr + 4;
6970 } else {
6971@@ -999,16 +899,16 @@
6972 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
6973 }
6974 break;
6975- case CON_STATE_READ_POST:
6976+ case CON_STATE_READ_POST:
6977 for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
6978 off_t weWant, weHave, toRead;
6979-
6980+
6981 weWant = con->request.content_length - dst_cq->bytes_in;
6982-
6983+
6984 assert(c->mem->used);
6985-
6986+
6987 weHave = c->mem->used - c->offset - 1;
6988-
6989+
6990 toRead = weHave > weWant ? weWant : weHave;
6991
6992 /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
6993@@ -1017,13 +917,13 @@
6994 /* copy everything to max 1Mb sized tempfiles */
6995
6996 /*
6997- * if the last chunk is
6998+ * if the last chunk is
6999 * - smaller than 1Mb (size < 1Mb)
7000 * - not read yet (offset == 0)
7001 * -> append to it
7002 * otherwise
7003- * -> create a new chunk
7004- *
7005+ * -> create a new chunk
7006+ *
7007 * */
7008
7009 if (dst_cq->last &&
7010@@ -1056,14 +956,14 @@
7011 /* we have a chunk, let's write to it */
7012
7013 if (dst_c->file.fd == -1) {
7014- /* we don't have file to write to,
7015+ /* we don't have file to write to,
7016 * EACCES might be one reason.
7017 *
7018 * Instead of sending 500 we send 413 and say the request is too large
7019 * */
7020
7021 log_error_write(srv, __FILE__, __LINE__, "sbs",
7022- "denying upload as opening to temp-file for upload failed:",
7023+ "denying upload as opening to temp-file for upload failed:",
7024 dst_c->file.name, strerror(errno));
7025
7026 con->http_status = 413; /* Request-Entity too large */
7027@@ -1074,15 +974,15 @@
7028 }
7029
7030 if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
7031- /* write failed for some reason ... disk full ? */
7032+ /* write failed for some reason ... disk full ? */
7033 log_error_write(srv, __FILE__, __LINE__, "sbs",
7034- "denying upload as writing to file failed:",
7035+ "denying upload as writing to file failed:",
7036 dst_c->file.name, strerror(errno));
7037-
7038+
7039 con->http_status = 413; /* Request-Entity too large */
7040 con->keep_alive = 0;
7041 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7042-
7043+
7044 close(dst_c->file.fd);
7045 dst_c->file.fd = -1;
7046
7047@@ -1090,7 +990,7 @@
7048 }
7049
7050 dst_c->file.length += toRead;
7051-
7052+
7053 if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
7054 /* we read everything, close the chunk */
7055 close(dst_c->file.fd);
7056@@ -1102,7 +1002,7 @@
7057 b = chunkqueue_get_append_buffer(dst_cq);
7058 buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
7059 }
7060-
7061+
7062 c->offset += toRead;
7063 dst_cq->bytes_in += toRead;
7064 }
7065@@ -1111,7 +1011,7 @@
7066 if (dst_cq->bytes_in == (off_t)con->request.content_length) {
7067 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7068 }
7069-
7070+
7071 break;
7072 }
7073
7074@@ -1123,9 +1023,9 @@
7075 handler_t connection_handle_fdevent(void *s, void *context, int revents) {
7076 server *srv = (server *)s;
7077 connection *con = context;
7078-
7079+
7080 joblist_append(srv, con);
7081-
7082+
7083 if (revents & FDEVENT_IN) {
7084 con->is_readable = 1;
7085 #if 0
7086@@ -1136,19 +1036,19 @@
7087 con->is_writable = 1;
7088 /* we don't need the event twice */
7089 }
7090-
7091-
7092+
7093+
7094 if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
7095 /* looks like an error */
7096-
7097+
7098 /* FIXME: revents = 0x19 still means that we should read from the queue */
7099 if (revents & FDEVENT_HUP) {
7100 if (con->state == CON_STATE_CLOSE) {
7101 con->close_timeout_ts = 0;
7102 } else {
7103 /* sigio reports the wrong event here
7104- *
7105- * there was no HUP at all
7106+ *
7107+ * there was no HUP at all
7108 */
7109 #ifdef USE_LINUX_SIGIO
7110 if (srv->ev->in_sigio == 1) {
7111@@ -1160,32 +1060,39 @@
7112 #else
7113 connection_set_state(srv, con, CON_STATE_ERROR);
7114 #endif
7115-
7116+
7117 }
7118 } else if (revents & FDEVENT_ERR) {
7119 #ifndef USE_LINUX_SIGIO
7120 log_error_write(srv, __FILE__, __LINE__, "sd",
7121 "connection closed: poll() -> ERR", con->fd);
7122-#endif
7123+#endif
7124 connection_set_state(srv, con, CON_STATE_ERROR);
7125 } else {
7126 log_error_write(srv, __FILE__, __LINE__, "sd",
7127 "connection closed: poll() -> ???", revents);
7128- }
7129+ }
7130 }
7131-
7132+
7133 if (con->state == CON_STATE_READ ||
7134 con->state == CON_STATE_READ_POST) {
7135 connection_handle_read_state(srv, con);
7136+ /**
7137+ * if SSL_read() is not readin in the full packet we won't get
7138+ * a fdevent as the low-level has already fetched everything.
7139+ *
7140+ * we have to call the state-engine to read the rest of the packet
7141+ */
7142+ if (con->is_readable) joblist_append(srv, con);
7143 }
7144-
7145+
7146 if (con->state == CON_STATE_WRITE &&
7147 !chunkqueue_is_empty(con->write_queue) &&
7148 con->is_writable) {
7149-
7150+
7151 if (-1 == connection_handle_write(srv, con)) {
7152 connection_set_state(srv, con, CON_STATE_ERROR);
7153-
7154+
7155 log_error_write(srv, __FILE__, __LINE__, "ds",
7156 con->fd,
7157 "handle write failed.");
7158@@ -1193,30 +1100,30 @@
7159 con->write_request_ts = srv->cur_ts;
7160 }
7161 }
7162-
7163+
7164 if (con->state == CON_STATE_CLOSE) {
7165 /* flush the read buffers */
7166 int b;
7167-
7168+
7169 if (ioctl(con->fd, FIONREAD, &b)) {
7170 log_error_write(srv, __FILE__, __LINE__, "ss",
7171 "ioctl() failed", strerror(errno));
7172 }
7173-
7174+
7175 if (b > 0) {
7176 char buf[1024];
7177 log_error_write(srv, __FILE__, __LINE__, "sdd",
7178 "CLOSE-read()", con->fd, b);
7179-
7180+
7181 /* */
7182 read(con->fd, buf, sizeof(buf));
7183 } else {
7184 /* nothing to read */
7185-
7186+
7187 con->close_timeout_ts = 0;
7188 }
7189 }
7190-
7191+
7192 return HANDLER_FINISHED;
7193 }
7194
7195@@ -1229,63 +1136,68 @@
7196 sock_addr cnt_addr;
7197 socklen_t cnt_len;
7198 /* accept it and register the fd */
7199-
7200+
7201 cnt_len = sizeof(cnt_addr);
7202
7203 if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
7204+#ifdef _WIN32
1175ccec 7205+ errno = WSAGetLastError();
f26f9fd5
ER
7206+#endif
7207 if ((errno != EAGAIN) &&
1175ccec 7208+ (errno != EWOULDBLOCK) &&
f26f9fd5
ER
7209 (errno != EINTR)) {
7210- log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
7211+ log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), srv_socket->fd);
7212 }
7213 return NULL;
7214 } else {
2519e6e5
ER
7215 connection *con;
7216-
7217+
7218 srv->cur_fds++;
7219-
7220+
7221 /* ok, we have the connection, register it */
7222 #if 0
7223 log_error_write(srv, __FILE__, __LINE__, "sd",
7224 "appected()", cnt);
7225 #endif
f26f9fd5 7226 srv->con_opened++;
2519e6e5
ER
7227-
7228+
f26f9fd5
ER
7229 con = connections_get_new_connection(srv);
7230-
7231 con->fd = cnt;
7232 con->fde_ndx = -1;
2519e6e5
ER
7233-#if 0
7234+#if 0
7235 gettimeofday(&(con->start_tv), NULL);
7236-#endif
7237+#endif
7238 fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
7239-
7240+
7241 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7242-
7243+
7244 con->connection_start = srv->cur_ts;
7245 con->dst_addr = cnt_addr;
7246 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
7247 con->srv_socket = srv_socket;
7248-
7249+
f26f9fd5
ER
7250 if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
7251 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
7252+ connection_close(srv, con);
7253 return NULL;
7254 }
7255 #ifdef USE_OPENSSL
2519e6e5
ER
7256 /* connect FD to SSL */
7257 if (srv_socket->is_ssl) {
f26f9fd5 7258 if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
2519e6e5
ER
7259- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7260+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
f26f9fd5
ER
7261 ERR_error_string(ERR_get_error(), NULL));
7262-
7263+ connection_close(srv, con);
7264 return NULL;
7265 }
2519e6e5
ER
7266-
7267+
7268 SSL_set_accept_state(con->ssl);
7269 con->conf.is_ssl=1;
7270-
7271+
f26f9fd5 7272 if (1 != (SSL_set_fd(con->ssl, cnt))) {
2519e6e5
ER
7273- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7274+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
f26f9fd5
ER
7275 ERR_error_string(ERR_get_error(), NULL));
7276+ connection_close(srv, con);
7277 return NULL;
7278 }
7279 }
2519e6e5
ER
7280@@ -1300,10 +1212,10 @@
7281 #ifdef USE_OPENSSL
7282 server_socket *srv_sock = con->srv_socket;
f26f9fd5 7283 #endif
2519e6e5 7284-
f673a614 7285+
2519e6e5
ER
7286 if (srv->srvconf.log_state_handling) {
7287- log_error_write(srv, __FILE__, __LINE__, "sds",
7288- "state at start",
7289+ log_error_write(srv, __FILE__, __LINE__, "sds",
7290+ "state at start",
7291 con->fd,
7292 connection_get_state(con->state));
7293 }
7294@@ -1311,91 +1223,91 @@
7295 while (done == 0) {
7296 size_t ostate = con->state;
7297 int b;
7298-
f26f9fd5 7299+
2519e6e5
ER
7300 switch (con->state) {
7301 case CON_STATE_REQUEST_START: /* transient */
7302 if (srv->srvconf.log_state_handling) {
7303- log_error_write(srv, __FILE__, __LINE__, "sds",
7304+ log_error_write(srv, __FILE__, __LINE__, "sds",
7305 "state for fd", con->fd, connection_get_state(con->state));
7306 }
7307-
7308+
7309 con->request_start = srv->cur_ts;
7310 con->read_idle_ts = srv->cur_ts;
7311-
7312+
7313 con->request_count++;
7314 con->loops_per_request = 0;
7315-
7316+
7317 connection_set_state(srv, con, CON_STATE_READ);
7318-
7319+
7320 break;
7321 case CON_STATE_REQUEST_END: /* transient */
7322 if (srv->srvconf.log_state_handling) {
7323- log_error_write(srv, __FILE__, __LINE__, "sds",
7324+ log_error_write(srv, __FILE__, __LINE__, "sds",
7325 "state for fd", con->fd, connection_get_state(con->state));
7326 }
7327-
7328+
7329 if (http_request_parse(srv, con)) {
7330 /* we have to read some data from the POST request */
7331-
7332+
7333 connection_set_state(srv, con, CON_STATE_READ_POST);
f673a614 7334
2519e6e5
ER
7335 break;
7336 }
7337-
f673a614 7338+
2519e6e5
ER
7339 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7340-
f673a614 7341+
2519e6e5
ER
7342 break;
7343 case CON_STATE_HANDLE_REQUEST:
7344- /*
7345+ /*
7346 * the request is parsed
7347- *
7348+ *
7349 * decided what to do with the request
7350- * -
7351- *
7352- *
7353+ * -
7354+ *
7355+ *
7356 */
7357-
f26f9fd5 7358+
2519e6e5
ER
7359 if (srv->srvconf.log_state_handling) {
7360- log_error_write(srv, __FILE__, __LINE__, "sds",
7361+ log_error_write(srv, __FILE__, __LINE__, "sds",
7362 "state for fd", con->fd, connection_get_state(con->state));
7363 }
7364-
f26f9fd5 7365+
2519e6e5
ER
7366 switch (r = http_response_prepare(srv, con)) {
7367 case HANDLER_FINISHED:
7368 if (con->http_status == 404 ||
7369 con->http_status == 403) {
7370 /* 404 error-handler */
7371-
7372- if (con->in_error_handler == 0 &&
f26f9fd5 7373+
2519e6e5
ER
7374+ if (con->in_error_handler == 0 &&
7375 (!buffer_is_empty(con->conf.error_handler) ||
7376 !buffer_is_empty(con->error_handler))) {
7377 /* call error-handler */
7378-
7379+
7380 con->error_handler_saved_status = con->http_status;
7381 con->http_status = 0;
7382-
7383+
7384 if (buffer_is_empty(con->error_handler)) {
7385 buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
7386 } else {
7387 buffer_copy_string_buffer(con->request.uri, con->error_handler);
7388 }
7389 buffer_reset(con->physical.path);
7390-
7391+
7392 con->in_error_handler = 1;
7393-
7394+
7395 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7396-
7397+
7398 done = -1;
7399 break;
7400 } else if (con->in_error_handler) {
7401 /* error-handler is a 404 */
7402-
7403+
7404 /* continue as normal, status is the same */
7405- log_error_write(srv, __FILE__, __LINE__, "sb",
7406+ log_error_write(srv, __FILE__, __LINE__, "sb",
7407 "Warning: Either the error-handler returned status 404 or the error-handler itself was not found:", con->request.uri);
7408- log_error_write(srv, __FILE__, __LINE__, "sd",
7409+ log_error_write(srv, __FILE__, __LINE__, "sd",
7410 "returning the original status", con->error_handler_saved_status);
7411- log_error_write(srv, __FILE__, __LINE__, "s",
7412+ log_error_write(srv, __FILE__, __LINE__, "s",
7413 "If this is a rails app: check your production.log");
7414 con->http_status = con->error_handler_saved_status;
f26f9fd5 7415 }
2519e6e5
ER
7416@@ -1403,26 +1315,26 @@
7417 /* error-handler is back and has generated content */
7418 /* if Status: was set, take it otherwise use 200 */
7419 }
7420-
f673a614 7421+
2519e6e5
ER
7422 if (con->http_status == 0) con->http_status = 200;
7423-
f673a614 7424+
2519e6e5
ER
7425 /* we have something to send, go on */
7426 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
7427 break;
7428 case HANDLER_WAIT_FOR_FD:
7429 srv->want_fds++;
7430-
f673a614 7431+
2519e6e5
ER
7432 fdwaitqueue_append(srv, con);
7433-
f673a614 7434+
2519e6e5
ER
7435 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7436-
f673a614 7437+
2519e6e5
ER
7438 break;
7439 case HANDLER_COMEBACK:
7440 done = -1;
7441 case HANDLER_WAIT_FOR_EVENT:
7442 /* come back here */
7443 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7444-
f673a614 7445+
2519e6e5
ER
7446 break;
7447 case HANDLER_ERROR:
7448 /* something went wrong */
7449@@ -1432,44 +1344,44 @@
7450 log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
7451 break;
7452 }
7453-
7454+
7455 break;
7456 case CON_STATE_RESPONSE_START:
7457- /*
7458+ /*
7459 * the decision is done
7460 * - create the HTTP-Response-Header
7461- *
7462+ *
7463 */
7464-
7465+
7466 if (srv->srvconf.log_state_handling) {
7467- log_error_write(srv, __FILE__, __LINE__, "sds",
7468+ log_error_write(srv, __FILE__, __LINE__, "sds",
7469 "state for fd", con->fd, connection_get_state(con->state));
7470 }
7471-
7472+
7473 if (-1 == connection_handle_write_prepare(srv, con)) {
7474 connection_set_state(srv, con, CON_STATE_ERROR);
7475-
7476+
7477 break;
7478 }
7479-
7480+
7481 connection_set_state(srv, con, CON_STATE_WRITE);
7482 break;
7483 case CON_STATE_RESPONSE_END: /* transient */
7484 /* log the request */
7485-
7486+
7487 if (srv->srvconf.log_state_handling) {
7488- log_error_write(srv, __FILE__, __LINE__, "sds",
7489+ log_error_write(srv, __FILE__, __LINE__, "sds",
7490 "state for fd", con->fd, connection_get_state(con->state));
7491 }
7492-
7493+
7494 plugins_call_handle_request_done(srv, con);
7495-
7496+
7497 srv->con_written++;
7498-
7499+
7500 if (con->keep_alive) {
7501 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7502-
7503-#if 0
7504+
7505+#if 0
7506 con->request_start = srv->cur_ts;
7507 con->read_idle_ts = srv->cur_ts;
7508 #endif
7509@@ -1482,7 +1394,7 @@
7510 log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
7511 break;
7512 }
7513-
f673a614 7514+
f26f9fd5 7515 #ifdef USE_OPENSSL
2519e6e5
ER
7516 if (srv_sock->is_ssl) {
7517 switch (SSL_shutdown(con->ssl)) {
7518@@ -1490,44 +1402,44 @@
7519 /* done */
7520 break;
7521 case 0:
7522- /* wait for fd-event
7523- *
7524+ /* wait for fd-event
7525+ *
7526 * FIXME: wait for fdevent and call SSL_shutdown again
7527- *
7528+ *
7529 */
7530-
7531+
7532 break;
7533 default:
7534- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7535+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7536 ERR_error_string(ERR_get_error(), NULL));
7537 }
7538 }
f26f9fd5 7539 #endif
2519e6e5
ER
7540 connection_close(srv, con);
7541-
7542+
7543 srv->con_closed++;
7544 }
7545-
7546+
7547 connection_reset(srv, con);
7548-
7549+
7550 break;
7551 case CON_STATE_CONNECT:
7552 if (srv->srvconf.log_state_handling) {
7553- log_error_write(srv, __FILE__, __LINE__, "sds",
7554+ log_error_write(srv, __FILE__, __LINE__, "sds",
7555 "state for fd", con->fd, connection_get_state(con->state));
7556 }
7557-
7558+
7559 chunkqueue_reset(con->read_queue);
7560-
7561+
7562 con->request_count = 0;
7563-
7564+
7565 break;
7566 case CON_STATE_CLOSE:
7567 if (srv->srvconf.log_state_handling) {
7568- log_error_write(srv, __FILE__, __LINE__, "sds",
7569+ log_error_write(srv, __FILE__, __LINE__, "sds",
7570 "state for fd", con->fd, connection_get_state(con->state));
7571 }
7572-
7573+
7574 if (con->keep_alive) {
7575 if (ioctl(con->fd, FIONREAD, &b)) {
7576 log_error_write(srv, __FILE__, __LINE__, "ss",
7577@@ -1537,43 +1449,43 @@
7578 char buf[1024];
7579 log_error_write(srv, __FILE__, __LINE__, "sdd",
7580 "CLOSE-read()", con->fd, b);
7581-
7582+
7583 /* */
7584 read(con->fd, buf, sizeof(buf));
7585 } else {
7586 /* nothing to read */
7587-
7588+
7589 con->close_timeout_ts = 0;
7590 }
7591 } else {
7592 con->close_timeout_ts = 0;
7593 }
7594-
7595+
7596 if (srv->cur_ts - con->close_timeout_ts > 1) {
7597 connection_close(srv, con);
7598-
7599+
7600 if (srv->srvconf.log_state_handling) {
7601- log_error_write(srv, __FILE__, __LINE__, "sd",
7602+ log_error_write(srv, __FILE__, __LINE__, "sd",
7603 "connection closed for fd", con->fd);
7604 }
7605 }
7606-
7607+
7608 break;
7609 case CON_STATE_READ_POST:
7610 case CON_STATE_READ:
7611 if (srv->srvconf.log_state_handling) {
7612- log_error_write(srv, __FILE__, __LINE__, "sds",
7613+ log_error_write(srv, __FILE__, __LINE__, "sds",
7614 "state for fd", con->fd, connection_get_state(con->state));
7615 }
7616-
7617+
7618 connection_handle_read_state(srv, con);
7619 break;
7620 case CON_STATE_WRITE:
7621 if (srv->srvconf.log_state_handling) {
7622- log_error_write(srv, __FILE__, __LINE__, "sds",
7623+ log_error_write(srv, __FILE__, __LINE__, "sds",
7624 "state for fd", con->fd, connection_get_state(con->state));
7625 }
7626-
7627+
7628 /* only try to write if we have something in the queue */
7629 if (!chunkqueue_is_empty(con->write_queue)) {
7630 #if 0
7631@@ -1593,10 +1505,10 @@
7632 con->write_request_ts = srv->cur_ts;
7633 }
7634 }
7635-
7636+
7637 break;
7638 case CON_STATE_ERROR: /* transient */
7639-
7640+
7641 /* even if the connection was drop we still have to write it to the access log */
7642 if (con->http_status) {
7643 plugins_call_handle_request_done(srv, con);
7644@@ -1612,19 +1524,19 @@
7645 SSL_shutdown(con->ssl);
7646 break;
7647 default:
7648- log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
7649- SSL_get_error(con->ssl, ret),
7650+ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
7651+ SSL_get_error(con->ssl, ret),
7652 ERR_error_string(ERR_get_error(), NULL));
7653 return -1;
7654 }
7655 }
f26f9fd5 7656 #endif
2519e6e5
ER
7657-
7658+
7659 switch(con->mode) {
7660 case DIRECT:
7661 #if 0
7662- log_error_write(srv, __FILE__, __LINE__, "sd",
7663- "emergency exit: direct",
7664+ log_error_write(srv, __FILE__, __LINE__, "sd",
7665+ "emergency exit: direct",
7666 con->fd);
7667 #endif
7668 break;
7669@@ -1639,35 +1551,35 @@
7670 }
7671 break;
7672 }
7673-
7674+
7675 connection_reset(srv, con);
7676-
7677+
7678 /* close the connection */
7679 if ((con->keep_alive == 1) &&
7680 (0 == shutdown(con->fd, SHUT_WR))) {
7681 con->close_timeout_ts = srv->cur_ts;
7682 connection_set_state(srv, con, CON_STATE_CLOSE);
7683-
7684+
7685 if (srv->srvconf.log_state_handling) {
7686- log_error_write(srv, __FILE__, __LINE__, "sd",
7687+ log_error_write(srv, __FILE__, __LINE__, "sd",
7688 "shutdown for fd", con->fd);
7689 }
7690 } else {
7691 connection_close(srv, con);
7692 }
7693-
7694+
7695 con->keep_alive = 0;
7696-
7697+
7698 srv->con_closed++;
7699-
7700+
7701 break;
7702 default:
7703- log_error_write(srv, __FILE__, __LINE__, "sdd",
7704+ log_error_write(srv, __FILE__, __LINE__, "sdd",
7705 "unknown state:", con->fd, con->state);
7706-
7707+
7708 break;
7709 }
7710-
7711+
7712 if (done == -1) {
7713 done = 0;
7714 } else if (ostate == con->state) {
7715@@ -1676,12 +1588,12 @@
7716 }
f673a614 7717
2519e6e5
ER
7718 if (srv->srvconf.log_state_handling) {
7719- log_error_write(srv, __FILE__, __LINE__, "sds",
7720- "state at exit:",
7721+ log_error_write(srv, __FILE__, __LINE__, "sds",
7722+ "state at exit:",
7723 con->fd,
7724 connection_get_state(con->state));
7725 }
7726-
7727+
7728 switch(con->state) {
7729 case CON_STATE_READ_POST:
7730 case CON_STATE_READ:
7731@@ -1689,11 +1601,11 @@
7732 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
7733 break;
7734 case CON_STATE_WRITE:
7735- /* request write-fdevent only if we really need it
7736+ /* request write-fdevent only if we really need it
7737 * - if we have data to write
7738- * - if the socket is not writable yet
7739+ * - if the socket is not writable yet
7740 */
7741- if (!chunkqueue_is_empty(con->write_queue) &&
7742+ if (!chunkqueue_is_empty(con->write_queue) &&
7743 (con->is_writable == 0) &&
7744 (con->traffic_limit_reached == 0)) {
7745 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
1175ccec 7746--- ../lighttpd-1.4.11/src/crc32.h 2005-09-30 20:18:59.000000000 +0300
36e2a29e 7747+++ lighttpd-1.4.12/src/crc32.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
7748@@ -6,6 +6,7 @@
7749 #endif
f673a614 7750
2519e6e5
ER
7751 #include <sys/types.h>
7752+#include <stdlib.h>
f673a614 7753
2519e6e5
ER
7754 #if defined HAVE_STDINT_H
7755 #include <stdint.h>
7756@@ -13,6 +14,10 @@
7757 #include <inttypes.h>
f26f9fd5 7758 #endif
f673a614 7759
f26f9fd5 7760+#ifdef _WIN32
2519e6e5 7761+#define uint32_t unsigned __int32
f26f9fd5
ER
7762+#endif
7763+
2519e6e5 7764 uint32_t generate_crc32c(char *string, size_t length);
f673a614 7765
f26f9fd5 7766 #endif
1175ccec 7767--- ../lighttpd-1.4.11/src/data_array.c 2005-08-23 17:36:12.000000000 +0300
36e2a29e 7768+++ lighttpd-1.4.12/src/data_array.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5 7769@@ -17,16 +17,16 @@
f673a614 7770
2519e6e5
ER
7771 static void data_array_free(data_unset *d) {
7772 data_array *ds = (data_array *)d;
7773-
7774+
7775 buffer_free(ds->key);
7776 array_free(ds->value);
7777-
7778+
7779 free(d);
7780 }
f673a614 7781
2519e6e5
ER
7782 static void data_array_reset(data_unset *d) {
7783 data_array *ds = (data_array *)d;
7784-
7785+
7786 /* reused array elements */
7787 buffer_reset(ds->key);
7788 array_reset(ds->value);
7789@@ -36,7 +36,7 @@
7790 UNUSED(dst);
f673a614 7791
2519e6e5
ER
7792 src->free(src);
7793-
f26f9fd5 7794+
2519e6e5 7795 return 0;
f673a614
ER
7796 }
7797
2519e6e5 7798@@ -48,18 +48,18 @@
f673a614 7799
2519e6e5
ER
7800 data_array *data_array_init(void) {
7801 data_array *ds;
7802-
7803+
7804 ds = calloc(1, sizeof(*ds));
7805-
7806+
7807 ds->key = buffer_init();
7808 ds->value = array_init();
7809-
7810+
7811 ds->copy = data_array_copy;
7812 ds->free = data_array_free;
7813 ds->reset = data_array_reset;
7814 ds->insert_dup = data_array_insert_dup;
7815 ds->print = data_array_print;
7816 ds->type = TYPE_ARRAY;
7817-
7818+
7819 return ds;
f673a614 7820 }
1175ccec 7821--- ../lighttpd-1.4.11/src/data_config.c 2005-08-17 12:53:19.000000000 +0300
36e2a29e 7822+++ lighttpd-1.4.12/src/data_config.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5 7823@@ -17,26 +17,26 @@
f673a614 7824
2519e6e5
ER
7825 static void data_config_free(data_unset *d) {
7826 data_config *ds = (data_config *)d;
7827-
7828+
7829 buffer_free(ds->key);
7830 buffer_free(ds->op);
7831 buffer_free(ds->comp_key);
7832-
7833+
7834 array_free(ds->value);
7835 array_free(ds->childs);
7836-
7837+
7838 if (ds->string) buffer_free(ds->string);
7839 #ifdef HAVE_PCRE_H
7840 if (ds->regex) pcre_free(ds->regex);
7841 if (ds->regex_study) pcre_free(ds->regex_study);
7842 #endif
7843-
7844+
7845 free(d);
7846 }
f673a614 7847
2519e6e5
ER
7848 static void data_config_reset(data_unset *d) {
7849 data_config *ds = (data_config *)d;
7850-
7851+
7852 /* reused array elements */
7853 buffer_reset(ds->key);
7854 buffer_reset(ds->comp_key);
7855@@ -45,9 +45,9 @@
f673a614 7856
2519e6e5
ER
7857 static int data_config_insert_dup(data_unset *dst, data_unset *src) {
7858 UNUSED(dst);
7859-
7860+
7861 src->free(src);
7862-
7863+
7864 return 0;
7865 }
f673a614 7866
2519e6e5
ER
7867@@ -56,7 +56,7 @@
7868 array *a = (array *)ds->value;
7869 size_t i;
7870 size_t maxlen;
f673a614 7871-
2519e6e5
ER
7872+
7873 if (0 == ds->context_ndx) {
7874 fprintf(stderr, "config {\n");
f26f9fd5 7875 }
2519e6e5
ER
7876@@ -117,22 +117,22 @@
7877
7878 data_config *data_config_init(void) {
7879 data_config *ds;
7880-
7881+
7882 ds = calloc(1, sizeof(*ds));
7883-
7884+
7885 ds->key = buffer_init();
7886 ds->op = buffer_init();
7887 ds->comp_key = buffer_init();
7888 ds->value = array_init();
7889 ds->childs = array_init();
7890 ds->childs->is_weakref = 1;
7891-
7892+
7893 ds->copy = data_config_copy;
7894 ds->free = data_config_free;
7895 ds->reset = data_config_reset;
7896 ds->insert_dup = data_config_insert_dup;
7897 ds->print = data_config_print;
7898 ds->type = TYPE_CONFIG;
7899-
7900+
7901 return ds;
f673a614 7902 }
1175ccec 7903--- ../lighttpd-1.4.11/src/data_count.c 2005-08-23 17:36:12.000000000 +0300
36e2a29e 7904+++ lighttpd-1.4.12/src/data_count.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5 7905@@ -16,53 +16,53 @@
f673a614 7906
2519e6e5
ER
7907 static void data_count_free(data_unset *d) {
7908 data_count *ds = (data_count *)d;
7909-
7910+
7911 buffer_free(ds->key);
7912-
7913+
7914 free(d);
7915 }
7916
7917 static void data_count_reset(data_unset *d) {
7918 data_count *ds = (data_count *)d;
7919-
7920+
7921 buffer_reset(ds->key);
7922-
7923+
7924 ds->count = 0;
7925 }
7926
7927 static int data_count_insert_dup(data_unset *dst, data_unset *src) {
7928 data_count *ds_dst = (data_count *)dst;
7929 data_count *ds_src = (data_count *)src;
7930-
7931+
7932 ds_dst->count += ds_src->count;
7933-
7934+
7935 src->free(src);
7936-
7937+
f26f9fd5 7938 return 0;
f673a614
ER
7939 }
7940
2519e6e5
ER
7941 static void data_count_print(const data_unset *d, int depth) {
7942 data_count *ds = (data_count *)d;
7943 UNUSED(depth);
7944-
7945+
7946 fprintf(stderr, "count(%d)", ds->count);
7947 }
f673a614 7948
f673a614 7949
2519e6e5
ER
7950 data_count *data_count_init(void) {
7951 data_count *ds;
7952-
7953+
7954 ds = calloc(1, sizeof(*ds));
7955-
7956+
7957 ds->key = buffer_init();
7958 ds->count = 1;
7959-
7960+
7961 ds->copy = data_count_copy;
7962 ds->free = data_count_free;
7963 ds->reset = data_count_reset;
7964 ds->insert_dup = data_count_insert_dup;
7965 ds->print = data_count_print;
7966 ds->type = TYPE_COUNT;
7967-
7968+
7969 return ds;
f673a614 7970 }
1175ccec 7971--- ../lighttpd-1.4.11/src/data_fastcgi.c 2005-08-23 17:36:12.000000000 +0300
36e2a29e 7972+++ lighttpd-1.4.12/src/data_fastcgi.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5 7973@@ -17,53 +17,53 @@
f673a614 7974
2519e6e5
ER
7975 static void data_fastcgi_free(data_unset *d) {
7976 data_fastcgi *ds = (data_fastcgi *)d;
7977-
7978+
7979 buffer_free(ds->key);
7980 buffer_free(ds->host);
7981-
7982+
7983 free(d);
7984 }
7985
7986 static void data_fastcgi_reset(data_unset *d) {
7987 data_fastcgi *ds = (data_fastcgi *)d;
7988-
7989+
7990 buffer_reset(ds->key);
7991 buffer_reset(ds->host);
7992-
7993+
7994 }
7995
7996 static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
7997 UNUSED(dst);
7998
7999 src->free(src);
8000-
8001+
f26f9fd5 8002 return 0;
f673a614
ER
8003 }
8004
2519e6e5
ER
8005 static void data_fastcgi_print(const data_unset *d, int depth) {
8006 data_fastcgi *ds = (data_fastcgi *)d;
8007 UNUSED(depth);
8008-
8009+
8010 fprintf(stderr, "fastcgi(%s)", ds->host->ptr);
8011 }
f673a614 8012
f673a614 8013
2519e6e5
ER
8014 data_fastcgi *data_fastcgi_init(void) {
8015 data_fastcgi *ds;
8016-
f673a614 8017+
2519e6e5
ER
8018 ds = calloc(1, sizeof(*ds));
8019-
8020+
8021 ds->key = buffer_init();
8022 ds->host = buffer_init();
8023 ds->port = 0;
8024 ds->is_disabled = 0;
8025-
8026+
8027 ds->copy = data_fastcgi_copy;
8028 ds->free = data_fastcgi_free;
8029 ds->reset = data_fastcgi_reset;
8030 ds->insert_dup = data_fastcgi_insert_dup;
8031 ds->print = data_fastcgi_print;
8032 ds->type = TYPE_FASTCGI;
8033-
8034+
8035 return ds;
8036 }
1175ccec 8037--- ../lighttpd-1.4.11/src/data_integer.c 2005-08-23 17:36:12.000000000 +0300
36e2a29e 8038+++ lighttpd-1.4.12/src/data_integer.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
8039@@ -16,15 +16,15 @@
8040
8041 static void data_integer_free(data_unset *d) {
8042 data_integer *ds = (data_integer *)d;
8043-
8044+
8045 buffer_free(ds->key);
8046-
8047+
8048 free(d);
8049 }
f26f9fd5 8050
2519e6e5
ER
8051 static void data_integer_reset(data_unset *d) {
8052 data_integer *ds = (data_integer *)d;
8053-
8054+
8055 /* reused integer elements */
8056 buffer_reset(ds->key);
8057 ds->value = 0;
8058@@ -32,9 +32,9 @@
f26f9fd5 8059
2519e6e5
ER
8060 static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
8061 UNUSED(dst);
8062-
8063+
8064 src->free(src);
8065-
8066+
8067 return 0;
f673a614
ER
8068 }
8069
2519e6e5 8070@@ -48,18 +48,18 @@
f673a614 8071
2519e6e5
ER
8072 data_integer *data_integer_init(void) {
8073 data_integer *ds;
8074-
8075+
8076 ds = calloc(1, sizeof(*ds));
8077-
8078+
8079 ds->key = buffer_init();
8080 ds->value = 0;
8081-
8082+
8083 ds->copy = data_integer_copy;
8084 ds->free = data_integer_free;
8085 ds->reset = data_integer_reset;
8086 ds->insert_dup = data_integer_insert_dup;
8087 ds->print = data_integer_print;
8088 ds->type = TYPE_INTEGER;
8089-
8090+
8091 return ds;
8092 }
1175ccec 8093--- ../lighttpd-1.4.11/src/data_string.c 2005-08-23 17:36:12.000000000 +0300
36e2a29e 8094+++ lighttpd-1.4.12/src/data_string.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
8095@@ -17,16 +17,16 @@
8096
8097 static void data_string_free(data_unset *d) {
8098 data_string *ds = (data_string *)d;
8099-
8100+
8101 buffer_free(ds->key);
8102 buffer_free(ds->value);
8103-
8104+
8105 free(d);
8106 }
8107
8108 static void data_string_reset(data_unset *d) {
8109 data_string *ds = (data_string *)d;
8110-
8111+
8112 /* reused array elements */
8113 buffer_reset(ds->key);
8114 buffer_reset(ds->value);
8115@@ -35,23 +35,23 @@
8116 static int data_string_insert_dup(data_unset *dst, data_unset *src) {
8117 data_string *ds_dst = (data_string *)dst;
8118 data_string *ds_src = (data_string *)src;
8119-
8120+
8121 if (ds_dst->value->used) {
8122 buffer_append_string(ds_dst->value, ", ");
8123 buffer_append_string_buffer(ds_dst->value, ds_src->value);
8124 } else {
8125 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
f26f9fd5 8126 }
2519e6e5
ER
8127-
8128+
8129 src->free(src);
8130-
8131+
f26f9fd5 8132 return 0;
f673a614
ER
8133 }
8134
2519e6e5
ER
8135 static int data_response_insert_dup(data_unset *dst, data_unset *src) {
8136 data_string *ds_dst = (data_string *)dst;
8137 data_string *ds_src = (data_string *)src;
8138-
8139+
8140 if (ds_dst->value->used) {
8141 buffer_append_string(ds_dst->value, "\r\n");
8142 buffer_append_string_buffer(ds_dst->value, ds_dst->key);
8143@@ -60,9 +60,9 @@
8144 } else {
8145 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8146 }
8147-
8148+
8149 src->free(src);
8150-
8151+
8152 return 0;
8153 }
8154
8155@@ -77,28 +77,28 @@
8156
8157 data_string *data_string_init(void) {
8158 data_string *ds;
8159-
8160+
8161 ds = calloc(1, sizeof(*ds));
8162 assert(ds);
8163-
8164+
8165 ds->key = buffer_init();
8166 ds->value = buffer_init();
8167-
8168+
8169 ds->copy = data_string_copy;
8170 ds->free = data_string_free;
8171 ds->reset = data_string_reset;
8172 ds->insert_dup = data_string_insert_dup;
8173 ds->print = data_string_print;
8174 ds->type = TYPE_STRING;
8175-
8176+
8177 return ds;
8178 }
8179
8180 data_string *data_response_init(void) {
8181 data_string *ds;
8182-
8183+
8184 ds = data_string_init();
8185 ds->insert_dup = data_response_insert_dup;
8186-
8187+
8188 return ds;
8189 }
1175ccec 8190--- ../lighttpd-1.4.11/src/etag.c 2005-08-11 01:26:40.000000000 +0300
36e2a29e 8191+++ lighttpd-1.4.12/src/etag.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
8192@@ -14,19 +14,19 @@
8193 buffer_append_off_t(etag, st->st_size);
8194 buffer_append_string_len(etag, CONST_STR_LEN("-"));
8195 buffer_append_long(etag, st->st_mtime);
8196-
8197+
8198 return 0;
8199 }
8200
8201 int etag_mutate(buffer *mut, buffer *etag) {
8202 size_t h, i;
8203-
8204+
8205 for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
8206-
8207+
8208 buffer_reset(mut);
8209 buffer_copy_string_len(mut, CONST_STR_LEN("\""));
8210 buffer_append_long(mut, h);
8211 buffer_append_string_len(mut, CONST_STR_LEN("\""));
8212-
8213+
8214 return 0;
8215 }
1175ccec 8216--- ../lighttpd-1.4.11/src/etag.h 2005-08-11 01:26:40.000000000 +0300
36e2a29e 8217+++ lighttpd-1.4.12/src/etag.h 2006-07-11 22:07:51.000000000 +0300
2519e6e5 8218@@ -3,13 +3,12 @@
f673a614 8219
2519e6e5
ER
8220 #include <sys/types.h>
8221 #include <sys/stat.h>
f26f9fd5 8222-#include <unistd.h>
f673a614 8223
2519e6e5 8224 #include "buffer.h"
f26f9fd5 8225
2519e6e5
ER
8226 int etag_is_equal(buffer *etag, const char *matches);
8227 int etag_create(buffer *etag, struct stat *st);
8228 int etag_mutate(buffer *mut, buffer *etag);
8229-
f673a614 8230+
2519e6e5 8231
f26f9fd5 8232 #endif
1175ccec 8233--- ../lighttpd-1.4.11/src/fastcgi.h 2005-08-11 01:26:40.000000000 +0300
36e2a29e 8234+++ lighttpd-1.4.12/src/fastcgi.h 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
8235@@ -1,4 +1,4 @@
8236-/*
8237+/*
8238 * fastcgi.h --
8239 *
8240 * Defines for the FastCGI protocol.
8241@@ -123,7 +123,7 @@
f26f9fd5 8242
f26f9fd5 8243
2519e6e5
ER
8244 typedef struct {
8245- unsigned char type;
8246+ unsigned char type;
8247 unsigned char reserved[7];
8248 } FCGI_UnknownTypeBody;
f673a614 8249
1175ccec 8250--- ../lighttpd-1.4.11/src/fdevent.c 2005-11-15 10:51:05.000000000 +0200
36e2a29e 8251+++ lighttpd-1.4.12/src/fdevent.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5 8252@@ -2,7 +2,6 @@
f673a614 8253
2519e6e5 8254 #include "settings.h"
f673a614 8255
2519e6e5 8256-#include <unistd.h>
f26f9fd5
ER
8257 #include <stdlib.h>
8258 #include <string.h>
8259 #include <errno.h>
2519e6e5
ER
8260@@ -12,59 +11,61 @@
8261 #include "fdevent.h"
f26f9fd5 8262 #include "buffer.h"
f673a614 8263
2519e6e5
ER
8264+#include "sys-socket.h"
8265+
8266 fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
8267 fdevents *ev;
8268-
8269+
8270 ev = calloc(1, sizeof(*ev));
8271 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
8272 ev->maxfds = maxfds;
8273-
8274+
8275 switch(type) {
8276 case FDEVENT_HANDLER_POLL:
8277 if (0 != fdevent_poll_init(ev)) {
8278- fprintf(stderr, "%s.%d: event-handler poll failed\n",
8279+ fprintf(stderr, "%s.%d: event-handler poll failed\n",
8280 __FILE__, __LINE__);
8281-
8282+
8283 return NULL;
8284 }
8285 break;
8286 case FDEVENT_HANDLER_SELECT:
8287 if (0 != fdevent_select_init(ev)) {
8288- fprintf(stderr, "%s.%d: event-handler select failed\n",
8289+ fprintf(stderr, "%s.%d: event-handler select failed\n",
8290 __FILE__, __LINE__);
8291 return NULL;
8292 }
8293 break;
8294 case FDEVENT_HANDLER_LINUX_RTSIG:
8295 if (0 != fdevent_linux_rtsig_init(ev)) {
8296- fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8297+ fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8298 __FILE__, __LINE__);
8299 return NULL;
8300 }
8301 break;
8302 case FDEVENT_HANDLER_LINUX_SYSEPOLL:
8303 if (0 != fdevent_linux_sysepoll_init(ev)) {
8304- fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8305+ fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8306 __FILE__, __LINE__);
8307 return NULL;
8308 }
8309 break;
8310 case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
8311 if (0 != fdevent_solaris_devpoll_init(ev)) {
8312- fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8313+ fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8314 __FILE__, __LINE__);
8315 return NULL;
8316 }
8317 break;
8318 case FDEVENT_HANDLER_FREEBSD_KQUEUE:
8319 if (0 != fdevent_freebsd_kqueue_init(ev)) {
8320- fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8321+ fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8322 __FILE__, __LINE__);
8323 return NULL;
f673a614 8324 }
2519e6e5
ER
8325 break;
8326 default:
8327- fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
8328+ fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
8329 __FILE__, __LINE__);
8330 return NULL;
f673a614 8331 }
2519e6e5
ER
8332@@ -75,26 +76,26 @@
8333 void fdevent_free(fdevents *ev) {
8334 size_t i;
8335 if (!ev) return;
8336-
8337+
8338 if (ev->free) ev->free(ev);
8339-
8340+
8341 for (i = 0; i < ev->maxfds; i++) {
8342 if (ev->fdarray[i]) free(ev->fdarray[i]);
8343 }
8344-
8345+
8346 free(ev->fdarray);
8347 free(ev);
f26f9fd5 8348 }
f26f9fd5 8349
2519e6e5
ER
8350 int fdevent_reset(fdevents *ev) {
8351 if (ev->reset) return ev->reset(ev);
8352-
f673a614 8353+
2519e6e5 8354 return 0;
f26f9fd5 8355 }
f26f9fd5 8356
2519e6e5
ER
8357 fdnode *fdnode_init() {
8358 fdnode *fdn;
f673a614 8359-
2519e6e5
ER
8360+
8361 fdn = calloc(1, sizeof(*fdn));
8362 fdn->fd = -1;
8363 return fdn;
8364@@ -106,12 +107,12 @@
f26f9fd5 8365
2519e6e5
ER
8366 int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
8367 fdnode *fdn;
8368-
f673a614 8369+
2519e6e5
ER
8370 fdn = fdnode_init();
8371 fdn->handler = handler;
8372 fdn->fd = fd;
8373 fdn->ctx = ctx;
8374-
f673a614 8375+
2519e6e5
ER
8376 ev->fdarray[fd] = fdn;
8377
8378 return 0;
8379@@ -121,31 +122,31 @@
8380 fdnode *fdn;
8381 if (!ev) return 0;
8382 fdn = ev->fdarray[fd];
8383-
f673a614 8384+
2519e6e5
ER
8385 fdnode_free(fdn);
8386-
f673a614 8387+
2519e6e5
ER
8388 ev->fdarray[fd] = NULL;
8389-
f673a614 8390+
2519e6e5
ER
8391 return 0;
8392 }
8393
8394 int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
8395 int fde = fde_ndx ? *fde_ndx : -1;
8396-
f673a614 8397+
2519e6e5
ER
8398 if (ev->event_del) fde = ev->event_del(ev, fde, fd);
8399-
f673a614 8400+
2519e6e5
ER
8401 if (fde_ndx) *fde_ndx = fde;
8402-
f673a614 8403+
2519e6e5
ER
8404 return 0;
8405 }
8406
8407 int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
8408 int fde = fde_ndx ? *fde_ndx : -1;
8409-
f673a614 8410+
2519e6e5
ER
8411 if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
8412-
f673a614 8413+
2519e6e5
ER
8414 if (fde_ndx) *fde_ndx = fde;
8415-
f673a614 8416+
2519e6e5
ER
8417 return 0;
8418 }
8419
8420@@ -156,38 +157,43 @@
8421
8422 int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
8423 if (ev->event_get_revent == NULL) SEGFAULT();
8424-
f673a614 8425+
2519e6e5
ER
8426 return ev->event_get_revent(ev, ndx);
8427 }
8428
8429 int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
8430 if (ev->event_get_fd == NULL) SEGFAULT();
8431-
f673a614 8432+
2519e6e5
ER
8433 return ev->event_get_fd(ev, ndx);
8434 }
8435
8436 fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
8437 if (ev->fdarray[fd] == NULL) SEGFAULT();
8438 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8439-
f673a614 8440+
2519e6e5
ER
8441 return ev->fdarray[fd]->handler;
8442 }
8443
8444 void * fdevent_get_context(fdevents *ev, int fd) {
8445 if (ev->fdarray[fd] == NULL) SEGFAULT();
8446 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8447-
f673a614 8448+
2519e6e5
ER
8449 return ev->fdarray[fd]->ctx;
8450 }
8451
8452 int fdevent_fcntl_set(fdevents *ev, int fd) {
8453+#ifdef _WIN32
8454+ int i = 1;
8455+#endif
8456 #ifdef FD_CLOEXEC
8457 /* close fd on exec (cgi) */
8458 fcntl(fd, F_SETFD, FD_CLOEXEC);
8459 #endif
8460 if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
8461-#ifdef O_NONBLOCK
8462+#ifdef O_NONBLOCK
8463 return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
8464+#elif defined _WIN32
8465+ return ioctlsocket(fd, FIONBIO, &i);
8466 #else
8467 return 0;
8468 #endif
8469@@ -196,7 +202,7 @@
8470
8471 int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
8472 if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
8473-
f673a614 8474+
2519e6e5
ER
8475 return -1;
8476 }
8477
1175ccec 8478--- ../lighttpd-1.4.11/src/fdevent.h 2005-09-27 11:26:33.000000000 +0300
36e2a29e 8479+++ lighttpd-1.4.12/src/fdevent.h 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
8480@@ -17,13 +17,13 @@
8481 # include <sys/epoll.h>
8482 #endif
8483
8484-/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
8485+/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
8486 * under /usr/include/sys/ */
8487 #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
8488 # define USE_POLL
8489 # ifdef HAVE_POLL_H
8490 # include <poll.h>
8491-# else
8492+# else
8493 # include <sys/poll.h>
8494 # endif
8495 # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
8496@@ -31,9 +31,11 @@
8497 # include <signal.h>
8498 # endif
8499 #endif
8500-
8501+#ifdef _WIN32
8502+# define HAVE_SELECT
8503+#endif
8504 #if defined HAVE_SELECT
8505-# ifdef __WIN32
8506+# ifdef _WIN32
8507 # include <winsock2.h>
8508 # endif
8509 # define USE_SELECT
8510@@ -67,14 +69,14 @@
8511 #define FDEVENT_HUP BV(4)
8512 #define FDEVENT_NVAL BV(5)
8513
8514-typedef enum { FD_EVENT_TYPE_UNSET = -1,
8515- FD_EVENT_TYPE_CONNECTION,
8516- FD_EVENT_TYPE_FCGI_CONNECTION,
8517- FD_EVENT_TYPE_DIRWATCH,
8518- FD_EVENT_TYPE_CGI_CONNECTION
8519+typedef enum { FD_EVENT_TYPE_UNSET = -1,
8520+ FD_EVENT_TYPE_CONNECTION,
8521+ FD_EVENT_TYPE_FCGI_CONNECTION,
8522+ FD_EVENT_TYPE_DIRWATCH,
8523+ FD_EVENT_TYPE_CGI_CONNECTION
8524 } fd_event_t;
8525
8526-typedef enum { FDEVENT_HANDLER_UNSET,
8527+typedef enum { FDEVENT_HANDLER_UNSET,
8528 FDEVENT_HANDLER_SELECT,
8529 FDEVENT_HANDLER_POLL,
8530 FDEVENT_HANDLER_LINUX_RTSIG,
8531@@ -86,7 +88,7 @@
8532
8533 /**
8534 * a mapping from fd to connection structure
8535- *
8536+ *
8537 */
8538 typedef struct {
8539 int fd; /**< the fd */
8540@@ -98,41 +100,41 @@
8541
8542 typedef struct {
8543 fd_conn *ptr;
8544-
8545+
8546 size_t size;
8547 size_t used;
8548 } fd_conn_buffer;
8549
8550 /**
8551 * array of unused fd's
8552- *
8553+ *
8554 */
8555
8556 typedef struct _fdnode {
8557 fdevent_handler handler;
8558 void *ctx;
8559 int fd;
8560-
8561+
8562 struct _fdnode *prev, *next;
8563 } fdnode;
8564
8565 typedef struct {
8566 int *ptr;
8567-
8568+
8569 size_t used;
8570 size_t size;
8571 } buffer_int;
8572
8573 /**
8574 * fd-event handler for select(), poll() and rt-signals on Linux 2.4
8575- *
8576+ *
8577 */
8578 typedef struct fdevents {
8579 fdevent_handler_t type;
8580-
8581+
8582 fdnode **fdarray;
8583 size_t maxfds;
8584-
8585+
8586 #ifdef USE_LINUX_SIGIO
8587 int in_sigio;
8588 int signum;
8589@@ -146,21 +148,21 @@
8590 #endif
8591 #ifdef USE_POLL
8592 struct pollfd *pollfds;
8593-
8594+
8595 size_t size;
8596 size_t used;
8597-
8598+
8599 buffer_int unused;
8600 #endif
8601 #ifdef USE_SELECT
8602 fd_set select_read;
8603 fd_set select_write;
8604 fd_set select_error;
8605-
8606+
8607 fd_set select_set_read;
8608 fd_set select_set_write;
8609 fd_set select_set_error;
8610-
8611+
8612 int select_max_fd;
8613 #endif
8614 #ifdef USE_SOLARIS_DEVPOLL
8615@@ -177,16 +179,16 @@
8616 #endif
8617 int (*reset)(struct fdevents *ev);
8618 void (*free)(struct fdevents *ev);
8619-
8620+
8621 int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events);
8622 int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
8623 int (*event_get_revent)(struct fdevents *ev, size_t ndx);
8624 int (*event_get_fd)(struct fdevents *ev, size_t ndx);
8625-
8626+
8627 int (*event_next_fdndx)(struct fdevents *ev, int ndx);
8628-
8629+
8630 int (*poll)(struct fdevents *ev, int timeout_ms);
8631-
8632+
8633 int (*fcntl_set)(struct fdevents *ev, int fd);
8634 } fdevents;
8635
1175ccec 8636--- ../lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c 2005-09-01 10:46:24.000000000 +0300
36e2a29e 8637+++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
8638@@ -1,6 +1,5 @@
8639 #include <sys/types.h>
8640
8641-#include <unistd.h>
8642 #include <stdlib.h>
8643 #include <stdio.h>
8644 #include <string.h>
8645@@ -48,7 +47,7 @@
8646
f26f9fd5
ER
8647 return -1;
8648 }
2519e6e5 8649-
f673a614 8650+
2519e6e5 8651 return -1;
f26f9fd5 8652 }
2519e6e5
ER
8653
8654@@ -65,7 +64,7 @@
8655
8656 ts.tv_sec = 0;
8657 ts.tv_nsec = 0;
f26f9fd5 8658-
2519e6e5
ER
8659+
8660 ret = kevent(ev->kq_fd,
8661 &kev, 1,
8662 NULL, 0,
8663@@ -77,7 +76,7 @@
8664
f26f9fd5
ER
8665 return -1;
8666 }
2519e6e5 8667-
f673a614 8668+
2519e6e5
ER
8669 if (filter == EVFILT_READ) {
8670 bitset_set_bit(ev->kq_bevents, fd);
8671 } else {
8672@@ -124,7 +123,7 @@
8673 } else if (e == EVFILT_WRITE) {
8674 events |= FDEVENT_OUT;
f26f9fd5 8675 }
2519e6e5
ER
8676-
8677+
8678 e = ev->kq_results[ndx].flags;
8679
8680 if (e & EV_EOF) {
8681@@ -152,10 +151,10 @@
8682 if (-1 == (ev->kq_fd = kqueue())) {
8683 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8684 __FILE__, __LINE__, strerror(errno));
8685-
8686+
8687 return -1;
f26f9fd5 8688 }
2519e6e5
ER
8689-
8690+
f26f9fd5
ER
8691 return 0;
8692 }
f673a614 8693
2519e6e5
ER
8694@@ -186,7 +185,7 @@
8695 if (-1 == (ev->kq_fd = kqueue())) {
8696 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8697 __FILE__, __LINE__, strerror(errno));
8698-
8699+
8700 return -1;
8701 }
f673a614 8702
1175ccec
ER
8703--- ../lighttpd-1.4.11/src/fdevent_linux_rtsig.c 2005-11-21 19:56:11.000000000 +0200
8704+++ lighttpd-1.4.12/src/fdevent_linux_rtsig.c 2006-07-15 22:43:21.000000000 +0300
2519e6e5
ER
8705@@ -1,6 +1,5 @@
8706 #include <sys/types.h>
8707
8708-#include <unistd.h>
8709 #include <stdlib.h>
8710 #include <stdio.h>
8711 #include <string.h>
1175ccec
ER
8712@@ -14,6 +13,7 @@
8713 #include "fdevent.h"
8714 #include "settings.h"
8715 #include "buffer.h"
8716+#include "sys-process.h"
8717
8718 #ifdef USE_LINUX_SIGIO
8719 static void fdevent_linux_rtsig_free(fdevents *ev) {
8720@@ -26,19 +26,19 @@
2519e6e5
ER
8721
8722 static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) {
8723 if (fde_ndx < 0) return -1;
8724-
8725+
8726 if ((size_t)fde_ndx >= ev->used) {
8727 fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used);
8728 SEGFAULT();
f673a614 8729 }
2519e6e5
ER
8730-
8731+
8732 if (ev->pollfds[fde_ndx].fd == fd) {
8733 size_t k = fde_ndx;
8734-
8735+
8736 ev->pollfds[k].fd = -1;
f673a614 8737
2519e6e5
ER
8738 bitset_clear_bit(ev->sigbset, fd);
8739-
f673a614 8740+
2519e6e5
ER
8741 if (ev->unused.size == 0) {
8742 ev->unused.size = 16;
8743 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
1175ccec 8744@@ -46,29 +46,29 @@
2519e6e5
ER
8745 ev->unused.size += 16;
8746 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
8747 }
8748-
f673a614 8749+
2519e6e5
ER
8750 ev->unused.ptr[ev->unused.used++] = k;
8751 } else {
8752 fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd);
8753-
f673a614 8754+
2519e6e5
ER
8755 SEGFAULT();
8756 }
8757-
f673a614 8758+
2519e6e5
ER
8759 return -1;
8760 }
f26f9fd5 8761
2519e6e5
ER
8762 #if 0
8763 static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
8764 size_t j;
8765-
8766+
8767 if (ev->used == 0) return 0;
8768 if (ev->unused.used != 0) return 0;
8769-
8770+
8771 for (j = ev->used - 1; j + 1 > 0; j--) {
8772 if (ev->pollfds[j].fd == -1) ev->used--;
8773 }
8774-
8775-
8776+
8777+
8778 return 0;
8779 }
f26f9fd5 8780 #endif
1175ccec 8781@@ -78,21 +78,21 @@
2519e6e5
ER
8782 if (fde_ndx != -1) {
8783 if (ev->pollfds[fde_ndx].fd == fd) {
8784 ev->pollfds[fde_ndx].events = events;
8785-
8786+
8787 return fde_ndx;
8788 }
8789 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
8790 SEGFAULT();
8791 }
8792-
8793+
8794 if (ev->unused.used > 0) {
8795 int k = ev->unused.ptr[--ev->unused.used];
8796-
8797+
8798 ev->pollfds[k].fd = fd;
8799 ev->pollfds[k].events = events;
f26f9fd5 8800
2519e6e5
ER
8801 bitset_set_bit(ev->sigbset, fd);
8802-
f673a614 8803+
2519e6e5
ER
8804 return k;
8805 } else {
8806 if (ev->size == 0) {
1175ccec 8807@@ -102,12 +102,12 @@
2519e6e5
ER
8808 ev->size += 16;
8809 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
8810 }
8811-
8812+
8813 ev->pollfds[ev->used].fd = fd;
8814 ev->pollfds[ev->used].events = events;
f26f9fd5 8815
2519e6e5
ER
8816 bitset_set_bit(ev->sigbset, fd);
8817-
8818+
8819 return ev->used++;
8820 }
f26f9fd5 8821 }
1175ccec 8822@@ -115,20 +115,20 @@
2519e6e5
ER
8823 static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
8824 struct timespec ts;
8825 int r;
8826-
8827+
8828 #if 0
8829 fdevent_linux_rtsig_event_compress(ev);
8830 #endif
8831-
8832+
8833 ev->in_sigio = 1;
8834-
8835+
8836 ts.tv_sec = timeout_ms / 1000;
8837 ts.tv_nsec = (timeout_ms % 1000) * 1000000;
8838 r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
8839-
8840- if (r == -1) {
8841+
8842+ if (r == -1) {
8843 if (errno == EAGAIN) return 0;
8844- return r;
8845+ return r;
8846 } else if (r == SIGIO) {
8847 struct sigaction act;
8848
1175ccec 8849@@ -140,7 +140,7 @@
2519e6e5
ER
8850 /* re-enable the signal queue */
8851 act.sa_handler = SIG_DFL;
8852 sigaction(ev->signum, &act, NULL);
8853-
8854+
8855 ev->in_sigio = 0;
8856 r = poll(ev->pollfds, ev->used, timeout_ms);
f26f9fd5 8857
1175ccec 8858@@ -162,12 +162,12 @@
2519e6e5
ER
8859 if (ev->siginfo.si_band == POLLERR) {
8860 fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno));
8861 }
8862-# endif
8863+# endif
8864 if (ndx != 0) {
8865 fprintf(stderr, "+\n");
8866 return 0;
8867 }
8868-
8869+
8870 return ev->siginfo.si_band & 0x3f;
8871 } else {
8872 if (ndx >= ev->used) {
1175ccec 8873@@ -188,13 +188,13 @@
f26f9fd5 8874
2519e6e5
ER
8875 static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
8876 static pid_t pid = 0;
8877-
8878+
8879 if (pid == 0) pid = getpid();
8880-
8881+
8882 if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
8883-
8884+
8885 if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
8886-
8887+
8888 return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
8889 }
8890
1175ccec 8891@@ -205,12 +205,12 @@
2519e6e5
ER
8892 return -1;
8893 } else {
8894 size_t i;
8895-
8896+
8897 i = (ndx < 0) ? 0 : ndx + 1;
8898 for (; i < ev->used; i++) {
8899 if (ev->pollfds[i].revents) break;
f26f9fd5 8900 }
2519e6e5
ER
8901-
8902+
8903 return i;
f26f9fd5 8904 }
f26f9fd5 8905 }
1175ccec 8906@@ -219,34 +219,34 @@
2519e6e5
ER
8907 ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
8908 #define SET(x) \
8909 ev->x = fdevent_linux_rtsig_##x;
8910-
8911+
8912 SET(free);
8913 SET(poll);
8914-
8915+
8916 SET(event_del);
8917 SET(event_add);
8918-
8919+
8920 SET(event_next_fdndx);
8921 SET(fcntl_set);
8922 SET(event_get_fd);
8923 SET(event_get_revent);
8924-
8925+
8926 ev->signum = SIGRTMIN + 1;
8927-
8928+
8929 sigemptyset(&(ev->sigset));
8930 sigaddset(&(ev->sigset), ev->signum);
8931 sigaddset(&(ev->sigset), SIGIO);
8932 if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) {
8933 fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8934 __FILE__, __LINE__, strerror(errno));
8935-
8936+
8937 return -1;
f26f9fd5 8938 }
2519e6e5
ER
8939-
8940+
8941 ev->in_sigio = 1;
8942
8943 ev->sigbset = bitset_init(ev->maxfds);
8944-
8945+
8946 return 0;
8947 }
f26f9fd5 8948 #else
1175ccec 8949--- ../lighttpd-1.4.11/src/fdevent_linux_sysepoll.c 2005-09-30 20:29:27.000000000 +0300
36e2a29e 8950+++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
8951@@ -1,6 +1,5 @@
8952 #include <sys/types.h>
f673a614 8953
2519e6e5
ER
8954-#include <unistd.h>
8955 #include <stdlib.h>
8956 #include <stdio.h>
8957 #include <string.h>
8958@@ -12,6 +11,8 @@
8959 #include "settings.h"
8960 #include "buffer.h"
f673a614 8961
2519e6e5
ER
8962+#include "sys-files.h"
8963+
8964 #ifdef USE_LINUX_EPOLL
8965 static void fdevent_linux_sysepoll_free(fdevents *ev) {
8966 close(ev->epoll_fd);
8967@@ -20,36 +21,36 @@
8968
8969 static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
8970 struct epoll_event ep;
8971-
8972+
8973 if (fde_ndx < 0) return -1;
8974-
8975+
8976 memset(&ep, 0, sizeof(ep));
8977-
8978+
8979 ep.data.fd = fd;
8980 ep.data.ptr = NULL;
8981-
8982+
8983 if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
8984 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
8985-
8986+
8987 SEGFAULT();
8988-
8989+
8990 return 0;
8991 }
8992-
8993-
8994+
8995+
8996 return -1;
f26f9fd5 8997 }
f673a614 8998
2519e6e5
ER
8999 static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9000 struct epoll_event ep;
9001 int add = 0;
9002-
9003+
9004 if (fde_ndx == -1) add = 1;
9005-
9006+
9007 memset(&ep, 0, sizeof(ep));
9008-
9009+
9010 ep.events = 0;
9011-
9012+
9013 if (events & FDEVENT_IN) ep.events |= EPOLLIN;
9014 if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
f673a614 9015
2519e6e5
ER
9016@@ -60,20 +61,20 @@
9017 * sent.
9018 *
9019 */
9020-
9021+
9022 ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
9023-
9024+
9025 ep.data.ptr = NULL;
9026 ep.data.fd = fd;
9027-
9028+
9029 if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
9030 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9031-
9032+
9033 SEGFAULT();
9034-
9035+
9036 return 0;
f673a614 9037 }
2519e6e5
ER
9038-
9039+
9040 return fd;
f673a614
ER
9041 }
9042
2519e6e5 9043@@ -83,14 +84,14 @@
f673a614 9044
2519e6e5
ER
9045 static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
9046 int events = 0, e;
9047-
f673a614 9048+
2519e6e5
ER
9049 e = ev->epoll_events[ndx].events;
9050 if (e & EPOLLIN) events |= FDEVENT_IN;
9051 if (e & EPOLLOUT) events |= FDEVENT_OUT;
9052 if (e & EPOLLERR) events |= FDEVENT_ERR;
9053 if (e & EPOLLHUP) events |= FDEVENT_HUP;
9054 if (e & EPOLLPRI) events |= FDEVENT_PRI;
9055-
9056+
9057 return e;
f673a614
ER
9058 }
9059
2519e6e5
ER
9060@@ -98,17 +99,17 @@
9061 # if 0
9062 fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
9063 # endif
9064-
9065+
9066 return ev->epoll_events[ndx].data.fd;
f673a614 9067 }
f673a614 9068
2519e6e5
ER
9069 static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
9070 size_t i;
9071-
9072+
9073 UNUSED(ev);
f673a614 9074
2519e6e5
ER
9075 i = (ndx < 0) ? 0 : ndx + 1;
9076-
9077+
9078 return i;
f673a614 9079 }
f26f9fd5 9080
2519e6e5
ER
9081@@ -116,17 +117,17 @@
9082 ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
9083 #define SET(x) \
9084 ev->x = fdevent_linux_sysepoll_##x;
9085-
9086+
9087 SET(free);
9088 SET(poll);
9089-
9090+
9091 SET(event_del);
9092 SET(event_add);
9093-
9094+
9095 SET(event_next_fdndx);
9096 SET(event_get_fd);
9097 SET(event_get_revent);
9098-
9099+
9100 if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
9101 fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9102 __FILE__, __LINE__, strerror(errno));
9103@@ -154,7 +155,7 @@
f26f9fd5 9104
2519e6e5
ER
9105 fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9106 __FILE__, __LINE__);
9107-
9108+
9109 return -1;
9110 }
f26f9fd5 9111 #endif
1175ccec 9112--- ../lighttpd-1.4.11/src/fdevent_poll.c 2005-11-18 13:59:16.000000000 +0200
36e2a29e 9113+++ lighttpd-1.4.12/src/fdevent_poll.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
9114@@ -1,6 +1,5 @@
9115 #include <sys/types.h>
f26f9fd5 9116
2519e6e5
ER
9117-#include <unistd.h>
9118 #include <stdlib.h>
9119 #include <stdio.h>
9120 #include <string.h>
9121@@ -20,19 +19,19 @@
f26f9fd5 9122
2519e6e5
ER
9123 static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
9124 if (fde_ndx < 0) return -1;
9125-
9126+
9127 if ((size_t)fde_ndx >= ev->used) {
9128 fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used);
9129 SEGFAULT();
9130 }
9131-
9132+
9133 if (ev->pollfds[fde_ndx].fd == fd) {
9134 size_t k = fde_ndx;
9135-
9136+
9137 ev->pollfds[k].fd = -1;
9138 /* ev->pollfds[k].events = 0; */
9139 /* ev->pollfds[k].revents = 0; */
9140-
9141+
9142 if (ev->unused.size == 0) {
9143 ev->unused.size = 16;
9144 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9145@@ -40,47 +39,47 @@
9146 ev->unused.size += 16;
9147 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9148 }
9149-
9150+
9151 ev->unused.ptr[ev->unused.used++] = k;
9152 } else {
9153 SEGFAULT();
9154 }
9155-
9156+
9157 return -1;
9158 }
f26f9fd5 9159
2519e6e5
ER
9160 #if 0
9161 static int fdevent_poll_event_compress(fdevents *ev) {
9162 size_t j;
9163-
9164+
9165 if (ev->used == 0) return 0;
9166 if (ev->unused.used != 0) return 0;
9167-
9168+
9169 for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
9170-
9171+
9172 return 0;
9173 }
f26f9fd5
ER
9174 #endif
9175
2519e6e5
ER
9176 static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9177 /* known index */
9178-
f673a614 9179+
2519e6e5
ER
9180 if (fde_ndx != -1) {
9181 if (ev->pollfds[fde_ndx].fd == fd) {
9182 ev->pollfds[fde_ndx].events = events;
9183-
9184+
9185 return fde_ndx;
9186 }
9187 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9188 SEGFAULT();
9189 }
f673a614 9190-
2519e6e5
ER
9191+
9192 if (ev->unused.used > 0) {
9193 int k = ev->unused.ptr[--ev->unused.used];
9194-
9195+
9196 ev->pollfds[k].fd = fd;
9197 ev->pollfds[k].events = events;
9198-
9199+
9200 return k;
9201 } else {
9202 if (ev->size == 0) {
9203@@ -90,10 +89,10 @@
9204 ev->size += 16;
9205 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9206 }
9207-
9208+
9209 ev->pollfds[ev->used].fd = fd;
9210 ev->pollfds[ev->used].events = events;
9211-
9212+
9213 return ev->used++;
9214 }
9215 }
9216@@ -109,12 +108,12 @@
9217 int r, poll_r;
9218 if (ndx >= ev->used) {
9219 fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used);
9220-
9221+
9222 SEGFAULT();
9223-
9224+
9225 return 0;
9226 }
f673a614 9227-
2519e6e5
ER
9228+
9229 if (ev->pollfds[ndx].revents & POLLNVAL) {
9230 /* should never happen */
9231 SEGFAULT();
9232@@ -131,7 +130,7 @@
9233 if (poll_r & POLLHUP) r |= FDEVENT_HUP;
9234 if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
9235 if (poll_r & POLLPRI) r |= FDEVENT_PRI;
9236-
9237+
9238 return ev->pollfds[ndx].revents;
9239 }
f673a614 9240
2519e6e5 9241@@ -141,12 +140,12 @@
f673a614 9242
2519e6e5
ER
9243 static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
9244 size_t i;
9245-
f673a614 9246+
2519e6e5
ER
9247 i = (ndx < 0) ? 0 : ndx + 1;
9248 for (; i < ev->used; i++) {
9249 if (ev->pollfds[i].revents) break;
9250 }
9251-
9252+
9253 return i;
9254 }
f673a614 9255
2519e6e5
ER
9256@@ -154,17 +153,17 @@
9257 ev->type = FDEVENT_HANDLER_POLL;
9258 #define SET(x) \
9259 ev->x = fdevent_poll_##x;
9260-
f673a614 9261+
2519e6e5
ER
9262 SET(free);
9263 SET(poll);
9264-
f673a614 9265+
2519e6e5
ER
9266 SET(event_del);
9267 SET(event_add);
9268-
9269+
9270 SET(event_next_fdndx);
9271 SET(event_get_fd);
9272 SET(event_get_revent);
9273-
9274+
9275 return 0;
9276 }
f673a614 9277
1175ccec 9278--- ../lighttpd-1.4.11/src/fdevent_select.c 2005-08-31 11:12:46.000000000 +0300
36e2a29e 9279+++ lighttpd-1.4.12/src/fdevent_select.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
9280@@ -1,18 +1,19 @@
9281-#include <sys/time.h>
9282 #include <sys/types.h>
9283
9284-#include <unistd.h>
9285 #include <stdlib.h>
9286 #include <string.h>
9287 #include <errno.h>
9288 #include <signal.h>
9289 #include <fcntl.h>
9290 #include <assert.h>
9291+#include <stdio.h>
9292
9293 #include "fdevent.h"
9294 #include "settings.h"
9295 #include "buffer.h"
9296
9297+#include "sys-socket.h"
9298+
9299 #ifdef USE_SELECT
9300
9301 static int fdevent_select_reset(fdevents *ev) {
9302@@ -38,7 +39,9 @@
9303 UNUSED(fde_ndx);
9304
9305 /* we should be protected by max-fds, but you never know */
f26f9fd5 9306+#ifndef _WIN32
2519e6e5
ER
9307 assert(fd < FD_SETSIZE);
9308+#endif
9309
9310 if (events & FDEVENT_IN) {
9311 FD_SET(fd, &(ev->select_set_read));
9312@@ -49,28 +52,28 @@
9313 FD_SET(fd, &(ev->select_set_write));
9314 }
9315 FD_SET(fd, &(ev->select_set_error));
9316-
f673a614 9317+
2519e6e5
ER
9318 if (fd > ev->select_max_fd) ev->select_max_fd = fd;
9319-
f673a614 9320+
2519e6e5
ER
9321 return fd;
9322 }
9323
9324 static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
9325 struct timeval tv;
9326-
f673a614 9327+
2519e6e5
ER
9328 tv.tv_sec = timeout_ms / 1000;
9329 tv.tv_usec = (timeout_ms % 1000) * 1000;
9330-
f673a614 9331+
2519e6e5
ER
9332 ev->select_read = ev->select_set_read;
9333 ev->select_write = ev->select_set_write;
9334 ev->select_error = ev->select_set_error;
9335-
9336+
9337 return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
f26f9fd5 9338 }
f673a614 9339
2519e6e5
ER
9340 static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
9341 int revents = 0;
f673a614 9342-
2519e6e5
ER
9343+
9344 if (FD_ISSET(ndx, &(ev->select_read))) {
9345 revents |= FDEVENT_IN;
9346 }
9347@@ -80,7 +83,7 @@
9348 if (FD_ISSET(ndx, &(ev->select_error))) {
9349 revents |= FDEVENT_ERR;
9350 }
f26f9fd5 9351-
2519e6e5
ER
9352+
9353 return revents;
9354 }
9355
9356@@ -92,15 +95,15 @@
9357
9358 static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
9359 int i;
f26f9fd5 9360-
2519e6e5
ER
9361+
9362 i = (ndx < 0) ? 0 : ndx + 1;
9363-
9364+
9365 for (; i < ev->select_max_fd + 1; i++) {
9366 if (FD_ISSET(i, &(ev->select_read))) break;
9367 if (FD_ISSET(i, &(ev->select_write))) break;
9368 if (FD_ISSET(i, &(ev->select_error))) break;
9369 }
9370-
9371+
9372 return i;
9373 }
9374
9375@@ -108,17 +111,17 @@
9376 ev->type = FDEVENT_HANDLER_SELECT;
9377 #define SET(x) \
9378 ev->x = fdevent_select_##x;
9379-
9380+
9381 SET(reset);
9382 SET(poll);
9383-
9384+
9385 SET(event_del);
9386 SET(event_add);
9387-
9388+
9389 SET(event_next_fdndx);
9390 SET(event_get_fd);
9391 SET(event_get_revent);
9392-
9393+
9394 return 0;
9395 }
9396
1175ccec 9397--- ../lighttpd-1.4.11/src/fdevent_solaris_devpoll.c 2005-09-01 10:45:26.000000000 +0300
36e2a29e 9398+++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
9399@@ -1,6 +1,5 @@
9400 #include <sys/types.h>
9401
9402-#include <unistd.h>
9403 #include <stdlib.h>
9404 #include <stdio.h>
9405 #include <string.h>
9406@@ -23,55 +22,55 @@
9407
9408 static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9409 struct pollfd pfd;
f26f9fd5 9410-
2519e6e5
ER
9411+
9412 if (fde_ndx < 0) return -1;
9413-
9414+
9415 pfd.fd = fd;
9416 pfd.events = POLLREMOVE;
9417 pfd.revents = 0;
9418-
9419+
9420 if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9421- fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9422- __FILE__, __LINE__,
9423+ fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9424+ __FILE__, __LINE__,
9425 fd, strerror(errno));
f26f9fd5 9426-
2519e6e5
ER
9427+
9428 return -1;
9429 }
9430-
9431+
9432 return -1;
9433 }
9434
9435 static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9436 struct pollfd pfd;
9437 int add = 0;
f26f9fd5 9438-
2519e6e5
ER
9439+
9440 if (fde_ndx == -1) add = 1;
9441-
9442+
9443 pfd.fd = fd;
9444 pfd.events = events;
9445 pfd.revents = 0;
9446-
9447+
9448 if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9449- fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9450- __FILE__, __LINE__,
9451+ fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9452+ __FILE__, __LINE__,
9453 fd, strerror(errno));
f26f9fd5 9454-
2519e6e5
ER
9455+
9456 return -1;
9457 }
f26f9fd5 9458-
2519e6e5
ER
9459+
9460 return fd;
9461 }
f673a614 9462
2519e6e5
ER
9463 static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
9464 struct dvpoll dopoll;
9465 int ret;
f673a614 9466-
2519e6e5
ER
9467+
9468 dopoll.dp_timeout = timeout_ms;
9469 dopoll.dp_nfds = ev->maxfds;
9470 dopoll.dp_fds = ev->devpollfds;
f673a614 9471-
2519e6e5
ER
9472+
9473 ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
9474-
9475+
9476 return ret;
9477 }
f673a614 9478
2519e6e5 9479@@ -85,11 +84,11 @@
f673a614 9480
2519e6e5
ER
9481 static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
9482 size_t i;
9483-
9484+
9485 UNUSED(ev);
f26f9fd5 9486
2519e6e5
ER
9487 i = (last_ndx < 0) ? 0 : last_ndx + 1;
9488-
f673a614 9489+
2519e6e5
ER
9490 return i;
9491 }
9492
9493@@ -117,20 +116,20 @@
9494 ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
9495 #define SET(x) \
9496 ev->x = fdevent_solaris_devpoll_##x;
9497-
f673a614 9498+
2519e6e5
ER
9499 SET(free);
9500 SET(poll);
9501 SET(reset);
9502-
f673a614 9503+
2519e6e5
ER
9504 SET(event_del);
9505 SET(event_add);
9506-
9507+
9508 SET(event_next_fdndx);
9509 SET(event_get_fd);
9510 SET(event_get_revent);
9511-
9512+
9513 ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
9514-
9515+
9516 if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
9517 fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9518 __FILE__, __LINE__, strerror(errno));
9519@@ -152,7 +151,7 @@
f673a614 9520
2519e6e5
ER
9521 fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9522 __FILE__, __LINE__);
9523-
9524+
9525 return -1;
9526 }
9527 #endif
1175ccec 9528--- ../lighttpd-1.4.11/src/http-header-glue.c 2006-02-08 15:31:36.000000000 +0200
36e2a29e 9529+++ lighttpd-1.4.12/src/http-header-glue.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
9530@@ -45,20 +45,20 @@
9531 # ifdef HAVE_STRUCT_SOCKADDR_STORAGE
9532 static size_t get_sa_len(const struct sockaddr *addr) {
9533 switch (addr->sa_family) {
9534-
9535+
9536 # ifdef AF_INET
9537 case AF_INET:
9538 return (sizeof (struct sockaddr_in));
9539 # endif
9540-
9541+
9542 # ifdef AF_INET6
9543 case AF_INET6:
9544 return (sizeof (struct sockaddr_in6));
9545 # endif
9546-
9547+
9548 default:
9549 return (sizeof (struct sockaddr));
9550-
9551+
9552 }
9553 }
9554 # define SA_LEN(addr) (get_sa_len(addr))
9555@@ -74,7 +74,7 @@
f673a614 9556
2519e6e5
ER
9557 int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9558 data_string *ds;
9559-
9560+
9561 UNUSED(srv);
f673a614 9562
2519e6e5
ER
9563 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
9564@@ -82,32 +82,32 @@
9565 }
9566 buffer_copy_string_len(ds->key, key, keylen);
9567 buffer_copy_string_len(ds->value, value, vallen);
9568-
f673a614 9569+
2519e6e5
ER
9570 array_insert_unique(con->response.headers, (data_unset *)ds);
9571-
f673a614 9572+
2519e6e5
ER
9573 return 0;
9574 }
f673a614 9575
2519e6e5
ER
9576 int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9577 data_string *ds;
9578-
9579+
9580 UNUSED(srv);
f673a614 9581
2519e6e5
ER
9582 /* if there already is a key by this name overwrite the value */
9583 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
9584 buffer_copy_string(ds->value, value);
9585-
f673a614 9586+
2519e6e5
ER
9587 return 0;
9588 }
9589-
f673a614 9590+
2519e6e5
ER
9591 return response_header_insert(srv, con, key, keylen, value, vallen);
9592 }
9593
9594 int http_response_redirect_to_directory(server *srv, connection *con) {
9595 buffer *o;
9596-
f673a614 9597+
2519e6e5
ER
9598 o = buffer_init();
9599-
f673a614 9600+
2519e6e5
ER
9601 if (con->conf.is_ssl) {
9602 buffer_copy_string(o, "https://");
9603 } else {
9604@@ -123,36 +123,36 @@
9605 #endif
9606 sock_addr our_addr;
9607 socklen_t our_addr_len;
9608-
f673a614 9609+
2519e6e5
ER
9610 our_addr_len = sizeof(our_addr);
9611-
f673a614 9612+
2519e6e5
ER
9613 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
9614 con->http_status = 500;
9615-
f673a614 9616+
2519e6e5
ER
9617 log_error_write(srv, __FILE__, __LINE__, "ss",
9618 "can't get sockname", strerror(errno));
f26f9fd5 9619-
2519e6e5
ER
9620+
9621 buffer_free(o);
9622 return 0;
9623 }
9624-
9625-
9626+
9627+
9628 /* Lookup name: secondly try to get hostname for bind address */
9629 switch(our_addr.plain.sa_family) {
9630 #ifdef HAVE_IPV6
9631 case AF_INET6:
9632- if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
9633- SA_LEN((const struct sockaddr *)&our_addr.ipv6),
9634+ if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
9635+ SA_LEN((const struct sockaddr *)&our_addr.ipv6),
9636 hbuf, sizeof(hbuf), NULL, 0, 0)) {
f26f9fd5 9637-
f673a614 9638+
2519e6e5
ER
9639 char dst[INET6_ADDRSTRLEN];
9640-
9641+
9642 log_error_write(srv, __FILE__, __LINE__,
9643 "SSSS", "NOTICE: getnameinfo failed: ",
9644 strerror(errno), ", using ip-address instead");
9645-
9646- buffer_append_string(o,
9647- inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
9648+
9649+ buffer_append_string(o,
9650+ inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
9651 dst, sizeof(dst)));
9652 } else {
9653 buffer_append_string(o, hbuf);
9654@@ -164,7 +164,7 @@
9655 log_error_write(srv, __FILE__, __LINE__,
9656 "SdSS", "NOTICE: gethostbyaddr failed: ",
9657 h_errno, ", using ip-address instead");
9658-
9659+
9660 buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
9661 } else {
9662 buffer_append_string(o, he->h_name);
9663@@ -173,12 +173,12 @@
9664 default:
9665 log_error_write(srv, __FILE__, __LINE__,
9666 "S", "ERROR: unsupported address-type");
9667-
9668+
9669 buffer_free(o);
9670 return -1;
f673a614 9671 }
2519e6e5
ER
9672-
9673- if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
9674+
9675+ if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
9676 (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
9677 buffer_append_string(o, ":");
9678 buffer_append_long(o, srv->srvconf.port);
9679@@ -190,41 +190,41 @@
9680 buffer_append_string(o, "?");
9681 buffer_append_string_buffer(o, con->uri.query);
f673a614 9682 }
2519e6e5
ER
9683-
9684+
9685 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
9686-
9687+
9688 con->http_status = 301;
9689 con->file_finished = 1;
9690-
9691+
9692 buffer_free(o);
9693-
9694+
f673a614
ER
9695 return 0;
9696 }
9697
2519e6e5
ER
9698 buffer * strftime_cache_get(server *srv, time_t last_mod) {
9699 struct tm *tm;
9700 size_t i;
9701-
9702+
9703 for (i = 0; i < FILE_CACHE_MAX; i++) {
9704 /* found cache-entry */
9705 if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;
9706-
9707+
9708 /* found empty slot */
9709 if (srv->mtime_cache[i].mtime == 0) break;
9710 }
9711-
9712+
9713 if (i == FILE_CACHE_MAX) {
9714 i = 0;
9715 }
9716-
9717+
9718 srv->mtime_cache[i].mtime = last_mod;
9719 buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
9720 tm = gmtime(&(srv->mtime_cache[i].mtime));
9721- srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
9722+ srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
9723 srv->mtime_cache[i].str->size - 1,
9724 "%a, %d %b %Y %H:%M:%S GMT", tm);
9725 srv->mtime_cache[i].str->used++;
9726-
9727+
9728 return srv->mtime_cache[i].str;
9729 }
9730
9731@@ -239,56 +239,60 @@
9732 * request. That is, if no entity tags match, then the server MUST NOT
9733 * return a 304 (Not Modified) response.
f26f9fd5 9734 */
2519e6e5
ER
9735-
9736+
9737 /* last-modified handling */
9738 if (con->request.http_if_none_match) {
9739 if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) {
9740- if (con->request.http_method == HTTP_METHOD_GET ||
9741+ if (con->request.http_method == HTTP_METHOD_GET ||
9742 con->request.http_method == HTTP_METHOD_HEAD) {
9743-
9744+
9745 /* check if etag + last-modified */
9746 if (con->request.http_if_modified_since) {
9747 size_t used_len;
9748 char *semicolon;
9749-
9750+
9751 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
9752 used_len = strlen(con->request.http_if_modified_since);
9753 } else {
9754 used_len = semicolon - con->request.http_if_modified_since;
9755 }
9756-
9757+
9758 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
9759 con->http_status = 304;
9760 return HANDLER_FINISHED;
9761 } else {
9762+#ifdef HAVE_STRPTIME
9763 char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
9764+ time_t t_header, t_file;
9765+ struct tm tm;
f673a614 9766
2519e6e5
ER
9767- /* convert to timestamp */
9768- if (used_len < sizeof(buf)) {
9769- time_t t_header, t_file;
9770- struct tm tm;
9771-
9772- strncpy(buf, con->request.http_if_modified_since, used_len);
9773- buf[used_len] = '\0';
9774-
9775- strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9776- t_header = mktime(&tm);
9777-
9778- strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9779- t_file = mktime(&tm);
9780-
9781- if (t_file > t_header) {
9782- con->http_status = 304;
9783- return HANDLER_FINISHED;
9784- }
9785- } else {
9786- log_error_write(srv, __FILE__, __LINE__, "ssdd",
9787- "DEBUG: Last-Modified check failed as the received timestamp was too long:",
9788+ /* check if we can safely copy the string */
9789+ if (used_len >= sizeof(buf)) {
9790+ log_error_write(srv, __FILE__, __LINE__, "ssdd",
9791+ "DEBUG: Last-Modified check failed as the received timestamp was too long:",
9792 con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
9793-
f673a614 9794+
2519e6e5
ER
9795 con->http_status = 412;
9796 return HANDLER_FINISHED;
9797 }
f26f9fd5 9798+
f26f9fd5 9799+
2519e6e5
ER
9800+ strncpy(buf, con->request.http_if_modified_since, used_len);
9801+ buf[used_len] = '\0';
f26f9fd5 9802+
2519e6e5
ER
9803+ strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9804+ t_header = mktime(&tm);
f26f9fd5 9805+
2519e6e5
ER
9806+ strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9807+ t_file = mktime(&tm);
f26f9fd5 9808+
2519e6e5 9809+ if (t_file > t_header) return HANDLER_GO_ON;
f26f9fd5 9810+
2519e6e5
ER
9811+ con->http_status = 304;
9812+ return HANDLER_FINISHED;
9813+#else
9814+ return HANDLER_GO_ON;
9815+#endif
9816 }
9817 } else {
9818 con->http_status = 304;
9819@@ -302,16 +306,41 @@
9820 } else if (con->request.http_if_modified_since) {
9821 size_t used_len;
9822 char *semicolon;
9823-
f673a614 9824+
2519e6e5
ER
9825 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
9826 used_len = strlen(con->request.http_if_modified_since);
9827 } else {
9828 used_len = semicolon - con->request.http_if_modified_since;
9829 }
9830-
f26f9fd5 9831+
2519e6e5
ER
9832 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
9833 con->http_status = 304;
9834 return HANDLER_FINISHED;
9835+ } else {
9836+#ifdef HAVE_STRPTIME
9837+ char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
9838+ time_t t_header, t_file;
9839+ struct tm tm;
9840+
9841+ /* convert to timestamp */
9842+ if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
9843+
9844+ strncpy(buf, con->request.http_if_modified_since, used_len);
9845+ buf[used_len] = '\0';
9846+
9847+ strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9848+ t_header = mktime(&tm);
9849+
9850+ strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9851+ t_file = mktime(&tm);
9852+
9853+ if (t_file > t_header) return HANDLER_GO_ON;
9854+
9855+ con->http_status = 304;
9856+ return HANDLER_FINISHED;
9857+#else
9858+ return HANDLER_GO_ON;
f26f9fd5 9859+#endif
f26f9fd5
ER
9860 }
9861 }
f673a614 9862
1175ccec 9863--- ../lighttpd-1.4.11/src/http_auth.c 2006-02-01 13:02:52.000000000 +0200
36e2a29e 9864+++ lighttpd-1.4.12/src/http_auth.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
9865@@ -22,7 +22,6 @@
9866 #include <string.h>
9867 #include <time.h>
f26f9fd5 9868 #include <errno.h>
2519e6e5
ER
9869-#include <unistd.h>
9870 #include <ctype.h>
f673a614 9871
2519e6e5
ER
9872 #include "server.h"
9873@@ -31,23 +30,14 @@
9874 #include "http_auth_digest.h"
9875 #include "stream.h"
f26f9fd5 9876
2519e6e5 9877+#include "sys-strings.h"
f673a614 9878+
2519e6e5
ER
9879 #ifdef USE_OPENSSL
9880 # include <openssl/md5.h>
9881 #else
9882 # include "md5.h"
f26f9fd5 9883 #endif
f26f9fd5 9884
2519e6e5
ER
9885-
9886-#ifdef USE_PAM
9887-#include <security/pam_appl.h>
9888-#include <security/pam_misc.h>
9889-
9890-static struct pam_conv conv = {
9891- misc_conv,
9892- NULL
9893-};
f26f9fd5 9894-#endif
2519e6e5
ER
9895-
9896 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
f26f9fd5 9897
2519e6e5
ER
9898 static const char base64_pad = '=';
9899@@ -75,25 +65,25 @@
9900 unsigned char *result;
9901 int ch, j = 0, k;
9902 size_t i;
9903-
f673a614 9904+
2519e6e5
ER
9905 size_t in_len = strlen(in);
9906-
9907+
9908 buffer_prepare_copy(out, in_len);
9909-
9910+
9911 result = (unsigned char *)out->ptr;
9912-
9913+
9914 ch = in[0];
9915 /* run through the whole string, converting as we go */
9916 for (i = 0; i < in_len; i++) {
9917 ch = in[i];
9918-
9919+
9920 if (ch == '\0') break;
9921-
9922+
9923 if (ch == base64_pad) break;
9924-
9925+
9926 ch = base64_reverse_table[ch];
9927 if (ch < 0) continue;
9928-
9929+
9930 switch(i % 4) {
9931 case 0:
9932 result[j] = ch << 2;
9933@@ -125,168 +115,168 @@
9934 }
9935 }
9936 result[k] = '\0';
9937-
9938+
9939 out->used = k;
9940-
9941+
9942 return result;
f26f9fd5 9943 }
f673a614 9944
2519e6e5
ER
9945 static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
9946 int ret = -1;
f26f9fd5 9947-
2519e6e5
ER
9948+
9949 if (!username->used|| !realm->used) return -1;
f26f9fd5 9950-
f673a614 9951+
2519e6e5
ER
9952 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
9953 stream f;
9954 char * f_line;
9955-
f673a614 9956+
2519e6e5 9957 if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
f26f9fd5 9958-
f673a614 9959+
2519e6e5
ER
9960 if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) {
9961 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno));
9962-
9963+
9964 return -1;
9965 }
f26f9fd5 9966-
f673a614 9967+
2519e6e5
ER
9968 f_line = f.start;
9969-
9970+
9971 while (f_line - f.start != f.size) {
9972 char *f_user, *f_pwd, *e, *f_realm;
9973 size_t u_len, pwd_len, r_len;
9974-
9975+
9976 f_user = f_line;
9977-
9978- /*
9979+
9980+ /*
9981 * htdigest format
9982- *
9983- * user:realm:md5(user:realm:password)
9984+ *
9985+ * user:realm:md5(user:realm:password)
9986 */
9987-
9988+
9989 if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
9990- log_error_write(srv, __FILE__, __LINE__, "sbs",
9991- "parsed error in", p->conf.auth_htdigest_userfile,
9992+ log_error_write(srv, __FILE__, __LINE__, "sbs",
9993+ "parsed error in", p->conf.auth_htdigest_userfile,
9994 "expected 'username:realm:hashed password'");
9995-
9996+
9997 stream_close(&f);
9998-
9999+
10000 return -1;
f673a614
ER
10001 }
10002-
f673a614 10003+
2519e6e5
ER
10004 if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) {
10005- log_error_write(srv, __FILE__, __LINE__, "sbs",
10006- "parsed error in", p->conf.auth_plain_userfile,
10007+ log_error_write(srv, __FILE__, __LINE__, "sbs",
10008+ "parsed error in", p->conf.auth_plain_userfile,
10009 "expected 'username:realm:hashed password'");
10010-
f673a614 10011+
2519e6e5
ER
10012 stream_close(&f);
10013-
10014+
10015 return -1;
10016 }
10017-
10018+
10019 /* get pointers to the fields */
10020- u_len = f_realm - f_user;
10021+ u_len = f_realm - f_user;
10022 f_realm++;
10023 r_len = f_pwd - f_realm;
10024 f_pwd++;
10025-
10026+
10027 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10028 pwd_len = e - f_pwd;
10029 } else {
10030 pwd_len = f.size - (f_pwd - f.start);
10031 }
10032-
10033+
10034 if (username->used - 1 == u_len &&
10035 (realm->used - 1 == r_len) &&
10036 (0 == strncmp(username->ptr, f_user, u_len)) &&
10037 (0 == strncmp(realm->ptr, f_realm, r_len))) {
10038 /* found */
10039-
10040+
10041 buffer_copy_string_len(password, f_pwd, pwd_len);
10042-
10043+
10044 ret = 0;
10045 break;
10046 }
10047-
10048+
10049 /* EOL */
10050 if (!e) break;
10051-
10052+
10053 f_line = e + 1;
10054 }
f26f9fd5 10055-
f673a614 10056+
2519e6e5
ER
10057 stream_close(&f);
10058 } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
10059 p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10060 stream f;
10061 char * f_line;
10062 buffer *auth_fn;
10063-
f673a614 10064+
2519e6e5
ER
10065 auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
10066-
f673a614 10067+
2519e6e5
ER
10068 if (buffer_is_empty(auth_fn)) return -1;
10069-
f673a614 10070+
2519e6e5
ER
10071 if (0 != stream_open(&f, auth_fn)) {
10072- log_error_write(srv, __FILE__, __LINE__, "sbss",
10073+ log_error_write(srv, __FILE__, __LINE__, "sbss",
10074 "opening plain-userfile", auth_fn, "failed:", strerror(errno));
10075-
f673a614 10076+
2519e6e5
ER
10077 return -1;
10078 }
10079-
f673a614 10080+
2519e6e5
ER
10081 f_line = f.start;
10082-
f673a614 10083+
2519e6e5
ER
10084 while (f_line - f.start != f.size) {
10085 char *f_user, *f_pwd, *e;
10086 size_t u_len, pwd_len;
f26f9fd5 10087-
2519e6e5
ER
10088+
10089 f_user = f_line;
10090-
10091- /*
10092+
10093+ /*
10094 * htpasswd format
10095- *
10096+ *
10097 * user:crypted passwd
10098 */
10099-
10100+
10101 if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10102- log_error_write(srv, __FILE__, __LINE__, "sbs",
10103- "parsed error in", auth_fn,
10104+ log_error_write(srv, __FILE__, __LINE__, "sbs",
10105+ "parsed error in", auth_fn,
10106 "expected 'username:hashed password'");
10107-
10108+
10109 stream_close(&f);
10110-
10111+
10112 return -1;
f673a614 10113 }
2519e6e5 10114-
f673a614 10115+
2519e6e5
ER
10116 /* get pointers to the fields */
10117- u_len = f_pwd - f_user;
10118+ u_len = f_pwd - f_user;
10119 f_pwd++;
10120-
10121+
10122 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10123 pwd_len = e - f_pwd;
10124 } else {
10125 pwd_len = f.size - (f_pwd - f.start);
f26f9fd5 10126 }
2519e6e5
ER
10127-
10128+
10129 if (username->used - 1 == u_len &&
10130 (0 == strncmp(username->ptr, f_user, u_len))) {
10131 /* found */
10132-
10133+
10134 buffer_copy_string_len(password, f_pwd, pwd_len);
10135-
10136+
10137 ret = 0;
10138 break;
10139 }
10140-
10141+
10142 /* EOL */
10143 if (!e) break;
10144-
10145+
10146 f_line = e + 1;
f673a614 10147 }
2519e6e5
ER
10148-
10149+
10150 stream_close(&f);
10151 } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10152 ret = 0;
10153 } else {
10154 return -1;
f673a614 10155 }
2519e6e5 10156-
f673a614 10157+
2519e6e5 10158 return ret;
f673a614
ER
10159 }
10160
2519e6e5
ER
10161@@ -296,7 +286,7 @@
10162 int username_len;
10163 data_string *require;
10164 array *req;
10165-
10166+
10167 UNUSED(group);
10168 UNUSED(host);
f26f9fd5 10169
2519e6e5
ER
10170@@ -304,12 +294,12 @@
10171 /* search auth-directives for path */
10172 for (i = 0; i < p->conf.auth_require->used; i++) {
10173 if (p->conf.auth_require->data[i]->key->used == 0) continue;
10174-
10175+
10176 if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
10177 break;
10178 }
10179 }
f673a614 10180-
2519e6e5
ER
10181+
10182 if (i == p->conf.auth_require->used) {
10183 return -1;
10184 }
10185@@ -317,72 +307,72 @@
10186 req = ((data_array *)(p->conf.auth_require->data[i]))->value;
10187
10188 require = (data_string *)array_get_element(req, "require");
f673a614 10189-
2519e6e5
ER
10190+
10191 /* if we get here, the user we got a authed user */
10192 if (0 == strcmp(require->value->ptr, "valid-user")) {
10193 return 0;
10194 }
f673a614 10195-
2519e6e5
ER
10196+
10197 /* user=name1|group=name3|host=name4 */
10198-
10199+
10200 /* seperate the string by | */
10201 #if 0
10202 log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
10203-#endif
10204-
10205+#endif
10206+
10207 username_len = username ? strlen(username) : 0;
10208-
10209+
10210 r = rules = require->value->ptr;
10211-
10212+
10213 while (1) {
10214 const char *eq;
10215 const char *k, *v, *e;
10216 int k_len, v_len, r_len;
f673a614 10217-
2519e6e5
ER
10218+
10219 e = strchr(r, '|');
10220-
10221+
10222 if (e) {
10223 r_len = e - r;
10224 } else {
10225 r_len = strlen(rules) - (r - rules);
f673a614 10226 }
f673a614 10227-
2519e6e5
ER
10228+
10229 /* from r to r + r_len is a rule */
f673a614 10230-
2519e6e5
ER
10231+
10232 if (0 == strncmp(r, "valid-user", r_len)) {
10233- log_error_write(srv, __FILE__, __LINE__, "sb",
10234+ log_error_write(srv, __FILE__, __LINE__, "sb",
10235 "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules",
10236 require->value);
10237 return -1;
10238 }
10239-
10240+
10241 /* search for = in the rules */
10242 if (NULL == (eq = strchr(r, '='))) {
10243- log_error_write(srv, __FILE__, __LINE__, "sb",
10244- "parsing the 'require' section in 'auth.require' failed: a = is missing",
10245+ log_error_write(srv, __FILE__, __LINE__, "sb",
10246+ "parsing the 'require' section in 'auth.require' failed: a = is missing",
10247 require->value);
10248 return -1;
10249 }
10250-
10251+
10252 /* = out of range */
10253 if (eq > r + r_len) {
10254- log_error_write(srv, __FILE__, __LINE__, "sb",
10255+ log_error_write(srv, __FILE__, __LINE__, "sb",
10256 "parsing the 'require' section in 'auth.require' failed: = out of range",
10257 require->value);
10258-
10259+
10260 return -1;
10261 }
10262-
10263+
10264 /* the part before the = is user|group|host */
10265-
10266+
10267 k = r;
10268 k_len = eq - r;
10269 v = eq + 1;
10270 v_len = r_len - k_len - 1;
10271-
10272+
10273 if (k_len == 4) {
10274 if (0 == strncmp(k, "user", k_len)) {
10275- if (username &&
10276+ if (username &&
10277 username_len == v_len &&
10278 0 == strncmp(username, v, v_len)) {
10279 return 0;
10280@@ -404,19 +394,19 @@
10281 log_error_write(srv, __FILE__, __LINE__, "s", "unknown key");
10282 return -1;
10283 }
10284-
10285+
10286 if (!e) break;
10287 r = e + 1;
f673a614 10288 }
2519e6e5
ER
10289-
10290+
10291 log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
10292-
10293+
10294 return -1;
10295 }
f673a614 10296
2519e6e5
ER
10297 /**
10298- *
10299- *
10300+ *
10301+ *
10302 * @param password password-string from the auth-backend
10303 * @param pw password-string from the client
10304 */
10305@@ -426,16 +416,16 @@
10306 UNUSED(req);
f673a614 10307
2519e6e5
ER
10308 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10309- /*
10310+ /*
10311 * htdigest format
10312- *
10313- * user:realm:md5(user:realm:password)
10314+ *
10315+ * user:realm:md5(user:realm:password)
10316 */
10317-
10318+
10319 MD5_CTX Md5Ctx;
10320 HASH HA1;
10321 char a1[256];
10322-
10323+
10324 MD5_Init(&Md5Ctx);
10325 MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1);
10326 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10327@@ -443,24 +433,24 @@
10328 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10329 MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
10330 MD5_Final(HA1, &Md5Ctx);
10331-
10332+
10333 CvtHex(HA1, a1);
10334-
10335+
10336 if (0 == strcmp(password->ptr, a1)) {
10337 return 0;
10338 }
10339- } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
10340-#ifdef HAVE_CRYPT
10341+ } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
10342+#ifdef HAVE_CRYPT
10343 char salt[32];
10344 char *crypted;
10345 size_t salt_len = 0;
10346- /*
10347+ /*
10348 * htpasswd format
10349- *
10350+ *
10351 * user:crypted password
10352 */
f673a614 10353
2519e6e5
ER
10354- /*
10355+ /*
10356 * Algorithm Salt
10357 * CRYPT_STD_DES 2-character (Default)
10358 * CRYPT_EXT_DES 9-character
10359@@ -478,7 +468,7 @@
10360 salt_len = 2;
10361 } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
10362 char *dollar = NULL;
10363-
10364+
10365 if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
10366 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10367 return -1;
10368@@ -495,7 +485,7 @@
10369 strncpy(salt, password->ptr, salt_len);
f673a614 10370
2519e6e5
ER
10371 salt[salt_len] = '\0';
10372-
10373+
10374 crypted = crypt(pw, salt);
f673a614 10375
2519e6e5
ER
10376 if (0 == strcmp(password->ptr, crypted)) {
10377@@ -503,40 +493,13 @@
10378 } else {
10379 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
f26f9fd5 10380 }
2519e6e5
ER
10381-
10382-#endif
10383- } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10384+
10385+#endif
10386+ } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10387 if (0 == strcmp(password->ptr, pw)) {
10388 return 0;
f26f9fd5 10389 }
2519e6e5
ER
10390- } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) {
10391-#ifdef USE_PAM
10392- pam_handle_t *pamh=NULL;
10393- int retval;
10394-
10395- retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
10396-
10397- if (retval == PAM_SUCCESS)
10398- retval = pam_authenticate(pamh, 0); /* is user really user? */
10399-
10400- if (retval == PAM_SUCCESS)
10401- retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
10402-
10403- /* This is where we have been authorized or not. */
10404-
10405- if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
10406- pamh = NULL;
10407- log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
f26f9fd5 10408- }
2519e6e5
ER
10409-
10410- if (retval == PAM_SUCCESS) {
10411- log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
10412- return 0;
f26f9fd5 10413- } else {
2519e6e5 10414- log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
f26f9fd5 10415- }
2519e6e5
ER
10416-#endif
10417- } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10418+ } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10419 #ifdef USE_LDAP
10420 LDAP *ldap;
10421 LDAPMessage *lm, *first;
10422@@ -544,45 +507,45 @@
10423 int ret;
10424 char *attrs[] = { LDAP_NO_ATTRS, NULL };
10425 size_t i;
f673a614 10426-
2519e6e5
ER
10427+
10428 /* for now we stay synchronous */
f673a614 10429-
2519e6e5 10430- /*
f673a614 10431+
2519e6e5
ER
10432+ /*
10433 * 1. connect anonymously (done in plugin init)
10434 * 2. get DN for uid = username
10435 * 3. auth against ldap server
10436 * 4. (optional) check a field
10437 * 5. disconnect
10438- *
10439+ *
10440 */
10441-
10442+
10443 /* check username
10444- *
10445+ *
10446 * we have to protect us againt username which modifies out filter in
10447 * a unpleasant way
10448 */
10449-
10450+
10451 for (i = 0; i < username->used - 1; i++) {
10452 char c = username->ptr[i];
10453-
10454+
10455 if (!isalpha(c) &&
10456 !isdigit(c)) {
10457-
10458- log_error_write(srv, __FILE__, __LINE__, "sbd",
10459+
10460+ log_error_write(srv, __FILE__, __LINE__, "sbd",
10461 "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
10462-
10463+
10464 return -1;
f673a614 10465 }
f26f9fd5 10466 }
2519e6e5
ER
10467-
10468-
10469-
f673a614 10470+
2519e6e5
ER
10471+
10472+
10473 /* build filter */
10474 buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
10475 buffer_append_string_buffer(p->ldap_filter, username);
10476 buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post);
10477-
10478-
10479+
10480+
10481 /* 2. */
10482 if (p->conf.ldap == NULL ||
10483 LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
10484@@ -590,71 +553,71 @@
10485 return -1;
10486 if (LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
f673a614 10487
2519e6e5
ER
10488- log_error_write(srv, __FILE__, __LINE__, "sssb",
10489+ log_error_write(srv, __FILE__, __LINE__, "sssb",
10490 "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
10491-
10492+
10493 return -1;
f26f9fd5
ER
10494 }
10495 }
2519e6e5 10496-
f673a614 10497+
2519e6e5
ER
10498 if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
10499 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10500-
f673a614 10501+
2519e6e5
ER
10502 ldap_msgfree(lm);
10503-
10504+
10505 return -1;
f26f9fd5 10506 }
2519e6e5 10507-
f673a614 10508+
2519e6e5
ER
10509 if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
10510 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10511-
10512+
10513 ldap_msgfree(lm);
10514-
10515+
10516 return -1;
f26f9fd5 10517 }
2519e6e5
ER
10518-
10519+
10520 ldap_msgfree(lm);
10521-
10522-
10523+
10524+
10525 /* 3. */
10526 if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) {
10527 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
10528 return -1;
f26f9fd5 10529 }
2519e6e5
ER
10530-
10531+
10532 ret = LDAP_VERSION3;
10533 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
10534 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10535-
10536+
10537 ldap_unbind_s(ldap);
10538-
10539+
10540 return -1;
f26f9fd5 10541 }
2519e6e5
ER
10542-
10543+
10544 if (p->conf.auth_ldap_starttls == 1) {
10545 if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL, NULL))) {
10546 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
10547-
10548+
10549 ldap_unbind_s(ldap);
10550-
10551+
10552 return -1;
10553 }
10554 }
f26f9fd5 10555
2519e6e5
ER
10556-
10557+
10558 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
10559 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10560-
10561+
10562 ldap_unbind_s(ldap);
10563-
10564+
10565 return -1;
f26f9fd5 10566 }
2519e6e5 10567-
f673a614 10568+
2519e6e5
ER
10569 /* 5. */
10570 ldap_unbind_s(ldap);
10571-
f673a614 10572+
2519e6e5
ER
10573 /* everything worked, good, access granted */
10574-
f673a614 10575+
2519e6e5
ER
10576 return 0;
10577 #endif
10578 }
10579@@ -664,65 +627,65 @@
10580 int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
10581 buffer *username, *password;
10582 char *pw;
10583-
f673a614 10584+
2519e6e5
ER
10585 data_string *realm;
10586-
f673a614 10587+
2519e6e5
ER
10588 realm = (data_string *)array_get_element(req, "realm");
10589-
f673a614 10590+
2519e6e5
ER
10591 username = buffer_init();
10592 password = buffer_init();
10593-
10594+
10595 base64_decode(username, realm_str);
10596-
10597+
10598 /* r2 == user:password */
10599 if (NULL == (pw = strchr(username->ptr, ':'))) {
10600 buffer_free(username);
10601-
10602+
10603 log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
10604-
10605+
10606 return 0;
f26f9fd5 10607 }
2519e6e5 10608-
f673a614 10609+
2519e6e5
ER
10610 *pw++ = '\0';
10611-
10612+
10613 username->used = pw - username->ptr;
10614-
10615+
10616 /* copy password to r1 */
10617 if (http_auth_get_password(srv, p, username, realm->value, password)) {
10618 buffer_free(username);
10619 buffer_free(password);
f26f9fd5 10620-
2519e6e5
ER
10621+
10622 log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed");
f26f9fd5 10623-
2519e6e5
ER
10624+
10625 return 0;
10626 }
10627-
10628+
10629 /* password doesn't match */
10630 if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
10631 log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
10632-
10633+
10634 buffer_free(username);
10635 buffer_free(password);
10636-
10637+
10638 return 0;
10639 }
10640-
10641+
10642 /* value is our allow-rules */
10643 if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
10644 buffer_free(username);
10645 buffer_free(password);
10646-
10647+
10648 log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
10649-
10650+
10651 return 0;
10652 }
10653-
10654+
10655 /* remember the username */
10656 buffer_copy_string_buffer(p->auth_user, username);
10657-
10658+
10659 buffer_free(username);
10660 buffer_free(password);
10661-
10662+
10663 return 1;
f673a614 10664 }
f673a614 10665
2519e6e5
ER
10666@@ -735,7 +698,7 @@
10667 int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
10668 char a1[256];
10669 char a2[256];
10670-
10671+
10672 char *username;
10673 char *realm;
10674 char *nonce;
10675@@ -745,18 +708,18 @@
10676 char *cnonce;
10677 char *nc;
10678 char *respons;
10679-
10680+
10681 char *e, *c;
10682 const char *m = NULL;
10683 int i;
10684 buffer *password, *b, *username_buf, *realm_buf;
10685-
10686+
10687 MD5_CTX Md5Ctx;
10688 HASH HA1;
10689 HASH HA2;
10690 HASH RespHash;
10691 HASHHEX HA2Hex;
10692-
10693+
f673a614 10694
2519e6e5
ER
10695 /* init pointers */
10696 #define S(x) \
10697@@ -771,11 +734,11 @@
10698 { S("cnonce=") },
10699 { S("nc=") },
10700 { S("response=") },
f673a614 10701-
2519e6e5
ER
10702+
10703 { NULL, 0, NULL }
10704 };
10705 #undef S
10706-
10707+
10708 dkv[0].ptr = &username;
10709 dkv[1].ptr = &realm;
10710 dkv[2].ptr = &nonce;
10711@@ -786,24 +749,24 @@
10712 dkv[7].ptr = &nc;
10713 dkv[8].ptr = &respons;
10714 dkv[9].ptr = NULL;
10715-
10716+
10717 UNUSED(req);
10718-
10719+
10720 for (i = 0; dkv[i].key; i++) {
10721 *(dkv[i].ptr) = NULL;
10722 }
10723-
10724-
10725+
10726+
10727 if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST &&
10728 p->conf.auth_backend != AUTH_BACKEND_PLAIN) {
10729- log_error_write(srv, __FILE__, __LINE__, "s",
10730+ log_error_write(srv, __FILE__, __LINE__, "s",
10731 "digest: unsupported backend (only htdigest or plain)");
10732-
10733+
10734 return -1;
10735 }
10736-
10737+
10738 b = buffer_init_string(realm_str);
10739-
10740+
10741 /* parse credentials from client */
10742 for (c = b->ptr; *c; c++) {
10743 /* skip whitespaces */
10744@@ -812,18 +775,18 @@
10745
10746 for (i = 0; dkv[i].key; i++) {
10747 if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) {
10748- if ((c[dkv[i].key_len] == '"') &&
10749+ if ((c[dkv[i].key_len] == '"') &&
10750 (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) {
10751 /* value with "..." */
10752 *(dkv[i].ptr) = c + dkv[i].key_len + 1;
10753 c = e;
10754-
10755+
10756 *e = '\0';
10757 } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) {
10758 /* value without "...", terminated by ',' */
10759 *(dkv[i].ptr) = c + dkv[i].key_len;
10760 c = e;
f26f9fd5 10761-
2519e6e5
ER
10762+
10763 *e = '\0';
10764 } else {
10765 /* value without "...", terminated by EOL */
10766@@ -833,7 +796,7 @@
10767 }
f673a614 10768 }
2519e6e5
ER
10769 }
10770-
10771+
10772 if (p->conf.auth_debug > 1) {
10773 log_error_write(srv, __FILE__, __LINE__, "ss", "username", username);
10774 log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm);
10775@@ -845,22 +808,22 @@
10776 log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc);
10777 log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons);
10778 }
10779-
10780+
10781 /* check if everything is transmitted */
10782- if (!username ||
10783+ if (!username ||
10784 !realm ||
10785 !nonce ||
10786 !uri ||
10787 (qop && (!nc || !cnonce)) ||
10788 !respons ) {
10789 /* missing field */
10790-
10791- log_error_write(srv, __FILE__, __LINE__, "s",
10792+
f26f9fd5 10793+ log_error_write(srv, __FILE__, __LINE__, "s",
2519e6e5
ER
10794 "digest: missing field");
10795 return -1;
f673a614 10796 }
f673a614 10797
2519e6e5
ER
10798- m = get_http_method_name(con->request.http_method);
10799+ m = get_http_method_name(con->request.http_method);
10800
10801 /* password-string == HA1 */
10802 password = buffer_init();
10803@@ -873,10 +836,10 @@
10804 buffer_free(realm_buf);
10805 return 0;
10806 }
f673a614 10807-
2519e6e5
ER
10808+
10809 buffer_free(username_buf);
10810 buffer_free(realm_buf);
f673a614 10811-
2519e6e5
ER
10812+
10813 if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10814 /* generate password from plain-text */
10815 MD5_Init(&Md5Ctx);
10816@@ -890,16 +853,16 @@
10817 /* HA1 */
10818 /* transform the 32-byte-hex-md5 to a 16-byte-md5 */
10819 for (i = 0; i < HASHLEN; i++) {
10820- HA1[i] = hex2int(password->ptr[i*2]) << 4;
10821- HA1[i] |= hex2int(password->ptr[i*2+1]);
10822+ HA1[i] = hex2int(password->ptr[i*2]) << 4;
10823+ HA1[i] |= hex2int(password->ptr[i*2+1]);
10824 }
10825 } else {
10826 /* we already check that above */
10827 SEGFAULT();
10828 }
f673a614 10829-
2519e6e5
ER
10830+
10831 buffer_free(password);
f673a614 10832-
2519e6e5
ER
10833+
10834 if (algorithm &&
10835 strcasecmp(algorithm, "md5-sess") == 0) {
10836 MD5_Init(&Md5Ctx);
10837@@ -910,9 +873,9 @@
10838 MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
10839 MD5_Final(HA1, &Md5Ctx);
10840 }
f673a614 10841-
2519e6e5
ER
10842+
10843 CvtHex(HA1, a1);
f26f9fd5 10844-
2519e6e5
ER
10845+
10846 /* calculate H(A2) */
10847 MD5_Init(&Md5Ctx);
10848 MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
10849@@ -924,7 +887,7 @@
10850 }
10851 MD5_Final(HA2, &Md5Ctx);
10852 CvtHex(HA2, HA2Hex);
10853-
10854+
10855 /* calculate response */
10856 MD5_Init(&Md5Ctx);
10857 MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN);
10858@@ -942,39 +905,39 @@
10859 MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN);
10860 MD5_Final(RespHash, &Md5Ctx);
10861 CvtHex(RespHash, a2);
10862-
10863+
10864 if (0 != strcmp(a2, respons)) {
10865 /* digest not ok */
f673a614 10866-
2519e6e5
ER
10867+
10868 if (p->conf.auth_debug) {
10869- log_error_write(srv, __FILE__, __LINE__, "sss",
10870+ log_error_write(srv, __FILE__, __LINE__, "sss",
10871 "digest: digest mismatch", a2, respons);
10872 }
f673a614 10873-
2519e6e5
ER
10874- log_error_write(srv, __FILE__, __LINE__, "sss",
10875+
10876+ log_error_write(srv, __FILE__, __LINE__, "sss",
10877 "digest: auth failed for", username, "wrong password");
f673a614 10878-
2519e6e5
ER
10879+
10880 buffer_free(b);
10881 return 0;
10882 }
f673a614 10883-
2519e6e5
ER
10884+
10885 /* value is our allow-rules */
10886 if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
10887 buffer_free(b);
f26f9fd5 10888-
2519e6e5
ER
10889- log_error_write(srv, __FILE__, __LINE__, "s",
10890+
10891+ log_error_write(srv, __FILE__, __LINE__, "s",
10892 "digest: rules did match");
10893-
10894+
10895 return 0;
10896 }
f673a614 10897-
2519e6e5
ER
10898+
10899 /* remember the username */
10900 buffer_copy_string(p->auth_user, username);
f673a614 10901-
2519e6e5
ER
10902+
10903 buffer_free(b);
f673a614 10904-
2519e6e5
ER
10905+
10906 if (p->conf.auth_debug) {
10907- log_error_write(srv, __FILE__, __LINE__, "s",
10908+ log_error_write(srv, __FILE__, __LINE__, "s",
10909 "digest: auth ok");
10910 }
10911 return 1;
10912@@ -985,23 +948,23 @@
10913 HASH h;
10914 MD5_CTX Md5Ctx;
10915 char hh[32];
f673a614 10916-
2519e6e5
ER
10917+
10918 UNUSED(p);
f673a614 10919
2519e6e5
ER
10920 /* generate shared-secret */
10921 MD5_Init(&Md5Ctx);
10922 MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
10923 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
10924-
10925+
10926 /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
10927 ltostr(hh, srv->cur_ts);
10928 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
10929 ltostr(hh, rand());
10930 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
10931-
10932+
10933 MD5_Final(h, &Md5Ctx);
10934-
10935+
10936 CvtHex(h, out);
10937-
10938+
10939 return 0;
10940 }
1175ccec 10941--- ../lighttpd-1.4.11/src/http_auth.h 2005-08-14 17:12:31.000000000 +0300
36e2a29e 10942+++ lighttpd-1.4.12/src/http_auth.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
10943@@ -9,22 +9,26 @@
10944 # include <ldap.h>
f673a614 10945 #endif
2519e6e5
ER
10946
10947-typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN,
10948- AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD,
10949- AUTH_BACKEND_HTDIGEST, AUTH_BACKEND_PAM } auth_backend_t;
10950+typedef enum {
10951+ AUTH_BACKEND_UNSET,
10952+ AUTH_BACKEND_PLAIN,
10953+ AUTH_BACKEND_LDAP,
10954+ AUTH_BACKEND_HTPASSWD,
10955+ AUTH_BACKEND_HTDIGEST
10956+} auth_backend_t;
10957
10958 typedef struct {
10959 /* auth */
10960 array *auth_require;
10961-
f26f9fd5 10962+
2519e6e5
ER
10963 buffer *auth_plain_groupfile;
10964 buffer *auth_plain_userfile;
10965-
10966+
10967 buffer *auth_htdigest_userfile;
10968 buffer *auth_htpasswd_userfile;
10969-
10970+
10971 buffer *auth_backend_conf;
10972-
10973+
10974 buffer *auth_ldap_hostname;
10975 buffer *auth_ldap_basedn;
10976 buffer *auth_ldap_binddn;
10977@@ -32,15 +36,15 @@
10978 buffer *auth_ldap_filter;
10979 buffer *auth_ldap_cafile;
10980 unsigned short auth_ldap_starttls;
10981-
10982+
10983 unsigned short auth_debug;
10984-
10985+
10986 /* generated */
10987 auth_backend_t auth_backend;
10988-
10989+
10990 #ifdef USE_LDAP
10991 LDAP *ldap;
10992-
10993+
10994 buffer *ldap_filter_pre;
10995 buffer *ldap_filter_post;
10996 #endif
10997@@ -49,15 +53,15 @@
10998 typedef struct {
10999 PLUGIN_DATA;
11000 buffer *tmp_buf;
11001-
11002+
11003 buffer *auth_user;
f26f9fd5 11004
2519e6e5
ER
11005 #ifdef USE_LDAP
11006 buffer *ldap_filter;
f26f9fd5 11007 #endif
2519e6e5 11008-
f673a614 11009+
2519e6e5
ER
11010 mod_auth_plugin_config **config_storage;
11011-
f26f9fd5 11012+
2519e6e5
ER
11013 mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
11014 } mod_auth_plugin_data;
f26f9fd5 11015
1175ccec 11016--- ../lighttpd-1.4.11/src/http_auth_digest.h 2006-01-05 00:54:01.000000000 +0200
36e2a29e 11017+++ lighttpd-1.4.12/src/http_auth_digest.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
11018@@ -12,7 +12,7 @@
11019 #ifdef USE_OPENSSL
11020 #define IN const
11021 #else
11022-#define IN
11023+#define IN
11024 #endif
11025 #define OUT
11026
1175ccec 11027--- ../lighttpd-1.4.11/src/http_chunk.c 2005-08-11 01:26:50.000000000 +0300
36e2a29e 11028+++ lighttpd-1.4.12/src/http_chunk.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
11029@@ -1,7 +1,7 @@
11030 /**
11031 * the HTTP chunk-API
11032- *
11033- *
11034+ *
11035+ *
11036 */
f26f9fd5 11037
f26f9fd5 11038 #include <sys/types.h>
2519e6e5 11039@@ -9,7 +9,6 @@
f26f9fd5 11040
2519e6e5
ER
11041 #include <stdlib.h>
11042 #include <fcntl.h>
11043-#include <unistd.h>
f26f9fd5 11044
2519e6e5
ER
11045 #include <stdio.h>
11046 #include <errno.h>
11047@@ -23,19 +22,19 @@
11048 static int http_chunk_append_len(server *srv, connection *con, size_t len) {
11049 size_t i, olen = len, j;
11050 buffer *b;
11051-
11052+
11053 b = srv->tmp_chunk_len;
11054-
11055+
11056 if (len == 0) {
11057 buffer_copy_string(b, "0");
11058 } else {
11059 for (i = 0; i < 8 && len; i++) {
11060 len >>= 4;
11061 }
11062-
11063+
11064 /* i is the number of hex digits we have */
11065 buffer_prepare_copy(b, i + 1);
11066-
11067+
11068 for (j = i-1, len = olen; j+1 > 0; j--) {
11069 b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
11070 len >>= 4;
11071@@ -43,61 +42,61 @@
11072 b->used = i;
11073 b->ptr[b->used++] = '\0';
11074 }
11075-
11076+
11077 buffer_append_string(b, "\r\n");
11078 chunkqueue_append_buffer(con->write_queue, b);
11079-
11080+
11081 return 0;
11082 }
f26f9fd5 11083
f26f9fd5 11084
2519e6e5
ER
11085 int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
11086 chunkqueue *cq;
11087-
f673a614 11088+
2519e6e5
ER
11089 if (!con) return -1;
11090-
f673a614 11091+
2519e6e5
ER
11092 cq = con->write_queue;
11093-
f673a614 11094+
2519e6e5
ER
11095 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11096 http_chunk_append_len(srv, con, len);
f26f9fd5 11097 }
2519e6e5
ER
11098-
11099+
11100 chunkqueue_append_file(cq, fn, offset, len);
11101-
11102+
11103 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
11104 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11105 }
11106-
11107+
f26f9fd5
ER
11108 return 0;
11109 }
f673a614 11110
2519e6e5
ER
11111 int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
11112 chunkqueue *cq;
11113-
11114+
11115 if (!con) return -1;
11116-
11117+
11118 cq = con->write_queue;
11119-
11120+
11121 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11122 http_chunk_append_len(srv, con, mem->used - 1);
11123 }
11124-
11125+
11126 chunkqueue_append_buffer(cq, mem);
11127-
11128+
11129 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
11130 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11131 }
11132-
11133+
11134 return 0;
f26f9fd5
ER
11135 }
11136
2519e6e5
ER
11137 int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
11138 chunkqueue *cq;
11139-
11140+
11141 if (!con) return -1;
11142-
11143+
11144 cq = con->write_queue;
11145-
11146+
11147 if (len == 0) {
11148 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11149 http_chunk_append_len(srv, con, 0);
11150@@ -107,17 +106,17 @@
f26f9fd5 11151 }
2519e6e5 11152 return 0;
f26f9fd5 11153 }
2519e6e5
ER
11154-
11155+
11156 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11157 http_chunk_append_len(srv, con, len - 1);
11158 }
11159-
11160+
11161 chunkqueue_append_mem(cq, mem, len);
11162-
11163+
11164 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11165 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11166 }
11167-
11168+
f26f9fd5
ER
11169 return 0;
11170 }
f26f9fd5 11171
2519e6e5
ER
11172@@ -125,9 +124,9 @@
11173 off_t http_chunkqueue_length(server *srv, connection *con) {
11174 if (!con) {
11175 log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
11176-
11177+
11178 return 0;
11179 }
11180-
11181+
11182 return chunkqueue_length(con->write_queue);
f26f9fd5 11183 }
1175ccec
ER
11184--- ../lighttpd-1.4.11/src/http_resp.c 1970-01-01 03:00:00.000000000 +0300
11185+++ lighttpd-1.4.12/src/http_resp.c 2006-07-15 22:43:21.000000000 +0300
11186@@ -0,0 +1,274 @@
2519e6e5
ER
11187+#include <string.h>
11188+#include <stdlib.h>
11189+#include <stdio.h>
11190+#include <assert.h>
11191+
11192+#include "http_resp.h"
11193+#include "http_resp_parser.h"
11194+
11195+/* declare prototypes for the parser */
11196+void *http_resp_parserAlloc(void *(*mallocProc)(size_t));
11197+void http_resp_parserFree(void *p, void (*freeProc)(void*));
11198+void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt);
11199+void http_resp_parser(void *, int, buffer *, http_resp_ctx_t *);
11200+
11201+typedef struct {
11202+ chunkqueue *cq;
11203+
11204+ chunk *c; /* current chunk in the chunkqueue */
1175ccec 11205+ size_t offset; /* current offset in current chunk */
2519e6e5 11206+
1175ccec
ER
11207+ chunk *lookup_c;
11208+ size_t lookup_offset;
2519e6e5 11209+
1175ccec
ER
11210+ int is_key;
11211+ int is_statusline;
2519e6e5
ER
11212+} http_resp_tokenizer_t;
11213+
11214+http_resp *http_response_init(void) {
1175ccec 11215+ http_resp *resp = calloc(1, sizeof(*resp));
2519e6e5 11216+
1175ccec
ER
11217+ resp->reason = buffer_init();
11218+ resp->headers = array_init();
2519e6e5 11219+
1175ccec 11220+ return resp;
2519e6e5
ER
11221+}
11222+
11223+void http_response_reset(http_resp *resp) {
1175ccec 11224+ if (!resp) return;
2519e6e5 11225+
1175ccec
ER
11226+ buffer_reset(resp->reason);
11227+ array_reset(resp->headers);
2519e6e5
ER
11228+
11229+}
11230+
11231+void http_response_free(http_resp *resp) {
1175ccec 11232+ if (!resp) return;
2519e6e5 11233+
1175ccec
ER
11234+ buffer_free(resp->reason);
11235+ array_free(resp->headers);
2519e6e5 11236+
1175ccec 11237+ free(resp);
2519e6e5
ER
11238+}
11239+
11240+static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
1175ccec
ER
11241+ if (t->offset == t->c->mem->used - 1) {
11242+ /* end of chunk, open next chunk */
2519e6e5 11243+
1175ccec 11244+ if (!t->c->next) return -1;
2519e6e5 11245+
1175ccec
ER
11246+ t->c = t->c->next;
11247+ t->offset = 0;
11248+ }
2519e6e5 11249+
1175ccec 11250+ *c = t->c->mem->ptr[t->offset++];
2519e6e5 11251+
1175ccec
ER
11252+ t->lookup_offset = t->offset;
11253+ t->lookup_c = t->c;
2519e6e5 11254+
1175ccec
ER
11255+#if 0
11256+ fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
11257+#endif
2519e6e5 11258+
1175ccec 11259+ return 0;
2519e6e5
ER
11260+}
11261+
11262+static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
1175ccec
ER
11263+ if (t->lookup_offset == t->lookup_c->mem->used - 1) {
11264+ /* end of chunk, open next chunk */
2519e6e5 11265+
1175ccec 11266+ if (!t->lookup_c->next) return -1;
2519e6e5 11267+
1175ccec
ER
11268+ t->lookup_c = t->lookup_c->next;
11269+ t->lookup_offset = 0;
11270+ }
36e2a29e 11271+
1175ccec
ER
11272+ *c = t->lookup_c->mem->ptr[t->lookup_offset++];
11273+#if 0
11274+ fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
11275+#endif
2519e6e5 11276+
1175ccec 11277+ return 0;
2519e6e5
ER
11278+}
11279+
11280+
11281+static int http_resp_tokenizer(
1175ccec
ER
11282+ http_resp_tokenizer_t *t,
11283+ int *token_id,
11284+ buffer *token
2519e6e5 11285+) {
1175ccec
ER
11286+ unsigned char c;
11287+ int tid = 0;
11288+
11289+ /* push the token to the parser */
11290+
11291+ while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
11292+ switch (c) {
11293+ case ':':
11294+ tid = TK_COLON;
11295+
11296+ t->is_key = 0;
11297+
11298+ break;
11299+ case ' ':
11300+ case '\t':
11301+ /* ignore WS */
11302+
11303+ break;
11304+ case '\r':
11305+ if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11306+
11307+ if (c == '\n') {
11308+ tid = TK_CRLF;
11309+
11310+ t->c = t->lookup_c;
11311+ t->offset = t->lookup_offset;
11312+
11313+ t->is_statusline = 0;
11314+ t->is_key = 1;
11315+ } else {
11316+ fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__);
11317+ return -1;
11318+ }
11319+ break;
11320+ case '\n':
11321+ tid = TK_CRLF;
11322+
11323+ t->is_statusline = 0;
11324+ t->is_key = 1;
11325+
11326+ break;
11327+ default:
11328+ while (c >= 32 && c != 127 && c != 255) {
11329+ if (t->is_statusline) {
11330+ if (c == ':') { t->is_statusline = 0; break; } /* this is not a status line by a real header */
11331+ if (c == 32) break; /* the space is a splitter in the statusline */
11332+ } else {
11333+ if (t->is_key) {
11334+ if (c == ':') break; /* the : is the splitter between key and value */
11335+ }
11336+ }
11337+ if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11338+ }
11339+
11340+ if (t->c == t->lookup_c &&
11341+ t->offset == t->lookup_offset + 1) {
11342+
11343+ fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__);
11344+ return -1;
11345+ }
11346+
11347+ tid = TK_STRING;
11348+
11349+ /* the lookup points to the first invalid char */
11350+ t->lookup_offset--;
11351+
11352+ /* no overlapping string */
11353+ if (t->c == t->lookup_c) {
11354+ buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
11355+ } else {
11356+ /* first chunk */
11357+ buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
11358+
11359+ /* chunks in the middle */
11360+ for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
11361+ buffer_append_string_buffer(token, t->c->mem);
11362+ t->offset = t->c->mem->used - 1;
11363+ }
11364+
11365+ /* last chunk */
11366+ buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
11367+ }
11368+
11369+ t->offset = t->lookup_offset;
11370+
11371+ break;
11372+ }
2519e6e5
ER
11373+ }
11374+
1175ccec 11375+ if (tid) {
2519e6e5
ER
11376+ *token_id = tid;
11377+
1175ccec
ER
11378+ return 1;
11379+ }
2519e6e5 11380+
1175ccec 11381+ return -1;
2519e6e5
ER
11382+}
11383+
11384+parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
1175ccec 11385+ http_resp_tokenizer_t t;
2519e6e5
ER
11386+ void *pParser = NULL;
11387+ int token_id = 0;
11388+ buffer *token = NULL;
11389+ http_resp_ctx_t context;
1175ccec
ER
11390+ parse_status_t ret = PARSE_UNSET;
11391+ int last_token_id = 0;
2519e6e5
ER
11392+
11393+ t.cq = cq;
1175ccec
ER
11394+ t.c = cq->first;
11395+ t.offset = t.c->offset;
11396+ t.is_key = 0;
11397+ t.is_statusline = 1;
2519e6e5
ER
11398+
11399+ context.ok = 1;
1175ccec
ER
11400+ context.errmsg = buffer_init();
11401+ context.resp = resp;
2519e6e5
ER
11402+
11403+ pParser = http_resp_parserAlloc( malloc );
11404+ token = buffer_init();
1175ccec
ER
11405+#if 0
11406+ http_resp_parserTrace(stderr, "http-response: ");
11407+#endif
2519e6e5
ER
11408+
11409+ while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) {
11410+ http_resp_parser(pParser, token_id, token, &context);
11411+
11412+ token = buffer_init();
11413+
1175ccec
ER
11414+ /* CRLF CRLF ... the header end sequence */
11415+ if (last_token_id == TK_CRLF &&
11416+ token_id == TK_CRLF) break;
2519e6e5 11417+
1175ccec 11418+ last_token_id = token_id;
2519e6e5
ER
11419+ }
11420+
1175ccec
ER
11421+ /* oops, the parser failed */
11422+ if (context.ok == 0) {
11423+ ret = PARSE_ERROR;
2519e6e5 11424+
1175ccec
ER
11425+ fprintf(stderr, "%s.%d: parsing failed at: ...%20s\r\n",
11426+ __FILE__, __LINE__, t.c->mem->ptr + t.offset);
11427+ }
2519e6e5
ER
11428+
11429+ http_resp_parser(pParser, 0, token, &context);
11430+ http_resp_parserFree(pParser, free );
11431+
1175ccec
ER
11432+ if (context.ok == 0) {
11433+ /* we are missing the some tokens */
2519e6e5 11434+
1175ccec
ER
11435+ if (!buffer_is_empty(context.errmsg)) {
11436+ fprintf(stderr, "%s.%d: hmm, %20s\r\n",
11437+ __FILE__, __LINE__, context.errmsg->ptr);
11438+ }
2519e6e5 11439+
1175ccec
ER
11440+ if (ret == PARSE_UNSET) {
11441+ ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR;
11442+ }
11443+ } else {
11444+ chunk *c;
11445+
11446+ for (c = cq->first; c != t.c; c = c->next) {
11447+ c->offset = c->mem->used - 1;
11448+ }
2519e6e5 11449+
1175ccec 11450+ c->offset = t.offset;
2519e6e5 11451+
1175ccec
ER
11452+ ret = PARSE_SUCCESS;
11453+ }
2519e6e5 11454+
1175ccec
ER
11455+ buffer_free(token);
11456+ buffer_free(context.errmsg);
2519e6e5 11457+
1175ccec 11458+ return ret;
2519e6e5
ER
11459+}
11460+
1175ccec 11461--- ../lighttpd-1.4.11/src/http_resp.h 1970-01-01 03:00:00.000000000 +0300
36e2a29e 11462+++ lighttpd-1.4.12/src/http_resp.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
11463@@ -0,0 +1,34 @@
11464+#ifndef _HTTP_RESP_H_
11465+#define _HTTP_RESP_H_
11466+
11467+#include "array.h"
11468+#include "chunk.h"
11469+
11470+typedef enum {
11471+ PARSE_UNSET,
11472+ PARSE_SUCCESS,
11473+ PARSE_ERROR,
11474+ PARSE_NEED_MORE
11475+} parse_status_t;
11476+
11477+typedef struct {
11478+ int protocol; /* http/1.0, http/1.1 */
11479+ int status; /* e.g. 200 */
11480+ buffer *reason; /* e.g. Ok */
11481+ array *headers;
11482+} http_resp;
11483+
11484+typedef struct {
11485+ int ok;
11486+ buffer *errmsg;
11487+
11488+ http_resp *resp;
11489+} http_resp_ctx_t;
11490+
11491+http_resp *http_response_init(void);
11492+void http_response_free(http_resp *resp);
11493+void http_response_reset(http_resp *resp);
11494+
11495+parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
11496+
11497+#endif
1175ccec
ER
11498--- ../lighttpd-1.4.11/src/http_resp_parser.c 1970-01-01 03:00:00.000000000 +0300
11499+++ lighttpd-1.4.12/src/http_resp_parser.c 2006-07-15 22:44:07.000000000 +0300
11500@@ -0,0 +1,895 @@
2519e6e5
ER
11501+/* Driver template for the LEMON parser generator.
11502+** The author disclaims copyright to this source code.
11503+*/
11504+/* First off, code is include which follows the "include" declaration
11505+** in the input file. */
11506+#include <stdio.h>
11507+#line 6 "./http_resp_parser.y"
11508+
11509+#include <assert.h>
11510+#include <string.h>
11511+#include "http_resp.h"
11512+#include "keyvalue.h"
11513+#include "array.h"
11514+
11515+#line 16 "http_resp_parser.c"
11516+/* Next is all token values, in a form suitable for use by makeheaders.
11517+** This section will be null unless lemon is run with the -m switch.
11518+*/
11519+/*
11520+** These constants (all generated automatically by the parser generator)
11521+** specify the various kinds of tokens (terminals) that the parser
11522+** understands.
11523+**
11524+** Each symbol here is a terminal symbol in the grammar.
11525+*/
11526+/* Make sure the INTERFACE macro is defined.
11527+*/
11528+#ifndef INTERFACE
11529+# define INTERFACE 1
11530+#endif
11531+/* The next thing included is series of defines which control
11532+** various aspects of the generated parser.
11533+** YYCODETYPE is the data type used for storing terminal
11534+** and nonterminal numbers. "unsigned char" is
11535+** used if there are fewer than 250 terminals
11536+** and nonterminals. "int" is used otherwise.
11537+** YYNOCODE is a number of type YYCODETYPE which corresponds
11538+** to no legal terminal or nonterminal number. This
11539+** number is used to fill in empty slots of the hash
11540+** table.
11541+** YYFALLBACK If defined, this indicates that one or more tokens
11542+** have fall-back values which should be used if the
11543+** original value of the token will not parse.
11544+** YYACTIONTYPE is the data type used for storing terminal
11545+** and nonterminal numbers. "unsigned char" is
11546+** used if there are fewer than 250 rules and
11547+** states combined. "int" is used otherwise.
11548+** http_resp_parserTOKENTYPE is the data type used for minor tokens given
11549+** directly to the parser from the tokenizer.
11550+** YYMINORTYPE is the data type used for all minor tokens.
11551+** This is typically a union of many types, one of
11552+** which is http_resp_parserTOKENTYPE. The entry in the union
11553+** for base tokens is called "yy0".
11554+** YYSTACKDEPTH is the maximum depth of the parser's stack.
11555+** http_resp_parserARG_SDECL A static variable declaration for the %extra_argument
11556+** http_resp_parserARG_PDECL A parameter declaration for the %extra_argument
11557+** http_resp_parserARG_STORE Code to store %extra_argument into yypParser
11558+** http_resp_parserARG_FETCH Code to extract %extra_argument from yypParser
11559+** YYNSTATE the combined number of states.
11560+** YYNRULE the number of rules in the grammar
11561+** YYERRORSYMBOL is the code number of the error symbol. If not
11562+** defined, then do no error processing.
11563+*/
11564+/* \ 1 */
11565+#define YYCODETYPE unsigned char
11566+#define YYNOCODE 12
11567+#define YYACTIONTYPE unsigned char
11568+#define http_resp_parserTOKENTYPE buffer *
11569+typedef union {
11570+ http_resp_parserTOKENTYPE yy0;
11571+ http_resp * yy2;
11572+ data_string * yy9;
11573+ array * yy12;
11574+ int yy20;
11575+ int yy23;
11576+} YYMINORTYPE;
11577+#define YYSTACKDEPTH 100
11578+#define http_resp_parserARG_SDECL http_resp_ctx_t *ctx;
11579+#define http_resp_parserARG_PDECL ,http_resp_ctx_t *ctx
11580+#define http_resp_parserARG_FETCH http_resp_ctx_t *ctx = yypParser->ctx
11581+#define http_resp_parserARG_STORE yypParser->ctx = ctx
11582+#define YYNSTATE 19
11583+#define YYNRULE 9
11584+#define YYERRORSYMBOL 4
11585+#define YYERRSYMDT yy23
11586+#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
11587+#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
11588+#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
11589+
11590+/* Next are that tables used to determine what action to take based on the
11591+** current state and lookahead token. These tables are used to implement
11592+** functions that take a state number and lookahead value and return an
11593+** action integer.
11594+**
11595+** Suppose the action integer is N. Then the action is determined as
11596+** follows
11597+**
11598+** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
11599+** token onto the stack and goto state N.
11600+**
11601+** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
11602+**
11603+** N == YYNSTATE+YYNRULE A syntax error has occurred.
11604+**
11605+** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
11606+**
11607+** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
11608+** slots in the yy_action[] table.
11609+**
11610+** The action table is constructed as a single large table named yy_action[].
11611+** Given state S and lookahead X, the action is computed as
11612+**
11613+** yy_action[ yy_shift_ofst[S] + X ]
11614+**
11615+** If the index value yy_shift_ofst[S]+X is out of range or if the value
11616+** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
11617+** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
11618+** and that yy_default[S] should be used instead.
11619+**
11620+** The formula above is for computing the action when the lookahead is
11621+** a terminal symbol. If the lookahead is a non-terminal (as occurs after
11622+** a reduce action) then the yy_reduce_ofst[] array is used in place of
11623+** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
11624+** YY_SHIFT_USE_DFLT.
11625+**
11626+** The following are the tables generated in this section:
11627+**
11628+** yy_action[] A single table containing all actions.
11629+** yy_lookahead[] A table containing the lookahead for each entry in
11630+** yy_action. Used to detect hash collisions.
11631+** yy_shift_ofst[] For each state, the offset into yy_action for
11632+** shifting terminals.
11633+** yy_reduce_ofst[] For each state, the offset into yy_action for
11634+** shifting non-terminals after a reduce.
11635+** yy_default[] Default action for each state.
11636+*/
11637+static YYACTIONTYPE yy_action[] = {
11638+ /* 0 */ 8, 29, 18, 1, 14, 2, 4, 11, 15, 12,
11639+ /* 10 */ 14, 13, 4, 21, 5, 19, 3, 5, 6, 7,
11640+ /* 20 */ 9, 17, 16, 4, 20, 22, 22, 10,
11641+};
11642+static YYCODETYPE yy_lookahead[] = {
11643+ /* 0 */ 5, 6, 2, 8, 9, 1, 2, 1, 2, 8,
11644+ /* 10 */ 9, 1, 2, 2, 3, 0, 9, 3, 2, 1,
11645+ /* 20 */ 7, 2, 2, 2, 0, 2, 11, 10,
11646+};
11647+#define YY_SHIFT_USE_DFLT (-1)
11648+static signed char yy_shift_ofst[] = {
11649+ /* 0 */ 0, 4, 15, -1, 14, 16, 18, -1, 19, 20,
11650+ /* 10 */ 6, 21, 10, 24, -1, -1, -1, 23, 11,
11651+};
11652+#define YY_REDUCE_USE_DFLT (-6)
11653+static signed char yy_reduce_ofst[] = {
11654+ /* 0 */ -5, 7, -6, -6, -6, -6, -6, -6, 13, 17,
11655+ /* 10 */ -6, 1, 7, -6, -6, -6, -6, -6, -6,
11656+};
11657+static YYACTIONTYPE yy_default[] = {
11658+ /* 0 */ 28, 28, 28, 25, 28, 28, 28, 27, 28, 28,
11659+ /* 10 */ 28, 28, 28, 28, 26, 24, 23, 28, 28,
11660+};
11661+#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
11662+
11663+/* The next table maps tokens into fallback tokens. If a construct
11664+** like the following:
11665+**
11666+** %fallback ID X Y Z.
11667+**
11668+** appears in the grammer, then ID becomes a fallback token for X, Y,
11669+** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
11670+** but it does not parse, the type of the token is changed to ID and
11671+** the parse is retried before an error is thrown.
11672+*/
11673+#ifdef YYFALLBACK
11674+static const YYCODETYPE yyFallback[] = {
11675+};
11676+#endif /* YYFALLBACK */
11677+
11678+/* The following structure represents a single element of the
11679+** parser's stack. Information stored includes:
11680+**
11681+** + The state number for the parser at this level of the stack.
11682+**
11683+** + The value of the token stored at this level of the stack.
11684+** (In other words, the "major" token.)
11685+**
11686+** + The semantic value stored at this level of the stack. This is
11687+** the information used by the action routines in the grammar.
11688+** It is sometimes called the "minor" token.
11689+*/
11690+struct yyStackEntry {
11691+ int stateno; /* The state-number */
11692+ int major; /* The major token value. This is the code
11693+ ** number for the token at this stack level */
11694+ YYMINORTYPE minor; /* The user-supplied minor token value. This
11695+ ** is the value of the token */
11696+};
11697+typedef struct yyStackEntry yyStackEntry;
11698+
11699+/* The state of the parser is completely contained in an instance of
11700+** the following structure */
11701+struct yyParser {
11702+ int yyidx; /* Index of top element in stack */
11703+ int yyerrcnt; /* Shifts left before out of the error */
11704+ http_resp_parserARG_SDECL /* A place to hold %extra_argument */
11705+ yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
11706+};
11707+typedef struct yyParser yyParser;
11708+
11709+#ifndef NDEBUG
11710+#include <stdio.h>
11711+static FILE *yyTraceFILE = 0;
11712+static char *yyTracePrompt = 0;
11713+#endif /* NDEBUG */
11714+
11715+#ifndef NDEBUG
11716+/*
11717+** Turn parser tracing on by giving a stream to which to write the trace
11718+** and a prompt to preface each trace message. Tracing is turned off
11719+** by making either argument NULL
11720+**
11721+** Inputs:
11722+** <ul>
11723+** <li> A FILE* to which trace output should be written.
11724+** If NULL, then tracing is turned off.
11725+** <li> A prefix string written at the beginning of every
11726+** line of trace output. If NULL, then tracing is
11727+** turned off.
11728+** </ul>
11729+**
11730+** Outputs:
11731+** None.
11732+*/
11733+void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt){
11734+ yyTraceFILE = TraceFILE;
11735+ yyTracePrompt = zTracePrompt;
11736+ if( yyTraceFILE==0 ) yyTracePrompt = 0;
11737+ else if( yyTracePrompt==0 ) yyTraceFILE = 0;
11738+}
11739+#endif /* NDEBUG */
11740+
11741+#ifndef NDEBUG
11742+/* For tracing shifts, the names of all terminals and nonterminals
11743+** are required. The following table supplies these names */
11744+static const char *yyTokenName[] = {
11745+ "$", "CRLF", "STRING", "COLON",
11746+ "error", "protocol", "response_hdr", "number",
11747+ "headers", "header", "reason",
11748+};
11749+#endif /* NDEBUG */
11750+
11751+#ifndef NDEBUG
11752+/* For tracing reduce actions, the names of all rules are required.
11753+*/
11754+static const char *yyRuleName[] = {
11755+ /* 0 */ "response_hdr ::= headers CRLF",
11756+ /* 1 */ "response_hdr ::= protocol number reason CRLF headers CRLF",
11757+ /* 2 */ "protocol ::= STRING",
11758+ /* 3 */ "number ::= STRING",
11759+ /* 4 */ "reason ::= STRING",
11760+ /* 5 */ "reason ::= reason STRING",
11761+ /* 6 */ "headers ::= headers header",
11762+ /* 7 */ "headers ::= header",
11763+ /* 8 */ "header ::= STRING COLON STRING CRLF",
11764+};
11765+#endif /* NDEBUG */
11766+
11767+/*
11768+** This function returns the symbolic name associated with a token
11769+** value.
11770+*/
11771+const char *http_resp_parserTokenName(int tokenType){
11772+#ifndef NDEBUG
11773+ if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
11774+ return yyTokenName[tokenType];
11775+ }else{
11776+ return "Unknown";
11777+ }
11778+#else
11779+ return "";
11780+#endif
11781+}
11782+
11783+/*
11784+** This function allocates a new parser.
11785+** The only argument is a pointer to a function which works like
11786+** malloc.
11787+**
11788+** Inputs:
11789+** A pointer to the function used to allocate memory.
11790+**
11791+** Outputs:
11792+** A pointer to a parser. This pointer is used in subsequent calls
11793+** to http_resp_parser and http_resp_parserFree.
11794+*/
11795+void *http_resp_parserAlloc(void *(*mallocProc)(size_t)){
11796+ yyParser *pParser;
11797+ pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
11798+ if( pParser ){
11799+ pParser->yyidx = -1;
11800+ }
11801+ return pParser;
11802+}
11803+
11804+/* The following function deletes the value associated with a
11805+** symbol. The symbol can be either a terminal or nonterminal.
11806+** "yymajor" is the symbol code, and "yypminor" is a pointer to
11807+** the value.
11808+*/
11809+static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
11810+ switch( yymajor ){
11811+ /* Here is inserted the actions which take place when a
11812+ ** terminal or non-terminal is destroyed. This can happen
11813+ ** when the symbol is popped from the stack during a
11814+ ** reduce or during error processing or when a parser is
11815+ ** being destroyed before it is finished parsing.
11816+ **
11817+ ** Note: during a reduce, the only symbols destroyed are those
11818+ ** which appear on the RHS of the rule, but which are not used
11819+ ** inside the C code.
11820+ */
11821+ case 1:
11822+ case 2:
11823+ case 3:
11824+#line 23 "./http_resp_parser.y"
11825+{ buffer_free((yypminor->yy0)); }
11826+#line 326 "http_resp_parser.c"
11827+ break;
11828+ default: break; /* If no destructor action specified: do nothing */
11829+ }
11830+}
11831+
11832+/*
11833+** Pop the parser's stack once.
11834+**
11835+** If there is a destructor routine associated with the token which
11836+** is popped from the stack, then call it.
11837+**
11838+** Return the major token number for the symbol popped.
11839+*/
11840+static int yy_pop_parser_stack(yyParser *pParser){
11841+ YYCODETYPE yymajor;
11842+ yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
11843+
11844+ if( pParser->yyidx<0 ) return 0;
11845+#ifndef NDEBUG
11846+ if( yyTraceFILE && pParser->yyidx>=0 ){
11847+ fprintf(yyTraceFILE,"%sPopping %s\n",
11848+ yyTracePrompt,
11849+ yyTokenName[yytos->major]);
11850+ }
11851+#endif
11852+ yymajor = yytos->major;
11853+ yy_destructor( yymajor, &yytos->minor);
11854+ pParser->yyidx--;
11855+ return yymajor;
11856+}
11857+
11858+/*
11859+** Deallocate and destroy a parser. Destructors are all called for
11860+** all stack elements before shutting the parser down.
11861+**
11862+** Inputs:
11863+** <ul>
11864+** <li> A pointer to the parser. This should be a pointer
11865+** obtained from http_resp_parserAlloc.
11866+** <li> A pointer to a function used to reclaim memory obtained
11867+** from malloc.
11868+** </ul>
11869+*/
11870+void http_resp_parserFree(
11871+ void *p, /* The parser to be deleted */
11872+ void (*freeProc)(void*) /* Function used to reclaim memory */
11873+){
11874+ yyParser *pParser = (yyParser*)p;
11875+ if( pParser==0 ) return;
11876+ while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
11877+ (*freeProc)((void*)pParser);
11878+}
11879+
11880+/*
11881+** Find the appropriate action for a parser given the terminal
11882+** look-ahead token iLookAhead.
11883+**
11884+** If the look-ahead token is YYNOCODE, then check to see if the action is
11885+** independent of the look-ahead. If it is, return the action, otherwise
11886+** return YY_NO_ACTION.
11887+*/
11888+static int yy_find_shift_action(
11889+ yyParser *pParser, /* The parser */
11890+ int iLookAhead /* The look-ahead token */
11891+){
11892+ int i;
11893+ int stateno = pParser->yystack[pParser->yyidx].stateno;
11894+
11895+ /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
11896+ i = yy_shift_ofst[stateno];
11897+ if( i==YY_SHIFT_USE_DFLT ){
11898+ return yy_default[stateno];
11899+ }
11900+ if( iLookAhead==YYNOCODE ){
11901+ return YY_NO_ACTION;
11902+ }
11903+ i += iLookAhead;
11904+ if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
11905+#ifdef YYFALLBACK
11906+ int iFallback; /* Fallback token */
11907+ if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
11908+ && (iFallback = yyFallback[iLookAhead])!=0 ){
11909+#ifndef NDEBUG
11910+ if( yyTraceFILE ){
11911+ fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
11912+ yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
11913+ }
11914+#endif
11915+ return yy_find_shift_action(pParser, iFallback);
11916+ }
11917+#endif
11918+ return yy_default[stateno];
11919+ }else{
11920+ return yy_action[i];
11921+ }
11922+}
11923+
11924+/*
11925+** Find the appropriate action for a parser given the non-terminal
11926+** look-ahead token iLookAhead.
11927+**
11928+** If the look-ahead token is YYNOCODE, then check to see if the action is
11929+** independent of the look-ahead. If it is, return the action, otherwise
11930+** return YY_NO_ACTION.
11931+*/
11932+static int yy_find_reduce_action(
11933+ yyParser *pParser, /* The parser */
11934+ int iLookAhead /* The look-ahead token */
11935+){
11936+ int i;
11937+ int stateno = pParser->yystack[pParser->yyidx].stateno;
11938+
11939+ i = yy_reduce_ofst[stateno];
11940+ if( i==YY_REDUCE_USE_DFLT ){
11941+ return yy_default[stateno];
11942+ }
11943+ if( iLookAhead==YYNOCODE ){
11944+ return YY_NO_ACTION;
11945+ }
11946+ i += iLookAhead;
11947+ if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
11948+ return yy_default[stateno];
11949+ }else{
11950+ return yy_action[i];
11951+ }
11952+}
11953+
11954+/*
11955+** Perform a shift action.
11956+*/
11957+static void yy_shift(
11958+ yyParser *yypParser, /* The parser to be shifted */
11959+ int yyNewState, /* The new state to shift in */
11960+ int yyMajor, /* The major token to shift in */
11961+ YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */
11962+){
11963+ yyStackEntry *yytos;
11964+ yypParser->yyidx++;
11965+ if( yypParser->yyidx>=YYSTACKDEPTH ){
11966+ http_resp_parserARG_FETCH;
11967+ yypParser->yyidx--;
11968+#ifndef NDEBUG
11969+ if( yyTraceFILE ){
11970+ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
11971+ }
11972+#endif
11973+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
11974+ /* Here code is inserted which will execute if the parser
11975+ ** stack every overflows */
11976+ http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument var */
11977+ return;
11978+ }
11979+ yytos = &yypParser->yystack[yypParser->yyidx];
11980+ yytos->stateno = yyNewState;
11981+ yytos->major = yyMajor;
11982+ yytos->minor = *yypMinor;
11983+#ifndef NDEBUG
11984+ if( yyTraceFILE && yypParser->yyidx>0 ){
11985+ int i;
11986+ fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
11987+ fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
11988+ for(i=1; i<=yypParser->yyidx; i++)
11989+ fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
11990+ fprintf(yyTraceFILE,"\n");
11991+ }
11992+#endif
11993+}
11994+
11995+/* The following table contains information about every rule that
11996+** is used during the reduce.
11997+*/
11998+static struct {
11999+ YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
12000+ unsigned char nrhs; /* Number of right-hand side symbols in the rule */
12001+} yyRuleInfo[] = {
12002+ { 6, 2 },
12003+ { 6, 6 },
12004+ { 5, 1 },
12005+ { 7, 1 },
12006+ { 10, 1 },
12007+ { 10, 2 },
12008+ { 8, 2 },
12009+ { 8, 1 },
12010+ { 9, 4 },
12011+};
12012+
12013+static void yy_accept(yyParser*); /* Forward Declaration */
12014+
12015+/*
12016+** Perform a reduce action and the shift that must immediately
12017+** follow the reduce.
12018+*/
12019+static void yy_reduce(
12020+ yyParser *yypParser, /* The parser */
12021+ int yyruleno /* Number of the rule by which to reduce */
12022+){
12023+ int yygoto; /* The next state */
12024+ int yyact; /* The next action */
12025+ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
12026+ yyStackEntry *yymsp; /* The top of the parser's stack */
12027+ int yysize; /* Amount to pop the stack */
12028+ http_resp_parserARG_FETCH;
12029+ yymsp = &yypParser->yystack[yypParser->yyidx];
12030+#ifndef NDEBUG
12031+ if( yyTraceFILE && yyruleno>=0
12032+ && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
12033+ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
12034+ yyRuleName[yyruleno]);
12035+ }
12036+#endif /* NDEBUG */
12037+
12038+ switch( yyruleno ){
12039+ /* Beginning here are the reduction cases. A typical example
12040+ ** follows:
12041+ ** case 0:
12042+ ** #line <lineno> <grammarfile>
12043+ ** { ... } // User supplied code
12044+ ** #line <lineno> <thisfile>
12045+ ** break;
12046+ */
12047+ case 0:
12048+#line 26 "./http_resp_parser.y"
12049+{
12050+ http_resp *resp = ctx->resp;
12051+ data_string *ds;
12052+
12053+ resp->protocol = HTTP_VERSION_UNSET;
12054+
12055+ buffer_copy_string(resp->reason, ""); /* no reason */
12056+ array_free(resp->headers);
12057+ resp->headers = yymsp[-1].minor.yy12;
12058+
12059+ if (NULL == (ds = (data_string *)array_get_element(yymsp[-1].minor.yy12, "Status"))) {
12060+ resp->status = 0;
12061+ } else {
12062+ char *err;
12063+ resp->status = strtol(ds->value->ptr, &err, 10);
1175ccec
ER
12064+
12065+ if (*err != '\0' && *err != ' ') {
2519e6e5
ER
12066+ buffer_copy_string(ctx->errmsg, "expected a number: ");
12067+ buffer_append_string_buffer(ctx->errmsg, ds->value);
1175ccec 12068+ buffer_append_string(ctx->errmsg, err);
2519e6e5
ER
12069+
12070+ ctx->ok = 0;
12071+ }
2519e6e5
ER
12072+ }
12073+
12074+ yymsp[-1].minor.yy12 = NULL;
12075+}
12076+#line 576 "http_resp_parser.c"
12077+ yy_destructor(1,&yymsp[0].minor);
12078+ break;
12079+ case 1:
12080+#line 54 "./http_resp_parser.y"
12081+{
12082+ http_resp *resp = ctx->resp;
12083+
12084+ resp->status = yymsp[-4].minor.yy20;
12085+ resp->protocol = yymsp[-5].minor.yy20;
12086+ buffer_copy_string_buffer(resp->reason, yymsp[-3].minor.yy0);
12087+
12088+ array_free(resp->headers);
12089+
12090+ resp->headers = yymsp[-1].minor.yy12;
12091+
12092+ yymsp[-1].minor.yy12 = NULL;
12093+}
12094+#line 594 "http_resp_parser.c"
12095+ yy_destructor(1,&yymsp[-2].minor);
12096+ yy_destructor(1,&yymsp[0].minor);
12097+ break;
12098+ case 2:
12099+#line 68 "./http_resp_parser.y"
12100+{
12101+ if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.0"))) {
12102+ yygotominor.yy20 = HTTP_VERSION_1_0;
12103+ } else if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.1"))) {
12104+ yygotominor.yy20 = HTTP_VERSION_1_1;
12105+ } else {
12106+ buffer_copy_string(ctx->errmsg, "unknown protocol: ");
12107+ buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12108+
12109+ ctx->ok = 0;
12110+ }
12111+}
12112+#line 612 "http_resp_parser.c"
12113+ break;
12114+ case 3:
12115+#line 81 "./http_resp_parser.y"
12116+{
12117+ char *err;
12118+ yygotominor.yy20 = strtol(yymsp[0].minor.yy0->ptr, &err, 10);
12119+
12120+ if (*err != '\0') {
12121+ buffer_copy_string(ctx->errmsg, "expected a number: ");
12122+ buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12123+
12124+ ctx->ok = 0;
12125+ }
12126+}
12127+#line 627 "http_resp_parser.c"
12128+ break;
12129+ case 4:
12130+#line 93 "./http_resp_parser.y"
12131+{
1175ccec
ER
12132+ yygotominor.yy0 = yymsp[0].minor.yy0;
12133+ yymsp[0].minor.yy0 = NULL;
2519e6e5 12134+}
1175ccec 12135+#line 635 "http_resp_parser.c"
2519e6e5
ER
12136+ break;
12137+ case 5:
1175ccec 12138+#line 98 "./http_resp_parser.y"
2519e6e5
ER
12139+{
12140+ yygotominor.yy0 = yymsp[-1].minor.yy0;
12141+
12142+ buffer_append_string(yygotominor.yy0, " ");
12143+ buffer_append_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12144+
12145+ yymsp[-1].minor.yy0 = NULL;
12146+}
1175ccec 12147+#line 647 "http_resp_parser.c"
2519e6e5
ER
12148+ break;
12149+ case 6:
1175ccec 12150+#line 107 "./http_resp_parser.y"
2519e6e5
ER
12151+{
12152+ yygotominor.yy12 = yymsp[-1].minor.yy12;
12153+
12154+ array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12155+
12156+ yymsp[-1].minor.yy12 = NULL;
12157+}
1175ccec 12158+#line 658 "http_resp_parser.c"
2519e6e5
ER
12159+ break;
12160+ case 7:
1175ccec 12161+#line 115 "./http_resp_parser.y"
2519e6e5
ER
12162+{
12163+ yygotominor.yy12 = array_init();
12164+
12165+ array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12166+}
1175ccec 12167+#line 667 "http_resp_parser.c"
2519e6e5
ER
12168+ break;
12169+ case 8:
1175ccec 12170+#line 120 "./http_resp_parser.y"
2519e6e5
ER
12171+{
12172+ yygotominor.yy9 = data_string_init();
12173+
12174+ buffer_copy_string_buffer(yygotominor.yy9->key, yymsp[-3].minor.yy0);
12175+ buffer_copy_string_buffer(yygotominor.yy9->value, yymsp[-1].minor.yy0);
12176+}
1175ccec 12177+#line 677 "http_resp_parser.c"
2519e6e5
ER
12178+ yy_destructor(3,&yymsp[-2].minor);
12179+ yy_destructor(1,&yymsp[0].minor);
12180+ break;
12181+ };
12182+ yygoto = yyRuleInfo[yyruleno].lhs;
12183+ yysize = yyRuleInfo[yyruleno].nrhs;
12184+ yypParser->yyidx -= yysize;
12185+ yyact = yy_find_reduce_action(yypParser,yygoto);
12186+ if( yyact < YYNSTATE ){
12187+ yy_shift(yypParser,yyact,yygoto,&yygotominor);
12188+ }else if( yyact == YYNSTATE + YYNRULE + 1 ){
12189+ yy_accept(yypParser);
12190+ }
12191+}
12192+
12193+/*
12194+** The following code executes when the parse fails
12195+*/
12196+static void yy_parse_failed(
12197+ yyParser *yypParser /* The parser */
12198+){
12199+ http_resp_parserARG_FETCH;
12200+#ifndef NDEBUG
12201+ if( yyTraceFILE ){
12202+ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
12203+ }
12204+#endif
12205+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12206+ /* Here code is inserted which will be executed whenever the
12207+ ** parser fails */
12208+#line 14 "./http_resp_parser.y"
12209+
12210+ ctx->ok = 0;
12211+
1175ccec 12212+#line 712 "http_resp_parser.c"
2519e6e5
ER
12213+ http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12214+}
12215+
12216+/*
12217+** The following code executes when a syntax error first occurs.
12218+*/
12219+static void yy_syntax_error(
12220+ yyParser *yypParser, /* The parser */
12221+ int yymajor, /* The major type of the error token */
12222+ YYMINORTYPE yyminor /* The minor type of the error token */
12223+){
12224+ http_resp_parserARG_FETCH;
12225+#define TOKEN (yyminor.yy0)
12226+ http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12227+}
12228+
12229+/*
12230+** The following is executed when the parser accepts
12231+*/
12232+static void yy_accept(
12233+ yyParser *yypParser /* The parser */
12234+){
12235+ http_resp_parserARG_FETCH;
12236+#ifndef NDEBUG
12237+ if( yyTraceFILE ){
12238+ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
12239+ }
12240+#endif
12241+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12242+ /* Here code is inserted which will be executed whenever the
12243+ ** parser accepts */
12244+ http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12245+}
12246+
12247+/* The main parser program.
12248+** The first argument is a pointer to a structure obtained from
12249+** "http_resp_parserAlloc" which describes the current state of the parser.
12250+** The second argument is the major token number. The third is
12251+** the minor token. The fourth optional argument is whatever the
12252+** user wants (and specified in the grammar) and is available for
12253+** use by the action routines.
12254+**
12255+** Inputs:
12256+** <ul>
12257+** <li> A pointer to the parser (an opaque structure.)
12258+** <li> The major token number.
12259+** <li> The minor token number.
12260+** <li> An option argument of a grammar-specified type.
12261+** </ul>
12262+**
12263+** Outputs:
12264+** None.
12265+*/
12266+void http_resp_parser(
12267+ void *yyp, /* The parser */
12268+ int yymajor, /* The major token code number */
12269+ http_resp_parserTOKENTYPE yyminor /* The value for the token */
12270+ http_resp_parserARG_PDECL /* Optional %extra_argument parameter */
12271+){
12272+ YYMINORTYPE yyminorunion;
12273+ int yyact; /* The parser action. */
12274+ int yyendofinput; /* True if we are at the end of input */
12275+ int yyerrorhit = 0; /* True if yymajor has invoked an error */
12276+ yyParser *yypParser; /* The parser */
12277+
12278+ /* (re)initialize the parser, if necessary */
12279+ yypParser = (yyParser*)yyp;
12280+ if( yypParser->yyidx<0 ){
12281+ if( yymajor==0 ) return;
12282+ yypParser->yyidx = 0;
12283+ yypParser->yyerrcnt = -1;
12284+ yypParser->yystack[0].stateno = 0;
12285+ yypParser->yystack[0].major = 0;
12286+ }
12287+ yyminorunion.yy0 = yyminor;
12288+ yyendofinput = (yymajor==0);
12289+ http_resp_parserARG_STORE;
12290+
12291+#ifndef NDEBUG
12292+ if( yyTraceFILE ){
12293+ fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
12294+ }
12295+#endif
12296+
12297+ do{
12298+ yyact = yy_find_shift_action(yypParser,yymajor);
12299+ if( yyact<YYNSTATE ){
12300+ yy_shift(yypParser,yyact,yymajor,&yyminorunion);
12301+ yypParser->yyerrcnt--;
12302+ if( yyendofinput && yypParser->yyidx>=0 ){
12303+ yymajor = 0;
12304+ }else{
12305+ yymajor = YYNOCODE;
12306+ }
12307+ }else if( yyact < YYNSTATE + YYNRULE ){
12308+ yy_reduce(yypParser,yyact-YYNSTATE);
12309+ }else if( yyact == YY_ERROR_ACTION ){
12310+ int yymx;
12311+#ifndef NDEBUG
12312+ if( yyTraceFILE ){
12313+ fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
12314+ }
12315+#endif
12316+#ifdef YYERRORSYMBOL
12317+ /* A syntax error has occurred.
12318+ ** The response to an error depends upon whether or not the
12319+ ** grammar defines an error token "ERROR".
12320+ **
12321+ ** This is what we do if the grammar does define ERROR:
12322+ **
12323+ ** * Call the %syntax_error function.
12324+ **
12325+ ** * Begin popping the stack until we enter a state where
12326+ ** it is legal to shift the error symbol, then shift
12327+ ** the error symbol.
12328+ **
12329+ ** * Set the error count to three.
12330+ **
12331+ ** * Begin accepting and shifting new tokens. No new error
12332+ ** processing will occur until three tokens have been
12333+ ** shifted successfully.
12334+ **
12335+ */
12336+ if( yypParser->yyerrcnt<0 ){
12337+ yy_syntax_error(yypParser,yymajor,yyminorunion);
12338+ }
12339+ yymx = yypParser->yystack[yypParser->yyidx].major;
12340+ if( yymx==YYERRORSYMBOL || yyerrorhit ){
12341+#ifndef NDEBUG
12342+ if( yyTraceFILE ){
12343+ fprintf(yyTraceFILE,"%sDiscard input token %s\n",
12344+ yyTracePrompt,yyTokenName[yymajor]);
12345+ }
12346+#endif
12347+ yy_destructor(yymajor,&yyminorunion);
12348+ yymajor = YYNOCODE;
12349+ }else{
12350+ while(
12351+ yypParser->yyidx >= 0 &&
12352+ yymx != YYERRORSYMBOL &&
12353+ (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
12354+ ){
12355+ yy_pop_parser_stack(yypParser);
12356+ }
12357+ if( yypParser->yyidx < 0 || yymajor==0 ){
12358+ yy_destructor(yymajor,&yyminorunion);
12359+ yy_parse_failed(yypParser);
12360+ yymajor = YYNOCODE;
12361+ }else if( yymx!=YYERRORSYMBOL ){
12362+ YYMINORTYPE u2;
12363+ u2.YYERRSYMDT = 0;
12364+ yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
12365+ }
12366+ }
12367+ yypParser->yyerrcnt = 3;
12368+ yyerrorhit = 1;
12369+#else /* YYERRORSYMBOL is not defined */
12370+ /* This is what we do if the grammar does not define ERROR:
12371+ **
12372+ ** * Report an error message, and throw away the input token.
12373+ **
12374+ ** * If the input token is $, then fail the parse.
12375+ **
12376+ ** As before, subsequent error messages are suppressed until
12377+ ** three input tokens have been successfully shifted.
12378+ */
12379+ if( yypParser->yyerrcnt<=0 ){
12380+ yy_syntax_error(yypParser,yymajor,yyminorunion);
12381+ }
12382+ yypParser->yyerrcnt = 3;
12383+ yy_destructor(yymajor,&yyminorunion);
12384+ if( yyendofinput ){
12385+ yy_parse_failed(yypParser);
12386+ }
12387+ yymajor = YYNOCODE;
12388+#endif
12389+ }else{
12390+ yy_accept(yypParser);
12391+ yymajor = YYNOCODE;
12392+ }
12393+ }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
12394+ return;
12395+}
1175ccec 12396--- ../lighttpd-1.4.11/src/inet_ntop_cache.c 2005-08-11 01:26:38.000000000 +0300
36e2a29e 12397+++ lighttpd-1.4.12/src/inet_ntop_cache.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
12398@@ -8,7 +8,7 @@
12399 #include "sys-socket.h"
12400
12401 const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
12402-#ifdef HAVE_IPV6
12403+#ifdef HAVE_IPV6
12404 size_t ndx = 0, i;
12405 for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
12406 if (srv->inet_ntop_cache[i].ts != 0) {
12407@@ -20,31 +20,31 @@
12408 srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
12409 /* IPv4 found in cache */
12410 break;
12411-
12412+
12413 }
12414 }
12415 }
12416-
12417+
12418 if (i == INET_NTOP_CACHE_MAX) {
12419 /* not found in cache */
12420-
12421+
12422 i = ndx;
12423- inet_ntop(addr->plain.sa_family,
12424- addr->plain.sa_family == AF_INET6 ?
12425+ inet_ntop(addr->plain.sa_family,
12426+ addr->plain.sa_family == AF_INET6 ?
12427 (const void *) &(addr->ipv6.sin6_addr) :
12428 (const void *) &(addr->ipv4.sin_addr),
12429 srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
12430-
12431+
12432 srv->inet_ntop_cache[i].ts = srv->cur_ts;
12433 srv->inet_ntop_cache[i].family = addr->plain.sa_family;
12434-
12435+
12436 if (srv->inet_ntop_cache[i].family == AF_INET) {
12437 srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
12438 } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
12439 memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
12440 }
12441 }
12442-
12443+
12444 return srv->inet_ntop_cache[i].b2;
12445 #else
12446 UNUSED(srv);
1175ccec 12447--- ../lighttpd-1.4.11/src/joblist.c 2005-08-11 01:26:41.000000000 +0300
36e2a29e 12448+++ lighttpd-1.4.12/src/joblist.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
12449@@ -7,7 +7,7 @@
12450
12451 int joblist_append(server *srv, connection *con) {
12452 if (con->in_joblist) return 0;
12453-
12454+
12455 if (srv->joblist->size == 0) {
12456 srv->joblist->size = 16;
12457 srv->joblist->ptr = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
12458@@ -15,15 +15,15 @@
12459 srv->joblist->size += 16;
12460 srv->joblist->ptr = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
12461 }
12462-
12463+
12464 srv->joblist->ptr[srv->joblist->used++] = con;
12465-
12466+
12467 return 0;
12468 }
12469
12470 void joblist_free(server *srv, connections *joblist) {
12471 UNUSED(srv);
12472-
12473+
12474 free(joblist->ptr);
12475 free(joblist);
12476 }
12477@@ -31,14 +31,14 @@
12478 connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
12479 connection *con;
12480 UNUSED(srv);
12481-
12482-
12483+
12484+
12485 if (fdwaitqueue->used == 0) return NULL;
12486-
12487+
12488 con = fdwaitqueue->ptr[0];
12489-
12490+
12491 memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
12492-
12493+
12494 return con;
12495 }
12496
12497@@ -50,9 +50,9 @@
12498 srv->fdwaitqueue->size += 16;
12499 srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
12500 }
12501-
12502+
12503 srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
12504-
12505+
12506 return 0;
12507 }
12508
1175ccec 12509--- ../lighttpd-1.4.11/src/keyvalue.c 2006-03-02 16:08:06.000000000 +0200
36e2a29e 12510+++ lighttpd-1.4.12/src/keyvalue.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
12511@@ -87,7 +87,8 @@
12512 { 504, "Gateway Timeout" },
12513 { 505, "HTTP Version Not Supported" },
12514 { 507, "Insufficient Storage" }, /* WebDAV */
12515-
12516+ { 509, "Bandwidth Limit exceeded" },
12517+
12518 { -1, NULL }
12519 };
12520
12521@@ -102,12 +103,12 @@
12522 { 501, "501.html" },
12523 { 503, "503.html" },
12524 { 505, "505.html" },
12525-
12526+
12527 { -1, NULL }
12528 };
12529
12530
12531-const char *keyvalue_get_value(keyvalue *kv, int k) {
12532+const char *keyvalue_get_value(keyvalue *kv, int k) {
12533 int i;
12534 for (i = 0; kv[i].value; i++) {
12535 if (kv[i].key == k) return kv[i].value;
12536@@ -115,7 +116,7 @@
12537 return NULL;
12538 }
12539
12540-int keyvalue_get_key(keyvalue *kv, const char *s) {
12541+int keyvalue_get_key(keyvalue *kv, const char *s) {
12542 int i;
12543 for (i = 0; kv[i].value; i++) {
12544 if (0 == strcmp(kv[i].value, s)) return kv[i].key;
12545@@ -125,9 +126,9 @@
12546
12547 keyvalue_buffer *keyvalue_buffer_init(void) {
12548 keyvalue_buffer *kvb;
12549-
12550+
12551 kvb = calloc(1, sizeof(*kvb));
12552-
12553+
12554 return kvb;
12555 }
12556
12557@@ -135,49 +136,49 @@
12558 size_t i;
12559 if (kvb->size == 0) {
12560 kvb->size = 4;
12561-
12562+
12563 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12564-
12565+
12566 for(i = 0; i < kvb->size; i++) {
12567 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12568 }
12569 } else if (kvb->used == kvb->size) {
12570 kvb->size += 4;
12571-
12572+
12573 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12574-
12575+
12576 for(i = kvb->used; i < kvb->size; i++) {
12577 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12578 }
12579 }
12580-
12581+
12582 kvb->kv[kvb->used]->key = key;
12583 kvb->kv[kvb->used]->value = strdup(value);
12584-
12585+
12586 kvb->used++;
12587-
12588+
12589 return 0;
12590 }
12591
12592 void keyvalue_buffer_free(keyvalue_buffer *kvb) {
12593 size_t i;
12594-
12595+
12596 for (i = 0; i < kvb->size; i++) {
12597 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12598 free(kvb->kv[i]);
12599 }
12600-
12601+
12602 if (kvb->kv) free(kvb->kv);
12603-
12604+
12605 free(kvb);
12606 }
12607
12608
12609 s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
12610 s_keyvalue_buffer *kvb;
12611-
12612+
12613 kvb = calloc(1, sizeof(*kvb));
12614-
12615+
12616 return kvb;
12617 }
12618
12619@@ -186,50 +187,50 @@
12620 if (kvb->size == 0) {
12621 kvb->size = 4;
12622 kvb->used = 0;
12623-
12624+
12625 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12626-
12627+
12628 for(i = 0; i < kvb->size; i++) {
12629 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12630 }
12631 } else if (kvb->used == kvb->size) {
12632 kvb->size += 4;
12633-
12634+
12635 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12636-
12637+
12638 for(i = kvb->used; i < kvb->size; i++) {
12639 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12640 }
12641 }
12642-
12643+
12644 kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
12645 kvb->kv[kvb->used]->value = strdup(value);
12646-
12647+
12648 kvb->used++;
12649-
12650+
12651 return 0;
12652 }
12653
12654 void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
12655 size_t i;
12656-
12657+
12658 for (i = 0; i < kvb->size; i++) {
12659 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12660 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12661 free(kvb->kv[i]);
12662 }
12663-
12664+
12665 if (kvb->kv) free(kvb->kv);
12666-
12667+
12668 free(kvb);
12669 }
12670
12671
12672 httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
12673 httpauth_keyvalue_buffer *kvb;
12674-
12675+
12676 kvb = calloc(1, sizeof(*kvb));
12677-
12678+
12679 return kvb;
12680 }
12681
12682@@ -237,42 +238,42 @@
12683 size_t i;
12684 if (kvb->size == 0) {
12685 kvb->size = 4;
12686-
12687+
12688 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12689-
12690+
12691 for(i = 0; i < kvb->size; i++) {
12692 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12693 }
12694 } else if (kvb->used == kvb->size) {
12695 kvb->size += 4;
12696-
12697+
12698 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12699-
12700+
12701 for(i = kvb->used; i < kvb->size; i++) {
12702 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12703 }
12704 }
12705-
12706+
12707 kvb->kv[kvb->used]->key = strdup(key);
12708 kvb->kv[kvb->used]->realm = strdup(realm);
12709 kvb->kv[kvb->used]->type = type;
12710-
12711+
12712 kvb->used++;
12713-
12714+
12715 return 0;
12716 }
12717
12718 void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
12719 size_t i;
12720-
12721+
12722 for (i = 0; i < kvb->size; i++) {
12723 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12724 if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
12725 free(kvb->kv[i]);
12726 }
12727-
12728+
12729 if (kvb->kv) free(kvb->kv);
12730-
12731+
12732 free(kvb);
12733 }
12734
12735@@ -306,9 +307,9 @@
12736
12737 pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
12738 pcre_keyvalue_buffer *kvb;
12739-
12740+
12741 kvb = calloc(1, sizeof(*kvb));
12742-
12743+
12744 return kvb;
12745 }
12746
12747@@ -319,46 +320,46 @@
12748 int erroff;
12749 pcre_keyvalue *kv;
12750 #endif
12751-
12752+
12753 if (!key) return -1;
12754
12755 #ifdef HAVE_PCRE_H
12756 if (kvb->size == 0) {
12757 kvb->size = 4;
12758 kvb->used = 0;
12759-
12760+
12761 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12762-
12763+
12764 for(i = 0; i < kvb->size; i++) {
12765 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12766 }
12767 } else if (kvb->used == kvb->size) {
12768 kvb->size += 4;
12769-
12770+
12771 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12772-
12773+
12774 for(i = kvb->used; i < kvb->size; i++) {
12775 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12776 }
12777 }
12778-
12779+
12780 kv = kvb->kv[kvb->used];
12781 if (NULL == (kv->key = pcre_compile(key,
12782 0, &errptr, &erroff, NULL))) {
12783-
12784+
12785 fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
12786 return -1;
12787 }
12788
12789- if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
12790+ if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
12791 errptr != NULL) {
12792 return -1;
12793 }
12794-
12795+
12796 kv->value = buffer_init_string(value);
12797-
12798+
12799 kvb->used++;
12800-
12801+
12802 return 0;
12803 #else
12804 UNUSED(kvb);
12805@@ -380,9 +381,9 @@
12806 if (kv->value) buffer_free(kv->value);
12807 free(kv);
12808 }
12809-
12810+
12811 if (kvb->kv) free(kvb->kv);
12812 #endif
12813-
12814+
12815 free(kvb);
12816 }
1175ccec 12817--- ../lighttpd-1.4.11/src/keyvalue.h 2006-03-02 16:08:06.000000000 +0200
36e2a29e 12818+++ lighttpd-1.4.12/src/keyvalue.h 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
12819@@ -9,19 +9,19 @@
12820 # include <pcre.h>
12821 #endif
12822
12823-typedef enum {
12824- HTTP_METHOD_UNSET = -1,
12825- HTTP_METHOD_GET,
12826- HTTP_METHOD_POST,
12827- HTTP_METHOD_HEAD,
12828- HTTP_METHOD_OPTIONS,
12829+typedef enum {
12830+ HTTP_METHOD_UNSET = -1,
12831+ HTTP_METHOD_GET,
12832+ HTTP_METHOD_POST,
12833+ HTTP_METHOD_HEAD,
12834+ HTTP_METHOD_OPTIONS,
12835 HTTP_METHOD_PROPFIND, /* WebDAV */
12836- HTTP_METHOD_MKCOL,
12837- HTTP_METHOD_PUT,
12838- HTTP_METHOD_DELETE,
12839- HTTP_METHOD_COPY,
12840- HTTP_METHOD_MOVE,
12841- HTTP_METHOD_PROPPATCH,
12842+ HTTP_METHOD_MKCOL,
12843+ HTTP_METHOD_PUT,
12844+ HTTP_METHOD_DELETE,
12845+ HTTP_METHOD_COPY,
12846+ HTTP_METHOD_MOVE,
12847+ HTTP_METHOD_PROPPATCH,
12848 HTTP_METHOD_REPORT, /* DeltaV */
12849 HTTP_METHOD_CHECKOUT,
12850 HTTP_METHOD_CHECKIN,
12851@@ -39,13 +39,13 @@
12852
12853 typedef struct {
12854 int key;
12855-
12856+
12857 char *value;
12858 } keyvalue;
12859
12860 typedef struct {
12861 char *key;
12862-
12863+
12864 char *value;
12865 } s_keyvalue;
12866
12867@@ -54,7 +54,7 @@
12868 pcre *key;
12869 pcre_extra *key_extra;
12870 #endif
12871-
12872+
12873 buffer *value;
12874 } pcre_keyvalue;
12875
12876@@ -62,7 +62,7 @@
12877
12878 typedef struct {
12879 char *key;
12880-
12881+
12882 char *realm;
12883 httpauth_type type;
12884 } httpauth_keyvalue;
1175ccec 12885--- ../lighttpd-1.4.11/src/lemon.c 2005-09-01 00:21:34.000000000 +0300
36e2a29e 12886+++ lighttpd-1.4.12/src/lemon.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
12887@@ -579,7 +579,7 @@
12888 */
12889
12890 /* Find a precedence symbol of every rule in the grammar.
12891-**
12892+**
12893 ** Those rules which have a precedence symbol coded in the input
12894 ** grammar using the "[symbol]" construct will already have the
12895 ** rp->precsym field filled. Other rules take as their precedence
12896@@ -869,7 +869,7 @@
12897 cfp->status = INCOMPLETE;
12898 }
12899 }
12900-
12901+
12902 do{
12903 progress = 0;
12904 for(i=0; i<lemp->nstate; i++){
12905@@ -900,7 +900,7 @@
12906 struct symbol *sp;
12907 struct rule *rp;
12908
12909- /* Add all of the reduce actions
12910+ /* Add all of the reduce actions
12911 ** A reduce action is added for each element of the followset of
12912 ** a configuration which has its dot at the extreme right.
12913 */
12914@@ -1017,7 +1017,7 @@
12915 apx->type = RD_RESOLVED;
12916 }
12917 }else{
12918- assert(
12919+ assert(
12920 apx->type==SH_RESOLVED ||
12921 apx->type==RD_RESOLVED ||
12922 apx->type==CONFLICT ||
12923@@ -1350,7 +1350,7 @@
12924 OptInit(argv,options,stderr);
12925 if( version ){
12926 printf("Lemon version 1.0\n");
12927- exit(0);
12928+ exit(0);
12929 }
12930 if( OptNArgs() < 1 ){
12931 fprintf(stderr,"Exactly one filename argument is required.\n");
12932@@ -2031,7 +2031,7 @@
12933 case IN_RHS:
12934 if( x[0]=='.' ){
12935 struct rule *rp;
12936- rp = (struct rule *)malloc( sizeof(struct rule) +
12937+ rp = (struct rule *)malloc( sizeof(struct rule) +
12938 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
12939 if( rp==0 ){
12940 ErrorMsg(psp->filename,psp->tokenlineno,
12941@@ -2546,7 +2546,7 @@
12942 return fp;
12943 }
12944
12945-/* Duplicate the input file without comments and without actions
12946+/* Duplicate the input file without comments and without actions
12947 ** on rules */
12948 void Reprint(lemp)
12949 struct lemon *lemp;
12950@@ -2822,7 +2822,7 @@
12951 PRIVATE FILE *tplt_open(lemp)
12952 struct lemon *lemp;
12953 {
12954-
12955+
12956 char buf[1000];
12957 FILE *in;
12958 char *tpltname;
12959@@ -2930,7 +2930,7 @@
12960 return ret;
12961 }
12962
12963-/*
12964+/*
12965 ** Generate code which executes when the rule "rp" is reduced. Write
12966 ** the code to "out". Make sure lineno stays up-to-date.
12967 */
12968@@ -3384,7 +3384,7 @@
12969
12970 /* Output the yy_shift_ofst[] table */
12971 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
12972- fprintf(out, "static %s yy_shift_ofst[] = {\n",
12973+ fprintf(out, "static %s yy_shift_ofst[] = {\n",
12974 minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
12975 n = lemp->nstate;
12976 for(i=j=0; i<n; i++){
12977@@ -3405,7 +3405,7 @@
12978
12979 /* Output the yy_reduce_ofst[] table */
12980 fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
12981- fprintf(out, "static %s yy_reduce_ofst[] = {\n",
12982+ fprintf(out, "static %s yy_reduce_ofst[] = {\n",
12983 minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
12984 n = lemp->nstate;
12985 for(i=j=0; i<n; i++){
12986@@ -3480,7 +3480,7 @@
12987 tplt_xfer(lemp->name,in,out,&lineno);
12988
12989 /* Generate code which executes every time a symbol is popped from
12990- ** the stack while processing errors or while destroying the parser.
12991+ ** the stack while processing errors or while destroying the parser.
12992 ** (In other words, generate the %destructor actions)
12993 */
12994 if( lemp->tokendest ){
12995@@ -3522,7 +3522,7 @@
12996 tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
12997 tplt_xfer(lemp->name,in,out,&lineno);
12998
12999- /* Generate the table of rule information
13000+ /* Generate the table of rule information
13001 **
13002 ** Note: This code depends on the fact that rules are number
13003 ** sequentually beginning with 0.
13004@@ -3589,7 +3589,7 @@
13005 for(i=1; i<lemp->nterminal; i++){
13006 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
13007 }
13008- fclose(out);
13009+ fclose(out);
13010 }
13011 return;
13012 }
13013@@ -3630,7 +3630,7 @@
13014 rbest = rp;
13015 }
13016 }
13017-
13018+
13019 /* Do not make a default if the number of rules to default
13020 ** is not at least 2 */
13021 if( nbest<2 ) continue;
13022@@ -3781,7 +3781,7 @@
13023 if( x1a ){
13024 x1a->size = 1024;
13025 x1a->count = 0;
13026- x1a->tbl = (x1node*)malloc(
13027+ x1a->tbl = (x1node*)malloc(
13028 (sizeof(x1node) + sizeof(x1node*))*1024 );
13029 if( x1a->tbl==0 ){
13030 free(x1a);
13031@@ -3943,7 +3943,7 @@
13032 if( x2a ){
13033 x2a->size = 128;
13034 x2a->count = 0;
13035- x2a->tbl = (x2node*)malloc(
13036+ x2a->tbl = (x2node*)malloc(
13037 (sizeof(x2node) + sizeof(x2node*))*128 );
13038 if( x2a->tbl==0 ){
13039 free(x2a);
13040@@ -4149,7 +4149,7 @@
13041 if( x3a ){
13042 x3a->size = 128;
13043 x3a->count = 0;
13044- x3a->tbl = (x3node*)malloc(
13045+ x3a->tbl = (x3node*)malloc(
13046 (sizeof(x3node) + sizeof(x3node*))*128 );
13047 if( x3a->tbl==0 ){
13048 free(x3a);
13049@@ -4295,7 +4295,7 @@
13050 if( x4a ){
13051 x4a->size = 64;
13052 x4a->count = 0;
13053- x4a->tbl = (x4node*)malloc(
13054+ x4a->tbl = (x4node*)malloc(
13055 (sizeof(x4node) + sizeof(x4node*))*64 );
13056 if( x4a->tbl==0 ){
13057 free(x4a);
1175ccec 13058--- ../lighttpd-1.4.11/src/lempar.c 2005-08-11 01:26:40.000000000 +0300
36e2a29e 13059+++ lighttpd-1.4.12/src/lempar.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
13060@@ -8,10 +8,10 @@
13061 /* Next is all token values, in a form suitable for use by makeheaders.
13062 ** This section will be null unless lemon is run with the -m switch.
13063 */
13064-/*
13065+/*
13066 ** These constants (all generated automatically by the parser generator)
13067 ** specify the various kinds of tokens (terminals) that the parser
13068-** understands.
13069+** understands.
13070 **
13071 ** Each symbol here is a terminal symbol in the grammar.
13072 */
13073@@ -29,7 +29,7 @@
13074 ** and nonterminals. "int" is used otherwise.
13075 ** YYNOCODE is a number of type YYCODETYPE which corresponds
13076 ** to no legal terminal or nonterminal number. This
13077-** number is used to fill in empty slots of the hash
13078+** number is used to fill in empty slots of the hash
13079 ** table.
13080 ** YYFALLBACK If defined, this indicates that one or more tokens
13081 ** have fall-back values which should be used if the
13082@@ -38,7 +38,7 @@
13083 ** and nonterminal numbers. "unsigned char" is
13084 ** used if there are fewer than 250 rules and
13085 ** states combined. "int" is used otherwise.
13086-** ParseTOKENTYPE is the data type used for minor tokens given
13087+** ParseTOKENTYPE is the data type used for minor tokens given
13088 ** directly to the parser from the tokenizer.
13089 ** YYMINORTYPE is the data type used for all minor tokens.
13090 ** This is typically a union of many types, one of
13091@@ -62,7 +62,7 @@
13092 /* Next are that tables used to determine what action to take based on the
13093 ** current state and lookahead token. These tables are used to implement
13094 ** functions that take a state number and lookahead value and return an
13095-** action integer.
13096+** action integer.
13097 **
13098 ** Suppose the action integer is N. Then the action is determined as
13099 ** follows
13100@@ -87,7 +87,7 @@
13101 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
13102 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
13103 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
13104-** and that yy_default[S] should be used instead.
13105+** and that yy_default[S] should be used instead.
13106 **
13107 ** The formula above is for computing the action when the lookahead is
13108 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
13109@@ -111,7 +111,7 @@
13110
13111 /* The next table maps tokens into fallback tokens. If a construct
13112 ** like the following:
13113-**
13114+**
13115 ** %fallback ID X Y Z.
13116 **
13117 ** appears in the grammer, then ID becomes a fallback token for X, Y,
13118@@ -163,10 +163,10 @@
13119 #endif /* NDEBUG */
13120
13121 #ifndef NDEBUG
13122-/*
13123+/*
13124 ** Turn parser tracing on by giving a stream to which to write the trace
13125 ** and a prompt to preface each trace message. Tracing is turned off
13126-** by making either argument NULL
13127+** by making either argument NULL
13128 **
13129 ** Inputs:
13130 ** <ul>
13131@@ -191,7 +191,7 @@
13132 #ifndef NDEBUG
13133 /* For tracing shifts, the names of all terminals and nonterminals
13134 ** are required. The following table supplies these names */
13135-static const char *yyTokenName[] = {
13136+static const char *yyTokenName[] = {
13137 %%
13138 };
13139 #endif /* NDEBUG */
13140@@ -220,7 +220,7 @@
13141 #endif
13142 }
13143
13144-/*
13145+/*
13146 ** This function allocates a new parser.
13147 ** The only argument is a pointer to a function which works like
13148 ** malloc.
13149@@ -251,7 +251,7 @@
13150 /* Here is inserted the actions which take place when a
13151 ** terminal or non-terminal is destroyed. This can happen
13152 ** when the symbol is popped from the stack during a
13153- ** reduce or during error processing or when a parser is
13154+ ** reduce or during error processing or when a parser is
13155 ** being destroyed before it is finished parsing.
13156 **
13157 ** Note: during a reduce, the only symbols destroyed are those
13158@@ -289,7 +289,7 @@
13159 return yymajor;
13160 }
13161
13162-/*
13163+/*
13164 ** Deallocate and destroy a parser. Destructors are all called for
13165 ** all stack elements before shutting the parser down.
13166 **
13167@@ -325,7 +325,7 @@
13168 ){
13169 int i;
13170 int stateno = pParser->yystack[pParser->yyidx].stateno;
13171-
13172+
13173 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
13174 i = yy_shift_ofst[stateno];
13175 if( i==YY_SHIFT_USE_DFLT ){
13176@@ -369,7 +369,7 @@
13177 ){
13178 int i;
13179 int stateno = pParser->yystack[pParser->yyidx].stateno;
13180-
13181+
13182 i = yy_reduce_ofst[stateno];
13183 if( i==YY_REDUCE_USE_DFLT ){
13184 return yy_default[stateno];
13185@@ -455,7 +455,7 @@
13186 ParseARG_FETCH;
13187 yymsp = &yypParser->yystack[yypParser->yyidx];
13188 #ifndef NDEBUG
13189- if( yyTraceFILE && yyruleno>=0
13190+ if( yyTraceFILE && yyruleno>=0
13191 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
13192 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
13193 yyRuleName[yyruleno]);
13194@@ -608,7 +608,7 @@
13195 #ifdef YYERRORSYMBOL
13196 /* A syntax error has occurred.
13197 ** The response to an error depends upon whether or not the
13198- ** grammar defines an error token "ERROR".
13199+ ** grammar defines an error token "ERROR".
13200 **
13201 ** This is what we do if the grammar does define ERROR:
13202 **
1175ccec
ER
13203--- ../lighttpd-1.4.11/src/log.c 2005-11-07 15:01:35.000000000 +0200
13204+++ lighttpd-1.4.12/src/log.c 2006-07-15 22:43:21.000000000 +0300
13205@@ -5,7 +5,6 @@
2519e6e5
ER
13206 #include <errno.h>
13207 #include <fcntl.h>
13208 #include <time.h>
13209-#include <unistd.h>
13210 #include <string.h>
13211 #include <stdlib.h>
13212
1175ccec 13213@@ -16,6 +15,10 @@
2519e6e5
ER
13214 #include "config.h"
13215 #endif
13216
13217+#ifdef _WIN32
13218+#undef HAVE_SYSLOG_H
13219+#endif
13220+
13221 #ifdef HAVE_SYSLOG_H
13222 #include <syslog.h>
13223 #endif
1175ccec 13224@@ -23,6 +26,8 @@
2519e6e5
ER
13225 #include "log.h"
13226 #include "array.h"
13227
13228+#include "sys-files.h"
13229+
13230 #ifdef HAVE_VALGRIND_VALGRIND_H
13231 #include <valgrind/valgrind.h>
13232 #endif
1175ccec 13233@@ -31,38 +36,38 @@
2519e6e5
ER
13234 # define O_LARGEFILE 0
13235 #endif
13236
13237-/**
13238+/**
13239 * open the errorlog
13240- *
13241+ *
13242 * we have 3 possibilities:
13243 * - stderr (default)
13244- * - syslog
13245+ * - syslog
13246 * - logfile
13247- *
13248+ *
13249 * if the open failed, report to the user and die
13250- *
13251+ *
13252 */
13253
13254 int log_error_open(server *srv) {
13255 int fd;
13256 int close_stderr = 1;
13257-
13258+
13259 #ifdef HAVE_SYSLOG_H
13260 /* perhaps someone wants to use syslog() */
13261 openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
13262 #endif
13263 srv->errorlog_mode = ERRORLOG_STDERR;
13264-
13265+
13266 if (srv->srvconf.errorlog_use_syslog) {
13267 srv->errorlog_mode = ERRORLOG_SYSLOG;
13268 } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
13269 const char *logfile = srv->srvconf.errorlog_file->ptr;
13270-
13271+
13272 if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13273- log_error_write(srv, __FILE__, __LINE__, "SSSS",
13274+ log_error_write(srv, __FILE__, __LINE__, "SSSS",
13275 "opening errorlog '", logfile,
13276 "' failed: ", strerror(errno));
13277-
13278+
13279 return -1;
13280 }
13281 #ifdef FD_CLOEXEC
1175ccec 13282@@ -71,15 +76,15 @@
2519e6e5
ER
13283 #endif
13284 srv->errorlog_mode = ERRORLOG_FILE;
13285 }
13286-
13287+
13288 log_error_write(srv, __FILE__, __LINE__, "s", "server started");
13289-
13290+
13291 #ifdef HAVE_VALGRIND_VALGRIND_H
13292 /* don't close stderr for debugging purposes if run in valgrind */
13293 if (RUNNING_ON_VALGRIND) close_stderr = 0;
13294 #endif
13295 if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
13296-
13297+
13298 /* move stderr to /dev/null */
13299 if (close_stderr &&
13300 -1 != (fd = open("/dev/null", O_WRONLY))) {
1175ccec 13301@@ -90,33 +95,33 @@
2519e6e5
ER
13302 return 0;
13303 }
13304
13305-/**
13306+/**
13307 * open the errorlog
13308- *
13309+ *
13310 * if the open failed, report to the user and die
13311 * if no filename is given, use syslog instead
13312- *
13313+ *
13314 */
13315
13316 int log_error_cycle(server *srv) {
13317 /* only cycle if we are not in syslog-mode */
13318-
13319+
13320 if (srv->errorlog_mode == ERRORLOG_FILE) {
13321 const char *logfile = srv->srvconf.errorlog_file->ptr;
13322 /* already check of opening time */
13323-
13324+
13325 int new_fd;
13326-
13327+
13328 if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13329 /* write to old log */
13330- log_error_write(srv, __FILE__, __LINE__, "SSSSS",
13331+ log_error_write(srv, __FILE__, __LINE__, "SSSSS",
13332 "cycling errorlog '", logfile,
13333 "' failed: ", strerror(errno),
13334 ", falling back to syslog()");
13335-
13336+
13337 close(srv->errorlog_fd);
13338 srv->errorlog_fd = -1;
13339-#ifdef HAVE_SYSLOG_H
13340+#ifdef HAVE_SYSLOG_H
13341 srv->errorlog_mode = ERRORLOG_SYSLOG;
13342 #endif
13343 } else {
1175ccec 13344@@ -125,15 +130,15 @@
2519e6e5
ER
13345 srv->errorlog_fd = new_fd;
13346 }
13347 }
13348-
13349+
13350 log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
13351-
13352+
13353 return 0;
13354 }
13355
13356 int log_error_close(server *srv) {
13357 log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
13358-
13359+
13360 switch(srv->errorlog_mode) {
13361 case ERRORLOG_FILE:
13362 close(srv->errorlog_fd);
1175ccec 13363@@ -146,13 +151,13 @@
2519e6e5
ER
13364 case ERRORLOG_STDERR:
13365 break;
13366 }
13367-
13368+
13369 return 0;
13370 }
13371
13372 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
13373 va_list ap;
13374-
13375+
13376 switch(srv->errorlog_mode) {
13377 case ERRORLOG_FILE:
13378 case ERRORLOG_STDERR:
1175ccec 13379@@ -161,7 +166,7 @@
2519e6e5
ER
13380 buffer_prepare_copy(srv->ts_debug_str, 255);
13381 strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
13382 srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
13383-
13384+
13385 srv->last_generated_debug_ts = srv->cur_ts;
13386 }
13387
1175ccec 13388@@ -173,19 +178,19 @@
2519e6e5
ER
13389 BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
13390 break;
13391 }
13392-
13393+
13394 buffer_append_string(srv->errorlog_buf, filename);
13395 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ".");
13396 buffer_append_long(srv->errorlog_buf, line);
13397 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") ");
13398-
13399-
13400+
13401+
13402 for(va_start(ap, fmt); *fmt; fmt++) {
13403 int d;
13404 char *s;
13405 buffer *b;
13406 off_t o;
13407-
13408+
13409 switch(*fmt) {
13410 case 's': /* string */
13411 s = va_arg(ap, char *);
1175ccec 13412@@ -227,7 +232,7 @@
2519e6e5
ER
13413 break;
13414 case '(':
13415 case ')':
13416- case '<':
13417+ case '<':
13418 case '>':
13419 case ',':
13420 case ' ':
1175ccec 13421@@ -236,7 +241,7 @@
2519e6e5
ER
13422 }
13423 }
13424 va_end(ap);
13425-
13426+
13427 switch(srv->errorlog_mode) {
13428 case ERRORLOG_FILE:
13429 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
1175ccec 13430@@ -246,11 +251,13 @@
2519e6e5
ER
13431 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13432 write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
13433 break;
13434+#ifdef HAVE_SYSLOG_H
13435 case ERRORLOG_SYSLOG:
13436 syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
13437 break;
13438+#endif
13439 }
13440-
13441+
13442 return 0;
13443 }
13444
1175ccec 13445--- ../lighttpd-1.4.11/src/log.h 2005-08-11 01:26:36.000000000 +0300
36e2a29e 13446+++ lighttpd-1.4.12/src/log.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
13447@@ -9,5 +9,5 @@
13448 int log_error_close(server *srv);
13449 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
13450 int log_error_cycle(server *srv);
13451-
13452+
13453 #endif
1175ccec 13454--- ../lighttpd-1.4.11/src/md5.h 2005-11-17 16:20:40.000000000 +0200
36e2a29e 13455+++ lighttpd-1.4.12/src/md5.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
13456@@ -30,9 +30,15 @@
13457 # include <inttypes.h>
13458 #endif
13459
13460+#ifdef _WIN32
13461+#define UINT4 unsigned __int32
13462+#define UINT2 unsigned __int16
13463+#define POINTER unsigned char *
13464+#else
13465 #define UINT4 uint32_t
13466 #define UINT2 uint16_t
13467 #define POINTER unsigned char *
13468+#endif
13469
13470 /* MD5 context. */
13471 typedef struct {
1175ccec 13472--- ../lighttpd-1.4.11/src/mod_access.c 2006-01-14 19:44:54.000000000 +0200
36e2a29e 13473+++ lighttpd-1.4.12/src/mod_access.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
13474@@ -8,126 +8,125 @@
13475
13476 #include "plugin.h"
13477
13478+#include "sys-strings.h"
13479+
13480 typedef struct {
13481 array *access_deny;
13482 } plugin_config;
13483
13484 typedef struct {
13485 PLUGIN_DATA;
13486-
13487+
13488 plugin_config **config_storage;
13489-
13490- plugin_config conf;
13491+
13492+ plugin_config conf;
13493 } plugin_data;
13494
13495 INIT_FUNC(mod_access_init) {
13496 plugin_data *p;
13497-
13498+
13499 p = calloc(1, sizeof(*p));
13500-
13501+
13502 return p;
13503 }
13504
13505 FREE_FUNC(mod_access_free) {
13506 plugin_data *p = p_d;
13507-
13508+
13509 UNUSED(srv);
13510
13511 if (!p) return HANDLER_GO_ON;
13512-
13513+
13514 if (p->config_storage) {
13515 size_t i;
13516 for (i = 0; i < srv->config_context->used; i++) {
13517 plugin_config *s = p->config_storage[i];
13518-
13519+
13520 array_free(s->access_deny);
13521-
13522+
13523 free(s);
13524 }
13525 free(p->config_storage);
13526 }
13527-
13528+
13529 free(p);
13530-
13531+
13532 return HANDLER_GO_ON;
13533 }
13534
13535 SETDEFAULTS_FUNC(mod_access_set_defaults) {
13536 plugin_data *p = p_d;
13537 size_t i = 0;
13538-
13539- config_values_t cv[] = {
13540+
13541+ config_values_t cv[] = {
13542 { "url.access-deny", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
13543 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
13544 };
13545-
13546+
13547 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
13548-
13549+
13550 for (i = 0; i < srv->config_context->used; i++) {
13551 plugin_config *s;
13552-
13553+
13554 s = calloc(1, sizeof(plugin_config));
13555 s->access_deny = array_init();
13556-
13557+
13558 cv[0].destination = s->access_deny;
13559-
13560+
13561 p->config_storage[i] = s;
13562-
13563+
13564 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
13565 return HANDLER_ERROR;
13566 }
13567 }
13568-
13569+
13570 return HANDLER_GO_ON;
13571 }
13572
13573-#define PATCH(x) \
13574- p->conf.x = s->x;
13575 static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
13576 size_t i, j;
13577 plugin_config *s = p->config_storage[0];
13578
13579- PATCH(access_deny);
13580-
13581+ PATCH_OPTION(access_deny);
13582+
13583 /* skip the first, the global context */
13584 for (i = 1; i < srv->config_context->used; i++) {
13585 data_config *dc = (data_config *)srv->config_context->data[i];
13586 s = p->config_storage[i];
13587-
13588+
13589 /* condition didn't match */
13590 if (!config_check_cond(srv, con, dc)) continue;
13591-
13592+
13593 /* merge config */
13594 for (j = 0; j < dc->value->used; j++) {
13595 data_unset *du = dc->value->data[j];
13596-
13597+
13598 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
13599- PATCH(access_deny);
13600+ PATCH_OPTION(access_deny);
13601 }
13602 }
13603 }
13604-
13605+
13606 return 0;
13607 }
13608-#undef PATCH
13609
13610 URIHANDLER_FUNC(mod_access_uri_handler) {
13611 plugin_data *p = p_d;
13612 int s_len;
13613 size_t k;
13614-
13615+
13616 if (con->uri.path->used == 0) return HANDLER_GO_ON;
13617-
13618+
13619 mod_access_patch_connection(srv, con, p);
13620-
13621+
13622 s_len = con->uri.path->used - 1;
13623-
13624+
13625 for (k = 0; k < p->conf.access_deny->used; k++) {
13626 data_string *ds = (data_string *)p->conf.access_deny->data[k];
13627 int ct_len = ds->value->used - 1;
13628-
13629+
13630 if (ct_len > s_len) continue;
13631-
13632+
13633 if (ds->value->used == 0) continue;
13634
13635 /* if we have a case-insensitive FS we have to lower-case the URI here too */
13636@@ -135,18 +134,18 @@
13637 if (con->conf.force_lowercase_filenames) {
13638 if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13639 con->http_status = 403;
13640-
13641+
13642 return HANDLER_FINISHED;
13643 }
13644 } else {
13645 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13646 con->http_status = 403;
13647-
13648+
13649 return HANDLER_FINISHED;
13650 }
13651 }
13652 }
13653-
13654+
13655 /* not found */
13656 return HANDLER_GO_ON;
13657 }
13658@@ -155,13 +154,13 @@
13659 int mod_access_plugin_init(plugin *p) {
13660 p->version = LIGHTTPD_VERSION_ID;
13661 p->name = buffer_init_string("access");
13662-
13663+
13664 p->init = mod_access_init;
13665 p->set_defaults = mod_access_set_defaults;
13666 p->handle_uri_clean = mod_access_uri_handler;
13667 p->cleanup = mod_access_free;
13668-
13669+
13670 p->data = NULL;
13671-
13672+
13673 return 0;
13674 }
1175ccec 13675--- ../lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200
36e2a29e 13676+++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
13677@@ -6,8 +6,7 @@
13678 #include <ctype.h>
13679 #include <stdlib.h>
13680 #include <string.h>
13681-#include <fcntl.h>
13682-#include <unistd.h>
13683+#include <fcntl.h> /* only the defines on windows */
13684 #include <errno.h>
13685 #include <time.h>
13686
13687@@ -22,6 +21,7 @@
13688 #include "inet_ntop_cache.h"
13689
13690 #include "sys-socket.h"
13691+#include "sys-files.h"
13692
13693 #ifdef HAVE_SYSLOG_H
13694 # include <syslog.h>
13695@@ -29,7 +29,7 @@
13696
13697 typedef struct {
13698 char key;
13699- enum {
13700+ enum {
13701 FORMAT_UNSET,
13702 FORMAT_UNSUPPORTED,
13703 FORMAT_PERCENT,
13704@@ -41,7 +41,7 @@
13705 FORMAT_STATUS,
13706 FORMAT_BYTES_OUT_NO_HEADER,
13707 FORMAT_HEADER,
13708-
13709+
13710 FORMAT_REMOTE_ADDR,
13711 FORMAT_LOCAL_ADDR,
13712 FORMAT_COOKIE,
13713@@ -59,20 +59,20 @@
13714 FORMAT_CONNECTION_STATUS,
13715 FORMAT_BYTES_IN,
13716 FORMAT_BYTES_OUT,
13717-
13718+
13719 FORMAT_RESPONSE_HEADER
13720 } type;
13721 } format_mapping;
13722
13723 /**
13724- *
13725- *
13726+ *
13727+ *
13728 * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
13729- *
13730+ *
13731 */
13732
13733-const format_mapping fmap[] =
13734-{
13735+const format_mapping fmap[] =
13736+{
13737 { '%', FORMAT_PERCENT },
13738 { 'h', FORMAT_REMOTE_HOST },
13739 { 'l', FORMAT_REMOTE_IDENT },
13740@@ -82,7 +82,7 @@
13741 { 's', FORMAT_STATUS },
13742 { 'b', FORMAT_BYTES_OUT_NO_HEADER },
13743 { 'i', FORMAT_HEADER },
13744-
13745+
13746 { 'a', FORMAT_REMOTE_ADDR },
13747 { 'A', FORMAT_LOCAL_ADDR },
13748 { 'B', FORMAT_BYTES_OUT_NO_HEADER },
13749@@ -103,23 +103,23 @@
13750 { 'X', FORMAT_CONNECTION_STATUS },
13751 { 'I', FORMAT_BYTES_IN },
13752 { 'O', FORMAT_BYTES_OUT },
13753-
13754+
13755 { 'o', FORMAT_RESPONSE_HEADER },
13756-
13757+
13758 { '\0', FORMAT_UNSET }
13759 };
13760
13761
13762 typedef struct {
13763 enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
13764-
13765+
13766 buffer *string;
13767 int field;
13768 } format_field;
13769
13770 typedef struct {
13771 format_field **ptr;
13772-
13773+
13774 size_t used;
13775 size_t size;
13776 } format_fields;
13777@@ -128,39 +128,39 @@
13778 buffer *access_logfile;
13779 buffer *format;
13780 unsigned short use_syslog;
13781-
13782-
13783+
13784+
13785 int log_access_fd;
13786 time_t last_generated_accesslog_ts;
13787 time_t *last_generated_accesslog_ts_ptr;
13788-
13789-
13790+
13791+
13792 buffer *access_logbuffer;
13793 buffer *ts_accesslog_str;
13794-
13795+
13796 format_fields *parsed_format;
13797 } plugin_config;
13798
13799 typedef struct {
13800 PLUGIN_DATA;
13801-
13802+
13803 plugin_config **config_storage;
13804- plugin_config conf;
13805+ plugin_config conf;
13806 } plugin_data;
13807
13808 INIT_FUNC(mod_accesslog_init) {
13809 plugin_data *p;
13810-
13811+
13812 p = calloc(1, sizeof(*p));
13813-
13814+
13815 return p;
13816 }
13817
13818 int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
13819 size_t i, j, k = 0, start = 0;
13820-
13821+
13822 for (i = 0; i < format->used - 1; i++) {
13823-
13824+
13825 switch(format->ptr[i]) {
13826 case '%':
13827 if (start != i) {
13828@@ -173,19 +173,19 @@
13829 fields->size += 16;
13830 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
13831 }
13832-
13833+
13834 fields->ptr[fields->used] = malloc(sizeof(format_fields));
13835 fields->ptr[fields->used]->type = FIELD_STRING;
13836 fields->ptr[fields->used]->string = buffer_init();
13837-
13838+
13839 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
13840-
13841+
13842 fields->used++;
13843 }
13844-
13845-
13846+
13847+
13848 /* we need a new field */
13849-
13850+
13851 if (fields->size == 0) {
13852 fields->size = 16;
13853 fields->used = 0;
13854@@ -194,43 +194,43 @@
13855 fields->size += 16;
13856 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
13857 }
13858-
13859+
13860 /* search for the terminating command */
13861 switch (format->ptr[i+1]) {
13862 case '>':
13863 case '<':
13864 /* only for s */
13865-
13866+
13867 for (j = 0; fmap[j].key != '\0'; j++) {
13868 if (fmap[j].key != format->ptr[i+2]) continue;
13869-
13870+
13871 /* found key */
13872-
13873+
13874 fields->ptr[fields->used] = malloc(sizeof(format_fields));
13875 fields->ptr[fields->used]->type = FIELD_FORMAT;
13876 fields->ptr[fields->used]->field = fmap[j].type;
13877 fields->ptr[fields->used]->string = NULL;
13878-
13879+
13880 fields->used++;
13881-
13882+
13883 break;
13884 }
13885-
13886+
13887 if (fmap[j].key == '\0') {
13888 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13889 return -1;
13890 }
13891-
13892+
13893 start = i + 3;
13894-
13895+
13896 break;
13897 case '{':
13898 /* go forward to } */
13899-
13900+
13901 for (k = i+2; k < format->used - 1; k++) {
13902 if (format->ptr[k] == '}') break;
13903 }
13904-
13905+
13906 if (k == format->used - 1) {
13907 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13908 return -1;
13909@@ -239,62 +239,62 @@
13910 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13911 return -1;
13912 }
13913-
13914+
13915 for (j = 0; fmap[j].key != '\0'; j++) {
13916 if (fmap[j].key != format->ptr[k+1]) continue;
13917-
13918+
13919 /* found key */
13920-
13921+
13922 fields->ptr[fields->used] = malloc(sizeof(format_fields));
13923 fields->ptr[fields->used]->type = FIELD_FORMAT;
13924 fields->ptr[fields->used]->field = fmap[j].type;
13925 fields->ptr[fields->used]->string = buffer_init();
13926-
13927+
13928 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
13929-
13930+
13931 fields->used++;
13932-
13933+
13934 break;
13935 }
13936-
13937+
13938 if (fmap[j].key == '\0') {
13939 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13940 return -1;
13941 }
13942-
13943+
13944 start = k + 2;
13945-
13946+
13947 break;
13948 default:
13949 for (j = 0; fmap[j].key != '\0'; j++) {
13950 if (fmap[j].key != format->ptr[i+1]) continue;
13951-
13952+
13953 /* found key */
13954-
13955+
13956 fields->ptr[fields->used] = malloc(sizeof(format_fields));
13957 fields->ptr[fields->used]->type = FIELD_FORMAT;
13958 fields->ptr[fields->used]->field = fmap[j].type;
13959 fields->ptr[fields->used]->string = NULL;
13960-
13961+
13962 fields->used++;
13963-
13964+
13965 break;
13966 }
13967-
13968+
13969 if (fmap[j].key == '\0') {
13970 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13971 return -1;
13972 }
13973-
13974+
13975 start = i + 2;
13976-
13977+
13978 break;
13979 }
13980-
13981+
13982 break;
13983 }
13984 }
13985-
13986+
13987 if (start < i) {
13988 /* copy the string */
13989 if (fields->size == 0) {
13990@@ -305,32 +305,32 @@
13991 fields->size += 16;
13992 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
13993 }
13994-
13995+
13996 fields->ptr[fields->used] = malloc(sizeof(format_fields));
13997 fields->ptr[fields->used]->type = FIELD_STRING;
13998 fields->ptr[fields->used]->string = buffer_init();
13999-
14000+
14001 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14002-
14003+
14004 fields->used++;
14005 }
14006-
14007+
14008 return 0;
14009 }
14010
14011 FREE_FUNC(mod_accesslog_free) {
14012 plugin_data *p = p_d;
14013 size_t i;
14014-
14015+
14016 if (!p) return HANDLER_GO_ON;
14017-
14018+
14019 if (p->config_storage) {
14020-
14021+
14022 for (i = 0; i < srv->config_context->used; i++) {
14023 plugin_config *s = p->config_storage[i];
14024
14025 if (!s) continue;
14026-
14027+
14028 if (s->access_logbuffer->used) {
14029 if (s->use_syslog) {
14030 # ifdef HAVE_SYSLOG_H
14031@@ -342,14 +342,14 @@
14032 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14033 }
14034 }
14035-
14036+
14037 if (s->log_access_fd != -1) close(s->log_access_fd);
14038-
14039+
14040 buffer_free(s->ts_accesslog_str);
14041 buffer_free(s->access_logbuffer);
14042 buffer_free(s->format);
14043 buffer_free(s->access_logfile);
14044-
14045+
14046 if (s->parsed_format) {
14047 size_t j;
14048 for (j = 0; j < s->parsed_format->used; j++) {
14049@@ -359,36 +359,36 @@
14050 free(s->parsed_format->ptr);
14051 free(s->parsed_format);
14052 }
14053-
14054+
14055 free(s);
14056 }
14057-
14058+
14059 free(p->config_storage);
14060 }
14061-
14062+
14063 free(p);
14064-
14065+
14066 return HANDLER_GO_ON;
14067 }
14068
14069 SETDEFAULTS_FUNC(log_access_open) {
14070 plugin_data *p = p_d;
14071 size_t i = 0;
14072-
14073- config_values_t cv[] = {
14074+
14075+ config_values_t cv[] = {
14076 { "accesslog.filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14077 { "accesslog.use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
14078 { "accesslog.format", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14079 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14080 };
14081-
14082+
14083 if (!p) return HANDLER_ERROR;
14084-
14085+
14086 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14087-
14088+
14089 for (i = 0; i < srv->config_context->used; i++) {
14090 plugin_config *s;
14091-
14092+
14093 s = calloc(1, sizeof(plugin_config));
14094 s->access_logfile = buffer_init();
14095 s->format = buffer_init();
14096@@ -397,44 +397,44 @@
14097 s->log_access_fd = -1;
14098 s->last_generated_accesslog_ts = 0;
14099 s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
14100-
14101-
14102+
14103+
14104 cv[0].destination = s->access_logfile;
14105 cv[1].destination = &(s->use_syslog);
14106 cv[2].destination = s->format;
14107-
14108+
14109 p->config_storage[i] = s;
14110-
14111+
14112 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14113 return HANDLER_ERROR;
14114 }
14115-
14116+
14117 if (i == 0 && buffer_is_empty(s->format)) {
14118 /* set a default logfile string */
14119-
14120+
14121 buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
14122 }
14123-
14124+
14125 /* parse */
14126-
14127+
14128 if (s->format->used) {
14129 s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
14130-
14131+
14132 if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
14133
14134- log_error_write(srv, __FILE__, __LINE__, "sb",
14135+ log_error_write(srv, __FILE__, __LINE__, "sb",
14136 "parsing accesslog-definition failed:", s->format);
14137
14138 return HANDLER_ERROR;
14139 }
14140 #if 0
14141- /* debugging */
14142+ /* debugging */
14143 for (j = 0; j < s->parsed_format->used; j++) {
14144 switch (s->parsed_format->ptr[j]->type) {
14145 case FIELD_FORMAT:
14146- log_error_write(srv, __FILE__, __LINE__, "ssds",
14147+ log_error_write(srv, __FILE__, __LINE__, "ssds",
14148 "config:", "format", s->parsed_format->ptr[j]->field,
14149- s->parsed_format->ptr[j]->string ?
14150+ s->parsed_format->ptr[j]->string ?
14151 s->parsed_format->ptr[j]->string->ptr : "" );
14152 break;
14153 case FIELD_STRING:
14154@@ -446,52 +446,52 @@
14155 }
14156 #endif
14157 }
14158-
14159+
14160 if (s->use_syslog) {
14161 /* ignore the next checks */
14162 continue;
14163 }
14164-
14165+
14166 if (buffer_is_empty(s->access_logfile)) continue;
14167-
14168+
14169 if (s->access_logfile->ptr[0] == '|') {
14170 #ifdef HAVE_FORK
14171 /* create write pipe and spawn process */
14172-
14173+
14174 int to_log_fds[2];
14175 pid_t pid;
14176-
14177+
14178 if (pipe(to_log_fds)) {
14179 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
14180 return HANDLER_ERROR;
14181 }
14182-
14183+
14184 /* fork, execve */
14185 switch (pid = fork()) {
14186- case 0:
14187+ case 0:
14188 /* child */
14189-
14190+
14191 close(STDIN_FILENO);
14192 dup2(to_log_fds[0], STDIN_FILENO);
14193 close(to_log_fds[0]);
14194 /* not needed */
14195 close(to_log_fds[1]);
14196-
14197+
14198 /* we don't need the client socket */
14199 for (i = 3; i < 256; i++) {
14200 close(i);
14201 }
14202-
14203- /* exec the log-process (skip the | )
14204- *
14205+
14206+ /* exec the log-process (skip the | )
14207+ *
14208 */
14209-
14210+
14211 execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
14212
14213- log_error_write(srv, __FILE__, __LINE__, "sss",
14214- "spawning log-process failed: ", strerror(errno),
14215+ log_error_write(srv, __FILE__, __LINE__, "sss",
14216+ "spawning log-process failed: ", strerror(errno),
14217 s->access_logfile->ptr + 1);
14218-
14219+
14220 exit(-1);
14221 break;
14222 case -1:
14223@@ -500,27 +500,28 @@
14224 break;
14225 default:
14226 close(to_log_fds[0]);
14227-
14228+
14229 s->log_access_fd = to_log_fds[1];
14230-
14231+
14232 break;
14233 }
14234 #else
14235 return -1;
14236 #endif
14237- } else if (-1 == (s->log_access_fd =
14238+ } else if (-1 == (s->log_access_fd =
14239 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14240-
14241- log_error_write(srv, __FILE__, __LINE__, "ssb",
14242- "opening access-log failed:",
14243+
14244+ log_error_write(srv, __FILE__, __LINE__, "ssb",
14245+ "opening access-log failed:",
14246 strerror(errno), s->access_logfile);
14247-
14248+
14249 return HANDLER_ERROR;
14250 }
14251+#ifndef _WIN32
14252 fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
14253-
14254+#endif
14255 }
14256-
14257+
14258 return HANDLER_GO_ON;
14259 }
14260
14261@@ -529,7 +530,7 @@
14262 size_t i;
14263
14264 if (!p->config_storage) return HANDLER_GO_ON;
14265-
14266+
14267 for (i = 0; i < srv->config_context->used; i++) {
14268 plugin_config *s = p->config_storage[i];
14269
14270@@ -544,90 +545,87 @@
14271 } else if (s->log_access_fd != -1) {
14272 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14273 }
14274-
14275+
14276 buffer_reset(s->access_logbuffer);
14277 }
14278-
14279+
14280 if (s->use_syslog == 0 &&
14281 !buffer_is_empty(s->access_logfile) &&
14282 s->access_logfile->ptr[0] != '|') {
14283-
14284+
14285 close(s->log_access_fd);
14286-
14287- if (-1 == (s->log_access_fd =
14288+
14289+ if (-1 == (s->log_access_fd =
14290 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14291-
14292+
14293 log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
14294-
14295+
14296 return HANDLER_ERROR;
14297 }
14298 }
14299 }
14300-
14301+
14302 return HANDLER_GO_ON;
14303 }
14304
14305-#define PATCH(x) \
14306- p->conf.x = s->x;
14307 static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
14308 size_t i, j;
14309 plugin_config *s = p->config_storage[0];
14310-
14311- PATCH(access_logfile);
14312- PATCH(format);
14313- PATCH(log_access_fd);
14314- PATCH(last_generated_accesslog_ts_ptr);
14315- PATCH(access_logbuffer);
14316- PATCH(ts_accesslog_str);
14317- PATCH(parsed_format);
14318- PATCH(use_syslog);
14319-
14320+
14321+ PATCH_OPTION(access_logfile);
14322+ PATCH_OPTION(format);
14323+ PATCH_OPTION(log_access_fd);
14324+ PATCH_OPTION(last_generated_accesslog_ts_ptr);
14325+ PATCH_OPTION(access_logbuffer);
14326+ PATCH_OPTION(ts_accesslog_str);
14327+ PATCH_OPTION(parsed_format);
14328+ PATCH_OPTION(use_syslog);
14329+
14330 /* skip the first, the global context */
14331 for (i = 1; i < srv->config_context->used; i++) {
14332 data_config *dc = (data_config *)srv->config_context->data[i];
14333 s = p->config_storage[i];
14334-
14335+
14336 /* condition didn't match */
14337 if (!config_check_cond(srv, con, dc)) continue;
14338-
14339+
14340 /* merge config */
14341 for (j = 0; j < dc->value->used; j++) {
14342 data_unset *du = dc->value->data[j];
14343-
14344+
14345 if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
14346- PATCH(access_logfile);
14347- PATCH(log_access_fd);
14348- PATCH(last_generated_accesslog_ts_ptr);
14349- PATCH(access_logbuffer);
14350- PATCH(ts_accesslog_str);
14351+ PATCH_OPTION(access_logfile);
14352+ PATCH_OPTION(log_access_fd);
14353+ PATCH_OPTION(last_generated_accesslog_ts_ptr);
14354+ PATCH_OPTION(access_logbuffer);
14355+ PATCH_OPTION(ts_accesslog_str);
14356 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
14357- PATCH(format);
14358- PATCH(parsed_format);
14359+ PATCH_OPTION(format);
14360+ PATCH_OPTION(parsed_format);
14361 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
14362- PATCH(use_syslog);
14363+ PATCH_OPTION(use_syslog);
14364 }
14365 }
14366 }
14367-
14368+
14369 return 0;
14370 }
14371-#undef PATCH
14372
14373 REQUESTDONE_FUNC(log_access_write) {
14374 plugin_data *p = p_d;
14375 buffer *b;
14376 size_t j;
14377-
14378+
14379 int newts = 0;
14380 data_string *ds;
14381-
14382+
14383 mod_accesslog_patch_connection(srv, con, p);
14384-
14385+
14386 b = p->conf.access_logbuffer;
14387 if (b->used == 0) {
14388 buffer_copy_string(b, "");
14389 }
14390-
14391+
14392 for (j = 0; j < p->conf.parsed_format->used; j++) {
14393 switch(p->conf.parsed_format->ptr[j]->type) {
14394 case FIELD_STRING:
14395@@ -636,14 +634,14 @@
14396 case FIELD_FORMAT:
14397 switch(p->conf.parsed_format->ptr[j]->field) {
14398 case FORMAT_TIMESTAMP:
14399-
14400+
14401 /* cache the generated timestamp */
14402 if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
14403 struct tm tm;
14404 #if defined(HAVE_STRUCT_TM_GMTOFF)
14405 long scd, hrs, min;
14406 #endif
14407-
14408+
14409 buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
14410 #if defined(HAVE_STRUCT_TM_GMTOFF)
14411 # ifdef HAVE_LOCALTIME_R
14412@@ -653,17 +651,17 @@
14413 strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S ", localtime_r(&(srv->cur_ts)));
14414 # endif
14415 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14416-
14417+
14418 buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
14419-
14420+
14421 scd = abs(tm.tm_gmtoff);
14422 hrs = scd / 3600;
14423 min = (scd % 3600) / 60;
14424-
14425+
14426 /* hours */
14427 if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14428 buffer_append_long(p->conf.ts_accesslog_str, hrs);
14429-
14430+
14431 if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14432 buffer_append_long(p->conf.ts_accesslog_str, min);
14433 BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]");
14434@@ -676,20 +674,20 @@
14435 #endif
14436 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14437 #endif
14438-
14439+
14440 *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
14441 newts = 1;
14442 }
14443-
14444+
14445 buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
14446-
14447+
14448 break;
14449 case FORMAT_REMOTE_HOST:
14450-
14451+
14452 /* handle inet_ntop cache */
14453-
14454+
14455 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
14456-
14457+
14458 break;
14459 case FORMAT_REMOTE_IDENT:
14460 /* ident */
14461@@ -710,10 +708,10 @@
14462 case FORMAT_STATUS:
14463 buffer_append_long(b, con->http_status);
14464 break;
14465-
14466+
14467 case FORMAT_BYTES_OUT_NO_HEADER:
14468 if (con->bytes_written > 0) {
14469- buffer_append_off_t(b,
14470+ buffer_append_off_t(b,
14471 con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
14472 } else {
14473 BUFFER_APPEND_STRING_CONST(b, "-");
14474@@ -772,7 +770,7 @@
14475 }
14476 break;
14477 case FORMAT_REQUEST_PROTOCOL:
14478- buffer_append_string(b,
14479+ buffer_append_string(b,
14480 con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
14481 break;
14482 case FORMAT_REQUEST_METHOD:
14483@@ -801,7 +799,7 @@
14484 { 'D', FORMAT_TIME_USED_MS },
14485 { 'e', FORMAT_ENV },
14486 */
14487-
14488+
14489 break;
14490 }
14491 break;
14492@@ -809,7 +807,7 @@
14493 break;
14494 }
14495 }
14496-
14497+
14498 BUFFER_APPEND_STRING_CONST(b, "\n");
14499
14500 if (p->conf.use_syslog || /* syslog doesn't cache */
14501@@ -828,7 +826,7 @@
14502 }
14503 buffer_reset(b);
14504 }
14505-
14506+
14507 return HANDLER_GO_ON;
14508 }
14509
14510@@ -836,15 +834,15 @@
14511 int mod_accesslog_plugin_init(plugin *p) {
14512 p->version = LIGHTTPD_VERSION_ID;
14513 p->name = buffer_init_string("accesslog");
14514-
14515+
14516 p->init = mod_accesslog_init;
14517 p->set_defaults= log_access_open;
14518 p->cleanup = mod_accesslog_free;
14519-
14520+
14521 p->handle_request_done = log_access_write;
14522 p->handle_sighup = log_access_cycle;
14523-
14524+
14525 p->data = NULL;
14526-
14527+
14528 return 0;
14529 }
1175ccec 14530--- ../lighttpd-1.4.11/src/mod_alias.c 2006-03-01 23:18:51.000000000 +0200
36e2a29e 14531+++ lighttpd-1.4.12/src/mod_alias.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
14532@@ -8,6 +8,7 @@
14533 #include "buffer.h"
14534
14535 #include "plugin.h"
14536+#include "sys-strings.h"
14537
14538 /* plugin config for all request/connections */
14539 typedef struct {
14540@@ -16,44 +17,44 @@
14541
14542 typedef struct {
14543 PLUGIN_DATA;
14544-
14545+
14546 plugin_config **config_storage;
14547-
14548- plugin_config conf;
14549+
14550+ plugin_config conf;
14551 } plugin_data;
14552
14553 /* init the plugin data */
14554 INIT_FUNC(mod_alias_init) {
14555 plugin_data *p;
14556-
14557+
14558 p = calloc(1, sizeof(*p));
14559-
14560-
14561-
14562+
14563+
14564+
14565 return p;
14566 }
14567
14568 /* detroy the plugin data */
14569 FREE_FUNC(mod_alias_free) {
14570 plugin_data *p = p_d;
14571-
14572+
14573 if (!p) return HANDLER_GO_ON;
14574-
14575+
14576 if (p->config_storage) {
14577 size_t i;
14578-
14579+
14580 for (i = 0; i < srv->config_context->used; i++) {
14581 plugin_config *s = p->config_storage[i];
14582-
14583+
14584 array_free(s->alias);
14585-
14586+
14587 free(s);
14588 }
14589 free(p->config_storage);
14590 }
14591-
14592+
14593 free(p);
14594-
14595+
14596 return HANDLER_GO_ON;
14597 }
14598
14599@@ -62,25 +63,25 @@
14600 SETDEFAULTS_FUNC(mod_alias_set_defaults) {
14601 plugin_data *p = p_d;
14602 size_t i = 0;
14603-
14604- config_values_t cv[] = {
14605+
14606+ config_values_t cv[] = {
14607 { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
14608 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14609 };
14610-
14611+
14612 if (!p) return HANDLER_ERROR;
14613-
14614+
14615 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14616-
14617+
14618 for (i = 0; i < srv->config_context->used; i++) {
14619 plugin_config *s;
14620-
14621+
14622 s = calloc(1, sizeof(plugin_config));
14623- s->alias = array_init();
14624+ s->alias = array_init();
14625 cv[0].destination = s->alias;
14626-
14627+
14628 p->config_storage[i] = s;
14629-
14630+
14631 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14632 return HANDLER_ERROR;
14633 }
14634@@ -110,76 +111,73 @@
14635 }
14636 }
14637 }
14638-
14639+
14640 return HANDLER_GO_ON;
14641 }
14642
14643-#define PATCH(x) \
14644- p->conf.x = s->x;
14645 static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
14646 size_t i, j;
14647 plugin_config *s = p->config_storage[0];
14648-
14649- PATCH(alias);
14650-
14651+
14652+ PATCH_OPTION(alias);
14653+
14654 /* skip the first, the global context */
14655 for (i = 1; i < srv->config_context->used; i++) {
14656 data_config *dc = (data_config *)srv->config_context->data[i];
14657 s = p->config_storage[i];
14658-
14659+
14660 /* condition didn't match */
14661 if (!config_check_cond(srv, con, dc)) continue;
14662-
14663+
14664 /* merge config */
14665 for (j = 0; j < dc->value->used; j++) {
14666 data_unset *du = dc->value->data[j];
14667-
14668+
14669 if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
14670- PATCH(alias);
14671+ PATCH_OPTION(alias);
14672 }
14673 }
14674 }
14675-
14676+
14677 return 0;
14678 }
14679-#undef PATCH
14680
14681 PHYSICALPATH_FUNC(mod_alias_physical_handler) {
14682 plugin_data *p = p_d;
14683 int uri_len, basedir_len;
14684 char *uri_ptr;
14685 size_t k;
14686-
14687+
14688 if (con->physical.path->used == 0) return HANDLER_GO_ON;
14689-
14690+
14691 mod_alias_patch_connection(srv, con, p);
14692-
14693+
14694 /* not to include the tailing slash */
14695 basedir_len = (con->physical.basedir->used - 1) - 1;
14696 uri_len = con->physical.path->used - 1 - basedir_len;
14697 uri_ptr = con->physical.path->ptr + basedir_len;
14698-
14699+
14700 for (k = 0; k < p->conf.alias->used; k++) {
14701 data_string *ds = (data_string *)p->conf.alias->data[k];
14702 int alias_len = ds->key->used - 1;
14703-
14704+
14705 if (alias_len > uri_len) continue;
14706 if (ds->key->used == 0) continue;
14707-
14708+
14709 if (0 == (con->conf.force_lowercase_filenames ?
14710 strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
14711 strncmp(uri_ptr, ds->key->ptr, alias_len))) {
14712 /* matched */
14713-
14714+
14715 buffer_copy_string_buffer(con->physical.basedir, ds->value);
14716 buffer_copy_string_buffer(srv->tmp_buf, ds->value);
14717 buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
14718 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
14719-
14720+
14721 return HANDLER_GO_ON;
14722 }
14723 }
14724-
14725+
14726 /* not found */
14727 return HANDLER_GO_ON;
14728 }
14729@@ -189,13 +187,13 @@
14730 int mod_alias_plugin_init(plugin *p) {
14731 p->version = LIGHTTPD_VERSION_ID;
14732 p->name = buffer_init_string("alias");
14733-
14734+
14735 p->init = mod_alias_init;
14736 p->handle_physical= mod_alias_physical_handler;
14737 p->set_defaults = mod_alias_set_defaults;
14738 p->cleanup = mod_alias_free;
14739-
14740+
14741 p->data = NULL;
14742-
14743+
14744 return 0;
14745 }
1175ccec 14746--- ../lighttpd-1.4.11/src/mod_auth.c 2006-02-15 20:01:31.000000000 +0200
36e2a29e 14747+++ lighttpd-1.4.12/src/mod_auth.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
14748@@ -5,168 +5,167 @@
14749 #include <string.h>
14750 #include <errno.h>
14751 #include <fcntl.h>
14752-#include <unistd.h>
14753
14754 #include "plugin.h"
14755 #include "http_auth.h"
14756 #include "log.h"
14757 #include "response.h"
14758
14759+#include "sys-strings.h"
14760+#include "sys-files.h"
14761+
14762 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
14763
14764
14765 /**
14766 * the basic and digest auth framework
14767- *
14768+ *
14769 * - config handling
14770 * - protocol handling
14771- *
14772- * http_auth.c
14773- * http_auth_digest.c
14774- *
14775+ *
14776+ * http_auth.c
14777+ * http_auth_digest.c
14778+ *
14779 * do the real work
14780 */
14781
14782 INIT_FUNC(mod_auth_init) {
14783 mod_auth_plugin_data *p;
14784-
14785+
14786 p = calloc(1, sizeof(*p));
14787-
14788+
14789 p->tmp_buf = buffer_init();
14790-
14791+
14792 p->auth_user = buffer_init();
14793 #ifdef USE_LDAP
14794 p->ldap_filter = buffer_init();
14795 #endif
14796-
14797+
14798 return p;
14799 }
14800
14801 FREE_FUNC(mod_auth_free) {
14802 mod_auth_plugin_data *p = p_d;
14803-
14804+
14805 UNUSED(srv);
14806
14807 if (!p) return HANDLER_GO_ON;
14808-
14809+
14810 buffer_free(p->tmp_buf);
14811 buffer_free(p->auth_user);
14812 #ifdef USE_LDAP
14813 buffer_free(p->ldap_filter);
14814 #endif
14815-
14816+
14817 if (p->config_storage) {
14818 size_t i;
14819 for (i = 0; i < srv->config_context->used; i++) {
14820 mod_auth_plugin_config *s = p->config_storage[i];
14821-
14822+
14823 if (!s) continue;
14824-
14825+
14826 array_free(s->auth_require);
14827 buffer_free(s->auth_plain_groupfile);
14828 buffer_free(s->auth_plain_userfile);
14829 buffer_free(s->auth_htdigest_userfile);
14830 buffer_free(s->auth_htpasswd_userfile);
14831 buffer_free(s->auth_backend_conf);
14832-
14833+
14834 buffer_free(s->auth_ldap_hostname);
14835 buffer_free(s->auth_ldap_basedn);
14836 buffer_free(s->auth_ldap_binddn);
14837 buffer_free(s->auth_ldap_bindpw);
14838 buffer_free(s->auth_ldap_filter);
14839 buffer_free(s->auth_ldap_cafile);
14840-
14841+
14842 #ifdef USE_LDAP
14843 buffer_free(s->ldap_filter_pre);
14844 buffer_free(s->ldap_filter_post);
14845-
14846+
14847 if (s->ldap) ldap_unbind_s(s->ldap);
14848 #endif
14849-
14850+
14851 free(s);
14852 }
14853 free(p->config_storage);
14854 }
14855-
14856+
14857 free(p);
14858-
14859+
14860 return HANDLER_GO_ON;
14861 }
14862
14863-#define PATCH(x) \
14864- p->conf.x = s->x;
14865 static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
14866 size_t i, j;
14867 mod_auth_plugin_config *s = p->config_storage[0];
14868
14869- PATCH(auth_backend);
14870- PATCH(auth_plain_groupfile);
14871- PATCH(auth_plain_userfile);
14872- PATCH(auth_htdigest_userfile);
14873- PATCH(auth_htpasswd_userfile);
14874- PATCH(auth_require);
14875- PATCH(auth_debug);
14876- PATCH(auth_ldap_hostname);
14877- PATCH(auth_ldap_basedn);
14878- PATCH(auth_ldap_binddn);
14879- PATCH(auth_ldap_bindpw);
14880- PATCH(auth_ldap_filter);
14881- PATCH(auth_ldap_cafile);
14882- PATCH(auth_ldap_starttls);
14883+ PATCH_OPTION(auth_backend);
14884+ PATCH_OPTION(auth_plain_groupfile);
14885+ PATCH_OPTION(auth_plain_userfile);
14886+ PATCH_OPTION(auth_htdigest_userfile);
14887+ PATCH_OPTION(auth_htpasswd_userfile);
14888+ PATCH_OPTION(auth_require);
14889+ PATCH_OPTION(auth_debug);
14890+ PATCH_OPTION(auth_ldap_hostname);
14891+ PATCH_OPTION(auth_ldap_basedn);
14892+ PATCH_OPTION(auth_ldap_binddn);
14893+ PATCH_OPTION(auth_ldap_bindpw);
14894+ PATCH_OPTION(auth_ldap_filter);
14895+ PATCH_OPTION(auth_ldap_cafile);
14896+ PATCH_OPTION(auth_ldap_starttls);
14897 #ifdef USE_LDAP
14898- PATCH(ldap);
14899- PATCH(ldap_filter_pre);
14900- PATCH(ldap_filter_post);
14901+ PATCH_OPTION(ldap);
14902+ PATCH_OPTION(ldap_filter_pre);
14903+ PATCH_OPTION(ldap_filter_post);
14904 #endif
14905-
14906+
14907 /* skip the first, the global context */
14908 for (i = 1; i < srv->config_context->used; i++) {
14909 data_config *dc = (data_config *)srv->config_context->data[i];
14910 s = p->config_storage[i];
14911-
14912+
14913 /* condition didn't match */
14914 if (!config_check_cond(srv, con, dc)) continue;
14915-
14916+
14917 /* merge config */
14918 for (j = 0; j < dc->value->used; j++) {
14919 data_unset *du = dc->value->data[j];
14920-
14921+
14922 if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
14923- PATCH(auth_backend);
14924+ PATCH_OPTION(auth_backend);
14925 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
14926- PATCH(auth_plain_groupfile);
14927+ PATCH_OPTION(auth_plain_groupfile);
14928 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
14929- PATCH(auth_plain_userfile);
14930+ PATCH_OPTION(auth_plain_userfile);
14931 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
14932- PATCH(auth_htdigest_userfile);
14933+ PATCH_OPTION(auth_htdigest_userfile);
14934 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
14935- PATCH(auth_htpasswd_userfile);
14936+ PATCH_OPTION(auth_htpasswd_userfile);
14937 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
14938- PATCH(auth_require);
14939+ PATCH_OPTION(auth_require);
14940 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
14941- PATCH(auth_debug);
14942+ PATCH_OPTION(auth_debug);
14943 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
14944- PATCH(auth_ldap_hostname);
14945+ PATCH_OPTION(auth_ldap_hostname);
14946 #ifdef USE_LDAP
14947- PATCH(ldap);
14948- PATCH(ldap_filter_pre);
14949- PATCH(ldap_filter_post);
14950+ PATCH_OPTION(ldap);
14951+ PATCH_OPTION(ldap_filter_pre);
14952+ PATCH_OPTION(ldap_filter_post);
14953 #endif
14954 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
14955- PATCH(auth_ldap_basedn);
14956+ PATCH_OPTION(auth_ldap_basedn);
14957 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
14958- PATCH(auth_ldap_filter);
14959+ PATCH_OPTION(auth_ldap_filter);
14960 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
14961- PATCH(auth_ldap_cafile);
14962+ PATCH_OPTION(auth_ldap_cafile);
14963 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
14964- PATCH(auth_ldap_starttls);
14965+ PATCH_OPTION(auth_ldap_starttls);
14966 }
14967 }
14968 }
14969-
14970+
14971 return 0;
14972 }
14973-#undef PATCH
14974
14975 static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
14976 size_t k;
14977@@ -175,22 +174,22 @@
14978 data_string *ds;
14979 mod_auth_plugin_data *p = p_d;
14980 array *req;
14981-
14982+
14983 /* select the right config */
14984 mod_auth_patch_connection(srv, con, p);
14985-
14986+
14987 if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
14988-
14989+
14990 /*
14991 * AUTH
14992- *
14993+ *
14994 */
14995-
14996+
14997 /* do we have to ask for auth ? */
14998-
14999+
15000 auth_required = 0;
15001 auth_satisfied = 0;
15002-
15003+
15004 /* search auth-directives for path */
15005 for (k = 0; k < p->conf.auth_require->used; k++) {
15006 buffer *req = p->conf.auth_require->data[k]->key;
15007@@ -212,31 +211,31 @@
15008 }
15009 }
15010 }
15011-
15012+
15013 /* nothing to do for us */
15014 if (auth_required == 0) return HANDLER_GO_ON;
15015-
15016+
15017 req = ((data_array *)(p->conf.auth_require->data[k]))->value;
15018-
15019+
15020 /* try to get Authorization-header */
15021-
15022+
15023 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
15024 http_authorization = ds->value->ptr;
15025 }
15026-
15027+
15028 if (ds && ds->value && ds->value->used) {
15029 char *auth_realm;
15030 data_string *method;
15031-
15032+
15033 method = (data_string *)array_get_element(req, "method");
15034-
15035+
15036 /* parse auth-header */
15037 if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
15038 int auth_type_len = auth_realm - http_authorization;
15039-
15040+
15041 if ((auth_type_len == 5) &&
15042 (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
15043-
15044+
15045 if (0 == strcmp(method->value->ptr, "basic")) {
15046 auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
15047 }
15048@@ -245,43 +244,43 @@
15049 if (0 == strcmp(method->value->ptr, "digest")) {
15050 if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
15051 con->http_status = 400;
15052-
15053+
15054 /* a field was missing */
15055-
15056+
15057 return HANDLER_FINISHED;
15058 }
15059 }
15060 } else {
15061- log_error_write(srv, __FILE__, __LINE__, "ss",
15062+ log_error_write(srv, __FILE__, __LINE__, "ss",
15063 "unknown authentification type:",
15064 http_authorization);
15065 }
15066 }
15067 }
15068-
15069+
15070 if (!auth_satisfied) {
15071 data_string *method, *realm;
15072 method = (data_string *)array_get_element(req, "method");
15073 realm = (data_string *)array_get_element(req, "realm");
15074-
15075+
15076 con->http_status = 401;
15077-
15078+
15079 if (0 == strcmp(method->value->ptr, "basic")) {
15080 buffer_copy_string(p->tmp_buf, "Basic realm=\"");
15081 buffer_append_string_buffer(p->tmp_buf, realm->value);
15082 buffer_append_string(p->tmp_buf, "\"");
15083-
15084+
15085 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15086 } else if (0 == strcmp(method->value->ptr, "digest")) {
15087 char hh[33];
15088 http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
15089-
15090+
15091 buffer_copy_string(p->tmp_buf, "Digest realm=\"");
15092 buffer_append_string_buffer(p->tmp_buf, realm->value);
15093 buffer_append_string(p->tmp_buf, "\", nonce=\"");
15094 buffer_append_string(p->tmp_buf, hh);
15095 buffer_append_string(p->tmp_buf, "\", qop=\"auth\"");
15096-
15097+
15098 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15099 } else {
15100 /* evil */
15101@@ -289,18 +288,18 @@
15102 return HANDLER_FINISHED;
15103 } else {
15104 /* the REMOTE_USER header */
15105-
15106+
15107 buffer_copy_string_buffer(con->authed_user, p->auth_user);
15108 }
15109-
15110+
15111 return HANDLER_GO_ON;
15112 }
15113
15114 SETDEFAULTS_FUNC(mod_auth_set_defaults) {
15115 mod_auth_plugin_data *p = p_d;
15116 size_t i;
15117-
15118- config_values_t cv[] = {
15119+
15120+ config_values_t cv[] = {
15121 { "auth.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15122 { "auth.backend.plain.groupfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15123 { "auth.backend.plain.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15124@@ -317,7 +316,7 @@
15125 { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
15126 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
15127 };
15128-
15129+
15130 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15131
15132 for (i = 0; i < srv->config_context->used; i++) {
15133@@ -325,14 +324,14 @@
15134 size_t n;
15135 data_array *da;
15136 array *ca;
15137-
15138+
15139 s = calloc(1, sizeof(mod_auth_plugin_config));
15140 s->auth_plain_groupfile = buffer_init();
15141 s->auth_plain_userfile = buffer_init();
15142 s->auth_htdigest_userfile = buffer_init();
15143 s->auth_htpasswd_userfile = buffer_init();
15144 s->auth_backend_conf = buffer_init();
15145-
15146+
15147 s->auth_ldap_hostname = buffer_init();
15148 s->auth_ldap_basedn = buffer_init();
15149 s->auth_ldap_binddn = buffer_init();
15150@@ -341,15 +340,15 @@
15151 s->auth_ldap_cafile = buffer_init();
15152 s->auth_ldap_starttls = 0;
15153 s->auth_debug = 0;
15154-
15155+
15156 s->auth_require = array_init();
15157-
15158+
15159 #ifdef USE_LDAP
15160 s->ldap_filter_pre = buffer_init();
15161 s->ldap_filter_post = buffer_init();
15162 s->ldap = NULL;
15163 #endif
15164-
15165+
15166 cv[0].destination = s->auth_backend_conf;
15167 cv[1].destination = s->auth_plain_groupfile;
15168 cv[2].destination = s->auth_plain_userfile;
15169@@ -364,14 +363,14 @@
15170 cv[11].destination = s->auth_htdigest_userfile;
15171 cv[12].destination = s->auth_htpasswd_userfile;
15172 cv[13].destination = &(s->auth_debug);
15173-
15174+
15175 p->config_storage[i] = s;
15176 ca = ((data_config *)srv->config_context->data[i])->value;
15177-
15178+
15179 if (0 != config_insert_values_global(srv, ca, cv)) {
15180 return HANDLER_ERROR;
15181 }
15182-
15183+
15184 if (s->auth_backend_conf->used) {
15185 if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
15186 s->auth_backend = AUTH_BACKEND_HTPASSWD;
15187@@ -383,31 +382,31 @@
15188 s->auth_backend = AUTH_BACKEND_LDAP;
15189 } else {
15190 log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
15191-
15192+
15193 return HANDLER_ERROR;
15194 }
15195 }
15196
15197 /* no auth.require for this section */
15198 if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
15199-
15200+
15201 if (da->type != TYPE_ARRAY) continue;
15202-
15203+
15204 for (n = 0; n < da->value->used; n++) {
15205 size_t m;
15206 data_array *da_file = (data_array *)da->value->data[n];
15207 const char *method, *realm, *require;
15208-
15209+
15210 if (da->value->data[n]->type != TYPE_ARRAY) {
15211- log_error_write(srv, __FILE__, __LINE__, "ss",
15212- "auth.require should contain an array as in:",
15213+ log_error_write(srv, __FILE__, __LINE__, "ss",
15214+ "auth.require should contain an array as in:",
15215 "auth.require = ( \"...\" => ( ..., ...) )");
15216
15217 return HANDLER_ERROR;
15218 }
15219-
15220+
15221 method = realm = require = NULL;
15222-
15223+
15224 for (m = 0; m < da_file->value->used; m++) {
15225 if (da_file->value->data[m]->type == TYPE_STRING) {
15226 if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
15227@@ -417,8 +416,8 @@
15228 } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
15229 require = ((data_string *)(da_file->value->data[m]))->value->ptr;
15230 } else {
15231- log_error_write(srv, __FILE__, __LINE__, "ssbs",
15232- "the field is unknown in:",
15233+ log_error_write(srv, __FILE__, __LINE__, "ssbs",
15234+ "the field is unknown in:",
15235 "auth.require = ( \"...\" => ( ..., -> \"",
15236 da_file->value->data[m]->key,
15237 "\" <- => \"...\" ) )");
15238@@ -426,19 +425,19 @@
15239 return HANDLER_ERROR;
15240 }
15241 } else {
15242- log_error_write(srv, __FILE__, __LINE__, "ssbs",
15243- "a string was expected for:",
15244+ log_error_write(srv, __FILE__, __LINE__, "ssbs",
15245+ "a string was expected for:",
15246 "auth.require = ( \"...\" => ( ..., -> \"",
15247 da_file->value->data[m]->key,
15248 "\" <- => \"...\" ) )");
15249-
15250+
15251 return HANDLER_ERROR;
15252 }
15253 }
15254-
15255+
15256 if (method == NULL) {
15257- log_error_write(srv, __FILE__, __LINE__, "ss",
15258- "the require field is missing in:",
15259+ log_error_write(srv, __FILE__, __LINE__, "ss",
15260+ "the require field is missing in:",
15261 "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
15262 return HANDLER_ERROR;
15263 } else {
15264@@ -450,60 +449,60 @@
15265 return HANDLER_ERROR;
15266 }
15267 }
15268-
15269+
15270 if (realm == NULL) {
15271- log_error_write(srv, __FILE__, __LINE__, "ss",
15272- "the require field is missing in:",
15273+ log_error_write(srv, __FILE__, __LINE__, "ss",
15274+ "the require field is missing in:",
15275 "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
15276 return HANDLER_ERROR;
15277 }
15278-
15279+
15280 if (require == NULL) {
15281- log_error_write(srv, __FILE__, __LINE__, "ss",
15282- "the require field is missing in:",
15283+ log_error_write(srv, __FILE__, __LINE__, "ss",
15284+ "the require field is missing in:",
15285 "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
15286 return HANDLER_ERROR;
15287 }
15288-
15289+
15290 if (method && realm && require) {
15291 data_string *ds;
15292 data_array *a;
15293-
15294+
15295 a = data_array_init();
15296 buffer_copy_string_buffer(a->key, da_file->key);
15297-
15298+
15299 ds = data_string_init();
15300-
15301+
15302 buffer_copy_string(ds->key, "method");
15303 buffer_copy_string(ds->value, method);
15304-
15305+
15306 array_insert_unique(a->value, (data_unset *)ds);
15307-
15308+
15309 ds = data_string_init();
15310-
15311+
15312 buffer_copy_string(ds->key, "realm");
15313 buffer_copy_string(ds->value, realm);
15314-
15315+
15316 array_insert_unique(a->value, (data_unset *)ds);
15317-
15318+
15319 ds = data_string_init();
15320-
15321+
15322 buffer_copy_string(ds->key, "require");
15323 buffer_copy_string(ds->value, require);
15324-
15325+
15326 array_insert_unique(a->value, (data_unset *)ds);
15327-
15328+
15329 array_insert_unique(s->auth_require, (data_unset *)a);
15330 }
15331 }
15332-
15333+
15334 switch(s->auth_backend) {
15335 case AUTH_BACKEND_PLAIN:
15336 if (s->auth_plain_userfile->used) {
15337 int fd;
15338 /* try to read */
15339 if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) {
15340- log_error_write(srv, __FILE__, __LINE__, "sbss",
15341+ log_error_write(srv, __FILE__, __LINE__, "sbss",
15342 "opening auth.backend.plain.userfile:", s->auth_plain_userfile,
15343 "failed:", strerror(errno));
15344 return HANDLER_ERROR;
15345@@ -516,7 +515,7 @@
15346 int fd;
15347 /* try to read */
15348 if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) {
15349- log_error_write(srv, __FILE__, __LINE__, "sbss",
15350+ log_error_write(srv, __FILE__, __LINE__, "sbss",
15351 "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile,
15352 "failed:", strerror(errno));
15353 return HANDLER_ERROR;
15354@@ -529,7 +528,7 @@
15355 int fd;
15356 /* try to read */
15357 if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) {
15358- log_error_write(srv, __FILE__, __LINE__, "sbss",
15359+ log_error_write(srv, __FILE__, __LINE__, "sbss",
15360 "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile,
15361 "failed:", strerror(errno));
15362 return HANDLER_ERROR;
15363@@ -554,75 +553,75 @@
15364 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
15365 #ifdef USE_LDAP
15366 int ret;
15367-#if 0
15368+#if 0
15369 if (s->auth_ldap_basedn->used == 0) {
15370 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
15371-
15372+
15373 return HANDLER_ERROR;
15374 }
15375 #endif
15376-
15377+
15378 if (s->auth_ldap_filter->used) {
15379 char *dollar;
15380-
15381+
15382 /* parse filter */
15383-
15384+
15385 if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
15386 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
15387-
15388+
15389 return HANDLER_ERROR;
15390 }
15391-
15392+
15393 buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
15394 buffer_copy_string(s->ldap_filter_post, dollar+1);
15395 }
15396-
15397+
15398 if (s->auth_ldap_hostname->used) {
15399 if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
15400 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
15401-
15402+
15403 return HANDLER_ERROR;
15404 }
15405-
15406+
15407 ret = LDAP_VERSION3;
15408 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
15409 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15410-
15411+
15412 return HANDLER_ERROR;
15413 }
15414
15415 if (s->auth_ldap_starttls) {
15416- /* if no CA file is given, it is ok, as we will use encryption
15417+ /* if no CA file is given, it is ok, as we will use encryption
15418 * if the server requires a CAfile it will tell us */
15419 if (!buffer_is_empty(s->auth_ldap_cafile)) {
15420- if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
15421+ if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
15422 s->auth_ldap_cafile->ptr))) {
15423- log_error_write(srv, __FILE__, __LINE__, "ss",
15424+ log_error_write(srv, __FILE__, __LINE__, "ss",
15425 "Loading CA certificate failed:", ldap_err2string(ret));
15426-
15427+
15428 return HANDLER_ERROR;
15429 }
15430 }
15431-
15432+
15433 if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL, NULL))) {
15434 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
15435-
15436+
15437 return HANDLER_ERROR;
15438 }
15439 }
15440-
15441-
15442+
15443+
15444 /* 1. */
15445 if (s->auth_ldap_binddn->used) {
15446 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
15447 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15448-
15449+
15450 return HANDLER_ERROR;
15451 }
15452 } else {
15453 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
15454 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15455-
15456+
15457 return HANDLER_ERROR;
15458 }
15459 }
15460@@ -641,8 +640,8 @@
15461 p->set_defaults = mod_auth_set_defaults;
15462 p->handle_uri_clean = mod_auth_uri_handler;
15463 p->cleanup = mod_auth_free;
15464-
15465+
15466 p->data = NULL;
15467-
15468+
15469 return 0;
15470 }
1175ccec 15471--- ../lighttpd-1.4.11/src/mod_cgi.c 2006-02-22 15:15:10.000000000 +0200
36e2a29e 15472+++ lighttpd-1.4.12/src/mod_cgi.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
15473@@ -1,21 +1,8 @@
15474 #include <sys/types.h>
15475-#ifdef __WIN32
15476-#include <winsock2.h>
15477-#else
15478-#include <sys/socket.h>
15479-#include <sys/wait.h>
15480-#include <sys/mman.h>
15481-
15482-#include <netinet/in.h>
15483-
15484-#include <arpa/inet.h>
15485-#endif
15486
15487-#include <unistd.h>
15488 #include <errno.h>
15489 #include <stdlib.h>
15490 #include <string.h>
15491-#include <fdevent.h>
15492 #include <signal.h>
15493 #include <ctype.h>
15494 #include <assert.h>
15495@@ -29,9 +16,16 @@
15496 #include "connections.h"
15497 #include "joblist.h"
15498 #include "http_chunk.h"
15499+#include "fdevent.h"
15500
15501 #include "plugin.h"
15502
15503+#include "sys-files.h"
15504+#include "sys-mmap.h"
15505+#include "sys-socket.h"
15506+#include "sys-strings.h"
15507+#include "sys-process.h"
15508+
15509 #ifdef HAVE_SYS_FILIO_H
15510 # include <sys/filio.h>
15511 #endif
15512@@ -40,11 +34,12 @@
15513
15514 typedef struct {
15515 char **ptr;
15516-
15517+
15518 size_t size;
15519 size_t used;
15520 } char_array;
15521
15522+#define pid_t int
15523 typedef struct {
15524 pid_t *ptr;
15525 size_t used;
15526@@ -58,23 +53,23 @@
15527 typedef struct {
15528 PLUGIN_DATA;
15529 buffer_pid_t cgi_pid;
15530-
15531+
15532 buffer *tmp_buf;
15533 buffer *parse_response;
15534-
15535+
15536 plugin_config **config_storage;
15537-
15538- plugin_config conf;
15539+
15540+ plugin_config conf;
15541 } plugin_data;
15542
15543 typedef struct {
15544 pid_t pid;
15545 int fd;
15546 int fde_ndx; /* index into the fd-event buffer */
15547-
15548+
15549 connection *remote_conn; /* dumb pointer */
15550 plugin_data *plugin_data; /* dumb pointer */
15551-
15552+
15553 buffer *response;
15554 buffer *response_header;
15555 } handler_ctx;
15556@@ -83,17 +78,17 @@
15557 handler_ctx *hctx = calloc(1, sizeof(*hctx));
15558
15559 assert(hctx);
15560-
15561+
15562 hctx->response = buffer_init();
15563 hctx->response_header = buffer_init();
15564-
15565+
15566 return hctx;
15567 }
15568
15569 static void cgi_handler_ctx_free(handler_ctx *hctx) {
15570 buffer_free(hctx->response);
15571 buffer_free(hctx->response_header);
15572-
15573+
15574 free(hctx);
15575 }
15576
15577@@ -101,14 +96,14 @@
15578
15579 INIT_FUNC(mod_cgi_init) {
15580 plugin_data *p;
15581-
15582+
15583 p = calloc(1, sizeof(*p));
15584
15585 assert(p);
15586-
15587+
15588 p->tmp_buf = buffer_init();
15589 p->parse_response = buffer_init();
15590-
15591+
15592 return p;
15593 }
15594
15595@@ -116,62 +111,62 @@
15596 FREE_FUNC(mod_cgi_free) {
15597 plugin_data *p = p_d;
15598 buffer_pid_t *r = &(p->cgi_pid);
15599-
15600+
15601 UNUSED(srv);
15602-
15603+
15604 if (p->config_storage) {
15605 size_t i;
15606 for (i = 0; i < srv->config_context->used; i++) {
15607 plugin_config *s = p->config_storage[i];
15608-
15609+
15610 array_free(s->cgi);
15611-
15612+
15613 free(s);
15614 }
15615 free(p->config_storage);
15616 }
15617-
15618+
15619
15620 if (r->ptr) free(r->ptr);
15621-
15622+
15623 buffer_free(p->tmp_buf);
15624 buffer_free(p->parse_response);
15625-
15626+
15627 free(p);
15628-
15629+
15630 return HANDLER_GO_ON;
15631 }
15632
15633 SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
15634 plugin_data *p = p_d;
15635 size_t i = 0;
15636-
15637- config_values_t cv[] = {
15638+
15639+ config_values_t cv[] = {
15640 { "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15641 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
15642 };
15643
15644 if (!p) return HANDLER_ERROR;
15645-
15646+
15647 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15648-
15649+
15650 for (i = 0; i < srv->config_context->used; i++) {
15651 plugin_config *s;
15652-
15653+
15654 s = calloc(1, sizeof(plugin_config));
15655 assert(s);
15656-
15657+
15658 s->cgi = array_init();
15659-
15660+
15661 cv[0].destination = s->cgi;
15662-
15663+
15664 p->config_storage[i] = s;
15665-
15666+
15667 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
15668 return HANDLER_ERROR;
15669 }
15670 }
15671-
15672+
15673 return HANDLER_GO_ON;
15674 }
15675
15676@@ -180,13 +175,13 @@
15677 int m = -1;
15678 size_t i;
15679 buffer_pid_t *r = &(p->cgi_pid);
15680-
15681+
15682 UNUSED(srv);
15683
15684 for (i = 0; i < r->used; i++) {
15685 if (r->ptr[i] > m) m = r->ptr[i];
15686 }
15687-
15688+
15689 if (r->size == 0) {
15690 r->size = 16;
15691 r->ptr = malloc(sizeof(*r->ptr) * r->size);
15692@@ -194,31 +189,31 @@
15693 r->size += 16;
15694 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
15695 }
15696-
15697+
15698 r->ptr[r->used++] = pid;
15699-
15700+
15701 return m;
15702 }
15703
15704 static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
15705 size_t i;
15706 buffer_pid_t *r = &(p->cgi_pid);
15707-
15708+
15709 UNUSED(srv);
15710
15711 for (i = 0; i < r->used; i++) {
15712 if (r->ptr[i] == pid) break;
15713 }
15714-
15715+
15716 if (i != r->used) {
15717 /* found */
15718-
15719+
15720 if (i != r->used - 1) {
15721 r->ptr[i] = r->ptr[r->used - 1];
15722 }
15723 r->used--;
15724 }
15725-
15726+
15727 return 0;
15728 }
15729
15730@@ -226,32 +221,32 @@
15731 char *ns;
15732 const char *s;
15733 int line = 0;
15734-
15735+
15736 UNUSED(srv);
15737-
15738+
15739 buffer_copy_string_buffer(p->parse_response, in);
15740-
15741- for (s = p->parse_response->ptr;
15742- NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
15743+
15744+ for (s = p->parse_response->ptr;
15745+ NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
15746 s = ns + (eol == EOL_RN ? 2 : 1), line++) {
15747 const char *key, *value;
15748 int key_len;
15749 data_string *ds;
15750-
15751+
15752 ns[0] = '\0';
15753-
15754- if (line == 0 &&
15755+
15756+ if (line == 0 &&
15757 0 == strncmp(s, "HTTP/1.", 7)) {
15758 /* non-parsed header ... we parse them anyway */
15759-
15760+
15761 if ((s[7] == '1' ||
15762 s[7] == '0') &&
15763 s[8] == ' ') {
15764 int status;
15765 /* after the space should be a status code for us */
15766-
15767+
15768 status = strtol(s+9, NULL, 10);
15769-
15770+
15771 if (con->http_status >= 100 &&
15772 con->http_status < 1000) {
15773 /* we expected 3 digits and didn't got them */
15774@@ -260,27 +255,27 @@
15775 }
15776 }
15777 } else {
15778-
15779+
15780 key = s;
15781 if (NULL == (value = strchr(s, ':'))) {
15782 /* we expect: "<key>: <value>\r\n" */
15783 continue;
15784 }
15785-
15786+
15787 key_len = value - key;
15788 value += 1;
15789-
15790+
15791 /* skip LWS */
15792 while (*value == ' ' || *value == '\t') value++;
15793-
15794+
15795 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
15796 ds = data_response_init();
15797 }
15798 buffer_copy_string_len(ds->key, key, key_len);
15799 buffer_copy_string(ds->value, value);
15800-
15801+
15802 array_insert_unique(con->response.headers, (data_unset *)ds);
15803-
15804+
15805 switch(key_len) {
15806 case 4:
15807 if (0 == strncasecmp(key, "Date", key_len)) {
15808@@ -315,13 +310,13 @@
15809 }
15810 }
15811 }
15812-
15813+
15814 /* CGI/1.1 rev 03 - 7.2.1.2 */
15815 if ((con->parsed_response & HTTP_LOCATION) &&
15816 !(con->parsed_response & HTTP_STATUS)) {
15817 con->http_status = 302;
15818 }
15819-
15820+
15821 return 0;
15822 }
15823
15824@@ -329,10 +324,10 @@
15825 static int cgi_demux_response(server *srv, handler_ctx *hctx) {
15826 plugin_data *p = hctx->plugin_data;
15827 connection *con = hctx->remote_conn;
15828-
15829+
15830 while(1) {
15831 int n;
15832-
15833+
15834 buffer_prepare_copy(hctx->response, 1024);
15835 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
15836 if (errno == EAGAIN || errno == EINTR) {
15837@@ -343,125 +338,125 @@
15838 log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
15839 return FDEVENT_HANDLED_ERROR;
15840 }
15841-
15842+
15843 if (n == 0) {
15844 /* read finished */
15845-
15846+
15847 con->file_finished = 1;
15848-
15849+
15850 /* send final chunk */
15851 http_chunk_append_mem(srv, con, NULL, 0);
15852 joblist_append(srv, con);
15853-
15854+
15855 return FDEVENT_HANDLED_FINISHED;
15856 }
15857-
15858+
15859 hctx->response->ptr[n] = '\0';
15860 hctx->response->used = n+1;
15861-
15862+
15863 /* split header from body */
15864-
15865+
15866 if (con->file_started == 0) {
15867 char *c;
15868 int in_header = 0;
15869 int header_end = 0;
15870 int cp, eol = EOL_UNSET;
15871 size_t used = 0;
15872-
15873+
15874 buffer_append_string_buffer(hctx->response_header, hctx->response);
15875-
15876+
15877 /* nph (non-parsed headers) */
15878 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
15879-
15880+
15881 /* search for the \r\n\r\n or \n\n in the string */
15882 for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
15883 if (*c == ':') in_header = 1;
15884 else if (*c == '\n') {
15885 if (in_header == 0) {
15886 /* got a response without a response header */
15887-
15888+
15889 c = NULL;
15890 header_end = 1;
15891 break;
15892 }
15893-
15894+
15895 if (eol == EOL_UNSET) eol = EOL_N;
15896-
15897+
15898 if (*(c+1) == '\n') {
15899 header_end = 1;
15900 break;
15901 }
15902-
15903+
15904 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
15905 if (in_header == 0) {
15906 /* got a response without a response header */
15907-
15908+
15909 c = NULL;
15910 header_end = 1;
15911 break;
15912 }
15913-
15914+
15915 if (eol == EOL_UNSET) eol = EOL_RN;
15916-
15917+
15918 if (used > 3 &&
15919- *(c+2) == '\r' &&
15920+ *(c+2) == '\r' &&
15921 *(c+3) == '\n') {
15922 header_end = 1;
15923 break;
15924 }
15925-
15926+
15927 /* skip the \n */
15928 c++;
15929 cp++;
15930 used--;
15931 }
15932 }
15933-
15934+
15935 if (header_end) {
15936 if (c == NULL) {
15937 /* no header, but a body */
15938-
15939+
15940 if (con->request.http_version == HTTP_VERSION_1_1) {
15941 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
15942 }
15943-
15944+
15945 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
15946 joblist_append(srv, con);
15947 } else {
15948 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
15949 size_t blen = hctx->response_header->used - hlen - 1;
15950-
15951+
15952 /* a small hack: terminate after at the second \r */
15953 hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
15954 hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
15955-
15956+
15957 /* parse the response header */
15958 cgi_response_parse(srv, con, p, hctx->response_header, eol);
15959-
15960+
15961 /* enable chunked-transfer-encoding */
15962 if (con->request.http_version == HTTP_VERSION_1_1 &&
15963 !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
15964 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
15965 }
15966-
15967+
15968 if ((hctx->response->used != hlen) && blen > 0) {
15969 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
15970 joblist_append(srv, con);
15971 }
15972 }
15973-
15974+
15975 con->file_started = 1;
15976 }
15977 } else {
15978 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
15979 joblist_append(srv, con);
15980 }
15981-
15982-#if 0
15983+
15984+#if 0
15985 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
15986 #endif
15987 }
15988-
15989+
15990 return FDEVENT_HANDLED_NOT_FINISHED;
15991 }
15992
15993@@ -470,45 +465,46 @@
15994 pid_t pid;
15995 plugin_data *p;
15996 connection *con;
15997-
15998+
15999 if (NULL == hctx) return HANDLER_GO_ON;
16000-
16001+
16002 p = hctx->plugin_data;
16003 con = hctx->remote_conn;
16004-
16005+
16006 if (con->mode != p->id) return HANDLER_GO_ON;
16007
16008-#ifndef __WIN32
16009-
16010+#ifndef _WIN32
16011+
16012 /* the connection to the browser went away, but we still have a connection
16013- * to the CGI script
16014+ * to the CGI script
16015 *
16016 * close cgi-connection
16017 */
16018-
16019+
16020 if (hctx->fd != -1) {
16021 /* close connection to the cgi-script */
16022 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16023 fdevent_unregister(srv->ev, hctx->fd);
16024-
16025+
16026 if (close(hctx->fd)) {
16027 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16028 }
16029-
16030+
16031 hctx->fd = -1;
16032 hctx->fde_ndx = -1;
16033 }
16034-
16035+
16036 pid = hctx->pid;
16037-
16038+
16039 con->plugin_ctx[p->id] = NULL;
16040-
16041+
16042 /* is this a good idea ? */
16043 cgi_handler_ctx_free(hctx);
16044-
16045+
16046 /* if waitpid hasn't been called by response.c yet, do it here */
16047 if (pid) {
16048 /* check if the CGI-script is already gone */
16049+#ifndef _WIN32
16050 switch(waitpid(pid, &status, WNOHANG)) {
16051 case 0:
16052 /* not finished yet */
16053@@ -519,19 +515,19 @@
16054 case -1:
16055 /* */
16056 if (errno == EINTR) break;
16057-
16058- /*
16059- * errno == ECHILD happens if _subrequest catches the process-status before
16060+
16061+ /*
16062+ * errno == ECHILD happens if _subrequest catches the process-status before
16063 * we have read the response of the cgi process
16064- *
16065+ *
16066 * -> catch status
16067 * -> WAIT_FOR_EVENT
16068 * -> read response
16069 * -> we get here with waitpid == ECHILD
16070- *
16071+ *
16072 */
16073 if (errno == ECHILD) return HANDLER_GO_ON;
16074-
16075+
16076 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16077 return HANDLER_ERROR;
16078 default:
16079@@ -541,13 +537,13 @@
16080 con->http_status = 500;
16081 con->mode = DIRECT;
16082 }
16083-
16084+
16085 if (WIFEXITED(status)) {
16086 #if 0
16087 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
16088 #endif
16089 pid = 0;
16090-
16091+
16092 return HANDLER_GO_ON;
16093 } else {
16094 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
16095@@ -555,20 +551,20 @@
16096 return HANDLER_GO_ON;
16097 }
16098 }
16099-
16100-
16101+
16102+
16103 kill(pid, SIGTERM);
16104-
16105+#endif
16106 /* cgi-script is still alive, queue the PID for removal */
16107 cgi_pid_add(srv, p, pid);
16108 }
16109-#endif
16110+#endif
16111 return HANDLER_GO_ON;
16112 }
16113
16114 static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
16115 plugin_data *p = p_d;
16116-
16117+
16118 return cgi_connection_close(srv, con->plugin_ctx[p->id]);
16119 }
16120
16121@@ -577,43 +573,43 @@
16122 server *srv = (server *)s;
16123 handler_ctx *hctx = ctx;
16124 connection *con = hctx->remote_conn;
16125-
16126+
16127 joblist_append(srv, con);
16128-
16129+
16130 if (hctx->fd == -1) {
16131 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
16132-
16133+
16134 return HANDLER_ERROR;
16135 }
16136-
16137+
16138 if (revents & FDEVENT_IN) {
16139 switch (cgi_demux_response(srv, hctx)) {
16140 case FDEVENT_HANDLED_NOT_FINISHED:
16141 break;
16142 case FDEVENT_HANDLED_FINISHED:
16143 /* we are done */
16144-
16145+
16146 #if 0
16147 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
16148 #endif
16149 cgi_connection_close(srv, hctx);
16150-
16151- /* if we get a IN|HUP and have read everything don't exec the close twice */
16152+
16153+ /* if we get a IN|HUP and have read everything don't exec the close twice */
16154 return HANDLER_FINISHED;
16155 case FDEVENT_HANDLED_ERROR:
16156 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
16157 con->http_status = 500;
16158 con->mode = DIRECT;
16159-
16160+
16161 log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
16162 break;
16163 }
16164 }
16165-
16166+
16167 if (revents & FDEVENT_OUT) {
16168 /* nothing to do */
16169 }
16170-
16171+
16172 /* perhaps this issue is already handled */
16173 if (revents & FDEVENT_HUP) {
16174 /* check if we still have a unfinished header package which is a body in reality */
16175@@ -623,54 +619,54 @@
16176 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16177 joblist_append(srv, con);
16178 }
16179-
16180+
16181 if (con->file_finished == 0) {
16182 http_chunk_append_mem(srv, con, NULL, 0);
16183 joblist_append(srv, con);
16184 }
16185-
16186+
16187 con->file_finished = 1;
16188-
16189+
16190 if (chunkqueue_is_empty(con->write_queue)) {
16191 /* there is nothing left to write */
16192 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
16193 } else {
16194 /* used the write-handler to finish the request on demand */
16195-
16196+
16197 }
16198-
16199+
16200 # if 0
16201 log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
16202 # endif
16203-
16204+
16205 /* rtsigs didn't liked the close */
16206 cgi_connection_close(srv, hctx);
16207 } else if (revents & FDEVENT_ERR) {
16208 con->file_finished = 1;
16209-
16210+
16211 /* kill all connections to the cgi process */
16212 cgi_connection_close(srv, hctx);
16213 #if 1
16214 log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
16215-#endif
16216+#endif
16217 return HANDLER_ERROR;
16218 }
16219-
16220+
16221 return HANDLER_FINISHED;
16222 }
16223
16224
16225 static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
16226 char *dst;
16227-
16228+
16229 if (!key || !val) return -1;
16230-
16231+
16232 dst = malloc(key_len + val_len + 3);
16233 memcpy(dst, key, key_len);
16234 dst[key_len] = '=';
16235 /* add the \0 from the value */
16236 memcpy(dst + key_len + 1, val, val_len + 1);
16237-
16238+
16239 if (env->size == 0) {
16240 env->size = 16;
16241 env->ptr = malloc(env->size * sizeof(*env->ptr));
16242@@ -678,45 +674,45 @@
16243 env->size += 16;
16244 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
16245 }
16246-
16247+
16248 env->ptr[env->used++] = dst;
16249-
16250+
16251 return 0;
16252 }
16253
16254 static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
16255 pid_t pid;
16256-
16257+
16258 #ifdef HAVE_IPV6
16259 char b2[INET6_ADDRSTRLEN + 1];
16260 #endif
16261-
16262+
16263 int to_cgi_fds[2];
16264 int from_cgi_fds[2];
16265 struct stat st;
16266-
16267-#ifndef __WIN32
16268-
16269+
16270+#ifndef _WIN32
16271+
16272 if (cgi_handler->used > 1) {
16273 /* stat the exec file */
16274 if (-1 == (stat(cgi_handler->ptr, &st))) {
16275- log_error_write(srv, __FILE__, __LINE__, "sbss",
16276+ log_error_write(srv, __FILE__, __LINE__, "sbss",
16277 "stat for cgi-handler", cgi_handler,
16278 "failed:", strerror(errno));
16279 return -1;
16280 }
16281 }
16282-
16283+
16284 if (pipe(to_cgi_fds)) {
16285 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16286 return -1;
16287 }
16288-
16289+
16290 if (pipe(from_cgi_fds)) {
16291 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16292 return -1;
16293 }
16294-
16295+
16296 /* fork, execve */
16297 switch (pid = fork()) {
16298 case 0: {
16299@@ -730,22 +726,22 @@
16300 char *c;
16301 const char *s;
16302 server_socket *srv_sock = con->srv_socket;
16303-
16304+
16305 /* move stdout to from_cgi_fd[1] */
16306 close(STDOUT_FILENO);
16307 dup2(from_cgi_fds[1], STDOUT_FILENO);
16308 close(from_cgi_fds[1]);
16309 /* not needed */
16310 close(from_cgi_fds[0]);
16311-
16312+
16313 /* move the stdin to to_cgi_fd[0] */
16314 close(STDIN_FILENO);
16315 dup2(to_cgi_fds[0], STDIN_FILENO);
16316 close(to_cgi_fds[0]);
16317 /* not needed */
16318 close(to_cgi_fds[1]);
16319-
16320- /* HACK:
16321+
16322+ /* HACK:
16323 * this is not nice, but it works
16324 *
16325 * we feed the stderr of the CGI to our errorlog, if possible
16326@@ -754,20 +750,20 @@
16327 close(STDERR_FILENO);
16328 dup2(srv->errorlog_fd, STDERR_FILENO);
16329 }
16330-
16331+
16332 /* create environment */
16333 env.ptr = NULL;
16334 env.size = 0;
16335 env.used = 0;
16336-
16337+
16338 cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
16339
16340 if (!buffer_is_empty(con->server_name)) {
16341 cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
16342 } else {
16343 #ifdef HAVE_IPV6
16344- s = inet_ntop(srv_sock->addr.plain.sa_family,
16345- srv_sock->addr.plain.sa_family == AF_INET6 ?
16346+ s = inet_ntop(srv_sock->addr.plain.sa_family,
16347+ srv_sock->addr.plain.sa_family == AF_INET6 ?
16348 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16349 (const void *) &(srv_sock->addr.ipv4.sin_addr),
16350 b2, sizeof(b2)-1);
16351@@ -779,10 +775,10 @@
16352 cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
16353
16354 s = get_http_version_name(con->request.http_version);
16355-
16356+
16357 cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
16358-
16359- ltostr(buf,
16360+
16361+ ltostr(buf,
16362 #ifdef HAVE_IPV6
16363 ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
16364 #else
16365@@ -790,10 +786,10 @@
16366 #endif
16367 );
16368 cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
16369-
16370+
16371 #ifdef HAVE_IPV6
16372- s = inet_ntop(srv_sock->addr.plain.sa_family,
16373- srv_sock->addr.plain.sa_family == AF_INET6 ?
16374+ s = inet_ntop(srv_sock->addr.plain.sa_family,
16375+ srv_sock->addr.plain.sa_family == AF_INET6 ?
16376 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16377 (const void *) &(srv_sock->addr.ipv4.sin_addr),
16378 b2, sizeof(b2)-1);
16379@@ -811,15 +807,18 @@
16380 cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
16381 if (!buffer_is_empty(con->uri.query)) {
16382 cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
16383+ } else {
16384+ /* set a empty QUERY_STRING */
16385+ cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
16386 }
16387 if (!buffer_is_empty(con->request.orig_uri)) {
16388 cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
16389 }
16390-
16391-
16392+
16393+
16394 #ifdef HAVE_IPV6
16395- s = inet_ntop(con->dst_addr.plain.sa_family,
16396- con->dst_addr.plain.sa_family == AF_INET6 ?
16397+ s = inet_ntop(con->dst_addr.plain.sa_family,
16398+ con->dst_addr.plain.sa_family == AF_INET6 ?
16399 (const void *) &(con->dst_addr.ipv6.sin6_addr) :
16400 (const void *) &(con->dst_addr.ipv4.sin_addr),
16401 b2, sizeof(b2)-1);
16402@@ -828,7 +827,7 @@
16403 #endif
16404 cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
16405
16406- ltostr(buf,
16407+ ltostr(buf,
16408 #ifdef HAVE_IPV6
16409 ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
16410 #else
16411@@ -836,19 +835,19 @@
16412 #endif
16413 );
16414 cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
16415-
16416+
16417 if (!buffer_is_empty(con->authed_user)) {
16418 cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
16419 CONST_BUF_LEN(con->authed_user));
16420 }
16421-
16422+
16423 /* request.content_length < SSIZE_MAX, see request.c */
16424 ltostr(buf, con->request.content_length);
16425 cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
16426 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
16427 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
16428 cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
16429-
16430+
16431 /* for valgrind */
16432 if (NULL != (s = getenv("LD_PRELOAD"))) {
16433 cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
16434@@ -863,24 +862,24 @@
16435 cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
16436 }
16437 #endif
16438-
16439+
16440 for (n = 0; n < con->request.headers->used; n++) {
16441 data_string *ds;
16442-
16443+
16444 ds = (data_string *)con->request.headers->data[n];
16445-
16446+
16447 if (ds->value->used && ds->key->used) {
16448 size_t j;
16449-
16450+
16451 buffer_reset(p->tmp_buf);
16452-
16453+
16454 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
16455 buffer_copy_string(p->tmp_buf, "HTTP_");
16456 p->tmp_buf->used--; /* strip \0 after HTTP_ */
16457 }
16458-
16459+
16460 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16461-
16462+
16463 for (j = 0; j < ds->key->used - 1; j++) {
16464 char cr = '_';
16465 if (light_isalpha(ds->key->ptr[j])) {
16466@@ -893,46 +892,46 @@
16467 p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
16468 }
16469 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16470-
16471+
16472 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16473 }
16474 }
16475-
16476+
16477 for (n = 0; n < con->environment->used; n++) {
16478 data_string *ds;
16479-
16480+
16481 ds = (data_string *)con->environment->data[n];
16482-
16483+
16484 if (ds->value->used && ds->key->used) {
16485 size_t j;
16486-
16487+
16488 buffer_reset(p->tmp_buf);
16489-
16490+
16491 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16492-
16493+
16494 for (j = 0; j < ds->key->used - 1; j++) {
16495- p->tmp_buf->ptr[p->tmp_buf->used++] =
16496- isalpha((unsigned char)ds->key->ptr[j]) ?
16497+ p->tmp_buf->ptr[p->tmp_buf->used++] =
16498+ isalpha((unsigned char)ds->key->ptr[j]) ?
16499 toupper((unsigned char)ds->key->ptr[j]) : '_';
16500 }
16501 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16502-
16503+
16504 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16505 }
16506 }
16507-
16508+
16509 if (env.size == env.used) {
16510 env.size += 16;
16511 env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
16512 }
16513-
16514+
16515 env.ptr[env.used] = NULL;
16516-
16517+
16518 /* set up args */
16519 argc = 3;
16520 args = malloc(sizeof(*args) * argc);
16521 i = 0;
16522-
16523+
16524 if (cgi_handler->used > 1) {
16525 args[i++] = cgi_handler->ptr;
16526 }
16527@@ -942,7 +941,7 @@
16528 /* search for the last / */
16529 if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
16530 *c = '\0';
16531-
16532+
16533 /* change to the physical directory */
16534 if (-1 == chdir(con->physical.path->ptr)) {
16535 log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
16536@@ -954,12 +953,12 @@
16537 for (i = 3; i < 256; i++) {
16538 if (i != srv->errorlog_fd) close(i);
16539 }
16540-
16541+
16542 /* exec the cgi */
16543 execve(args[0], args, env.ptr);
16544-
16545+
16546 log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
16547-
16548+
16549 /* */
16550 SEGFAULT();
16551 break;
16552@@ -974,11 +973,11 @@
16553
16554 close(from_cgi_fds[1]);
16555 close(to_cgi_fds[0]);
16556-
16557+
16558 if (con->request.content_length) {
16559 chunkqueue *cq = con->request_content_queue;
16560 chunk *c;
16561-
16562+
16563 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
16564
16565 /* there is content to send */
16566@@ -993,16 +992,16 @@
16567 if (-1 == c->file.fd && /* open the file if not already open */
16568 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
16569 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
16570-
16571+
16572 close(from_cgi_fds[0]);
16573 close(to_cgi_fds[1]);
16574 return -1;
16575 }
16576
16577 c->file.mmap.length = c->file.length;
16578-
16579+
16580 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
16581- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
16582+ log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
16583 strerror(errno), c->file.name, c->file.fd);
16584
16585 close(from_cgi_fds[0]);
16586@@ -1012,7 +1011,7 @@
16587
16588 close(c->file.fd);
16589 c->file.fd = -1;
16590-
16591+
16592 /* chunk_reset() or chunk_free() will cleanup for us */
16593 }
16594
16595@@ -1020,7 +1019,7 @@
16596 switch(errno) {
16597 case ENOSPC:
16598 con->http_status = 507;
16599-
16600+
16601 break;
16602 default:
16603 con->http_status = 403;
16604@@ -1033,7 +1032,7 @@
16605 switch(errno) {
16606 case ENOSPC:
16607 con->http_status = 507;
16608-
16609+
16610 break;
16611 default:
16612 con->http_status = 403;
16613@@ -1056,103 +1055,100 @@
16614 }
16615
16616 close(to_cgi_fds[1]);
16617-
16618+
16619 /* register PID and wait for them asyncronously */
16620 con->mode = p->id;
16621 buffer_reset(con->physical.path);
16622-
16623+
16624 hctx = cgi_handler_ctx_init();
16625-
16626+
16627 hctx->remote_conn = con;
16628 hctx->plugin_data = p;
16629 hctx->pid = pid;
16630 hctx->fd = from_cgi_fds[0];
16631 hctx->fde_ndx = -1;
16632-
16633+
16634 con->plugin_ctx[p->id] = hctx;
16635-
16636+
16637 fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
16638 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
16639-
16640+
16641 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
16642 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
16643-
16644+
16645 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16646 fdevent_unregister(srv->ev, hctx->fd);
16647-
16648+
16649 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
16650-
16651+
16652 close(hctx->fd);
16653-
16654+
16655 cgi_handler_ctx_free(hctx);
16656-
16657+
16658 con->plugin_ctx[p->id] = NULL;
16659-
16660+
16661 return -1;
16662 }
16663-
16664+
16665 break;
16666 }
16667 }
16668-
16669+
16670 return 0;
16671 #else
16672 return -1;
16673 #endif
16674 }
16675
16676-#define PATCH(x) \
16677- p->conf.x = s->x;
16678 static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
16679 size_t i, j;
16680 plugin_config *s = p->config_storage[0];
16681-
16682- PATCH(cgi);
16683-
16684+
16685+ PATCH_OPTION(cgi);
16686+
16687 /* skip the first, the global context */
16688 for (i = 1; i < srv->config_context->used; i++) {
16689 data_config *dc = (data_config *)srv->config_context->data[i];
16690 s = p->config_storage[i];
16691-
16692+
16693 /* condition didn't match */
16694 if (!config_check_cond(srv, con, dc)) continue;
16695-
16696+
16697 /* merge config */
16698 for (j = 0; j < dc->value->used; j++) {
16699 data_unset *du = dc->value->data[j];
16700-
16701+
16702 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
16703- PATCH(cgi);
16704+ PATCH_OPTION(cgi);
16705 }
16706 }
16707 }
16708-
16709+
16710 return 0;
16711 }
16712-#undef PATCH
16713
16714 URIHANDLER_FUNC(cgi_is_handled) {
16715 size_t k, s_len;
16716 plugin_data *p = p_d;
16717 buffer *fn = con->physical.path;
16718-
16719+
16720 if (fn->used == 0) return HANDLER_GO_ON;
16721-
16722+
16723 mod_cgi_patch_connection(srv, con, p);
16724-
16725+
16726 s_len = fn->used - 1;
16727-
16728+
16729 for (k = 0; k < p->conf.cgi->used; k++) {
16730 data_string *ds = (data_string *)p->conf.cgi->data[k];
16731 size_t ct_len = ds->key->used - 1;
16732-
16733+
16734 if (ds->key->used == 0) continue;
16735 if (s_len < ct_len) continue;
16736-
16737+
16738 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
16739 if (cgi_create_env(srv, con, p, ds->value)) {
16740 con->http_status = 500;
16741-
16742+
16743 buffer_reset(con->physical.path);
16744 return HANDLER_FINISHED;
16745 }
16746@@ -1160,7 +1156,7 @@
16747 break;
16748 }
16749 }
16750-
16751+
16752 return HANDLER_GO_ON;
16753 }
16754
16755@@ -1168,11 +1164,11 @@
16756 plugin_data *p = p_d;
16757 size_t ndx;
16758 /* the trigger handle only cares about lonely PID which we have to wait for */
16759-#ifndef __WIN32
16760+#ifndef _WIN32
16761
16762 for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
16763 int status;
16764-
16765+
16766 switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
16767 case 0:
16768 /* not finished yet */
16769@@ -1182,7 +1178,7 @@
16770 break;
16771 case -1:
16772 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16773-
16774+
16775 return HANDLER_ERROR;
16776 default:
16777
16778@@ -1193,16 +1189,16 @@
16779 } else {
16780 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
16781 }
16782-
16783+
16784 cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
16785- /* del modified the buffer structure
16786+ /* del modified the buffer structure
16787 * and copies the last entry to the current one
16788 * -> recheck the current index
16789 */
16790 ndx--;
16791 }
16792 }
16793-#endif
16794+#endif
16795 return HANDLER_GO_ON;
16796 }
16797
16798@@ -1210,15 +1206,15 @@
16799 int status;
16800 plugin_data *p = p_d;
16801 handler_ctx *hctx = con->plugin_ctx[p->id];
16802-
16803+
16804 if (con->mode != p->id) return HANDLER_GO_ON;
16805 if (NULL == hctx) return HANDLER_GO_ON;
16806-
16807+
16808 #if 0
16809 log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
16810-#endif
16811+#endif
16812 if (hctx->pid == 0) return HANDLER_FINISHED;
16813-#ifndef __WIN32
16814+#ifndef _WIN32
16815 switch(waitpid(hctx->pid, &status, WNOHANG)) {
16816 case 0:
16817 /* we only have for events here if we don't have the header yet,
16818@@ -1228,61 +1224,61 @@
16819 return HANDLER_WAIT_FOR_EVENT;
16820 case -1:
16821 if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
16822-
16823+
16824 if (errno == ECHILD && con->file_started == 0) {
16825 /*
16826- * second round but still not response
16827+ * second round but still not response
16828 */
16829- return HANDLER_WAIT_FOR_EVENT;
16830+ return HANDLER_WAIT_FOR_EVENT;
16831 }
16832-
16833+
16834 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16835 con->mode = DIRECT;
16836 con->http_status = 500;
16837-
16838+
16839 hctx->pid = 0;
16840-
16841+
16842 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16843 fdevent_unregister(srv->ev, hctx->fd);
16844-
16845+
16846 if (close(hctx->fd)) {
16847 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16848 }
16849-
16850+
16851 cgi_handler_ctx_free(hctx);
16852-
16853+
16854 con->plugin_ctx[p->id] = NULL;
16855-
16856+
16857 return HANDLER_FINISHED;
16858 default:
16859- /* cgi process exited cleanly
16860- *
16861- * check if we already got the response
16862+ /* cgi process exited cleanly
16863+ *
16864+ * check if we already got the response
16865 */
16866-
16867+
16868 if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
16869-
16870+
16871 if (WIFEXITED(status)) {
16872 /* nothing */
16873 } else {
16874 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
16875-
16876+
16877 con->mode = DIRECT;
16878 con->http_status = 500;
16879-
16880+
16881 }
16882-
16883+
16884 hctx->pid = 0;
16885-
16886+
16887 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16888 fdevent_unregister(srv->ev, hctx->fd);
16889-
16890+
16891 if (close(hctx->fd)) {
16892 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16893 }
16894-
16895+
16896 cgi_handler_ctx_free(hctx);
16897-
16898+
16899 con->plugin_ctx[p->id] = NULL;
16900 return HANDLER_FINISHED;
16901 }
16902@@ -1306,8 +1302,8 @@
16903 p->init = mod_cgi_init;
16904 p->cleanup = mod_cgi_free;
16905 p->set_defaults = mod_fastcgi_set_defaults;
16906-
16907+
16908 p->data = NULL;
16909-
16910+
16911 return 0;
16912 }
1175ccec 16913--- ../lighttpd-1.4.11/src/mod_cml.c 2006-01-30 13:51:48.000000000 +0200
36e2a29e 16914+++ lighttpd-1.4.12/src/mod_cml.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
16915@@ -4,7 +4,6 @@
16916 #include <stdlib.h>
16917 #include <string.h>
16918 #include <errno.h>
16919-#include <unistd.h>
16920 #include <stdio.h>
16921
16922 #include "buffer.h"
16923@@ -20,50 +19,50 @@
16924 /* init the plugin data */
16925 INIT_FUNC(mod_cml_init) {
16926 plugin_data *p;
16927-
16928+
16929 p = calloc(1, sizeof(*p));
16930-
16931+
16932 p->basedir = buffer_init();
16933 p->baseurl = buffer_init();
16934 p->trigger_handler = buffer_init();
16935-
16936+
16937 return p;
16938 }
16939
16940 /* detroy the plugin data */
16941 FREE_FUNC(mod_cml_free) {
16942 plugin_data *p = p_d;
16943-
16944+
16945 UNUSED(srv);
16946
16947 if (!p) return HANDLER_GO_ON;
16948-
16949+
16950 if (p->config_storage) {
16951 size_t i;
16952 for (i = 0; i < srv->config_context->used; i++) {
16953 plugin_config *s = p->config_storage[i];
16954-
16955+
16956 buffer_free(s->ext);
16957-
16958+
16959 buffer_free(s->mc_namespace);
16960 buffer_free(s->power_magnet);
16961 array_free(s->mc_hosts);
16962-
16963+
16964 #if defined(HAVE_MEMCACHE_H)
16965 if (s->mc) mc_free(s->mc);
16966 #endif
16967-
16968+
16969 free(s);
16970 }
16971 free(p->config_storage);
16972 }
16973-
16974+
16975 buffer_free(p->trigger_handler);
16976 buffer_free(p->basedir);
16977 buffer_free(p->baseurl);
16978-
16979+
16980 free(p);
16981-
16982+
16983 return HANDLER_GO_ON;
16984 }
16985
16986@@ -72,22 +71,22 @@
16987 SETDEFAULTS_FUNC(mod_cml_set_defaults) {
16988 plugin_data *p = p_d;
16989 size_t i = 0;
16990-
16991- config_values_t cv[] = {
16992+
16993+ config_values_t cv[] = {
16994 { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
16995 { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
16996 { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
16997 { "cml.power-magnet", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
16998 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
16999 };
17000-
17001+
17002 if (!p) return HANDLER_ERROR;
17003-
17004+
17005 p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
17006-
17007+
17008 for (i = 0; i < srv->config_context->used; i++) {
17009 plugin_config *s;
17010-
17011+
17012 s = malloc(sizeof(plugin_config));
17013 s->ext = buffer_init();
17014 s->mc_hosts = array_init();
17015@@ -96,87 +95,84 @@
17016 #if defined(HAVE_MEMCACHE_H)
17017 s->mc = NULL;
17018 #endif
17019-
17020+
17021 cv[0].destination = s->ext;
17022 cv[1].destination = s->mc_hosts;
17023 cv[2].destination = s->mc_namespace;
17024 cv[3].destination = s->power_magnet;
17025-
17026+
17027 p->config_storage[i] = s;
17028-
17029+
17030 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
17031 return HANDLER_ERROR;
17032 }
17033-
17034+
17035 if (s->mc_hosts->used) {
17036 #if defined(HAVE_MEMCACHE_H)
17037 size_t k;
17038 s->mc = mc_new();
17039-
17040+
17041 for (k = 0; k < s->mc_hosts->used; k++) {
17042 data_string *ds = (data_string *)s->mc_hosts->data[k];
17043-
17044+
17045 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
17046- log_error_write(srv, __FILE__, __LINE__, "sb",
17047- "connection to host failed:",
17048+ log_error_write(srv, __FILE__, __LINE__, "sb",
17049+ "connection to host failed:",
17050 ds->value);
17051-
17052+
17053 return HANDLER_ERROR;
17054 }
17055 }
17056 #else
17057- log_error_write(srv, __FILE__, __LINE__, "s",
17058+ log_error_write(srv, __FILE__, __LINE__, "s",
17059 "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
17060 return HANDLER_ERROR;
17061 #endif
17062 }
17063 }
17064-
17065+
17066 return HANDLER_GO_ON;
17067 }
17068
17069-#define PATCH(x) \
17070- p->conf.x = s->x;
17071 static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
17072 size_t i, j;
17073 plugin_config *s = p->config_storage[0];
17074-
17075- PATCH(ext);
17076+
17077+ PATCH_OPTION(ext);
17078 #if defined(HAVE_MEMCACHE_H)
17079- PATCH(mc);
17080+ PATCH_OPTION(mc);
17081 #endif
17082- PATCH(mc_namespace);
17083- PATCH(power_magnet);
17084-
17085+ PATCH_OPTION(mc_namespace);
17086+ PATCH_OPTION(power_magnet);
17087+
17088 /* skip the first, the global context */
17089 for (i = 1; i < srv->config_context->used; i++) {
17090 data_config *dc = (data_config *)srv->config_context->data[i];
17091 s = p->config_storage[i];
17092-
17093+
17094 /* condition didn't match */
17095 if (!config_check_cond(srv, con, dc)) continue;
17096-
17097+
17098 /* merge config */
17099 for (j = 0; j < dc->value->used; j++) {
17100 data_unset *du = dc->value->data[j];
17101-
17102+
17103 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
17104- PATCH(ext);
17105+ PATCH_OPTION(ext);
17106 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
17107 #if defined(HAVE_MEMCACHE_H)
17108- PATCH(mc);
17109+ PATCH_OPTION(mc);
17110 #endif
17111 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
17112- PATCH(mc_namespace);
17113+ PATCH_OPTION(mc_namespace);
17114 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
17115- PATCH(power_magnet);
17116+ PATCH_OPTION(power_magnet);
17117 }
17118 }
17119 }
17120-
17121+
17122 return 0;
17123 }
17124-#undef PATCH
17125
17126 int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
17127 buffer *b;
17128@@ -187,57 +183,57 @@
17129 b = p->baseurl;
17130 buffer_copy_string_buffer(b, con->uri.path);
17131 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17132-
17133+
17134 if (*c == '/') {
17135 b->used = c - b->ptr + 2;
17136 *(c+1) = '\0';
17137 }
17138-
17139+
17140 b = p->basedir;
17141 buffer_copy_string_buffer(b, con->physical.path);
17142 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17143-
17144+
17145 if (*c == '/') {
17146 b->used = c - b->ptr + 2;
17147 *(c+1) = '\0';
17148 }
17149-
17150+
17151
17152 /* prepare variables
17153 * - cookie-based
17154 * - get-param-based
17155 */
17156-
17157+
17158 return cache_parse_lua(srv, con, p, cml_file);
17159-
17160+
17161 }
17162
17163 URIHANDLER_FUNC(mod_cml_power_magnet) {
17164 plugin_data *p = p_d;
17165-
17166+
17167 mod_cml_patch_connection(srv, con, p);
17168-
17169+
17170 buffer_reset(p->basedir);
17171 buffer_reset(p->baseurl);
17172 buffer_reset(p->trigger_handler);
17173
17174 if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
17175-
17176- /*
17177+
17178+ /*
17179 * power-magnet:
17180 * cml.power-magnet = server.docroot + "/rewrite.cml"
17181 *
17182 * is called on EACH request, take the original REQUEST_URI and modifies the
17183- * request header as neccesary.
17184+ * request header as neccesary.
17185 *
17186 * First use:
17187 * if file_exists("/maintainance.html") {
17188 * output_include = ( "/maintainance.html" )
17189- * return CACHE_HIT
17190+ * return CACHE_HIT
17191 * }
17192 *
17193 * as we only want to rewrite HTML like requests we should cover it in a conditional
17194- *
17195+ *
17196 * */
17197
17198 switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
17199@@ -266,20 +262,20 @@
17200
17201 URIHANDLER_FUNC(mod_cml_is_handled) {
17202 plugin_data *p = p_d;
17203-
17204+
17205 if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
17206-
17207+
17208 mod_cml_patch_connection(srv, con, p);
17209-
17210+
17211 buffer_reset(p->basedir);
17212 buffer_reset(p->baseurl);
17213 buffer_reset(p->trigger_handler);
17214
17215 if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
17216-
17217+
17218 if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
17219 return HANDLER_GO_ON;
17220- }
17221+ }
17222
17223 switch(cache_call_lua(srv, con, p, con->physical.path)) {
17224 case -1:
17225@@ -311,15 +307,15 @@
17226 int mod_cml_plugin_init(plugin *p) {
17227 p->version = LIGHTTPD_VERSION_ID;
17228 p->name = buffer_init_string("cache");
17229-
17230+
17231 p->init = mod_cml_init;
17232 p->cleanup = mod_cml_free;
17233 p->set_defaults = mod_cml_set_defaults;
17234-
17235+
17236 p->handle_subrequest_start = mod_cml_is_handled;
17237 p->handle_physical = mod_cml_power_magnet;
17238-
17239+
17240 p->data = NULL;
17241-
17242+
17243 return 0;
17244 }
1175ccec 17245--- ../lighttpd-1.4.11/src/mod_cml.h 2006-01-30 13:51:35.000000000 +0200
36e2a29e 17246+++ lighttpd-1.4.12/src/mod_cml.h 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
17247@@ -16,10 +16,10 @@
17248
17249 typedef struct {
17250 buffer *ext;
17251-
17252+
17253 array *mc_hosts;
17254 buffer *mc_namespace;
17255-#if defined(HAVE_MEMCACHE_H)
17256+#if defined(HAVE_MEMCACHE_H)
17257 struct memcache *mc;
17258 #endif
17259 buffer *power_magnet;
17260@@ -27,15 +27,15 @@
17261
17262 typedef struct {
17263 PLUGIN_DATA;
17264-
17265+
17266 buffer *basedir;
17267 buffer *baseurl;
17268-
17269+
17270 buffer *trigger_handler;
17271-
17272+
17273 plugin_config **config_storage;
17274-
17275- plugin_config conf;
17276+
17277+ plugin_config conf;
17278 } plugin_data;
17279
17280 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
1175ccec 17281--- ../lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200
36e2a29e 17282+++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
17283@@ -4,8 +4,7 @@
17284 #include <stdlib.h>
17285 #include <string.h>
17286 #include <errno.h>
17287-#include <unistd.h>
17288-#include <dirent.h>
17289+
17290 #include <stdio.h>
17291
17292 #include "buffer.h"
17293@@ -13,6 +12,7 @@
17294 #include "log.h"
17295 #include "plugin.h"
17296 #include "response.h"
17297+#include "sys-files.h"
17298
17299 #include "mod_cml.h"
17300 #include "mod_cml_funcs.h"
17301@@ -30,7 +30,7 @@
17302 #ifdef USE_OPENSSL
17303 #define IN const
17304 #else
17305-#define IN
17306+#define IN
17307 #endif
17308 #define OUT
17309
17310@@ -42,29 +42,29 @@
17311 buffer b;
17312 char hex[33];
17313 int n = lua_gettop(L);
17314-
17315+
17316 b.ptr = hex;
17317 b.used = 0;
17318 b.size = sizeof(hex);
17319-
17320+
17321 if (n != 1) {
17322 lua_pushstring(L, "md5: expected one argument");
17323 lua_error(L);
17324 }
17325-
17326+
17327 if (!lua_isstring(L, 1)) {
17328 lua_pushstring(L, "md5: argument has to be a string");
17329 lua_error(L);
17330 }
17331-
17332+
17333 MD5_Init(&Md5Ctx);
17334 MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
17335 MD5_Final(HA1, &Md5Ctx);
17336-
17337+
17338 buffer_copy_string_hex(&b, (char *)HA1, 16);
17339-
17340+
17341 lua_pushstring(L, b.ptr);
17342-
17343+
17344 return 1;
17345 }
17346
17347@@ -72,37 +72,37 @@
17348 int f_file_mtime(lua_State *L) {
17349 struct stat st;
17350 int n = lua_gettop(L);
17351-
17352+
17353 if (n != 1) {
17354 lua_pushstring(L, "file_mtime: expected one argument");
17355 lua_error(L);
17356 }
17357-
17358+
17359 if (!lua_isstring(L, 1)) {
17360 lua_pushstring(L, "file_mtime: argument has to be a string");
17361 lua_error(L);
17362 }
17363-
17364+
17365 if (-1 == stat(lua_tostring(L, 1), &st)) {
17366 lua_pushnil(L);
17367 return 1;
17368 }
17369-
17370+
17371 lua_pushnumber(L, st.st_mtime);
17372-
17373+
17374 return 1;
17375 }
17376-
17377+#ifndef _WIN32
17378 int f_dir_files_iter(lua_State *L) {
17379 DIR *d;
17380 struct dirent *de;
17381-
17382+
17383 d = lua_touserdata(L, lua_upvalueindex(1));
17384-
17385+
17386 if (NULL == (de = readdir(d))) {
17387 /* EOF */
17388 closedir(d);
17389-
17390+
17391 return 0;
17392 } else {
17393 lua_pushstring(L, de->d_name);
17394@@ -113,75 +113,75 @@
17395 int f_dir_files(lua_State *L) {
17396 DIR *d;
17397 int n = lua_gettop(L);
17398-
17399+
17400 if (n != 1) {
17401 lua_pushstring(L, "dir_files: expected one argument");
17402 lua_error(L);
17403 }
17404-
17405+
17406 if (!lua_isstring(L, 1)) {
17407 lua_pushstring(L, "dir_files: argument has to be a string");
17408 lua_error(L);
17409 }
17410-
17411- /* check if there is a valid DIR handle on the stack */
17412+
17413+ /* check if there is a valid DIR handle on the stack */
17414 if (NULL == (d = opendir(lua_tostring(L, 1)))) {
17415 lua_pushnil(L);
17416 return 1;
17417 }
17418-
17419+
17420 /* push d into registry */
17421 lua_pushlightuserdata(L, d);
17422 lua_pushcclosure(L, f_dir_files_iter, 1);
17423-
17424+
17425 return 1;
17426 }
17427-
17428+#endif
17429 int f_file_isreg(lua_State *L) {
17430 struct stat st;
17431 int n = lua_gettop(L);
17432-
17433+
17434 if (n != 1) {
17435 lua_pushstring(L, "file_isreg: expected one argument");
17436 lua_error(L);
17437 }
17438-
17439+
17440 if (!lua_isstring(L, 1)) {
17441 lua_pushstring(L, "file_isreg: argument has to be a string");
17442 lua_error(L);
17443 }
17444-
17445+
17446 if (-1 == stat(lua_tostring(L, 1), &st)) {
17447 lua_pushnil(L);
17448 return 1;
17449 }
17450-
17451+
17452 lua_pushnumber(L, S_ISREG(st.st_mode));
17453-
17454+
17455 return 1;
17456 }
17457
17458 int f_file_isdir(lua_State *L) {
17459 struct stat st;
17460 int n = lua_gettop(L);
17461-
17462+
17463 if (n != 1) {
17464 lua_pushstring(L, "file_isreg: expected one argument");
17465 lua_error(L);
17466 }
17467-
17468+
17469 if (!lua_isstring(L, 1)) {
17470 lua_pushstring(L, "file_isreg: argument has to be a string");
17471 lua_error(L);
17472 }
17473-
17474+
17475 if (-1 == stat(lua_tostring(L, 1), &st)) {
17476 lua_pushnil(L);
17477 return 1;
17478 }
17479-
17480+
17481 lua_pushnumber(L, S_ISDIR(st.st_mode));
17482-
17483+
17484 return 1;
17485 }
17486
17487@@ -192,33 +192,33 @@
17488 char *r;
17489 int n = lua_gettop(L);
17490 struct memcache *mc;
17491-
17492+
17493 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17494 lua_pushstring(L, "where is my userdata ?");
17495 lua_error(L);
17496 }
17497-
17498+
17499 mc = lua_touserdata(L, lua_upvalueindex(1));
17500-
17501+
17502 if (n != 1) {
17503 lua_pushstring(L, "expected one argument");
17504 lua_error(L);
17505 }
17506-
17507+
17508 if (!lua_isstring(L, 1)) {
17509 lua_pushstring(L, "argument has to be a string");
17510 lua_error(L);
17511 }
17512-
17513- if (NULL == (r = mc_aget(mc,
17514+
17515+ if (NULL == (r = mc_aget(mc,
17516 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17517-
17518+
17519 lua_pushboolean(L, 0);
17520 return 1;
17521 }
17522-
17523+
17524 free(r);
17525-
17526+
17527 lua_pushboolean(L, 1);
17528 return 1;
17529 }
17530@@ -226,74 +226,74 @@
17531 int f_memcache_get_string(lua_State *L) {
17532 char *r;
17533 int n = lua_gettop(L);
17534-
17535+
17536 struct memcache *mc;
17537-
17538+
17539 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17540 lua_pushstring(L, "where is my userdata ?");
17541 lua_error(L);
17542 }
17543-
17544+
17545 mc = lua_touserdata(L, lua_upvalueindex(1));
17546-
17547-
17548+
17549+
17550 if (n != 1) {
17551 lua_pushstring(L, "expected one argument");
17552 lua_error(L);
17553 }
17554-
17555+
17556 if (!lua_isstring(L, 1)) {
17557 lua_pushstring(L, "argument has to be a string");
17558 lua_error(L);
17559 }
17560-
17561- if (NULL == (r = mc_aget(mc,
17562+
17563+ if (NULL == (r = mc_aget(mc,
17564 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17565 lua_pushnil(L);
17566 return 1;
17567 }
17568-
17569+
17570 lua_pushstring(L, r);
17571-
17572+
17573 free(r);
17574-
17575+
17576 return 1;
17577 }
17578
17579 int f_memcache_get_long(lua_State *L) {
17580 char *r;
17581 int n = lua_gettop(L);
17582-
17583+
17584 struct memcache *mc;
17585-
17586+
17587 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17588 lua_pushstring(L, "where is my userdata ?");
17589 lua_error(L);
17590 }
17591-
17592+
17593 mc = lua_touserdata(L, lua_upvalueindex(1));
17594-
17595-
17596+
17597+
17598 if (n != 1) {
17599 lua_pushstring(L, "expected one argument");
17600 lua_error(L);
17601 }
17602-
17603+
17604 if (!lua_isstring(L, 1)) {
17605 lua_pushstring(L, "argument has to be a string");
17606 lua_error(L);
17607 }
17608-
17609- if (NULL == (r = mc_aget(mc,
17610+
17611+ if (NULL == (r = mc_aget(mc,
17612 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17613 lua_pushnil(L);
17614 return 1;
17615 }
17616-
17617+
17618 lua_pushnumber(L, strtol(r, NULL, 10));
17619-
17620+
17621 free(r);
17622-
17623+
17624 return 1;
17625 }
17626 #endif
1175ccec 17627--- ../lighttpd-1.4.11/src/mod_cml_lua.c 2006-01-30 13:56:40.000000000 +0200
36e2a29e 17628+++ lighttpd-1.4.12/src/mod_cml_lua.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
17629@@ -23,7 +23,7 @@
17630 #ifdef USE_OPENSSL
17631 #define IN const
17632 #else
17633-#define IN
17634+#define IN
17635 #endif
17636 #define OUT
17637
17638@@ -31,6 +31,7 @@
17639
17640 #include <lua.h>
17641 #include <lualib.h>
17642+#include <lauxlib.h>
17643
17644 typedef struct {
17645 stream st;
17646@@ -39,11 +40,11 @@
17647
17648 static const char * load_file(lua_State *L, void *data, size_t *size) {
17649 readme *rm = data;
17650-
17651+
17652 UNUSED(L);
17653-
17654+
17655 if (rm->done) return 0;
17656-
17657+
17658 *size = rm->st.size;
17659 rm->done = 1;
17660 return rm->st.start;
17661@@ -51,47 +52,47 @@
17662
17663 static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
17664 int curelem;
17665-
17666+
17667 lua_pushstring(L, varname);
17668-
17669+
17670 curelem = lua_gettop(L);
17671 lua_gettable(L, LUA_GLOBALSINDEX);
17672-
17673+
17674 /* it should be a table */
17675 if (!lua_isstring(L, curelem)) {
17676 lua_settop(L, curelem - 1);
17677-
17678+
17679 return -1;
17680 }
17681-
17682+
17683 buffer_copy_string(b, lua_tostring(L, curelem));
17684-
17685+
17686 lua_pop(L, 1);
17687-
17688+
17689 assert(curelem - 1 == lua_gettop(L));
17690-
17691+
17692 return 0;
17693 }
17694
17695 static int lua_to_c_is_table(lua_State *L, const char *varname) {
17696 int curelem;
17697-
17698+
17699 lua_pushstring(L, varname);
17700-
17701+
17702 curelem = lua_gettop(L);
17703 lua_gettable(L, LUA_GLOBALSINDEX);
17704-
17705+
17706 /* it should be a table */
17707 if (!lua_istable(L, curelem)) {
17708 lua_settop(L, curelem - 1);
17709-
17710+
17711 return 0;
17712 }
17713-
17714+
17715 lua_settop(L, curelem - 1);
17716-
17717+
17718 assert(curelem - 1 == lua_gettop(L));
17719-
17720+
17721 return 1;
17722 }
17723
17724@@ -99,7 +100,7 @@
17725 lua_pushlstring(L, key, key_len);
17726 lua_pushlstring(L, val, val_len);
17727 lua_settable(L, tbl);
17728-
17729+
17730 return 0;
17731 }
17732
17733@@ -108,21 +109,21 @@
17734 size_t is_key = 1;
17735 size_t i;
17736 char *key = NULL, *val = NULL;
17737-
17738+
17739 key = qrystr->ptr;
17740-
17741+
17742 /* we need the \0 */
17743 for (i = 0; i < qrystr->used; i++) {
17744 switch(qrystr->ptr[i]) {
17745 case '=':
17746 if (is_key) {
17747 val = qrystr->ptr + i + 1;
17748-
17749+
17750 qrystr->ptr[i] = '\0';
17751-
17752+
17753 is_key = 0;
17754 }
17755-
17756+
17757 break;
17758 case '&':
17759 case '\0': /* fin symbol */
17760@@ -131,19 +132,19 @@
17761
17762 /* terminate the value */
17763 qrystr->ptr[i] = '\0';
17764-
17765- c_to_lua_push(L, tbl,
17766+
17767+ c_to_lua_push(L, tbl,
17768 key, strlen(key),
17769 val, strlen(val));
17770 }
17771-
17772+
17773 key = qrystr->ptr + i + 1;
17774 val = NULL;
17775 is_key = 1;
17776 break;
17777 }
17778 }
17779-
17780+
17781 return 0;
17782 }
17783 #if 0
17784@@ -151,21 +152,21 @@
17785 data_unset *d;
17786
17787 UNUSED(srv);
17788-
17789+
17790 if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
17791 data_string *ds = (data_string *)d;
17792 size_t key = 0, value = 0;
17793 size_t is_key = 1, is_sid = 0;
17794 size_t i;
17795-
17796+
17797 /* found COOKIE */
17798 if (!DATA_IS_STRING(d)) return -1;
17799 if (ds->value->used == 0) return -1;
17800-
17801+
17802 if (ds->value->ptr[0] == '\0' ||
17803 ds->value->ptr[0] == '=' ||
17804 ds->value->ptr[0] == ';') return -1;
17805-
17806+
17807 buffer_reset(p->session_id);
17808 for (i = 0; i < ds->value->used; i++) {
17809 switch(ds->value->ptr[i]) {
17810@@ -176,16 +177,16 @@
17811 is_sid = 1;
17812 }
17813 value = i + 1;
17814-
17815+
17816 is_key = 0;
17817 }
17818-
17819+
17820 break;
17821 case ';':
17822 if (is_sid) {
17823 buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
17824 }
17825-
17826+
17827 is_sid = 0;
17828 key = i + 1;
17829 value = 0;
17830@@ -204,48 +205,43 @@
17831 }
17832 }
17833 }
17834-
17835+
17836 return 0;
17837 }
17838 #endif
17839
17840 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
17841- lua_State *L;
17842+ lua_State *L;
17843 readme rm;
17844 int ret = -1;
17845 buffer *b = buffer_init();
17846 int header_tbl = 0;
17847-
17848+
17849 rm.done = 0;
17850 stream_open(&rm.st, fn);
17851-
17852+
17853 /* push the lua file to the interpreter and see what happends */
17854- L = lua_open();
17855-
17856- luaopen_base(L);
17857- luaopen_table(L);
17858- luaopen_string(L);
17859- luaopen_math(L);
17860- luaopen_io(L);
17861-
17862+ L = luaL_newstate();
17863+ luaL_openlibs(L);
17864+
17865 /* register functions */
17866 lua_register(L, "md5", f_crypto_md5);
17867 lua_register(L, "file_mtime", f_file_mtime);
17868 lua_register(L, "file_isreg", f_file_isreg);
17869 lua_register(L, "file_isdir", f_file_isreg);
17870 lua_register(L, "dir_files", f_dir_files);
17871-
17872+
17873 #ifdef HAVE_MEMCACHE_H
17874 lua_pushliteral(L, "memcache_get_long");
17875 lua_pushlightuserdata(L, p->conf.mc);
17876 lua_pushcclosure(L, f_memcache_get_long, 1);
17877 lua_settable(L, LUA_GLOBALSINDEX);
17878-
17879+
17880 lua_pushliteral(L, "memcache_get_string");
17881 lua_pushlightuserdata(L, p->conf.mc);
17882 lua_pushcclosure(L, f_memcache_get_string, 1);
17883 lua_settable(L, LUA_GLOBALSINDEX);
17884-
17885+
17886 lua_pushliteral(L, "memcache_exists");
17887 lua_pushlightuserdata(L, p->conf.mc);
17888 lua_pushcclosure(L, f_memcache_exists, 1);
17889@@ -255,11 +251,11 @@
17890 lua_pushliteral(L, "request");
17891 lua_newtable(L);
17892 lua_settable(L, LUA_GLOBALSINDEX);
17893-
17894+
17895 lua_pushliteral(L, "request");
17896 header_tbl = lua_gettop(L);
17897 lua_gettable(L, LUA_GLOBALSINDEX);
17898-
17899+
17900 c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
17901 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
17902 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
17903@@ -267,84 +263,84 @@
17904 if (!buffer_is_empty(con->request.pathinfo)) {
17905 c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
17906 }
17907-
17908+
17909 c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
17910 c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
17911-
17912+
17913 /* register GET parameter */
17914 lua_pushliteral(L, "get");
17915 lua_newtable(L);
17916 lua_settable(L, LUA_GLOBALSINDEX);
17917-
17918+
17919 lua_pushliteral(L, "get");
17920 header_tbl = lua_gettop(L);
17921 lua_gettable(L, LUA_GLOBALSINDEX);
17922-
17923+
17924 buffer_copy_string_buffer(b, con->uri.query);
17925 cache_export_get_params(L, header_tbl, b);
17926 buffer_reset(b);
17927
17928- /* 2 default constants */
17929+ /* 2 default constants */
17930 lua_pushliteral(L, "CACHE_HIT");
17931 lua_pushboolean(L, 0);
17932 lua_settable(L, LUA_GLOBALSINDEX);
17933-
17934+
17935 lua_pushliteral(L, "CACHE_MISS");
17936 lua_pushboolean(L, 1);
17937 lua_settable(L, LUA_GLOBALSINDEX);
17938-
17939+
17940 /* load lua program */
17941 if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
17942 log_error_write(srv, __FILE__, __LINE__, "s",
17943 lua_tostring(L,-1));
17944-
17945+
17946 goto error;
17947 }
17948-
17949+
17950 /* get return value */
17951 ret = (int)lua_tonumber(L, -1);
17952 lua_pop(L, 1);
17953-
17954- /* fetch the data from lua */
17955+
17956+ /* fetch the data from lua */
17957 lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
17958-
17959+
17960 if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
17961 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
17962 }
17963-
17964+
17965 if (ret == 0) {
17966 /* up to now it is a cache-hit, check if all files exist */
17967-
17968+
17969 int curelem;
17970 time_t mtime = 0;
17971-
17972+
17973 if (!lua_to_c_is_table(L, "output_include")) {
17974 log_error_write(srv, __FILE__, __LINE__, "s",
17975 "output_include is missing or not a table");
17976 ret = -1;
17977-
17978+
17979 goto error;
17980 }
17981-
17982+
17983 lua_pushstring(L, "output_include");
17984-
17985+
17986 curelem = lua_gettop(L);
17987 lua_gettable(L, LUA_GLOBALSINDEX);
17988
17989 /* HOW-TO build a etag ?
17990- * as we don't just have one file we have to take the stat()
17991+ * as we don't just have one file we have to take the stat()
17992 * from all base files, merge them and build the etag from
17993 * it later.
17994- *
17995+ *
17996 * The mtime of the content is the mtime of the freshest base file
17997- *
17998+ *
17999 * */
18000-
18001+
18002 lua_pushnil(L); /* first key */
18003 while (lua_next(L, curelem) != 0) {
18004 stat_cache_entry *sce = NULL;
18005 /* key' is at index -2 and value' at index -1 */
18006-
18007+
18008 if (lua_isstring(L, -1)) {
18009 const char *s = lua_tostring(L, -1);
18010
18011@@ -364,18 +360,18 @@
18012 /* a file is missing, call the handler to generate it */
18013 if (!buffer_is_empty(p->trigger_handler)) {
18014 ret = 1; /* cache-miss */
18015-
18016+
18017 log_error_write(srv, __FILE__, __LINE__, "s",
18018 "a file is missing, calling handler");
18019-
18020+
18021 break;
18022 } else {
18023 /* handler not set -> 500 */
18024 ret = -1;
18025-
18026+
18027 log_error_write(srv, __FILE__, __LINE__, "s",
18028 "a file missing and no handler set");
18029-
18030+
18031 break;
18032 }
18033 break;
18034@@ -393,12 +389,12 @@
18035 "not a string");
18036 break;
18037 }
18038-
18039+
18040 lua_pop(L, 1); /* removes value'; keeps key' for next iteration */
18041 }
18042-
18043+
18044 lua_settop(L, curelem - 1);
18045-
18046+
18047 if (ret == 0) {
18048 data_string *ds;
18049 char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
18050@@ -410,9 +406,9 @@
18051
18052 /* no Last-Modified specified */
18053 if ((mtime) && (NULL == ds)) {
18054-
18055+
18056 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
18057-
18058+
18059 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
18060
18061
18062@@ -428,9 +424,9 @@
18063 tbuf.used = 0;
18064 tbuf.ptr = NULL;
18065 }
18066-
18067+
18068 if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
18069- /* ok, the client already has our content,
18070+ /* ok, the client already has our content,
18071 * no need to send it again */
18072
18073 chunkqueue_reset(con->write_queue);
18074@@ -440,24 +436,24 @@
18075 chunkqueue_reset(con->write_queue);
18076 }
18077 }
18078-
18079+
18080 if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
18081 /* cache-miss */
18082 buffer_copy_string_buffer(con->uri.path, p->baseurl);
18083 buffer_append_string_buffer(con->uri.path, p->trigger_handler);
18084-
18085+
18086 buffer_copy_string_buffer(con->physical.path, p->basedir);
18087 buffer_append_string_buffer(con->physical.path, p->trigger_handler);
18088-
18089+
18090 chunkqueue_reset(con->write_queue);
18091 }
18092-
18093+
18094 error:
18095 lua_close(L);
18096-
18097+
18098 stream_close(&rm.st);
18099 buffer_free(b);
18100-
18101+
18102 return ret /* cache-error */;
18103 }
18104 #else
1175ccec 18105--- ../lighttpd-1.4.11/src/mod_compress.c 2005-11-18 13:49:14.000000000 +0200
36e2a29e 18106+++ lighttpd-1.4.12/src/mod_compress.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
18107@@ -2,7 +2,6 @@
18108 #include <sys/stat.h>
18109
18110 #include <fcntl.h>
18111-#include <unistd.h>
18112 #include <ctype.h>
18113 #include <stdlib.h>
18114 #include <string.h>
18115@@ -14,6 +13,7 @@
18116 #include "buffer.h"
18117 #include "response.h"
18118 #include "stat_cache.h"
18119+#include "http_chunk.h"
18120
18121 #include "plugin.h"
18122
18123@@ -33,6 +33,7 @@
18124 #endif
18125
18126 #include "sys-mmap.h"
18127+#include "sys-files.h"
18128
18129 /* request: accept-encoding */
18130 #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
18131@@ -55,97 +56,127 @@
18132 PLUGIN_DATA;
18133 buffer *ofn;
18134 buffer *b;
18135-
18136+
18137 plugin_config **config_storage;
18138- plugin_config conf;
18139+ plugin_config conf;
18140 } plugin_data;
18141
18142 INIT_FUNC(mod_compress_init) {
18143 plugin_data *p;
18144-
18145+
18146 p = calloc(1, sizeof(*p));
18147-
18148+
18149 p->ofn = buffer_init();
18150 p->b = buffer_init();
18151-
18152+
18153 return p;
18154 }
18155
18156 FREE_FUNC(mod_compress_free) {
18157 plugin_data *p = p_d;
18158-
18159+
18160 UNUSED(srv);
18161
18162 if (!p) return HANDLER_GO_ON;
18163-
18164+
18165 buffer_free(p->ofn);
18166 buffer_free(p->b);
18167-
18168+
18169 if (p->config_storage) {
18170 size_t i;
18171 for (i = 0; i < srv->config_context->used; i++) {
18172 plugin_config *s = p->config_storage[i];
18173
18174 if (!s) continue;
18175-
18176+
18177 array_free(s->compress);
18178 buffer_free(s->compress_cache_dir);
18179-
18180+
18181 free(s);
18182 }
18183 free(p->config_storage);
18184 }
18185-
18186-
18187+
18188+
18189 free(p);
18190-
18191+
18192 return HANDLER_GO_ON;
18193 }
18194
18195+void mkdir_recursive(const char *dir) {
18196+
18197+ char dir_copy[256];
18198+ char *p = dir_copy;
18199+
18200+ if (!dir || !dir[0])
18201+ return;
18202+
18203+ strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
18204+
18205+ while ((p = strchr(p + 1, '/')) != NULL) {
18206+
18207+ *p = '\0';
18208+ if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
18209+ return;
18210+
18211+ *p++ = '/';
18212+ }
18213+
18214+ mkdir(dir, 0700);
18215+}
18216+
18217 SETDEFAULTS_FUNC(mod_compress_setdefaults) {
18218 plugin_data *p = p_d;
18219 size_t i = 0;
18220-
18221- config_values_t cv[] = {
18222+
18223+ config_values_t cv[] = {
18224 { "compress.cache-dir", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
18225 { "compress.filetype", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
18226 { "compress.max-filesize", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
18227 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
18228 };
18229-
18230+
18231 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
18232-
18233+
18234 for (i = 0; i < srv->config_context->used; i++) {
18235 plugin_config *s;
18236-
18237+
18238 s = calloc(1, sizeof(plugin_config));
18239 s->compress_cache_dir = buffer_init();
18240 s->compress = array_init();
18241 s->compress_max_filesize = 0;
18242-
18243+
18244 cv[0].destination = s->compress_cache_dir;
18245 cv[1].destination = s->compress;
18246 cv[2].destination = &(s->compress_max_filesize);
18247-
18248+
18249 p->config_storage[i] = s;
18250-
18251+
18252 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18253 return HANDLER_ERROR;
18254 }
18255-
18256+
18257 if (!buffer_is_empty(s->compress_cache_dir)) {
18258 struct stat st;
18259 if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18260- log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
18261+
18262+ log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
18263 s->compress_cache_dir, strerror(errno));
18264-
18265- return HANDLER_ERROR;
18266+ mkdir_recursive(s->compress_cache_dir->ptr);
18267+
18268+ if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18269+
18270+ log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
18271+ s->compress_cache_dir, strerror(errno));
18272+
18273+ return HANDLER_ERROR;
18274+ }
18275 }
18276 }
18277 }
18278-
18279+
18280 return HANDLER_GO_ON;
18281-
18282+
18283 }
18284
18285 #ifdef USE_ZLIB
18286@@ -153,32 +184,32 @@
18287 unsigned char *c;
18288 unsigned long crc;
18289 z_stream z;
18290-
18291+
18292 UNUSED(srv);
18293 UNUSED(con);
18294
18295 z.zalloc = Z_NULL;
18296 z.zfree = Z_NULL;
18297 z.opaque = Z_NULL;
18298-
18299- if (Z_OK != deflateInit2(&z,
18300+
18301+ if (Z_OK != deflateInit2(&z,
18302 Z_DEFAULT_COMPRESSION,
18303- Z_DEFLATED,
18304+ Z_DEFLATED,
18305 -MAX_WBITS, /* supress zlib-header */
18306 8,
18307 Z_DEFAULT_STRATEGY)) {
18308 return -1;
18309 }
18310-
18311+
18312 z.next_in = (unsigned char *)start;
18313 z.avail_in = st_size;
18314 z.total_in = 0;
18315-
18316-
18317+
18318+
18319 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
18320-
18321+
18322 /* write gzip header */
18323-
18324+
18325 c = (unsigned char *)p->b->ptr;
18326 c[0] = 0x1f;
18327 c[1] = 0x8b;
18328@@ -190,24 +221,24 @@
18329 c[7] = (mtime >> 24) & 0xff;
18330 c[8] = 0x00; /* extra flags */
18331 c[9] = 0x03; /* UNIX */
18332-
18333+
18334 p->b->used = 10;
18335 z.next_out = (unsigned char *)p->b->ptr + p->b->used;
18336 z.avail_out = p->b->size - p->b->used - 8;
18337 z.total_out = 0;
18338-
18339+
18340 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18341 deflateEnd(&z);
18342 return -1;
18343 }
18344-
18345+
18346 /* trailer */
18347 p->b->used += z.total_out;
18348-
18349+
18350 crc = generate_crc32c(start, st_size);
18351-
18352+
18353 c = (unsigned char *)p->b->ptr + p->b->used;
18354-
18355+
18356 c[0] = (crc >> 0) & 0xff;
18357 c[1] = (crc >> 8) & 0xff;
18358 c[2] = (crc >> 16) & 0xff;
18359@@ -221,51 +252,51 @@
18360 if (Z_OK != deflateEnd(&z)) {
18361 return -1;
18362 }
18363-
18364+
18365 return 0;
18366 }
18367
18368 static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18369 z_stream z;
18370-
18371+
18372 UNUSED(srv);
18373 UNUSED(con);
18374
18375 z.zalloc = Z_NULL;
18376 z.zfree = Z_NULL;
18377 z.opaque = Z_NULL;
18378-
18379- if (Z_OK != deflateInit2(&z,
18380+
18381+ if (Z_OK != deflateInit2(&z,
18382 Z_DEFAULT_COMPRESSION,
18383- Z_DEFLATED,
18384+ Z_DEFLATED,
18385 -MAX_WBITS, /* supress zlib-header */
18386 8,
18387 Z_DEFAULT_STRATEGY)) {
18388 return -1;
18389 }
18390-
18391+
18392 z.next_in = start;
18393 z.avail_in = st_size;
18394 z.total_in = 0;
18395-
18396+
18397 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
18398-
18399+
18400 z.next_out = (unsigned char *)p->b->ptr;
18401 z.avail_out = p->b->size;
18402 z.total_out = 0;
18403-
18404+
18405 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18406 deflateEnd(&z);
18407 return -1;
18408 }
18409-
18410+
18411 /* trailer */
18412 p->b->used += z.total_out;
18413-
18414+
18415 if (Z_OK != deflateEnd(&z)) {
18416 return -1;
18417 }
18418-
18419+
18420 return 0;
18421 }
18422
18423@@ -274,48 +305,48 @@
18424 #ifdef USE_BZ2LIB
18425 static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18426 bz_stream bz;
18427-
18428+
18429 UNUSED(srv);
18430 UNUSED(con);
18431
18432 bz.bzalloc = NULL;
18433 bz.bzfree = NULL;
18434 bz.opaque = NULL;
18435-
18436- if (BZ_OK != BZ2_bzCompressInit(&bz,
18437+
18438+ if (BZ_OK != BZ2_bzCompressInit(&bz,
18439 9, /* blocksize = 900k */
18440 0, /* no output */
18441 0)) { /* workFactor: default */
18442 return -1;
18443 }
18444-
18445+
18446 bz.next_in = (char *)start;
18447 bz.avail_in = st_size;
18448 bz.total_in_lo32 = 0;
18449 bz.total_in_hi32 = 0;
18450-
18451+
18452 buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
18453-
18454+
18455 bz.next_out = p->b->ptr;
18456 bz.avail_out = p->b->size;
18457 bz.total_out_lo32 = 0;
18458 bz.total_out_hi32 = 0;
18459-
18460+
18461 if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
18462 BZ2_bzCompressEnd(&bz);
18463 return -1;
18464 }
18465-
18466+
18467 /* file is too large for now */
18468 if (bz.total_out_hi32) return -1;
18469-
18470+
18471 /* trailer */
18472 p->b->used = bz.total_out_lo32;
18473-
18474+
18475 if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
18476 return -1;
18477 }
18478-
18479+
18480 return 0;
18481 }
18482 #endif
18483@@ -326,47 +357,50 @@
18484 void *start;
18485 const char *filename = fn->ptr;
18486 ssize_t r;
18487-
18488+ stat_cache_entry *compressed_sce = NULL;
18489+
18490+ if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
18491+
18492 /* overflow */
18493 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18494-
18495- /* don't mmap files > 128Mb
18496- *
18497+
18498+ /* don't mmap files > 128Mb
18499+ *
18500 * we could use a sliding window, but currently there is no need for it
18501 */
18502-
18503+
18504 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18505-
18506+
18507 buffer_reset(p->ofn);
18508 buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
18509- BUFFER_APPEND_SLASH(p->ofn);
18510-
18511+ PATHNAME_APPEND_SLASH(p->ofn);
18512+
18513 if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
18514 size_t offset = p->ofn->used - 1;
18515 char *dir, *nextdir;
18516-
18517+
18518 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
18519-
18520+
18521 buffer_copy_string_buffer(p->b, p->ofn);
18522-
18523+
18524 /* mkdir -p ... */
18525 for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
18526 *nextdir = '\0';
18527-
18528+
18529 if (-1 == mkdir(p->b->ptr, 0700)) {
18530 if (errno != EEXIST) {
18531 log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
18532-
18533+
18534 return -1;
18535 }
18536 }
18537-
18538+
18539 *nextdir = '/';
18540 }
18541 } else {
18542 buffer_append_string_buffer(p->ofn, con->uri.path);
18543 }
18544-
18545+
18546 switch(type) {
18547 case HTTP_ACCEPT_ENCODING_GZIP:
18548 buffer_append_string(p->ofn, "-gzip-");
18549@@ -381,55 +415,64 @@
18550 log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type);
18551 return -1;
18552 }
18553-
18554+
18555 buffer_append_string_buffer(p->ofn, sce->etag);
18556-
18557+
18558+
18559+ if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
18560+ /* file exists */
18561+
18562+ http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
18563+ con->file_finished = 1;
18564+
18565+ return 0;
18566+ }
18567+
18568 if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
18569 if (errno == EEXIST) {
18570 /* cache-entry exists */
18571-#if 0
18572- log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
18573-#endif
18574- buffer_copy_string_buffer(con->physical.path, p->ofn);
18575-
18576- return 0;
18577+
18578 }
18579-
18580- log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
18581-
18582+
18583+ log_error_write(srv, __FILE__, __LINE__, "sbss",
18584+ "creating cachefile", p->ofn,
18585+ "failed", strerror(errno));
18586+
18587 return -1;
18588 }
18589-#if 0
18590- log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
18591-#endif
18592+
18593 if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
18594- log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18595-
18596+ log_error_write(srv, __FILE__, __LINE__, "sbss",
18597+ "opening plain-file", fn,
18598+ "failed", strerror(errno));
18599+
18600 close(ofd);
18601-
18602+
18603 return -1;
18604 }
18605-
18606-
18607+
18608+
18609 if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18610- log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18611-
18612+ log_error_write(srv, __FILE__, __LINE__, "sbss",
18613+ "mmaping", fn,
18614+ "failed", strerror(errno));
18615+
18616 close(ofd);
18617 close(ifd);
18618 return -1;
18619 }
18620-
18621+
18622 switch(type) {
18623 #ifdef USE_ZLIB
18624- case HTTP_ACCEPT_ENCODING_GZIP:
18625+ case HTTP_ACCEPT_ENCODING_GZIP:
18626 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
18627 break;
18628- case HTTP_ACCEPT_ENCODING_DEFLATE:
18629+ case HTTP_ACCEPT_ENCODING_DEFLATE:
18630 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
18631 break;
18632 #endif
18633 #ifdef USE_BZ2LIB
18634- case HTTP_ACCEPT_ENCODING_BZIP2:
18635+ case HTTP_ACCEPT_ENCODING_BZIP2:
18636 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
18637 break;
18638 #endif
18639@@ -437,26 +480,27 @@
18640 ret = -1;
18641 break;
18642 }
18643-
18644+
18645 if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
18646- munmap(start, sce->st.st_size);
18647+ munmap(start, sce->st.st_size);
18648 close(ofd);
18649 close(ifd);
18650 return -1;
18651 }
18652-
18653+
18654 if ((size_t)r != p->b->used) {
18655-
18656+
18657 }
18658-
18659+
18660 munmap(start, sce->st.st_size);
18661 close(ofd);
18662 close(ifd);
18663-
18664+
18665 if (ret != 0) return -1;
18666-
18667- buffer_copy_string_buffer(con->physical.path, p->ofn);
18668-
18669+
18670+ http_chunk_append_file(srv, con, p->ofn, 0, r);
18671+ con->file_finished = 1;
18672+
18673 return 0;
18674 }
18675
18676@@ -465,43 +509,44 @@
18677 int ret = -1;
18678 void *start;
18679 buffer *b;
18680-
18681+
18682 /* overflow */
18683 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18684-
18685+
18686 /* don't mmap files > 128M
18687- *
18688+ *
18689 * we could use a sliding window, but currently there is no need for it
18690 */
18691-
18692+
18693 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18694-
18695-
18696+
18697 if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
18698 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18699-
18700+
18701 return -1;
18702 }
18703-
18704-
18705- if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18706+
18707+ start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
18708+
18709+ close(ifd);
18710+
18711+ if (MAP_FAILED == start) {
18712 log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18713-
18714- close(ifd);
18715+
18716 return -1;
18717 }
18718-
18719+
18720 switch(type) {
18721 #ifdef USE_ZLIB
18722- case HTTP_ACCEPT_ENCODING_GZIP:
18723+ case HTTP_ACCEPT_ENCODING_GZIP:
18724 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
18725 break;
18726- case HTTP_ACCEPT_ENCODING_DEFLATE:
18727+ case HTTP_ACCEPT_ENCODING_DEFLATE:
18728 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
18729 break;
18730 #endif
18731 #ifdef USE_BZ2LIB
18732- case HTTP_ACCEPT_ENCODING_BZIP2:
18733+ case HTTP_ACCEPT_ENCODING_BZIP2:
18734 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
18735 break;
18736 #endif
18737@@ -509,69 +554,64 @@
18738 ret = -1;
18739 break;
18740 }
18741-
18742+
18743 munmap(start, sce->st.st_size);
18744- close(ifd);
18745-
18746+
18747 if (ret != 0) return -1;
18748-
18749+
18750 chunkqueue_reset(con->write_queue);
18751 b = chunkqueue_get_append_buffer(con->write_queue);
18752 buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
18753-
18754+
18755 buffer_reset(con->physical.path);
18756-
18757+
18758 con->file_finished = 1;
18759 con->file_started = 1;
18760-
18761+
18762 return 0;
18763 }
18764
18765-
18766-#define PATCH(x) \
18767- p->conf.x = s->x;
18768 static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
18769 size_t i, j;
18770 plugin_config *s = p->config_storage[0];
18771
18772- PATCH(compress_cache_dir);
18773- PATCH(compress);
18774- PATCH(compress_max_filesize);
18775-
18776+ PATCH_OPTION(compress_cache_dir);
18777+ PATCH_OPTION(compress);
18778+ PATCH_OPTION(compress_max_filesize);
18779+
18780 /* skip the first, the global context */
18781 for (i = 1; i < srv->config_context->used; i++) {
18782 data_config *dc = (data_config *)srv->config_context->data[i];
18783 s = p->config_storage[i];
18784-
18785+
18786 /* condition didn't match */
18787 if (!config_check_cond(srv, con, dc)) continue;
18788-
18789+
18790 /* merge config */
18791 for (j = 0; j < dc->value->used; j++) {
18792 data_unset *du = dc->value->data[j];
18793-
18794+
18795 if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
18796- PATCH(compress_cache_dir);
18797+ PATCH_OPTION(compress_cache_dir);
18798 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
18799- PATCH(compress);
18800+ PATCH_OPTION(compress);
18801 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
18802- PATCH(compress_max_filesize);
18803+ PATCH_OPTION(compress_max_filesize);
18804 }
18805 }
18806 }
18807-
18808+
18809 return 0;
18810 }
18811-#undef PATCH
18812
18813 PHYSICALPATH_FUNC(mod_compress_physical) {
18814 plugin_data *p = p_d;
18815 size_t m;
18816 off_t max_fsize;
18817 stat_cache_entry *sce = NULL;
18818-
18819+
18820 /* only GET and POST can get compressed */
18821- if (con->request.http_method != HTTP_METHOD_GET &&
18822+ if (con->request.http_method != HTTP_METHOD_GET &&
18823 con->request.http_method != HTTP_METHOD_POST) {
18824 return HANDLER_GO_ON;
18825 }
18826@@ -579,46 +619,49 @@
18827 if (buffer_is_empty(con->physical.path)) {
18828 return HANDLER_GO_ON;
18829 }
18830-
18831+
18832 mod_compress_patch_connection(srv, con, p);
18833-
18834+
18835 max_fsize = p->conf.compress_max_filesize;
18836
18837 stat_cache_get_entry(srv, con, con->physical.path, &sce);
18838
18839 /* don't compress files that are too large as we need to much time to handle them */
18840 if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
18841-
18842+
18843+ /* compressing the file might lead to larger files instead */
18844+ if (sce->st.st_size < 128) return HANDLER_GO_ON;
18845+
18846 /* check if mimetype is in compress-config */
18847 for (m = 0; m < p->conf.compress->used; m++) {
18848 data_string *compress_ds = (data_string *)p->conf.compress->data[m];
18849-
18850+
18851 if (!compress_ds) {
18852 log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
18853-
18854+
18855 return HANDLER_GO_ON;
18856 }
18857-
18858+
18859 if (buffer_is_equal(compress_ds->value, sce->content_type)) {
18860 /* mimetype found */
18861 data_string *ds;
18862-
18863+
18864 /* the response might change according to Accept-Encoding */
18865 response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
18866-
18867+
18868 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
18869 int accept_encoding = 0;
18870 char *value = ds->value->ptr;
18871 int srv_encodings = 0;
18872 int matched_encodings = 0;
18873-
18874+
18875 /* get client side support encodings */
18876 if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
18877 if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
18878 if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
18879 if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
18880 if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
18881-
18882+
18883 /* get server side supported ones */
18884 #ifdef USE_BZ2LIB
18885 srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
18886@@ -627,18 +670,31 @@
18887 srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
18888 srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
18889 #endif
18890-
18891+
18892 /* find matching entries */
18893 matched_encodings = accept_encoding & srv_encodings;
18894-
18895+
18896 if (matched_encodings) {
18897 const char *dflt_gzip = "gzip";
18898 const char *dflt_deflate = "deflate";
18899 const char *dflt_bzip2 = "bzip2";
18900-
18901+
18902 const char *compression_name = NULL;
18903 int compression_type = 0;
18904-
18905+ buffer *mtime;
18906+
18907+ mtime = strftime_cache_get(srv, sce->st.st_mtime);
18908+ etag_mutate(con->physical.etag, sce->etag);
18909+
18910+ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
18911+ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
18912+
18913+ /* perhaps we don't even have to compress the file as the browser still has the
18914+ * current version */
18915+ if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
18916+ return HANDLER_FINISHED;
18917+ }
18918+
18919 /* select best matching encoding */
18920 if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
18921 compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
18922@@ -650,31 +706,21 @@
18923 compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
18924 compression_name = dflt_deflate;
18925 }
18926-
18927- /* deflate it */
18928- if (p->conf.compress_cache_dir->used) {
18929- if (0 == deflate_file_to_file(srv, con, p,
18930- con->physical.path, sce, compression_type)) {
18931- buffer *mtime;
18932-
18933- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
18934-
18935- mtime = strftime_cache_get(srv, sce->st.st_mtime);
18936- response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
18937-
18938- etag_mutate(con->physical.etag, sce->etag);
18939- response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
18940-
18941- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
18942-
18943- return HANDLER_GO_ON;
18944- }
18945- } else if (0 == deflate_file_to_buffer(srv, con, p,
18946- con->physical.path, sce, compression_type)) {
18947-
18948- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
18949- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
18950-
18951+
18952+ /* deflate it to file (cached) or to memory */
18953+ if (0 == deflate_file_to_file(srv, con, p,
18954+ con->physical.path, sce, compression_type) ||
18955+ 0 == deflate_file_to_buffer(srv, con, p,
18956+ con->physical.path, sce, compression_type)) {
18957+
18958+ response_header_overwrite(srv, con,
18959+ CONST_STR_LEN("Content-Encoding"),
18960+ compression_name, strlen(compression_name));
18961+
18962+ response_header_overwrite(srv, con,
18963+ CONST_STR_LEN("Content-Type"),
18964+ CONST_BUF_LEN(sce->content_type));
18965+
18966 return HANDLER_FINISHED;
18967 }
18968 break;
18969@@ -682,20 +728,20 @@
18970 }
18971 }
18972 }
18973-
18974+
18975 return HANDLER_GO_ON;
18976 }
18977
18978 int mod_compress_plugin_init(plugin *p) {
18979 p->version = LIGHTTPD_VERSION_ID;
18980 p->name = buffer_init_string("compress");
18981-
18982+
18983 p->init = mod_compress_init;
18984 p->set_defaults = mod_compress_setdefaults;
18985 p->handle_subrequest_start = mod_compress_physical;
18986 p->cleanup = mod_compress_free;
18987-
18988+
18989 p->data = NULL;
18990-
18991+
18992 return 0;
18993 }
1175ccec
ER
18994--- ../lighttpd-1.4.11/src/mod_dirlisting.c 2006-01-13 00:00:45.000000000 +0200
18995+++ lighttpd-1.4.12/src/mod_dirlisting.c 2006-07-15 22:43:21.000000000 +0300
2519e6e5
ER
18996@@ -1,11 +1,9 @@
18997 #include <ctype.h>
18998 #include <stdlib.h>
18999 #include <string.h>
19000-#include <dirent.h>
19001 #include <assert.h>
19002 #include <errno.h>
19003 #include <stdio.h>
19004-#include <unistd.h>
19005 #include <time.h>
19006
19007 #include "base.h"
1175ccec
ER
19008@@ -17,6 +15,9 @@
19009 #include "response.h"
19010 #include "stat_cache.h"
19011 #include "stream.h"
19012+#include "etag.h"
19013+
19014+#include "sys-strings.h"
19015
19016 /**
19017 * this is a dirlisting for a lighttpd plugin
19018@@ -27,10 +28,13 @@
19019 #include <sys/syslimits.h>
19020 #endif
19021
19022-#ifdef HAVE_ATTR_ATTRIBUTES_H
19023+#ifdef HAVE_XATTR
2519e6e5
ER
19024 #include <attr/attributes.h>
19025 #endif
19026
19027+#include "sys-files.h"
19028+#include "sys-strings.h"
19029+
19030 /* plugin config for all request/connections */
19031
19032 typedef struct {
1175ccec 19033@@ -54,7 +58,7 @@
2519e6e5
ER
19034 unsigned short hide_readme_file;
19035 unsigned short show_header;
19036 unsigned short hide_header_file;
19037-
19038+
19039 excludes_buffer *excludes;
19040
19041 buffer *external_css;
1175ccec 19042@@ -63,13 +67,14 @@
2519e6e5
ER
19043
19044 typedef struct {
19045 PLUGIN_DATA;
19046-
19047+
19048 buffer *tmp_buf;
19049 buffer *content_charset;
19050-
1175ccec 19051+ buffer *path;
2519e6e5
ER
19052+
19053 plugin_config **config_storage;
19054-
19055- plugin_config conf;
19056+
19057+ plugin_config conf;
19058 } plugin_data;
19059
19060 excludes_buffer *excludes_buffer_init(void) {
1175ccec 19061@@ -146,44 +151,46 @@
2519e6e5
ER
19062 /* init the plugin data */
19063 INIT_FUNC(mod_dirlisting_init) {
19064 plugin_data *p;
19065-
19066+
19067 p = calloc(1, sizeof(*p));
19068
19069 p->tmp_buf = buffer_init();
19070 p->content_charset = buffer_init();
19071-
1175ccec 19072+ p->path = buffer_init();
2519e6e5
ER
19073+
19074 return p;
19075 }
19076
19077 /* detroy the plugin data */
19078 FREE_FUNC(mod_dirlisting_free) {
19079 plugin_data *p = p_d;
19080-
19081+
19082 UNUSED(srv);
19083
19084 if (!p) return HANDLER_GO_ON;
19085-
19086+
19087 if (p->config_storage) {
19088 size_t i;
19089 for (i = 0; i < srv->config_context->used; i++) {
19090 plugin_config *s = p->config_storage[i];
19091-
19092+
19093 if (!s) continue;
19094-
19095+
19096 excludes_buffer_free(s->excludes);
19097 buffer_free(s->external_css);
19098 buffer_free(s->encoding);
19099-
19100+
19101 free(s);
19102 }
19103 free(p->config_storage);
19104 }
19105-
19106+
19107 buffer_free(p->tmp_buf);
1175ccec 19108+ buffer_free(p->path);
2519e6e5
ER
19109 buffer_free(p->content_charset);
19110-
19111+
19112 free(p);
19113-
19114+
19115 return HANDLER_GO_ON;
19116 }
19117
1175ccec 19118@@ -215,10 +222,10 @@
2519e6e5
ER
19119 if (0 != excludes_buffer_append(s->excludes,
19120 ((data_string *)(da->value->data[j]))->value)) {
19121 #ifdef HAVE_PCRE_H
19122- log_error_write(srv, __FILE__, __LINE__, "sb",
19123+ log_error_write(srv, __FILE__, __LINE__, "sb",
19124 "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
19125 #else
19126- log_error_write(srv, __FILE__, __LINE__, "s",
19127+ log_error_write(srv, __FILE__, __LINE__, "s",
19128 "pcre support is missing, please install libpcre and the headers");
19129 #endif
19130 }
1175ccec 19131@@ -233,8 +240,8 @@
2519e6e5
ER
19132 SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
19133 plugin_data *p = p_d;
19134 size_t i = 0;
19135-
19136- config_values_t cv[] = {
19137+
19138+ config_values_t cv[] = {
19139 { "dir-listing.exclude", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
19140 { "dir-listing.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
19141 { "dir-listing.hide-dotfiles", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
1175ccec 19142@@ -245,18 +252,18 @@
2519e6e5
ER
19143 { "dir-listing.show-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
19144 { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
19145 { "server.dir-listing", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
19146-
19147+
19148 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19149 };
19150-
19151+
19152 if (!p) return HANDLER_ERROR;
19153-
19154+
19155 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19156-
19157+
19158 for (i = 0; i < srv->config_context->used; i++) {
19159 plugin_config *s;
19160 array *ca;
19161-
19162+
19163 s = calloc(1, sizeof(plugin_config));
19164 s->excludes = excludes_buffer_init();
19165 s->dir_listing = 0;
1175ccec 19166@@ -267,7 +274,7 @@
2519e6e5
ER
19167 s->show_header = 0;
19168 s->hide_header_file = 0;
19169 s->encoding = buffer_init();
19170-
19171+
19172 cv[0].destination = s->excludes;
19173 cv[1].destination = &(s->dir_listing);
19174 cv[2].destination = &(s->hide_dot_files);
1175ccec 19175@@ -292,60 +299,57 @@
2519e6e5
ER
19176 return HANDLER_GO_ON;
19177 }
19178
19179-#define PATCH(x) \
19180- p->conf.x = s->x;
19181 static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
19182 size_t i, j;
19183 plugin_config *s = p->config_storage[0];
19184
19185- PATCH(dir_listing);
19186- PATCH(external_css);
19187- PATCH(hide_dot_files);
19188- PATCH(encoding);
19189- PATCH(show_readme);
19190- PATCH(hide_readme_file);
19191- PATCH(show_header);
19192- PATCH(hide_header_file);
19193- PATCH(excludes);
19194-
19195+ PATCH_OPTION(dir_listing);
19196+ PATCH_OPTION(external_css);
19197+ PATCH_OPTION(hide_dot_files);
19198+ PATCH_OPTION(encoding);
19199+ PATCH_OPTION(show_readme);
19200+ PATCH_OPTION(hide_readme_file);
19201+ PATCH_OPTION(show_header);
19202+ PATCH_OPTION(hide_header_file);
19203+ PATCH_OPTION(excludes);
19204+
19205 /* skip the first, the global context */
19206 for (i = 1; i < srv->config_context->used; i++) {
19207 data_config *dc = (data_config *)srv->config_context->data[i];
19208 s = p->config_storage[i];
19209-
19210+
19211 /* condition didn't match */
19212 if (!config_check_cond(srv, con, dc)) continue;
19213-
19214+
19215 /* merge config */
19216 for (j = 0; j < dc->value->used; j++) {
19217 data_unset *du = dc->value->data[j];
19218-
19219+
19220 if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
19221 buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
19222- PATCH(dir_listing);
19223+ PATCH_OPTION(dir_listing);
19224 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
19225- PATCH(hide_dot_files);
19226+ PATCH_OPTION(hide_dot_files);
19227 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
19228- PATCH(external_css);
19229+ PATCH_OPTION(external_css);
19230 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
19231- PATCH(encoding);
19232+ PATCH_OPTION(encoding);
19233 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
19234- PATCH(show_readme);
19235+ PATCH_OPTION(show_readme);
19236 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
19237- PATCH(hide_readme_file);
19238+ PATCH_OPTION(hide_readme_file);
19239 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
19240- PATCH(show_header);
19241+ PATCH_OPTION(show_header);
19242 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
19243- PATCH(hide_header_file);
19244+ PATCH_OPTION(hide_header_file);
19245 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
19246- PATCH(excludes);
19247+ PATCH_OPTION(excludes);
19248 }
19249 }
19250 }
19251-
19252+
19253 return 0;
19254 }
19255-#undef PATCH
19256
19257 typedef struct {
19258 size_t namelen;
1175ccec 19259@@ -432,7 +436,7 @@
2519e6e5
ER
19260
19261 static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
19262 UNUSED(srv);
19263-
19264+
19265 BUFFER_APPEND_STRING_CONST(out,
19266 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
19267 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
1175ccec 19268@@ -492,11 +496,11 @@
2519e6e5
ER
19269 if (p->conf.show_header) {
19270 stream s;
19271 /* if we have a HEADER file, display it in <pre class="header"></pre> */
19272-
19273+
19274 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
19275- BUFFER_APPEND_SLASH(p->tmp_buf);
19276+ PATHNAME_APPEND_SLASH(p->tmp_buf);
19277 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
19278-
19279+
19280 if (-1 != stream_open(&s, p->tmp_buf)) {
19281 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
19282 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
1175ccec 19283@@ -531,21 +535,21 @@
2519e6e5
ER
19284
19285 static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
19286 UNUSED(srv);
19287-
19288+
19289 BUFFER_APPEND_STRING_CONST(out,
19290 "</tbody>\n"
19291 "</table>\n"
19292 "</div>\n"
19293 );
19294-
19295+
19296 if (p->conf.show_readme) {
19297 stream s;
19298 /* if we have a README file, display it in <pre class="readme"></pre> */
19299-
19300+
19301 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
19302- BUFFER_APPEND_SLASH(p->tmp_buf);
19303+ PATHNAME_APPEND_SLASH(p->tmp_buf);
19304 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
19305-
19306+
19307 if (-1 != stream_open(&s, p->tmp_buf)) {
19308 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
19309 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
1175ccec 19310@@ -553,7 +557,7 @@
2519e6e5
ER
19311 }
19312 stream_close(&s);
19313 }
19314-
19315+
19316 BUFFER_APPEND_STRING_CONST(out,
19317 "<div class=\"foot\">"
19318 );
1175ccec
ER
19319@@ -576,7 +580,6 @@
19320 buffer *out;
19321 struct dirent *dent;
19322 struct stat st;
19323- char *path, *path_file;
19324 size_t i;
19325 int hide_dotfiles = p->conf.hide_dot_files;
19326 dirls_list_t dirs, files, *list;
19327@@ -586,6 +589,7 @@
19328 size_t k;
19329 const char *content_type;
19330 long name_max;
19331+
19332 #ifdef HAVE_XATTR
19333 char attrval[128];
19334 int attrlen;
19335@@ -594,10 +598,10 @@
19336 struct tm tm;
2519e6e5
ER
19337 #endif
19338
1175ccec 19339- if (dir->used == 0) return -1;
2519e6e5 19340-
1175ccec
ER
19341- i = dir->used - 1;
19342+ /* empty pathname, never ... */
19343+ if (buffer_is_empty(dir)) return -1;
2519e6e5 19344
1175ccec 19345+ /* max-length for the opendir */
2519e6e5 19346 #ifdef HAVE_PATHCONF
1175ccec
ER
19347 if (-1 == (name_max = pathconf(dir->ptr, _PC_NAME_MAX))) {
19348 #ifdef NAME_MAX
19349@@ -606,22 +610,24 @@
2519e6e5
ER
19350 name_max = 256; /* stupid default */
19351 #endif
19352 }
19353-#elif defined __WIN32
19354+#elif defined _WIN32
19355 name_max = FILENAME_MAX;
19356 #else
19357 name_max = NAME_MAX;
19358 #endif
19359-
1175ccec
ER
19360- path = malloc(dir->used + name_max);
19361- assert(path);
19362- strcpy(path, dir->ptr);
19363- path_file = path + i;
19364
19365- if (NULL == (dp = opendir(path))) {
19366- log_error_write(srv, __FILE__, __LINE__, "sbs",
19367+ buffer_copy_string_buffer(p->path, dir);
19368+ PATHNAME_APPEND_SLASH(p->path);
2519e6e5 19369+
2519e6e5 19370+#ifdef _WIN32
1175ccec
ER
19371+ /* append *.* to the path */
19372+ buffer_append_string(path, "*.*");
2519e6e5 19373+#endif
1175ccec
ER
19374+
19375+ if (NULL == (dp = opendir(p->path->ptr))) {
2519e6e5
ER
19376+ log_error_write(srv, __FILE__, __LINE__, "sbs",
19377 "opendir failed:", dir, strerror(errno));
19378
1175ccec
ER
19379- free(path);
19380 return -1;
19381 }
19382
19383@@ -633,7 +639,7 @@
2519e6e5
ER
19384 assert(files.ent);
19385 files.size = DIRLIST_BLOB_SIZE;
19386 files.used = 0;
19387-
19388+
19389 while ((dent = readdir(dp)) != NULL) {
19390 unsigned short exclude_match = 0;
19391
1175ccec 19392@@ -686,15 +692,21 @@
2519e6e5
ER
19393 #endif
19394
19395 i = strlen(dent->d_name);
19396-
19397+
19398 /* NOTE: the manual says, d_name is never more than NAME_MAX
19399 * so this should actually not be a buffer-overflow-risk
19400 */
19401 if (i > (size_t)name_max) continue;
19402-
1175ccec 19403- memcpy(path_file, dent->d_name, i + 1);
2519e6e5 19404- if (stat(path, &st) != 0)
1175ccec
ER
19405+
19406+ /* build the dirname */
19407+ buffer_copy_string_buffer(p->path, dir);
19408+ PATHNAME_APPEND_SLASH(p->path);
19409+ buffer_append_string(p->path, dent->d_name);
19410+
19411+ if (stat(p->path->ptr, &st) != 0) {
19412+ fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, p->path->ptr, strerror(errno));
2519e6e5 19413 continue;
1175ccec 19414+ }
2519e6e5
ER
19415
19416 list = &files;
19417 if (S_ISDIR(st.st_mode))
1175ccec 19418@@ -740,7 +752,7 @@
2519e6e5
ER
19419 #else
19420 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
19421 #endif
19422-
19423+
19424 BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
19425 buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
19426 BUFFER_APPEND_STRING_CONST(out, "/\">");
1175ccec
ER
19427@@ -757,18 +769,22 @@
19428 tmp = files.ent[i];
2519e6e5
ER
19429
19430 content_type = NULL;
1175ccec 19431+
2519e6e5
ER
19432 #ifdef HAVE_XATTR
19433-
2519e6e5 19434 if (con->conf.use_xattr) {
1175ccec
ER
19435- memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
19436+ /* build the dirname */
19437+ buffer_copy_string_buffer(p->path, dir);
19438+ PATHNAME_APPEND_SLASH(p->path);
19439+ buffer_append_string_len(p->path, DIRLIST_ENT_NAME(tmp), tmp->namelen);
19440+
2519e6e5 19441 attrlen = sizeof(attrval) - 1;
1175ccec
ER
19442- if (attr_get(path, "Content-Type", attrval, &attrlen, 0) == 0) {
19443+ if (attr_get(p->path->ptr, "Content-Type", attrval, &attrlen, 0) == 0) {
19444 attrval[attrlen] = '\0';
19445 content_type = attrval;
2519e6e5
ER
19446 }
19447 }
19448 #endif
19449-
19450+
19451 if (content_type == NULL) {
19452 content_type = "application/octet-stream";
19453 for (k = 0; k < con->conf.mimetypes->used; k++) {
1175ccec 19454@@ -788,7 +804,7 @@
2519e6e5
ER
19455 }
19456 }
19457 }
19458-
19459+
19460 #ifdef HAVE_LOCALTIME_R
19461 localtime_r(&(tmp->mtime), &tm);
19462 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
1175ccec
ER
19463@@ -814,7 +830,6 @@
19464
19465 free(files.ent);
19466 free(dirs.ent);
19467- free(path);
19468
19469 http_list_directory_footer(srv, con, p, out);
19470
19471@@ -837,36 +852,55 @@
2519e6e5
ER
19472 URIHANDLER_FUNC(mod_dirlisting_subrequest) {
19473 plugin_data *p = p_d;
19474 stat_cache_entry *sce = NULL;
19475-
1175ccec 19476- UNUSED(srv);
2519e6e5 19477-
1175ccec
ER
19478- if (con->physical.path->used == 0) return HANDLER_GO_ON;
19479- if (con->uri.path->used == 0) return HANDLER_GO_ON;
19480+ buffer *mtime;
19481+ data_string *ds;
2519e6e5 19482+
1175ccec 19483+ if (con->uri.path->used < 2) return HANDLER_GO_ON;
2519e6e5
ER
19484 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
19485-
1175ccec 19486+ if (con->physical.path->used == 0) return HANDLER_GO_ON;
2519e6e5
ER
19487+
19488 mod_dirlisting_patch_connection(srv, con, p);
19489
19490 if (!p->conf.dir_listing) return HANDLER_GO_ON;
19491-
1175ccec
ER
19492+
19493+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19494+ /* just a second ago the file was still there */
19495+ return HANDLER_GO_ON;
19496+ }
19497+
19498+ if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
2519e6e5
ER
19499+
19500 if (con->conf.log_request_handling) {
19501 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Dir-Listing");
19502 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
19503 }
19504-
1175ccec
ER
19505- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19506- fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
19507- SEGFAULT();
2519e6e5 19508+
1175ccec
ER
19509+ /* perhaps this a cachable request
19510+ * - we use the etag of the directory
19511+ * */
19512+
19513+ etag_mutate(con->physical.etag, sce->etag);
19514+ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19515+
19516+ /* prepare header */
19517+ if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
19518+ mtime = strftime_cache_get(srv, sce->st.st_mtime);
19519+ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19520+ } else {
19521+ mtime = ds->value;
2519e6e5
ER
19522 }
19523-
1175ccec 19524- if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
2519e6e5 19525-
1175ccec
ER
19526+
19527+ if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
19528+ return HANDLER_FINISHED;
19529+ }
2519e6e5
ER
19530+
19531 if (http_list_directory(srv, con, p, con->physical.path)) {
19532 /* dirlisting failed */
19533 con->http_status = 403;
19534 }
19535-
19536+
19537 buffer_reset(con->physical.path);
19538-
19539+
19540 /* not found */
19541 return HANDLER_FINISHED;
19542 }
1175ccec 19543@@ -876,13 +910,13 @@
2519e6e5
ER
19544 int mod_dirlisting_plugin_init(plugin *p) {
19545 p->version = LIGHTTPD_VERSION_ID;
19546 p->name = buffer_init_string("dirlisting");
19547-
19548+
19549 p->init = mod_dirlisting_init;
19550 p->handle_subrequest_start = mod_dirlisting_subrequest;
19551 p->set_defaults = mod_dirlisting_set_defaults;
19552 p->cleanup = mod_dirlisting_free;
19553-
19554+
19555 p->data = NULL;
19556-
19557+
19558 return 0;
19559 }
1175ccec 19560--- ../lighttpd-1.4.11/src/mod_evasive.c 2006-01-04 15:24:51.000000000 +0200
36e2a29e 19561+++ lighttpd-1.4.12/src/mod_evasive.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
19562@@ -31,100 +31,97 @@
19563
19564 typedef struct {
19565 PLUGIN_DATA;
19566-
19567+
19568 plugin_config **config_storage;
19569-
19570- plugin_config conf;
19571+
19572+ plugin_config conf;
19573 } plugin_data;
19574
19575 INIT_FUNC(mod_evasive_init) {
19576 plugin_data *p;
19577-
19578+
19579 p = calloc(1, sizeof(*p));
19580-
19581+
19582 return p;
19583 }
19584
19585 FREE_FUNC(mod_evasive_free) {
19586 plugin_data *p = p_d;
19587-
19588+
19589 UNUSED(srv);
19590
19591 if (!p) return HANDLER_GO_ON;
19592-
19593+
19594 if (p->config_storage) {
19595 size_t i;
19596 for (i = 0; i < srv->config_context->used; i++) {
19597 plugin_config *s = p->config_storage[i];
19598-
19599+
19600 free(s);
19601 }
19602 free(p->config_storage);
19603 }
19604-
19605+
19606 free(p);
19607-
19608+
19609 return HANDLER_GO_ON;
19610 }
19611
19612 SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
19613 plugin_data *p = p_d;
19614 size_t i = 0;
19615-
19616- config_values_t cv[] = {
19617+
19618+ config_values_t cv[] = {
19619 { "evasive.max-conns-per-ip", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
19620 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19621 };
19622-
19623+
19624 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19625-
19626+
19627 for (i = 0; i < srv->config_context->used; i++) {
19628 plugin_config *s;
19629-
19630+
19631 s = calloc(1, sizeof(plugin_config));
19632 s->max_conns = 0;
19633-
19634+
19635 cv[0].destination = &(s->max_conns);
19636-
19637+
19638 p->config_storage[i] = s;
19639-
19640+
19641 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19642 return HANDLER_ERROR;
19643 }
19644 }
19645-
19646+
19647 return HANDLER_GO_ON;
19648 }
19649
19650-#define PATCH(x) \
19651- p->conf.x = s->x;
19652 static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
19653 size_t i, j;
19654 plugin_config *s = p->config_storage[0];
19655
19656- PATCH(max_conns);
19657-
19658+ PATCH_OPTION(max_conns);
19659+
19660 /* skip the first, the global context */
19661 for (i = 1; i < srv->config_context->used; i++) {
19662 data_config *dc = (data_config *)srv->config_context->data[i];
19663 s = p->config_storage[i];
19664-
19665+
19666 /* condition didn't match */
19667 if (!config_check_cond(srv, con, dc)) continue;
19668-
19669+
19670 /* merge config */
19671 for (j = 0; j < dc->value->used; j++) {
19672 data_unset *du = dc->value->data[j];
19673-
19674+
19675 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
19676- PATCH(max_conns);
19677+ PATCH_OPTION(max_conns);
19678 }
19679 }
19680 }
19681-
19682+
19683 return 0;
19684 }
19685-#undef PATCH
19686
19687 URIHANDLER_FUNC(mod_evasive_uri_handler) {
19688 plugin_data *p = p_d;
19689@@ -132,10 +129,10 @@
19690 size_t j;
19691
19692 if (con->uri.path->used == 0) return HANDLER_GO_ON;
19693-
19694+
19695 mod_evasive_patch_connection(srv, con, p);
19696-
19697- /* no limit set, nothing to block */
19698+
19699+ /* no limit set, nothing to block */
19700 if (p->conf.max_conns == 0) return HANDLER_GO_ON;
19701
19702 for (j = 0; j < srv->conns->used; j++) {
19703@@ -147,7 +144,7 @@
19704 if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
19705 c->state > CON_STATE_REQUEST_END) {
19706 conns_by_ip++;
19707-
19708+
19709 if (conns_by_ip > p->conf.max_conns) {
19710 log_error_write(srv, __FILE__, __LINE__, "ss",
19711 inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
19712@@ -158,7 +155,7 @@
19713 }
19714 }
19715 }
19716-
19717+
19718 return HANDLER_GO_ON;
19719 }
19720
19721@@ -166,13 +163,13 @@
19722 int mod_evasive_plugin_init(plugin *p) {
19723 p->version = LIGHTTPD_VERSION_ID;
19724 p->name = buffer_init_string("evasive");
19725-
19726+
19727 p->init = mod_evasive_init;
19728 p->set_defaults = mod_evasive_set_defaults;
19729 p->handle_uri_clean = mod_evasive_uri_handler;
19730 p->cleanup = mod_evasive_free;
19731-
19732+
19733 p->data = NULL;
19734-
19735+
19736 return 0;
19737 }
1175ccec 19738--- ../lighttpd-1.4.11/src/mod_evhost.c 2005-08-17 10:42:03.000000000 +0300
36e2a29e 19739+++ lighttpd-1.4.12/src/mod_evhost.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
19740@@ -7,10 +7,12 @@
19741 #include "response.h"
19742 #include "stat_cache.h"
19743
19744+#include "sys-files.h"
19745+
19746 typedef struct {
19747 /* unparsed pieces */
19748 buffer *path_pieces_raw;
19749-
19750+
19751 /* pieces for path creation */
19752 size_t len;
19753 buffer **path_pieces;
19754@@ -21,14 +23,14 @@
19755 buffer *tmp_buf;
19756
19757 plugin_config **config_storage;
19758- plugin_config conf;
19759+ plugin_config conf;
19760 } plugin_data;
19761
19762 INIT_FUNC(mod_evhost_init) {
19763 plugin_data *p;
19764-
19765+
19766 p = calloc(1, sizeof(*p));
19767-
19768+
19769 p->tmp_buf = buffer_init();
19770
19771 return p;
19772@@ -36,34 +38,34 @@
19773
19774 FREE_FUNC(mod_evhost_free) {
19775 plugin_data *p = p_d;
19776-
19777+
19778 UNUSED(srv);
19779
19780 if (!p) return HANDLER_GO_ON;
19781-
19782+
19783 if (p->config_storage) {
19784 size_t i;
19785 for (i = 0; i < srv->config_context->used; i++) {
19786 plugin_config *s = p->config_storage[i];
19787
19788 if (!s) continue;
19789-
19790+
19791 if(s->path_pieces) {
19792 size_t j;
19793 for (j = 0; j < s->len; j++) {
19794 buffer_free(s->path_pieces[j]);
19795 }
19796-
19797+
19798 free(s->path_pieces);
19799 }
19800-
19801+
19802 buffer_free(s->path_pieces_raw);
19803-
19804+
19805 free(s);
19806 }
19807 free(p->config_storage);
19808 }
19809-
19810+
19811 buffer_free(p->tmp_buf);
19812
19813 free(p);
19814@@ -73,30 +75,30 @@
19815
19816 static void mod_evhost_parse_pattern(plugin_config *s) {
19817 char *ptr = s->path_pieces_raw->ptr,*pos;
19818-
19819+
19820 s->path_pieces = NULL;
19821-
19822+
19823 for(pos=ptr;*ptr;ptr++) {
19824 if(*ptr == '%') {
19825 s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
19826 s->path_pieces[s->len] = buffer_init();
19827 s->path_pieces[s->len+1] = buffer_init();
19828-
19829+
19830 buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
19831 pos = ptr + 2;
19832-
19833+
19834 buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
19835-
19836+
19837 s->len += 2;
19838 }
19839 }
19840-
19841+
19842 if(*pos != '\0') {
19843 s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
19844 s->path_pieces[s->len] = buffer_init();
19845-
19846+
19847 buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
19848-
19849+
19850 s->len += 1;
19851 }
19852 }
19853@@ -104,9 +106,9 @@
19854 SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
19855 plugin_data *p = p_d;
19856 size_t i;
19857-
19858+
19859 /**
19860- *
19861+ *
19862 * #
19863 * # define a pattern for the host url finding
19864 * # %% => % sign
19865@@ -117,39 +119,39 @@
19866 * # %4 => subdomain 2 name
19867 * #
19868 * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
19869- *
19870+ *
19871 */
19872-
19873- config_values_t cv[] = {
19874+
19875+ config_values_t cv[] = {
19876 { "evhost.path-pattern", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
19877 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19878 };
19879-
19880+
19881 if (!p) return HANDLER_ERROR;
19882-
19883+
19884 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19885-
19886+
19887 for (i = 0; i < srv->config_context->used; i++) {
19888 plugin_config *s;
19889-
19890+
19891 s = calloc(1, sizeof(plugin_config));
19892 s->path_pieces_raw = buffer_init();
19893 s->path_pieces = NULL;
19894 s->len = 0;
19895-
19896+
19897 cv[0].destination = s->path_pieces_raw;
19898-
19899+
19900 p->config_storage[i] = s;
19901-
19902+
19903 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19904 return HANDLER_ERROR;
19905 }
19906-
19907+
19908 if (s->path_pieces_raw->used != 0) {
19909 mod_evhost_parse_pattern(s);
19910 }
19911 }
19912-
19913+
19914 return HANDLER_GO_ON;
19915 }
19916
19917@@ -158,7 +160,7 @@
19918 * - %0 - full hostname (authority w/o port)
19919 * - %1 - tld
19920 * - %2 - domain.tld
19921- * - %3 -
19922+ * - %3 -
19923 */
19924
19925 static int mod_evhost_parse_host(connection *con,array *host) {
19926@@ -168,7 +170,7 @@
19927 int first = 1;
19928 data_string *ds;
19929 int i;
19930-
19931+
19932 /* first, find the domain + tld */
19933 for(;ptr > con->uri.authority->ptr;ptr--) {
19934 if(*ptr == '.') {
19935@@ -179,18 +181,18 @@
19936 first = 1;
19937 }
19938 }
19939-
19940+
19941 ds = data_string_init();
19942 buffer_copy_string(ds->key,"%0");
19943-
19944+
19945 /* if we stopped at a dot, skip the dot */
19946 if (*ptr == '.') ptr++;
19947 buffer_copy_string_len(ds->value, ptr, colon-ptr);
19948-
19949+
19950 array_insert_unique(host,(data_unset *)ds);
19951-
19952+
19953 /* if the : is not the start of the authority, go on parsing the hostname */
19954-
19955+
19956 if (colon != con->uri.authority->ptr) {
19957 for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
19958 if(*ptr == '.') {
19959@@ -200,59 +202,55 @@
19960 buffer_copy_string(ds->key,"%");
19961 buffer_append_long(ds->key, i++);
19962 buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
19963-
19964+
19965 array_insert_unique(host,(data_unset *)ds);
19966 }
19967 colon = ptr;
19968 }
19969 }
19970-
19971+
19972 /* if the . is not the first charactor of the hostname */
19973 if (colon != ptr) {
19974 ds = data_string_init();
19975 buffer_copy_string(ds->key,"%");
19976 buffer_append_long(ds->key, i++);
19977 buffer_copy_string_len(ds->value,ptr,colon-ptr);
19978-
19979+
19980 array_insert_unique(host,(data_unset *)ds);
19981 }
19982 }
19983-
19984+
19985 return 0;
19986 }
19987
19988-#define PATCH(x) \
19989- p->conf.x = s->x;
19990 static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
19991 size_t i, j;
19992 plugin_config *s = p->config_storage[0];
19993-
19994- PATCH(path_pieces);
19995- PATCH(len);
19996-
19997+
19998+ PATCH_OPTION(path_pieces);
19999+ PATCH_OPTION(len);
20000+
20001 /* skip the first, the global context */
20002 for (i = 1; i < srv->config_context->used; i++) {
20003 data_config *dc = (data_config *)srv->config_context->data[i];
20004 s = p->config_storage[i];
20005-
20006+
20007 /* condition didn't match */
20008 if (!config_check_cond(srv, con, dc)) continue;
20009-
20010+
20011 /* merge config */
20012 for (j = 0; j < dc->value->used; j++) {
20013 data_unset *du = dc->value->data[j];
20014-
20015+
20016 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
20017- PATCH(path_pieces);
20018- PATCH(len);
20019+ PATCH_OPTION(path_pieces);
20020+ PATCH_OPTION(len);
20021 }
20022 }
20023 }
20024-
20025+
20026 return 0;
20027 }
20028-#undef PATCH
20029-
20030
20031 static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
20032 plugin_data *p = p_d;
20033@@ -261,29 +259,29 @@
20034 register char *ptr;
20035 int not_good = 0;
20036 stat_cache_entry *sce = NULL;
20037-
20038+
20039 /* not authority set */
20040 if (con->uri.authority->used == 0) return HANDLER_GO_ON;
20041-
20042+
20043 mod_evhost_patch_connection(srv, con, p);
20044-
20045+
20046 /* missing even default(global) conf */
20047 if (0 == p->conf.len) {
20048 return HANDLER_GO_ON;
20049 }
20050
20051 parsed_host = array_init();
20052-
20053+
20054 mod_evhost_parse_host(con, parsed_host);
20055-
20056+
20057 /* build document-root */
20058 buffer_reset(p->tmp_buf);
20059-
20060+
20061 for (i = 0; i < p->conf.len; i++) {
20062 ptr = p->conf.path_pieces[i]->ptr;
20063 if (*ptr == '%') {
20064 data_string *ds;
20065-
20066+
20067 if (*(ptr+1) == '%') {
20068 /* %% */
20069 BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
20070@@ -298,11 +296,11 @@
20071 buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
20072 }
20073 }
20074-
20075- BUFFER_APPEND_SLASH(p->tmp_buf);
20076-
20077+
20078+ PATHNAME_APPEND_SLASH(p->tmp_buf);
20079+
20080 array_free(parsed_host);
20081-
20082+
20083 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
20084 log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
20085 not_good = 1;
20086@@ -310,11 +308,11 @@
20087 log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
20088 not_good = 1;
20089 }
20090-
20091+
20092 if (!not_good) {
20093 buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
20094 }
20095-
20096+
20097 return HANDLER_GO_ON;
20098 }
20099
20100@@ -325,9 +323,9 @@
20101 p->set_defaults = mod_evhost_set_defaults;
20102 p->handle_docroot = mod_evhost_uri_handler;
20103 p->cleanup = mod_evhost_free;
20104-
20105+
20106 p->data = NULL;
20107-
20108+
20109 return 0;
20110 }
20111
1175ccec 20112--- ../lighttpd-1.4.11/src/mod_expire.c 2005-11-03 09:52:13.000000000 +0200
36e2a29e 20113+++ lighttpd-1.4.12/src/mod_expire.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
20114@@ -12,8 +12,8 @@
20115 #include "stat_cache.h"
20116
20117 /**
20118- * this is a expire module for a lighttpd
20119- *
20120+ * this is a expire module for a lighttpd
20121+ *
20122 * set 'Expires:' HTTP Headers on demand
20123 */
20124
20125@@ -27,51 +27,51 @@
20126
20127 typedef struct {
20128 PLUGIN_DATA;
20129-
20130+
20131 buffer *expire_tstmp;
20132-
20133+
20134 plugin_config **config_storage;
20135-
20136- plugin_config conf;
20137+
20138+ plugin_config conf;
20139 } plugin_data;
20140
20141 /* init the plugin data */
20142 INIT_FUNC(mod_expire_init) {
20143 plugin_data *p;
20144-
20145+
20146 p = calloc(1, sizeof(*p));
20147-
20148+
20149 p->expire_tstmp = buffer_init();
20150-
20151+
20152 buffer_prepare_copy(p->expire_tstmp, 255);
20153-
20154+
20155 return p;
20156 }
20157
20158 /* detroy the plugin data */
20159 FREE_FUNC(mod_expire_free) {
20160 plugin_data *p = p_d;
20161-
20162+
20163 UNUSED(srv);
20164
20165 if (!p) return HANDLER_GO_ON;
20166-
20167+
20168 buffer_free(p->expire_tstmp);
20169-
20170+
20171 if (p->config_storage) {
20172 size_t i;
20173 for (i = 0; i < srv->config_context->used; i++) {
20174 plugin_config *s = p->config_storage[i];
20175-
20176+
20177 array_free(s->expire_url);
20178-
20179+
20180 free(s);
20181 }
20182 free(p->config_storage);
20183 }
20184-
20185+
20186 free(p);
20187-
20188+
20189 return HANDLER_GO_ON;
20190 }
20191
20192@@ -79,25 +79,25 @@
20193 char *ts;
20194 int type = -1;
20195 int retts = 0;
20196-
20197+
20198 UNUSED(p);
20199
20200- /*
20201+ /*
20202 * parse
20203- *
20204+ *
20205 * '(access|modification) [plus] {<num> <type>}*'
20206- *
20207+ *
20208 * e.g. 'access 1 years'
20209 */
20210-
20211+
20212 if (expire->used == 0) {
20213- log_error_write(srv, __FILE__, __LINE__, "s",
20214+ log_error_write(srv, __FILE__, __LINE__, "s",
20215 "empty:");
20216 return -1;
20217 }
20218-
20219+
20220 ts = expire->ptr;
20221-
20222+
20223 if (0 == strncmp(ts, "access ", 7)) {
20224 type = 0;
20225 ts += 7;
20226@@ -110,39 +110,39 @@
20227 "invalid <base>:", ts);
20228 return -1;
20229 }
20230-
20231+
20232 if (0 == strncmp(ts, "plus ", 5)) {
20233 /* skip the optional plus */
20234 ts += 5;
20235 }
20236-
20237+
20238 /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
20239 while (1) {
20240 char *space, *err;
20241 int num;
20242-
20243+
20244 if (NULL == (space = strchr(ts, ' '))) {
20245- log_error_write(srv, __FILE__, __LINE__, "ss",
20246+ log_error_write(srv, __FILE__, __LINE__, "ss",
20247 "missing space after <num>:", ts);
20248 return -1;
20249 }
20250-
20251+
20252 num = strtol(ts, &err, 10);
20253 if (*err != ' ') {
20254- log_error_write(srv, __FILE__, __LINE__, "ss",
20255+ log_error_write(srv, __FILE__, __LINE__, "ss",
20256 "missing <type> after <num>:", ts);
20257 return -1;
20258 }
20259-
20260+
20261 ts = space + 1;
20262-
20263+
20264 if (NULL != (space = strchr(ts, ' '))) {
20265 int slen;
20266 /* */
20267-
20268+
20269 slen = space - ts;
20270-
20271- if (slen == 5 &&
20272+
20273+ if (slen == 5 &&
20274 0 == strncmp(ts, "years", slen)) {
20275 num *= 60 * 60 * 24 * 30 * 12;
20276 } else if (slen == 6 &&
20277@@ -161,13 +161,13 @@
20278 0 == strncmp(ts, "seconds", slen)) {
20279 num *= 1;
20280 } else {
20281- log_error_write(srv, __FILE__, __LINE__, "ss",
20282+ log_error_write(srv, __FILE__, __LINE__, "ss",
20283 "unknown type:", ts);
20284 return -1;
20285 }
20286-
20287+
20288 retts += num;
20289-
20290+
20291 ts = space + 1;
20292 } else {
20293 if (0 == strcmp(ts, "years")) {
20294@@ -183,19 +183,19 @@
20295 } else if (0 == strcmp(ts, "seconds")) {
20296 num *= 1;
20297 } else {
20298- log_error_write(srv, __FILE__, __LINE__, "ss",
20299+ log_error_write(srv, __FILE__, __LINE__, "ss",
20300 "unknown type:", ts);
20301 return -1;
20302 }
20303-
20304+
20305 retts += num;
20306-
20307+
20308 break;
20309 }
20310 }
20311-
20312+
20313 if (offset != NULL) *offset = retts;
20314-
20315+
20316 return type;
20317 }
20318
20319@@ -205,102 +205,99 @@
20320 SETDEFAULTS_FUNC(mod_expire_set_defaults) {
20321 plugin_data *p = p_d;
20322 size_t i = 0, k;
20323-
20324- config_values_t cv[] = {
20325+
20326+ config_values_t cv[] = {
20327 { "expire.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
20328 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20329 };
20330-
20331+
20332 if (!p) return HANDLER_ERROR;
20333-
20334+
20335 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20336-
20337+
20338 for (i = 0; i < srv->config_context->used; i++) {
20339 plugin_config *s;
20340-
20341+
20342 s = calloc(1, sizeof(plugin_config));
20343 s->expire_url = array_init();
20344-
20345+
20346 cv[0].destination = s->expire_url;
20347-
20348+
20349 p->config_storage[i] = s;
20350-
20351+
20352 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
20353 return HANDLER_ERROR;
20354 }
20355-
20356+
20357 for (k = 0; k < s->expire_url->used; k++) {
20358 data_string *ds = (data_string *)s->expire_url->data[k];
20359-
20360+
20361 /* parse lines */
20362 if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
20363- log_error_write(srv, __FILE__, __LINE__, "sb",
20364+ log_error_write(srv, __FILE__, __LINE__, "sb",
20365 "parsing expire.url failed:", ds->value);
20366 return HANDLER_ERROR;
20367 }
20368 }
20369 }
20370-
20371-
20372+
20373+
20374 return HANDLER_GO_ON;
20375 }
20376
20377-#define PATCH(x) \
20378- p->conf.x = s->x;
20379 static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
20380 size_t i, j;
20381 plugin_config *s = p->config_storage[0];
20382-
20383- PATCH(expire_url);
20384-
20385+
20386+ PATCH_OPTION(expire_url);
20387+
20388 /* skip the first, the global context */
20389 for (i = 1; i < srv->config_context->used; i++) {
20390 data_config *dc = (data_config *)srv->config_context->data[i];
20391 s = p->config_storage[i];
20392-
20393+
20394 /* condition didn't match */
20395 if (!config_check_cond(srv, con, dc)) continue;
20396-
20397+
20398 /* merge config */
20399 for (j = 0; j < dc->value->used; j++) {
20400 data_unset *du = dc->value->data[j];
20401-
20402+
20403 if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
20404- PATCH(expire_url);
20405+ PATCH_OPTION(expire_url);
20406 }
20407 }
20408 }
20409-
20410+
20411 return 0;
20412 }
20413-#undef PATCH
20414
20415 URIHANDLER_FUNC(mod_expire_path_handler) {
20416 plugin_data *p = p_d;
20417 int s_len;
20418 size_t k;
20419-
20420+
20421 if (con->uri.path->used == 0) return HANDLER_GO_ON;
20422-
20423+
20424 mod_expire_patch_connection(srv, con, p);
20425-
20426+
20427 s_len = con->uri.path->used - 1;
20428-
20429+
20430 for (k = 0; k < p->conf.expire_url->used; k++) {
20431 data_string *ds = (data_string *)p->conf.expire_url->data[k];
20432 int ct_len = ds->key->used - 1;
20433-
20434+
20435 if (ct_len > s_len) continue;
20436 if (ds->key->used == 0) continue;
20437-
20438+
20439 if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
20440 int ts;
20441 time_t t;
20442 size_t len;
20443 stat_cache_entry *sce = NULL;
20444-
20445+
20446 stat_cache_get_entry(srv, con, con->physical.path, &sce);
20447-
20448+
20449 switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
20450 case 0:
20451 /* access */
20452@@ -308,38 +305,38 @@
20453 break;
20454 case 1:
20455 /* modification */
20456-
20457+
20458 t = (ts + sce->st.st_mtime);
20459 break;
20460 default:
20461 /* -1 is handled at parse-time */
20462 break;
20463 }
20464-
20465-
20466- if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
20467+
20468+
20469+ if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
20470 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
20471 /* could not set expire header, out of mem */
20472-
20473+
20474 return HANDLER_GO_ON;
20475-
20476+
20477 }
20478-
20479+
20480 p->expire_tstmp->used = len + 1;
20481-
20482- /* HTTP/1.0 */
20483+
20484+ /* HTTP/1.0 */
20485 response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
20486
20487- /* HTTP/1.1 */
20488+ /* HTTP/1.1 */
20489 buffer_copy_string(p->expire_tstmp, "max-age=");
20490 buffer_append_long(p->expire_tstmp, ts);
20491-
20492+
20493 response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
20494-
20495+
20496 return HANDLER_GO_ON;
20497 }
20498 }
20499-
20500+
20501 /* not found */
20502 return HANDLER_GO_ON;
20503 }
20504@@ -349,13 +346,13 @@
20505 int mod_expire_plugin_init(plugin *p) {
20506 p->version = LIGHTTPD_VERSION_ID;
20507 p->name = buffer_init_string("expire");
20508-
20509+
20510 p->init = mod_expire_init;
20511 p->handle_subrequest_start = mod_expire_path_handler;
20512 p->set_defaults = mod_expire_set_defaults;
20513 p->cleanup = mod_expire_free;
20514-
20515+
20516 p->data = NULL;
20517-
20518+
20519 return 0;
20520 }
1175ccec 20521--- ../lighttpd-1.4.11/src/mod_fastcgi.c 2006-03-09 13:18:39.000000000 +0200
36e2a29e 20522+++ lighttpd-1.4.12/src/mod_fastcgi.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
20523@@ -1,5 +1,4 @@
20524 #include <sys/types.h>
20525-#include <unistd.h>
20526 #include <errno.h>
20527 #include <fcntl.h>
20528 #include <string.h>
20529@@ -24,7 +23,7 @@
20530 #include "inet_ntop_cache.h"
20531 #include "stat_cache.h"
20532
20533-#include <fastcgi.h>
20534+#include "fastcgi.h"
20535 #include <stdio.h>
20536
20537 #ifdef HAVE_SYS_FILIO_H
20538@@ -32,7 +31,11 @@
20539 #endif
20540
20541 #include "sys-socket.h"
20542+#include "sys-files.h"
20543+#include "sys-strings.h"
20544+#include "sys-process.h"
20545
20546+#include "http_resp.h"
20547
20548 #ifndef UNIX_PATH_MAX
20549 # define UNIX_PATH_MAX 108
20550@@ -45,14 +48,13 @@
20551 #include <sys/wait.h>
20552 #endif
20553
20554-
20555 /*
20556- *
20557+ *
20558 * TODO:
20559- *
20560+ *
20561 * - add timeout for a connect to a non-fastcgi process
20562 * (use state_timestamp + state)
20563- *
20564+ *
20565 */
20566
20567 typedef struct fcgi_proc {
20568@@ -61,7 +63,7 @@
20569 unsigned port; /* config.port + pno */
20570
20571 buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
20572-
20573+
20574 pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
20575
20576
20577@@ -70,20 +72,20 @@
20578 time_t last_used; /* see idle_timeout */
20579 size_t requests; /* see max_requests */
20580 struct fcgi_proc *prev, *next; /* see first */
20581-
20582+
20583 time_t disabled_until; /* this proc is disabled until, use something else until than */
20584-
20585+
20586 int is_local;
20587
20588- enum {
20589+ enum {
20590 PROC_STATE_UNSET, /* init-phase */
20591 PROC_STATE_RUNNING, /* alive */
20592- PROC_STATE_OVERLOADED, /* listen-queue is full,
20593+ PROC_STATE_OVERLOADED, /* listen-queue is full,
20594 don't send something to this proc for the next 2 seconds */
20595 PROC_STATE_DIED_WAIT_FOR_PID, /* */
20596 PROC_STATE_DIED, /* marked as dead, should be restarted */
20597 PROC_STATE_KILLED /* was killed as we don't have the load anymore */
20598- } state;
20599+ } state;
20600 } fcgi_proc;
20601
20602 typedef struct {
20603@@ -94,20 +96,20 @@
20604 * sorted by lowest load
20605 *
20606 * whenever a job is done move it up in the list
20607- * until it is sorted, move it down as soon as the
20608+ * until it is sorted, move it down as soon as the
20609 * job is started
20610 */
20611- fcgi_proc *first;
20612- fcgi_proc *unused_procs;
20613+ fcgi_proc *first;
20614+ fcgi_proc *unused_procs;
20615
20616- /*
20617+ /*
20618 * spawn at least min_procs, at max_procs.
20619 *
20620- * as soon as the load of the first entry
20621+ * as soon as the load of the first entry
20622 * is max_load_per_proc we spawn a new one
20623- * and add it to the first entry and give it
20624+ * and add it to the first entry and give it
20625 * the load
20626- *
20627+ *
20628 */
20629
20630 unsigned short min_procs;
20631@@ -119,44 +121,44 @@
20632
20633 /*
20634 * kick the process from the list if it was not
20635- * used for idle_timeout until min_procs is
20636+ * used for idle_timeout until min_procs is
20637 * reached. this helps to get the processlist
20638 * small again we had a small peak load.
20639 *
20640 */
20641-
20642+
20643 unsigned short idle_timeout;
20644-
20645+
20646 /*
20647 * time after a disabled remote connection is tried to be re-enabled
20648- *
20649- *
20650+ *
20651+ *
20652 */
20653-
20654+
20655 unsigned short disable_time;
20656
20657 /*
20658 * same fastcgi processes get a little bit larger
20659- * than wanted. max_requests_per_proc kills a
20660+ * than wanted. max_requests_per_proc kills a
20661 * process after a number of handled requests.
20662 *
20663 */
20664 size_t max_requests_per_proc;
20665-
20666+
20667
20668 /* config */
20669
20670- /*
20671- * host:port
20672+ /*
20673+ * host:port
20674 *
20675- * if host is one of the local IP adresses the
20676+ * if host is one of the local IP adresses the
20677 * whole connection is local
20678 *
20679 * if tcp/ip should be used host AND port have
20680- * to be specified
20681- *
20682- */
20683- buffer *host;
20684+ * to be specified
20685+ *
20686+ */
20687+ buffer *host;
20688 unsigned short port;
20689
20690 /*
20691@@ -169,7 +171,7 @@
20692 */
20693 buffer *unixsocket;
20694
20695- /* if socket is local we can start the fastcgi
20696+ /* if socket is local we can start the fastcgi
20697 * process ourself
20698 *
20699 * bin-path is the path to the binary
20700@@ -177,19 +179,19 @@
20701 * check min_procs and max_procs for the number
20702 * of process to start-up
20703 */
20704- buffer *bin_path;
20705-
20706- /* bin-path is set bin-environment is taken to
20707+ buffer *bin_path;
20708+
20709+ /* bin-path is set bin-environment is taken to
20710 * create the environement before starting the
20711 * FastCGI process
20712- *
20713+ *
20714 */
20715 array *bin_env;
20716-
20717+
20718 array *bin_env_copy;
20719-
20720+
20721 /*
20722- * docroot-translation between URL->phys and the
20723+ * docroot-translation between URL->phys and the
20724 * remote host
20725 *
20726 * reasons:
20727@@ -208,7 +210,7 @@
20728 unsigned short mode;
20729
20730 /*
20731- * check_local tell you if the phys file is stat()ed
20732+ * check_local tell you if the phys file is stat()ed
20733 * or not. FastCGI doesn't care if the service is
20734 * remote. If the web-server side doesn't contain
20735 * the fastcgi-files we should not stat() for them
20736@@ -218,11 +220,11 @@
20737
20738 /*
20739 * append PATH_INFO to SCRIPT_FILENAME
20740- *
20741+ *
20742 * php needs this if cgi.fix_pathinfo is provied
20743- *
20744+ *
20745 */
20746-
20747+
20748 unsigned short break_scriptfilename_for_php;
20749
20750 /*
20751@@ -231,12 +233,12 @@
20752 *
20753 */
20754 unsigned short allow_xsendfile;
20755-
20756+
20757 ssize_t load; /* replace by host->load */
20758
20759 size_t max_id; /* corresponds most of the time to
20760 num_procs.
20761-
20762+
20763 only if a process is killed max_id waits for the process itself
20764 to die and decrements its afterwards */
20765
20766@@ -245,17 +247,17 @@
20767
20768 /*
20769 * one extension can have multiple hosts assigned
20770- * one host can spawn additional processes on the same
20771+ * one host can spawn additional processes on the same
20772 * socket (if we control it)
20773 *
20774 * ext -> host -> procs
20775 * 1:n 1:n
20776 *
20777- * if the fastcgi process is remote that whole goes down
20778+ * if the fastcgi process is remote that whole goes down
20779 * to
20780 *
20781 * ext -> host -> procs
20782- * 1:n 1:1
20783+ * 1:n 1:1
20784 *
20785 * in case of PHP and FCGI_CHILDREN we have again a procs
20786 * but we don't control it directly.
20787@@ -268,7 +270,7 @@
20788 int note_is_sent;
20789
20790 fcgi_extension_host **hosts;
20791-
20792+
20793 size_t used;
20794 size_t size;
20795 } fcgi_extension;
20796@@ -282,10 +284,10 @@
20797
20798
20799 typedef struct {
20800- fcgi_exts *exts;
20801+ fcgi_exts *exts;
20802
20803 array *ext_mapping;
20804-
20805+
20806 int debug;
20807 } plugin_config;
20808
20809@@ -297,7 +299,7 @@
20810
20811 typedef struct {
20812 char **ptr;
20813-
20814+
20815 size_t size;
20816 size_t used;
20817 } char_array;
20818@@ -306,44 +308,44 @@
20819 typedef struct {
20820 PLUGIN_DATA;
20821 buffer_uint fcgi_request_id;
20822-
20823+
20824 buffer *fcgi_env;
20825-
20826+
20827 buffer *path;
20828- buffer *parse_response;
20829
20830 buffer *statuskey;
20831-
20832+
20833+ http_resp *resp;
20834+
20835 plugin_config **config_storage;
20836-
20837+
20838 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
20839 } plugin_data;
20840
20841 /* connection specific data */
20842-typedef enum {
20843+typedef enum {
20844 FCGI_STATE_UNSET,
20845- FCGI_STATE_INIT,
20846- FCGI_STATE_CONNECT_DELAYED,
20847- FCGI_STATE_PREPARE_WRITE,
20848- FCGI_STATE_WRITE,
20849- FCGI_STATE_READ
20850+ FCGI_STATE_INIT,
20851+ FCGI_STATE_CONNECT_DELAYED,
20852+ FCGI_STATE_PREPARE_WRITE,
20853+ FCGI_STATE_WRITE,
20854+ FCGI_STATE_READ
20855 } fcgi_connection_state_t;
20856
20857 typedef struct {
20858 fcgi_proc *proc;
20859 fcgi_extension_host *host;
20860 fcgi_extension *ext;
20861-
20862+
20863 fcgi_connection_state_t state;
20864 time_t state_timestamp;
20865-
20866+
20867 int reconnects; /* number of reconnect attempts */
20868-
20869- chunkqueue *rb; /* read queue */
20870+
20871+ chunkqueue *rb; /* the raw fcgi read-queue */
20872+ chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
20873 chunkqueue *wb; /* write queue */
20874-
20875- buffer *response_header;
20876-
20877+
20878 size_t request_id;
20879 int fd; /* fd to the fastcgi process */
20880 int fde_ndx; /* index into the fd-event buffer */
20881@@ -352,9 +354,9 @@
20882 int got_proc;
20883
20884 int send_content_body;
20885-
20886+
20887 plugin_config conf;
20888-
20889+
20890 connection *remote_conn; /* dumb pointer */
20891 plugin_data *plugin_data; /* dumb pointer */
20892 } handler_ctx;
20893@@ -380,7 +382,7 @@
20894 return di;
20895 }
20896
20897-/* dummies of the statistic framework functions
20898+/* dummies of the statistic framework functions
20899 * they will be moved to a statistics.c later */
20900 int status_counter_inc(server *srv, const char *s, size_t len) {
20901 data_integer *di = status_counter_get_counter(srv, s, len);
20902@@ -429,7 +431,7 @@
20903 CLEAN(".connected");
20904 CLEAN(".load");
20905
20906-#undef CLEAN
20907+#undef CLEAN
20908
20909 #define CLEAN(x) \
20910 fastcgi_status_copy_procname(b, host, NULL); \
20911@@ -438,33 +440,32 @@
20912
20913 CLEAN(".load");
20914
20915-#undef CLEAN
20916+#undef CLEAN
20917
20918 return 0;
20919 }
20920
20921 static handler_ctx * handler_ctx_init() {
20922 handler_ctx * hctx;
20923-
20924+
20925 hctx = calloc(1, sizeof(*hctx));
20926 assert(hctx);
20927-
20928+
20929 hctx->fde_ndx = -1;
20930-
20931- hctx->response_header = buffer_init();
20932-
20933+
20934 hctx->request_id = 0;
20935 hctx->state = FCGI_STATE_INIT;
20936 hctx->proc = NULL;
20937-
20938+
20939 hctx->fd = -1;
20940-
20941+
20942 hctx->reconnects = 0;
20943 hctx->send_content_body = 1;
20944
20945 hctx->rb = chunkqueue_init();
20946+ hctx->http_rb = chunkqueue_init();
20947 hctx->wb = chunkqueue_init();
20948-
20949+
20950 return hctx;
20951 }
20952
20953@@ -473,10 +474,9 @@
20954 hctx->host->load--;
20955 hctx->host = NULL;
20956 }
20957-
20958- buffer_free(hctx->response_header);
20959
20960 chunkqueue_free(hctx->rb);
20961+ chunkqueue_free(hctx->http_rb);
20962 chunkqueue_free(hctx->wb);
20963
20964 free(hctx);
20965@@ -488,21 +488,21 @@
20966 f = calloc(1, sizeof(*f));
20967 f->unixsocket = buffer_init();
20968 f->connection_name = buffer_init();
20969-
20970+
20971 f->prev = NULL;
20972 f->next = NULL;
20973-
20974+
20975 return f;
20976 }
20977
20978 void fastcgi_process_free(fcgi_proc *f) {
20979 if (!f) return;
20980-
20981+
20982 fastcgi_process_free(f->next);
20983-
20984+
20985 buffer_free(f->unixsocket);
20986 buffer_free(f->connection_name);
20987-
20988+
20989 free(f);
20990 }
20991
20992@@ -519,13 +519,13 @@
20993 f->bin_env = array_init();
20994 f->bin_env_copy = array_init();
20995 f->strip_request_uri = buffer_init();
20996-
20997+
20998 return f;
20999 }
21000
21001 void fastcgi_host_free(fcgi_extension_host *h) {
21002 if (!h) return;
21003-
21004+
21005 buffer_free(h->id);
21006 buffer_free(h->host);
21007 buffer_free(h->unixsocket);
21008@@ -534,49 +534,49 @@
21009 buffer_free(h->strip_request_uri);
21010 array_free(h->bin_env);
21011 array_free(h->bin_env_copy);
21012-
21013+
21014 fastcgi_process_free(h->first);
21015 fastcgi_process_free(h->unused_procs);
21016-
21017+
21018 free(h);
21019-
21020+
21021 }
21022
21023 fcgi_exts *fastcgi_extensions_init() {
21024 fcgi_exts *f;
21025
21026 f = calloc(1, sizeof(*f));
21027-
21028+
21029 return f;
21030 }
21031
21032 void fastcgi_extensions_free(fcgi_exts *f) {
21033 size_t i;
21034-
21035+
21036 if (!f) return;
21037-
21038+
21039 for (i = 0; i < f->used; i++) {
21040 fcgi_extension *fe;
21041 size_t j;
21042-
21043+
21044 fe = f->exts[i];
21045-
21046+
21047 for (j = 0; j < fe->used; j++) {
21048 fcgi_extension_host *h;
21049-
21050+
21051 h = fe->hosts[j];
21052-
21053+
21054 fastcgi_host_free(h);
21055 }
21056-
21057+
21058 buffer_free(fe->key);
21059 free(fe->hosts);
21060-
21061+
21062 free(fe);
21063 }
21064-
21065+
21066 free(f->exts);
21067-
21068+
21069 free(f);
21070 }
21071
21072@@ -625,24 +625,25 @@
21073 assert(fe->hosts);
21074 }
21075
21076- fe->hosts[fe->used++] = fh;
21077+ fe->hosts[fe->used++] = fh;
21078
21079 return 0;
21080-
21081+
21082 }
21083
21084 INIT_FUNC(mod_fastcgi_init) {
21085 plugin_data *p;
21086-
21087+
21088 p = calloc(1, sizeof(*p));
21089-
21090+
21091 p->fcgi_env = buffer_init();
21092-
21093+
21094 p->path = buffer_init();
21095- p->parse_response = buffer_init();
21096+
21097+ p->resp = http_response_init();
21098
21099 p->statuskey = buffer_init();
21100-
21101+
21102 return p;
21103 }
21104
21105@@ -650,81 +651,82 @@
21106 FREE_FUNC(mod_fastcgi_free) {
21107 plugin_data *p = p_d;
21108 buffer_uint *r = &(p->fcgi_request_id);
21109-
21110+
21111 UNUSED(srv);
21112
21113 if (r->ptr) free(r->ptr);
21114-
21115+
21116 buffer_free(p->fcgi_env);
21117 buffer_free(p->path);
21118- buffer_free(p->parse_response);
21119 buffer_free(p->statuskey);
21120-
21121+
21122+ http_response_free(p->resp);
21123+
21124 if (p->config_storage) {
21125 size_t i, j, n;
21126 for (i = 0; i < srv->config_context->used; i++) {
21127 plugin_config *s = p->config_storage[i];
21128 fcgi_exts *exts;
21129-
21130+
21131 if (!s) continue;
21132-
21133+
21134 exts = s->exts;
21135
21136 for (j = 0; j < exts->used; j++) {
21137 fcgi_extension *ex;
21138-
21139+
21140 ex = exts->exts[j];
21141-
21142+
21143 for (n = 0; n < ex->used; n++) {
21144 fcgi_proc *proc;
21145 fcgi_extension_host *host;
21146-
21147+
21148 host = ex->hosts[n];
21149-
21150+
21151 for (proc = host->first; proc; proc = proc->next) {
21152 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21153-
21154- if (proc->is_local &&
21155+
21156+ if (proc->is_local &&
21157 !buffer_is_empty(proc->unixsocket)) {
21158 unlink(proc->unixsocket->ptr);
21159 }
21160 }
21161-
21162+
21163 for (proc = host->unused_procs; proc; proc = proc->next) {
21164 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21165-
21166- if (proc->is_local &&
21167+
21168+ if (proc->is_local &&
21169 !buffer_is_empty(proc->unixsocket)) {
21170 unlink(proc->unixsocket->ptr);
21171 }
21172 }
21173 }
21174 }
21175-
21176+
21177 fastcgi_extensions_free(s->exts);
21178 array_free(s->ext_mapping);
21179-
21180+
21181 free(s);
21182 }
21183 free(p->config_storage);
21184 }
21185-
21186+
21187 free(p);
21188-
21189+
21190 return HANDLER_GO_ON;
21191 }
21192
21193 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
21194 char *dst;
21195-
21196+
21197 if (!key || !val) return -1;
21198-
21199+
21200 dst = malloc(key_len + val_len + 3);
21201 memcpy(dst, key, key_len);
21202 dst[key_len] = '=';
21203 /* add the \0 from the value */
21204 memcpy(dst + key_len + 1, val, val_len + 1);
21205-
21206+
21207 if (env->size == 0) {
21208 env->size = 16;
21209 env->ptr = malloc(env->size * sizeof(*env->ptr));
21210@@ -732,9 +734,9 @@
21211 env->size += 16;
21212 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21213 }
21214-
21215+
21216 env->ptr[env->used++] = dst;
21217-
21218+
21219 return 0;
21220 }
21221
21222@@ -753,15 +755,15 @@
21223 if (env->size == 0) {
21224 env->size = 16;
21225 env->ptr = malloc(env->size * sizeof(*env->ptr));
21226- } else if (env->size == env->used) {
21227+ } else if (env->size == env->used) {
21228 env->size += 16;
21229 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21230 }
21231-
21232+
21233 b->ptr[i] = '\0';
21234
21235 env->ptr[env->used++] = start;
21236-
21237+
21238 start = b->ptr + i + 1;
21239 break;
21240 default:
21241@@ -794,7 +796,7 @@
21242 return 0;
21243 }
21244
21245-static int fcgi_spawn_connection(server *srv,
21246+static int fcgi_spawn_connection(server *srv,
21247 plugin_data *p,
21248 fcgi_extension_host *host,
21249 fcgi_proc *proc) {
21250@@ -806,31 +808,27 @@
21251 #endif
21252 struct sockaddr_in fcgi_addr_in;
21253 struct sockaddr *fcgi_addr;
21254-
21255+
21256 socklen_t servlen;
21257-
21258+
21259 #ifndef HAVE_FORK
21260 return -1;
21261 #endif
21262-
21263+
21264 if (p->conf.debug) {
21265 log_error_write(srv, __FILE__, __LINE__, "sdb",
21266 "new proc, socket:", proc->port, proc->unixsocket);
21267 }
21268-
21269+
21270 if (!buffer_is_empty(proc->unixsocket)) {
21271 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
21272-
21273+
21274 #ifdef HAVE_SYS_UN_H
21275 fcgi_addr_un.sun_family = AF_UNIX;
21276 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
21277-
21278-#ifdef SUN_LEN
21279+
21280 servlen = SUN_LEN(&fcgi_addr_un);
21281-#else
21282- /* stevens says: */
21283- servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
21284-#endif
21285+
21286 socket_type = AF_UNIX;
21287 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
21288
21289@@ -844,108 +842,108 @@
21290 #endif
21291 } else {
21292 fcgi_addr_in.sin_family = AF_INET;
21293-
21294+
21295 if (buffer_is_empty(host->host)) {
21296 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21297 } else {
21298 struct hostent *he;
21299-
21300+
21301 /* set a usefull default */
21302 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21303-
21304-
21305+
21306+
21307 if (NULL == (he = gethostbyname(host->host->ptr))) {
21308- log_error_write(srv, __FILE__, __LINE__,
21309- "sdb", "gethostbyname failed: ",
21310+ log_error_write(srv, __FILE__, __LINE__,
21311+ "sdb", "gethostbyname failed: ",
21312 h_errno, host->host);
21313 return -1;
21314 }
21315-
21316+
21317 if (he->h_addrtype != AF_INET) {
21318 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
21319 return -1;
21320 }
21321-
21322+
21323 if (he->h_length != sizeof(struct in_addr)) {
21324 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
21325 return -1;
21326 }
21327-
21328+
21329 memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
21330-
21331+
21332 }
21333 fcgi_addr_in.sin_port = htons(proc->port);
21334 servlen = sizeof(fcgi_addr_in);
21335-
21336+
21337 socket_type = AF_INET;
21338 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
21339-
21340+
21341 buffer_copy_string(proc->connection_name, "tcp:");
21342 buffer_append_string_buffer(proc->connection_name, host->host);
21343 buffer_append_string(proc->connection_name, ":");
21344 buffer_append_long(proc->connection_name, proc->port);
21345 }
21346-
21347+
21348 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21349- log_error_write(srv, __FILE__, __LINE__, "ss",
21350+ log_error_write(srv, __FILE__, __LINE__, "ss",
21351 "failed:", strerror(errno));
21352 return -1;
21353 }
21354-
21355+
21356 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
21357 /* server is not up, spawn in */
21358 pid_t child;
21359 int val;
21360-
21361- if (errno != ENOENT &&
21362+
21363+ if (errno != ENOENT &&
21364 !buffer_is_empty(proc->unixsocket)) {
21365 unlink(proc->unixsocket->ptr);
21366 }
21367-
21368+
21369 close(fcgi_fd);
21370-
21371+
21372 /* reopen socket */
21373 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21374- log_error_write(srv, __FILE__, __LINE__, "ss",
21375+ log_error_write(srv, __FILE__, __LINE__, "ss",
21376 "socket failed:", strerror(errno));
21377 return -1;
21378 }
21379-
21380+
21381 val = 1;
21382 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
21383- log_error_write(srv, __FILE__, __LINE__, "ss",
21384+ log_error_write(srv, __FILE__, __LINE__, "ss",
21385 "socketsockopt failed:", strerror(errno));
21386 return -1;
21387 }
21388-
21389+
21390 /* create socket */
21391 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
21392- log_error_write(srv, __FILE__, __LINE__, "sbs",
21393- "bind failed for:",
21394+ log_error_write(srv, __FILE__, __LINE__, "sbs",
21395+ "bind failed for:",
21396 proc->connection_name,
21397 strerror(errno));
21398 return -1;
21399 }
21400-
21401+
21402 if (-1 == listen(fcgi_fd, 1024)) {
21403- log_error_write(srv, __FILE__, __LINE__, "ss",
21404+ log_error_write(srv, __FILE__, __LINE__, "ss",
21405 "listen failed:", strerror(errno));
21406 return -1;
21407 }
21408-
21409-#ifdef HAVE_FORK
21410+
21411+#ifndef _WIN32
21412 switch ((child = fork())) {
21413 case 0: {
21414 size_t i = 0;
21415 char *c;
21416 char_array env;
21417 char_array arg;
21418-
21419+
21420 /* create environment */
21421 env.ptr = NULL;
21422 env.size = 0;
21423 env.used = 0;
21424-
21425+
21426 arg.ptr = NULL;
21427 arg.size = 0;
21428 arg.used = 0;
21429@@ -955,18 +953,18 @@
21430 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
21431 close(fcgi_fd);
21432 }
21433-
21434+
21435 /* we don't need the client socket */
21436 for (i = 3; i < 256; i++) {
21437 close(i);
21438 }
21439-
21440+
21441 /* build clean environment */
21442 if (host->bin_env_copy->used) {
21443 for (i = 0; i < host->bin_env_copy->used; i++) {
21444 data_string *ds = (data_string *)host->bin_env_copy->data[i];
21445 char *ge;
21446-
21447+
21448 if (NULL != (ge = getenv(ds->value->ptr))) {
21449 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
21450 }
21451@@ -974,39 +972,39 @@
21452 } else {
21453 for (i = 0; environ[i]; i++) {
21454 char *eq;
21455-
21456+
21457 if (NULL != (eq = strchr(environ[i], '='))) {
21458 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
21459 }
21460 }
21461 }
21462-
21463+
21464 /* create environment */
21465 for (i = 0; i < host->bin_env->used; i++) {
21466 data_string *ds = (data_string *)host->bin_env->data[i];
21467-
21468+
21469 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
21470 }
21471-
21472+
21473 for (i = 0; i < env.used; i++) {
21474 /* search for PHP_FCGI_CHILDREN */
21475 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
21476 }
21477-
21478+
21479 /* not found, add a default */
21480 if (i == env.used) {
21481 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
21482 }
21483-
21484+
21485 env.ptr[env.used] = NULL;
21486
21487 parse_binpath(&arg, host->bin_path);
21488-
21489+
21490 /* chdir into the base of the bin-path,
21491 * search for the last / */
21492 if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
21493 *c = '\0';
21494-
21495+
21496 /* change to the physical directory */
21497 if (-1 == chdir(arg.ptr[0])) {
21498 *c = '/';
21499@@ -1018,12 +1016,12 @@
21500
21501 /* exec the cgi */
21502 execve(arg.ptr[0], arg.ptr, env.ptr);
21503-
21504- log_error_write(srv, __FILE__, __LINE__, "sbs",
21505+
21506+ log_error_write(srv, __FILE__, __LINE__, "sbs",
21507 "execve failed for:", host->bin_path, strerror(errno));
21508-
21509+
21510 exit(errno);
21511-
21512+
21513 break;
21514 }
21515 case -1:
21516@@ -1031,17 +1029,17 @@
21517 break;
21518 default:
21519 /* father */
21520-
21521+
21522 /* wait */
21523 select(0, NULL, NULL, NULL, &tv);
21524-
21525+
21526 switch (waitpid(child, &status, WNOHANG)) {
21527 case 0:
21528 /* child still running after timeout, good */
21529 break;
21530 case -1:
21531 /* no PID found ? should never happen */
21532- log_error_write(srv, __FILE__, __LINE__, "ss",
21533+ log_error_write(srv, __FILE__, __LINE__, "ss",
21534 "pid not found:", strerror(errno));
21535 return -1;
21536 default:
21537@@ -1049,10 +1047,10 @@
21538 "the fastcgi-backend", host->bin_path, "failed to start:");
21539 /* the child should not terminate at all */
21540 if (WIFEXITED(status)) {
21541- log_error_write(srv, __FILE__, __LINE__, "sdb",
21542- "child exited with status",
21543+ log_error_write(srv, __FILE__, __LINE__, "sdb",
21544+ "child exited with status",
21545 WEXITSTATUS(status), host->bin_path);
21546- log_error_write(srv, __FILE__, __LINE__, "s",
21547+ log_error_write(srv, __FILE__, __LINE__, "s",
21548 "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n"
21549 "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' "
21550 "in the output, NOT (cgi) NOR (cli)\n"
21551@@ -1060,8 +1058,8 @@
21552 log_error_write(srv, __FILE__, __LINE__, "s",
21553 "If this is PHP on Gentoo add fastcgi to the USE flags");
21554 } else if (WIFSIGNALED(status)) {
21555- log_error_write(srv, __FILE__, __LINE__, "sd",
21556- "terminated by signal:",
21557+ log_error_write(srv, __FILE__, __LINE__, "sd",
21558+ "terminated by signal:",
21559 WTERMSIG(status));
21560
21561 if (WTERMSIG(status) == 11) {
21562@@ -1071,8 +1069,8 @@
21563 "If this is PHP try to remove the byte-code caches for now and try again.");
21564 }
21565 } else {
21566- log_error_write(srv, __FILE__, __LINE__, "sd",
21567- "child died somehow:",
21568+ log_error_write(srv, __FILE__, __LINE__, "sd",
21569+ "child died somehow:",
21570 status);
21571 }
21572 return -1;
21573@@ -1082,26 +1080,26 @@
21574 proc->pid = child;
21575 proc->last_used = srv->cur_ts;
21576 proc->is_local = 1;
21577-
21578+
21579 break;
21580 }
21581 #endif
21582 } else {
21583 proc->is_local = 0;
21584 proc->pid = 0;
21585-
21586+
21587 if (p->conf.debug) {
21588 log_error_write(srv, __FILE__, __LINE__, "sb",
21589 "(debug) socket is already used, won't spawn:",
21590 proc->connection_name);
21591 }
21592 }
21593-
21594+
21595 proc->state = PROC_STATE_RUNNING;
21596 host->active_procs++;
21597-
21598+
21599 close(fcgi_fd);
21600-
21601+
21602 return 0;
21603 }
21604
21605@@ -1111,93 +1109,93 @@
21606 data_unset *du;
21607 size_t i = 0;
21608 buffer *fcgi_mode = buffer_init();
21609-
21610- config_values_t cv[] = {
21611+
21612+ config_values_t cv[] = {
21613 { "fastcgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
21614 { "fastcgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
21615 { "fastcgi.map-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
21616 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21617 };
21618-
21619+
21620 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21621-
21622+
21623 for (i = 0; i < srv->config_context->used; i++) {
21624 plugin_config *s;
21625 array *ca;
21626-
21627+
21628 s = malloc(sizeof(plugin_config));
21629 s->exts = fastcgi_extensions_init();
21630 s->debug = 0;
21631 s->ext_mapping = array_init();
21632-
21633+
21634 cv[0].destination = s->exts;
21635 cv[1].destination = &(s->debug);
21636 cv[2].destination = s->ext_mapping;
21637-
21638+
21639 p->config_storage[i] = s;
21640 ca = ((data_config *)srv->config_context->data[i])->value;
21641-
21642+
21643 if (0 != config_insert_values_global(srv, ca, cv)) {
21644 return HANDLER_ERROR;
21645 }
21646-
21647- /*
21648+
21649+ /*
21650 * <key> = ( ... )
21651 */
21652-
21653+
21654 if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
21655 size_t j;
21656 data_array *da = (data_array *)du;
21657-
21658+
21659 if (du->type != TYPE_ARRAY) {
21660- log_error_write(srv, __FILE__, __LINE__, "sss",
21661+ log_error_write(srv, __FILE__, __LINE__, "sss",
21662 "unexpected type for key: ", "fastcgi.server", "array of strings");
21663-
21664+
21665 return HANDLER_ERROR;
21666 }
21667-
21668-
21669- /*
21670- * fastcgi.server = ( "<ext>" => ( ... ),
21671+
21672+
21673+ /*
21674+ * fastcgi.server = ( "<ext>" => ( ... ),
21675 * "<ext>" => ( ... ) )
21676 */
21677-
21678+
21679 for (j = 0; j < da->value->used; j++) {
21680 size_t n;
21681 data_array *da_ext = (data_array *)da->value->data[j];
21682-
21683+
21684 if (da->value->data[j]->type != TYPE_ARRAY) {
21685- log_error_write(srv, __FILE__, __LINE__, "sssbs",
21686- "unexpected type for key: ", "fastcgi.server",
21687+ log_error_write(srv, __FILE__, __LINE__, "sssbs",
21688+ "unexpected type for key: ", "fastcgi.server",
21689 "[", da->value->data[j]->key, "](string)");
21690-
21691+
21692 return HANDLER_ERROR;
21693 }
21694-
21695- /*
21696- * da_ext->key == name of the extension
21697+
21698+ /*
21699+ * da_ext->key == name of the extension
21700 */
21701-
21702- /*
21703- * fastcgi.server = ( "<ext>" =>
21704- * ( "<host>" => ( ... ),
21705+
21706+ /*
21707+ * fastcgi.server = ( "<ext>" =>
21708+ * ( "<host>" => ( ... ),
21709 * "<host>" => ( ... )
21710- * ),
21711+ * ),
21712 * "<ext>" => ... )
21713 */
21714-
21715+
21716 for (n = 0; n < da_ext->value->used; n++) {
21717 data_array *da_host = (data_array *)da_ext->value->data[n];
21718-
21719+
21720 fcgi_extension_host *host;
21721-
21722- config_values_t fcv[] = {
21723+
21724+ config_values_t fcv[] = {
21725 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
21726 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
21727 { "mode", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
21728 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
21729 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
21730-
21731+
21732 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
21733 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
21734 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
21735@@ -1205,28 +1203,28 @@
21736 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
21737 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
21738 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
21739-
21740+
21741 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
21742 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
21743-
21744+
21745 { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
21746 { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
21747 { "strip-request-uri", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
21748-
21749+
21750 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21751 };
21752-
21753+
21754 if (da_host->type != TYPE_ARRAY) {
21755- log_error_write(srv, __FILE__, __LINE__, "ssSBS",
21756- "unexpected type for key:",
21757- "fastcgi.server",
21758+ log_error_write(srv, __FILE__, __LINE__, "ssSBS",
21759+ "unexpected type for key:",
21760+ "fastcgi.server",
21761 "[", da_host->key, "](string)");
21762-
21763+
21764 return HANDLER_ERROR;
21765 }
21766-
21767+
21768 host = fastcgi_host_init();
21769-
21770+
21771 buffer_copy_string_buffer(host->id, da_host->key);
21772
21773 host->check_local = 1;
21774@@ -1238,13 +1236,13 @@
21775 host->disable_time = 60;
21776 host->break_scriptfilename_for_php = 0;
21777 host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
21778-
21779+
21780 fcv[0].destination = host->host;
21781 fcv[1].destination = host->docroot;
21782 fcv[2].destination = fcgi_mode;
21783 fcv[3].destination = host->unixsocket;
21784 fcv[4].destination = host->bin_path;
21785-
21786+
21787 fcv[5].destination = &(host->check_local);
21788 fcv[6].destination = &(host->port);
21789 fcv[7].destination = &(host->min_procs);
21790@@ -1252,35 +1250,35 @@
21791 fcv[9].destination = &(host->max_load_per_proc);
21792 fcv[10].destination = &(host->idle_timeout);
21793 fcv[11].destination = &(host->disable_time);
21794-
21795+
21796 fcv[12].destination = host->bin_env;
21797 fcv[13].destination = host->bin_env_copy;
21798 fcv[14].destination = &(host->break_scriptfilename_for_php);
21799 fcv[15].destination = &(host->allow_xsendfile);
21800 fcv[16].destination = host->strip_request_uri;
21801-
21802+
21803 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
21804 return HANDLER_ERROR;
21805 }
21806-
21807- if ((!buffer_is_empty(host->host) || host->port) &&
21808+
21809+ if ((!buffer_is_empty(host->host) || host->port) &&
21810 !buffer_is_empty(host->unixsocket)) {
21811- log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21812+ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21813 "either host/port or socket have to be set in:",
21814- da->key, "= (",
21815+ da->key, "= (",
21816 da_ext->key, " => (",
21817 da_host->key, " ( ...");
21818
21819 return HANDLER_ERROR;
21820 }
21821-
21822+
21823 if (!buffer_is_empty(host->unixsocket)) {
21824 /* unix domain socket */
21825-
21826+
21827 if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
21828- log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21829+ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21830 "unixsocket is too long in:",
21831- da->key, "= (",
21832+ da->key, "= (",
21833 da_ext->key, " => (",
21834 da_host->key, " ( ...");
21835
21836@@ -1288,37 +1286,37 @@
21837 }
21838 } else {
21839 /* tcp/ip */
21840-
21841- if (buffer_is_empty(host->host) &&
21842+
21843+ if (buffer_is_empty(host->host) &&
21844 buffer_is_empty(host->bin_path)) {
21845- log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21846+ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21847 "host or binpath have to be set in:",
21848- da->key, "= (",
21849+ da->key, "= (",
21850 da_ext->key, " => (",
21851 da_host->key, " ( ...");
21852-
21853+
21854 return HANDLER_ERROR;
21855 } else if (host->port == 0) {
21856- log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21857+ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21858 "port has to be set in:",
21859- da->key, "= (",
21860+ da->key, "= (",
21861 da_ext->key, " => (",
21862 da_host->key, " ( ...");
21863
21864 return HANDLER_ERROR;
21865 }
21866 }
21867-
21868- if (!buffer_is_empty(host->bin_path)) {
21869+
21870+ if (!buffer_is_empty(host->bin_path)) {
21871 /* a local socket + self spawning */
21872 size_t pno;
21873
21874 /* HACK: just to make sure the adaptive spawing is disabled */
21875 host->min_procs = host->max_procs;
21876-
21877+
21878 if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
21879 if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
21880-
21881+
21882 if (s->debug) {
21883 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
21884 "--- fastcgi spawning local",
21885@@ -1328,7 +1326,7 @@
21886 "\n\tmin-procs:", host->min_procs,
21887 "\n\tmax-procs:", host->max_procs);
21888 }
21889-
21890+
21891 for (pno = 0; pno < host->min_procs; pno++) {
21892 fcgi_proc *proc;
21893
21894@@ -1343,7 +1341,7 @@
21895 buffer_append_string(proc->unixsocket, "-");
21896 buffer_append_long(proc->unixsocket, pno);
21897 }
21898-
21899+
21900 if (s->debug) {
21901 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
21902 "--- fastcgi spawning",
21903@@ -1351,7 +1349,7 @@
21904 "\n\tsocket", host->unixsocket,
21905 "\n\tcurrent:", pno, "/", host->min_procs);
21906 }
21907-
21908+
21909 if (fcgi_spawn_connection(srv, p, host, proc)) {
21910 log_error_write(srv, __FILE__, __LINE__, "s",
21911 "[ERROR]: spawning fcgi failed.");
21912@@ -1359,35 +1357,35 @@
21913 }
21914
21915 fastcgi_status_init(srv, p->statuskey, host, proc);
21916-
21917+
21918 proc->next = host->first;
21919 if (host->first) host->first->prev = proc;
21920-
21921+
21922 host->first = proc;
21923 }
21924 } else {
21925 fcgi_proc *proc;
21926-
21927+
21928 proc = fastcgi_process_init();
21929 proc->id = host->num_procs++;
21930 host->max_id++;
21931 host->active_procs++;
21932 proc->state = PROC_STATE_RUNNING;
21933-
21934+
21935 if (buffer_is_empty(host->unixsocket)) {
21936 proc->port = host->port;
21937 } else {
21938 buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
21939 }
21940-
21941+
21942 fastcgi_status_init(srv, p->statuskey, host, proc);
21943
21944 host->first = proc;
21945-
21946+
21947 host->min_procs = 1;
21948 host->max_procs = 1;
21949 }
21950-
21951+
21952 if (!buffer_is_empty(fcgi_mode)) {
21953 if (strcmp(fcgi_mode->ptr, "responder") == 0) {
21954 host->mode = FCGI_RESPONDER;
21955@@ -1411,16 +1409,16 @@
21956 }
21957 }
21958 }
21959-
21960+
21961 buffer_free(fcgi_mode);
21962-
21963+
21964 return HANDLER_GO_ON;
21965 }
21966
21967 static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) {
21968 hctx->state = state;
21969 hctx->state_timestamp = srv->cur_ts;
21970-
21971+
21972 return 0;
21973 }
21974
21975@@ -1429,13 +1427,13 @@
21976 size_t m = 0;
21977 size_t i;
21978 buffer_uint *r = &(p->fcgi_request_id);
21979-
21980+
21981 UNUSED(srv);
21982
21983 for (i = 0; i < r->used; i++) {
21984 if (r->ptr[i] > m) m = r->ptr[i];
21985 }
21986-
21987+
21988 if (r->size == 0) {
21989 r->size = 16;
21990 r->ptr = malloc(sizeof(*r->ptr) * r->size);
21991@@ -1443,54 +1441,54 @@
21992 r->size += 16;
21993 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
21994 }
21995-
21996+
21997 r->ptr[r->used++] = ++m;
21998-
21999+
22000 return m;
22001 }
22002
22003 static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
22004 size_t i;
22005 buffer_uint *r = &(p->fcgi_request_id);
22006-
22007+
22008 UNUSED(srv);
22009
22010 for (i = 0; i < r->used; i++) {
22011 if (r->ptr[i] == request_id) break;
22012 }
22013-
22014+
22015 if (i != r->used) {
22016 /* found */
22017-
22018+
22019 if (i != r->used - 1) {
22020 r->ptr[i] = r->ptr[r->used - 1];
22021 }
22022 r->used--;
22023 }
22024-
22025+
22026 return 0;
22027 }
22028 void fcgi_connection_close(server *srv, handler_ctx *hctx) {
22029 plugin_data *p;
22030 connection *con;
22031-
22032+
22033 if (NULL == hctx) return;
22034-
22035+
22036 p = hctx->plugin_data;
22037 con = hctx->remote_conn;
22038-
22039+
22040 if (con->mode != p->id) {
22041 WP();
22042 return;
22043 }
22044-
22045+
22046 if (hctx->fd != -1) {
22047 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
22048 fdevent_unregister(srv->ev, hctx->fd);
22049 close(hctx->fd);
22050 srv->cur_fds--;
22051 }
22052-
22053+
22054 if (hctx->request_id != 0) {
22055 fcgi_requestid_del(srv, p, hctx->request_id);
22056 }
22057@@ -1499,7 +1497,7 @@
22058 if (hctx->got_proc) {
22059 /* after the connect the process gets a load */
22060 hctx->proc->load--;
22061-
22062+
22063 status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
22064
22065 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
22066@@ -1509,39 +1507,39 @@
22067
22068 if (p->conf.debug) {
22069 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
22070- "released proc:",
22071- "pid:", hctx->proc->pid,
22072- "socket:", hctx->proc->connection_name,
22073+ "released proc:",
22074+ "pid:", hctx->proc->pid,
22075+ "socket:", hctx->proc->connection_name,
22076 "load:", hctx->proc->load);
22077 }
22078 }
22079 }
22080
22081-
22082+
22083 handler_ctx_free(hctx);
22084- con->plugin_ctx[p->id] = NULL;
22085+ con->plugin_ctx[p->id] = NULL;
22086 }
22087
22088 static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
22089 plugin_data *p = hctx->plugin_data;
22090-
22091- /* child died
22092- *
22093- * 1.
22094- *
22095+
22096+ /* child died
22097+ *
22098+ * 1.
22099+ *
22100 * connect was ok, connection was accepted
22101 * but the php accept loop checks after the accept if it should die or not.
22102- *
22103- * if yes we can only detect it at a write()
22104- *
22105+ *
22106+ * if yes we can only detect it at a write()
22107+ *
22108 * next step is resetting this attemp and setup a connection again
22109- *
22110+ *
22111 * if we have more then 5 reconnects for the same request, die
22112- *
22113- * 2.
22114- *
22115+ *
22116+ * 2.
22117+ *
22118 * we have a connection but the child died by some other reason
22119- *
22120+ *
22121 */
22122
22123 if (hctx->fd != -1) {
22124@@ -1551,59 +1549,59 @@
22125 srv->cur_fds--;
22126 hctx->fd = -1;
22127 }
22128-
22129+
22130 fcgi_requestid_del(srv, p, hctx->request_id);
22131-
22132+
22133 fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
22134-
22135+
22136 hctx->request_id = 0;
22137 hctx->reconnects++;
22138-
22139+
22140 if (p->conf.debug > 2) {
22141 if (hctx->proc) {
22142 log_error_write(srv, __FILE__, __LINE__, "sdb",
22143- "release proc for reconnect:",
22144+ "release proc for reconnect:",
22145 hctx->proc->pid, hctx->proc->connection_name);
22146 } else {
22147 log_error_write(srv, __FILE__, __LINE__, "sb",
22148- "release proc for reconnect:",
22149+ "release proc for reconnect:",
22150 hctx->host->unixsocket);
22151 }
22152 }
22153
22154- if (hctx->proc && hctx->got_proc) {
22155+ if (hctx->proc && hctx->got_proc) {
22156 hctx->proc->load--;
22157 }
22158
22159 /* perhaps another host gives us more luck */
22160 hctx->host->load--;
22161 hctx->host = NULL;
22162-
22163+
22164 return 0;
22165 }
22166
22167
22168 static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
22169 plugin_data *p = p_d;
22170-
22171+
22172 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
22173-
22174+
22175 return HANDLER_GO_ON;
22176 }
22177
22178
22179 static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
22180 size_t len;
22181-
22182+
22183 if (!key || !val) return -1;
22184-
22185+
22186 len = key_len + val_len;
22187-
22188+
22189 len += key_len > 127 ? 4 : 1;
22190 len += val_len > 127 ? 4 : 1;
22191-
22192+
22193 buffer_prepare_append(env, len);
22194-
22195+
22196 if (key_len > 127) {
22197 env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
22198 env->ptr[env->used++] = (key_len >> 16) & 0xff;
22199@@ -1612,7 +1610,7 @@
22200 } else {
22201 env->ptr[env->used++] = (key_len >> 0) & 0xff;
22202 }
22203-
22204+
22205 if (val_len > 127) {
22206 env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
22207 env->ptr[env->used++] = (val_len >> 16) & 0xff;
22208@@ -1621,12 +1619,12 @@
22209 } else {
22210 env->ptr[env->used++] = (val_len >> 0) & 0xff;
22211 }
22212-
22213+
22214 memcpy(env->ptr + env->used, key, key_len);
22215 env->used += key_len;
22216 memcpy(env->ptr + env->used, val, val_len);
22217 env->used += val_len;
22218-
22219+
22220 return 0;
22221 }
22222
22223@@ -1639,11 +1637,11 @@
22224 header->contentLengthB1 = (contentLength >> 8) & 0xff;
22225 header->paddingLength = paddingLength;
22226 header->reserved = 0;
22227-
22228+
22229 return 0;
22230 }
22231 /**
22232- *
22233+ *
22234 * returns
22235 * -1 error
22236 * 0 connected
22237@@ -1665,26 +1663,23 @@
22238 struct sockaddr_un fcgi_addr_un;
22239 #endif
22240 socklen_t servlen;
22241-
22242+
22243 fcgi_extension_host *host = hctx->host;
22244 fcgi_proc *proc = hctx->proc;
22245 int fcgi_fd = hctx->fd;
22246-
22247+
22248 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
22249-
22250+
22251 if (!buffer_is_empty(proc->unixsocket)) {
22252 #ifdef HAVE_SYS_UN_H
22253 /* use the unix domain socket */
22254 fcgi_addr_un.sun_family = AF_UNIX;
22255 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
22256-#ifdef SUN_LEN
22257+
22258 servlen = SUN_LEN(&fcgi_addr_un);
22259-#else
22260- /* stevens says: */
22261- servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
22262-#endif
22263+
22264 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
22265-
22266+
22267 if (buffer_is_empty(proc->connection_name)) {
22268 /* on remote spawing we have to set the connection-name now */
22269 buffer_copy_string(proc->connection_name, "unix:");
22270@@ -1695,16 +1690,18 @@
22271 #endif
22272 } else {
22273 fcgi_addr_in.sin_family = AF_INET;
22274+
22275 if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
22276- log_error_write(srv, __FILE__, __LINE__, "sbs",
22277- "converting IP-adress failed for", host->host,
22278+ log_error_write(srv, __FILE__, __LINE__, "sbs",
22279+ "converting IP-adress failed for", host->host,
22280 "\nBe sure to specify an IP address here");
22281-
22282+
22283 return -1;
22284 }
22285+
22286 fcgi_addr_in.sin_port = htons(proc->port);
22287 servlen = sizeof(fcgi_addr_in);
22288-
22289+
22290 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
22291
22292 if (buffer_is_empty(proc->connection_name)) {
22293@@ -1715,20 +1712,20 @@
22294 buffer_append_long(proc->connection_name, proc->port);
22295 }
22296 }
22297-
22298+
22299 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
22300- if (errno == EINPROGRESS ||
22301+ if (errno == EINPROGRESS ||
22302 errno == EALREADY ||
22303 errno == EINTR) {
22304 if (hctx->conf.debug > 2) {
22305- log_error_write(srv, __FILE__, __LINE__, "sb",
22306+ log_error_write(srv, __FILE__, __LINE__, "sb",
22307 "connect delayed, will continue later:", proc->connection_name);
22308 }
22309-
22310+
22311 return CONNECTION_DELAYED;
22312 } else if (errno == EAGAIN) {
22313 if (hctx->conf.debug) {
22314- log_error_write(srv, __FILE__, __LINE__, "sbsd",
22315+ log_error_write(srv, __FILE__, __LINE__, "sbsd",
22316 "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
22317 "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
22318 "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
22319@@ -1736,8 +1733,8 @@
22320
22321 return CONNECTION_OVERLOADED;
22322 } else {
22323- log_error_write(srv, __FILE__, __LINE__, "sssb",
22324- "connect failed:",
22325+ log_error_write(srv, __FILE__, __LINE__, "sssb",
22326+ "connect failed:",
22327 strerror(errno), "on",
22328 proc->connection_name);
22329
22330@@ -1747,7 +1744,7 @@
22331
22332 hctx->reconnects = 0;
22333 if (hctx->conf.debug > 1) {
22334- log_error_write(srv, __FILE__, __LINE__, "sd",
22335+ log_error_write(srv, __FILE__, __LINE__, "sd",
22336 "connect succeeded: ", fcgi_fd);
22337 }
22338
22339@@ -1756,21 +1753,21 @@
22340
22341 static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
22342 size_t i;
22343-
22344+
22345 for (i = 0; i < con->request.headers->used; i++) {
22346 data_string *ds;
22347-
22348+
22349 ds = (data_string *)con->request.headers->data[i];
22350-
22351+
22352 if (ds->value->used && ds->key->used) {
22353 size_t j;
22354 buffer_reset(srv->tmp_buf);
22355-
22356+
22357 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
22358 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
22359 srv->tmp_buf->used--;
22360 }
22361-
22362+
22363 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22364 for (j = 0; j < ds->key->used - 1; j++) {
22365 char c = '_';
22366@@ -1784,20 +1781,20 @@
22367 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22368 }
22369 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22370-
22371+
22372 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22373 }
22374 }
22375-
22376+
22377 for (i = 0; i < con->environment->used; i++) {
22378 data_string *ds;
22379-
22380+
22381 ds = (data_string *)con->environment->data[i];
22382-
22383+
22384 if (ds->value->used && ds->key->used) {
22385 size_t j;
22386 buffer_reset(srv->tmp_buf);
22387-
22388+
22389 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22390 for (j = 0; j < ds->key->used - 1; j++) {
22391 char c = '_';
22392@@ -1811,11 +1808,11 @@
22393 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22394 }
22395 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22396-
22397+
22398 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22399 }
22400 }
22401-
22402+
22403 return 0;
22404 }
22405
22406@@ -1824,24 +1821,24 @@
22407 FCGI_BeginRequestRecord beginRecord;
22408 FCGI_Header header;
22409 buffer *b;
22410-
22411+
22412 char buf[32];
22413 const char *s;
22414 #ifdef HAVE_IPV6
22415 char b2[INET6_ADDRSTRLEN + 1];
22416 #endif
22417-
22418+
22419 plugin_data *p = hctx->plugin_data;
22420 fcgi_extension_host *host= hctx->host;
22421
22422 connection *con = hctx->remote_conn;
22423 server_socket *srv_sock = con->srv_socket;
22424-
22425+
22426 sock_addr our_addr;
22427 socklen_t our_addr_len;
22428-
22429+
22430 /* send FCGI_BEGIN_REQUEST */
22431-
22432+
22433 fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0);
22434 beginRecord.body.roleB0 = host->mode;
22435 beginRecord.body.roleB1 = 0;
22436@@ -1849,21 +1846,21 @@
22437 memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
22438
22439 b = chunkqueue_get_append_buffer(hctx->wb);
22440-
22441+
22442 buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
22443-
22444+
22445 /* send FCGI_PARAMS */
22446 buffer_prepare_copy(p->fcgi_env, 1024);
22447
22448
22449 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
22450-
22451+
22452 if (con->server_name->used) {
22453 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
22454 } else {
22455 #ifdef HAVE_IPV6
22456- s = inet_ntop(srv_sock->addr.plain.sa_family,
22457- srv_sock->addr.plain.sa_family == AF_INET6 ?
22458+ s = inet_ntop(srv_sock->addr.plain.sa_family,
22459+ srv_sock->addr.plain.sa_family == AF_INET6 ?
22460 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
22461 (const void *) &(srv_sock->addr.ipv4.sin_addr),
22462 b2, sizeof(b2)-1);
22463@@ -1872,50 +1869,50 @@
22464 #endif
22465 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
22466 }
22467-
22468+
22469 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
22470-
22471- ltostr(buf,
22472+
22473+ ltostr(buf,
22474 #ifdef HAVE_IPV6
22475 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
22476 #else
22477 ntohs(srv_sock->addr.ipv4.sin_port)
22478 #endif
22479 );
22480-
22481+
22482 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
22483-
22484+
22485 /* get the server-side of the connection to the client */
22486 our_addr_len = sizeof(our_addr);
22487-
22488+
22489 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
22490 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
22491 } else {
22492 s = inet_ntop_cache_get_ip(srv, &(our_addr));
22493 }
22494 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
22495-
22496- ltostr(buf,
22497+
22498+ ltostr(buf,
22499 #ifdef HAVE_IPV6
22500 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
22501 #else
22502 ntohs(con->dst_addr.ipv4.sin_port)
22503 #endif
22504 );
22505-
22506+
22507 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
22508-
22509+
22510 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
22511 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
22512-
22513+
22514 if (!buffer_is_empty(con->authed_user)) {
22515 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
22516 CONST_BUF_LEN(con->authed_user));
22517 }
22518-
22519+
22520 if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
22521 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
22522-
22523+
22524 /* request.content_length < SSIZE_MAX, see request.c */
22525 ltostr(buf, con->request.content_length);
22526 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
22527@@ -1930,12 +1927,12 @@
22528 */
22529
22530 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
22531-
22532+
22533 if (!buffer_is_empty(con->request.pathinfo)) {
22534 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
22535-
22536+
22537 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
22538-
22539+
22540 if (!buffer_is_empty(host->docroot)) {
22541 buffer_copy_string_buffer(p->path, host->docroot);
22542 } else {
22543@@ -1957,27 +1954,27 @@
22544 */
22545
22546 if (!buffer_is_empty(host->docroot)) {
22547- /*
22548- * rewrite SCRIPT_FILENAME
22549- *
22550+ /*
22551+ * rewrite SCRIPT_FILENAME
22552+ *
22553 */
22554-
22555+
22556 buffer_copy_string_buffer(p->path, host->docroot);
22557 buffer_append_string_buffer(p->path, con->uri.path);
22558-
22559+
22560 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22561 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
22562 } else {
22563 buffer_copy_string_buffer(p->path, con->physical.path);
22564-
22565- /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22566- *
22567+
22568+ /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22569+ *
22570 * see src/sapi/cgi_main.c, init_request_info()
22571 */
22572 if (host->break_scriptfilename_for_php) {
22573 buffer_append_string_buffer(p->path, con->request.pathinfo);
22574 }
22575-
22576+
22577 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22578 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
22579 }
22580@@ -1987,7 +1984,7 @@
22581 /**
22582 * /app1/index/list
22583 *
22584- * stripping /app1 or /app1/ should lead to
22585+ * stripping /app1 or /app1/ should lead to
22586 *
22587 * /index/list
22588 *
22589@@ -2001,7 +1998,7 @@
22590 0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
22591 /* the left is the same */
22592
22593- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
22594+ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
22595 con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
22596 con->request.orig_uri->used - (host->strip_request_uri->used - 2));
22597 } else {
22598@@ -2018,26 +2015,26 @@
22599 } else {
22600 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
22601 }
22602-
22603+
22604 s = get_http_method_name(con->request.http_method);
22605 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
22606 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
22607 s = get_http_version_name(con->request.http_version);
22608 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
22609-
22610+
22611 #ifdef USE_OPENSSL
22612 if (srv_sock->is_ssl) {
22613 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
22614 }
22615 #endif
22616-
22617-
22618+
22619+
22620 fcgi_env_add_request_headers(srv, con, p);
22621-
22622+
22623 fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
22624 buffer_append_memory(b, (const char *)&header, sizeof(header));
22625 buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used);
22626-
22627+
22628 fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
22629 buffer_append_memory(b, (const char *)&header, sizeof(header));
22630
22631@@ -2057,7 +2054,7 @@
22632
22633 /* we announce toWrite octects
22634 * now take all the request_content chunk that we need to fill this request
22635- * */
22636+ * */
22637
22638 b = chunkqueue_get_append_buffer(hctx->wb);
22639 fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0);
22640@@ -2080,16 +2077,16 @@
22641 if (weHave > weWant - written) weHave = weWant - written;
22642
22643 if (p->conf.debug > 10) {
22644- fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22645- __FILE__, __LINE__,
22646- weHave,
22647- req_c->offset,
22648- req_c->file.length,
22649+ fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22650+ __FILE__, __LINE__,
22651+ weHave,
22652+ req_c->offset,
22653+ req_c->file.length,
22654 req_c->file.name->ptr);
22655 }
22656
22657 assert(weHave != 0);
22658-
22659+
22660 chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
22661
22662 req_c->offset += weHave;
22663@@ -2104,7 +2101,7 @@
22664 * - we reference the tempfile from the request-content-queue several times
22665 * if the req_c is larger than FCGI_MAX_LENGTH
22666 * - we can't simply cleanup the request-content-queue as soon as possible
22667- * as it would remove the tempfiles
22668+ * as it would remove the tempfiles
22669 * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
22670 * referencing chunk of the fastcgi-write-queue
22671 *
22672@@ -2141,7 +2138,7 @@
22673 req_c->offset += weHave;
22674 req_cq->bytes_out += weHave;
22675 written += weHave;
22676-
22677+
22678 hctx->wb->bytes_in += weHave;
22679
22680 if (req_c->offset == req_c->mem->used - 1) {
22681@@ -2155,12 +2152,12 @@
22682 break;
22683 }
22684 }
22685-
22686+
22687 b->used++; /* add virtual \0 */
22688 offset += weWant;
22689 }
22690 }
22691-
22692+
22693 b = chunkqueue_get_append_buffer(hctx->wb);
22694 /* terminate STDIN */
22695 fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0);
22696@@ -2175,118 +2172,19 @@
22697 if ((i+1) % 16 == 0) {
22698 size_t j;
22699 for (j = i-15; j <= i; j++) {
22700- fprintf(stderr, "%c",
22701+ fprintf(stderr, "%c",
22702 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
22703 }
22704 fprintf(stderr, "\n");
22705 }
22706 }
22707 #endif
22708-
22709- return 0;
22710-}
22711-
22712-static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
22713- char *s, *ns;
22714-
22715- handler_ctx *hctx = con->plugin_ctx[p->id];
22716- fcgi_extension_host *host= hctx->host;
22717-
22718- UNUSED(srv);
22719
22720- buffer_copy_string_buffer(p->parse_response, in);
22721-
22722- /* search for \n */
22723- for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
22724- char *key, *value;
22725- int key_len;
22726- data_string *ds;
22727-
22728- /* a good day. Someone has read the specs and is sending a \r\n to us */
22729-
22730- if (ns > p->parse_response->ptr &&
22731- *(ns-1) == '\r') {
22732- *(ns-1) = '\0';
22733- }
22734-
22735- ns[0] = '\0';
22736-
22737- key = s;
22738- if (NULL == (value = strchr(s, ':'))) {
22739- /* we expect: "<key>: <value>\n" */
22740- continue;
22741- }
22742-
22743- key_len = value - key;
22744-
22745- value++;
22746- /* strip WS */
22747- while (*value == ' ' || *value == '\t') value++;
22748-
22749- if (host->mode != FCGI_AUTHORIZER ||
22750- !(con->http_status == 0 ||
22751- con->http_status == 200)) {
22752- /* authorizers shouldn't affect the response headers sent back to the client */
22753-
22754- /* don't forward Status: */
22755- if (0 != strncasecmp(key, "Status", key_len)) {
22756- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
22757- ds = data_response_init();
22758- }
22759- buffer_copy_string_len(ds->key, key, key_len);
22760- buffer_copy_string(ds->value, value);
22761-
22762- array_insert_unique(con->response.headers, (data_unset *)ds);
22763- }
22764- }
22765-
22766- switch(key_len) {
22767- case 4:
22768- if (0 == strncasecmp(key, "Date", key_len)) {
22769- con->parsed_response |= HTTP_DATE;
22770- }
22771- break;
22772- case 6:
22773- if (0 == strncasecmp(key, "Status", key_len)) {
22774- con->http_status = strtol(value, NULL, 10);
22775- con->parsed_response |= HTTP_STATUS;
22776- }
22777- break;
22778- case 8:
22779- if (0 == strncasecmp(key, "Location", key_len)) {
22780- con->parsed_response |= HTTP_LOCATION;
22781- }
22782- break;
22783- case 10:
22784- if (0 == strncasecmp(key, "Connection", key_len)) {
22785- con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
22786- con->parsed_response |= HTTP_CONNECTION;
22787- }
22788- break;
22789- case 14:
22790- if (0 == strncasecmp(key, "Content-Length", key_len)) {
22791- con->response.content_length = strtol(value, NULL, 10);
22792- con->parsed_response |= HTTP_CONTENT_LENGTH;
22793-
22794- if (con->response.content_length < 0) con->response.content_length = 0;
22795- }
22796- break;
22797- default:
22798- break;
22799- }
22800- }
22801-
22802- /* CGI/1.1 rev 03 - 7.2.1.2 */
22803- if ((con->parsed_response & HTTP_LOCATION) &&
22804- !(con->parsed_response & HTTP_STATUS)) {
22805- con->http_status = 302;
22806- }
22807-
22808 return 0;
22809 }
22810
22811 typedef struct {
22812- buffer *b;
22813+ buffer *b;
22814 size_t len;
22815 int type;
22816 int padding;
22817@@ -2327,9 +2225,9 @@
22818 return -1;
22819 }
22820
22821- /* we have at least a header, now check how much me have to fetch */
22822+ /* we have at least a header, now check how much me have to fetch */
22823 header = (FCGI_Header *)(packet->b->ptr);
22824-
22825+
22826 packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
22827 packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
22828 packet->type = header->type;
22829@@ -2348,7 +2246,7 @@
22830 size_t weHave = c->mem->used - c->offset - offset - 1;
22831
22832 if (weHave > weWant) weHave = weWant;
22833-
22834+
22835 buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
22836
22837 /* we only skipped the first 8 bytes as they are the fcgi header */
22838@@ -2380,65 +2278,37 @@
22839 }
22840
22841 chunkqueue_remove_finished_chunks(hctx->rb);
22842-
22843+
22844 return 0;
22845 }
22846
22847 static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
22848 int fin = 0;
22849- int toread;
22850- ssize_t r;
22851-
22852+
22853 plugin_data *p = hctx->plugin_data;
22854 connection *con = hctx->remote_conn;
22855- int fcgi_fd = hctx->fd;
22856 fcgi_extension_host *host= hctx->host;
22857 fcgi_proc *proc = hctx->proc;
22858-
22859- /*
22860- * check how much we have to read
22861- */
22862- if (ioctl(hctx->fd, FIONREAD, &toread)) {
22863- log_error_write(srv, __FILE__, __LINE__, "sd",
22864- "unexpected end-of-file (perhaps the fastcgi process died):",
22865- fcgi_fd);
22866- return -1;
22867- }
22868-
22869- /* init read-buffer */
22870-
22871- if (toread > 0) {
22872- buffer *b;
22873-
22874- b = chunkqueue_get_append_buffer(hctx->rb);
22875- buffer_prepare_copy(b, toread + 1);
22876-
22877- /* append to read-buffer */
22878- if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
22879- log_error_write(srv, __FILE__, __LINE__, "sds",
22880- "unexpected end-of-file (perhaps the fastcgi process died):",
22881- fcgi_fd, strerror(errno));
22882- return -1;
22883- }
22884-
22885- /* this should be catched by the b > 0 above */
22886- assert(r);
22887
22888- b->used = r + 1; /* one extra for the fake \0 */
22889- b->ptr[b->used - 1] = '\0';
22890- } else {
22891- log_error_write(srv, __FILE__, __LINE__, "ssdsb",
22892+ switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) {
22893+ case NETWORK_STATUS_WAIT_FOR_EVENT:
22894+ /* we are only triggered when there is a event */
22895+ log_error_write(srv, __FILE__, __LINE__, "ssdsb",
22896 "unexpected end-of-file (perhaps the fastcgi process died):",
22897 "pid:", proc->pid,
22898 "socket:", proc->connection_name);
22899-
22900+ return -1;
22901+ case NETWORK_STATUS_SUCCESS:
22902+ break;
22903+ default:
22904+ log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
22905 return -1;
22906 }
22907
22908 /*
22909 * parse the fastcgi packets and forward the content to the write-queue
22910 *
22911- */
22912+ */
22913 while (fin == 0) {
22914 fastcgi_response_packet packet;
22915
22916@@ -2454,92 +2324,135 @@
22917
22918 /* is the header already finished */
22919 if (0 == con->file_started) {
22920- char *c;
22921- size_t blen;
22922- data_string *ds;
22923-
22924- /* search for header terminator
22925- *
22926- * if we start with \r\n check if last packet terminated with \r\n
22927- * if we start with \n check if last packet terminated with \n
22928- * search for \r\n\r\n
22929- * search for \n\n
22930- */
22931-
22932- if (hctx->response_header->used == 0) {
22933- buffer_copy_string_buffer(hctx->response_header, packet.b);
22934- } else {
22935- buffer_append_string_buffer(hctx->response_header, packet.b);
22936- }
22937-
22938- if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
22939- blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
22940- hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
22941- c += 4; /* point the the start of the response */
22942- } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
22943- blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
22944- hctx->response_header->used = c - hctx->response_header->ptr + 2;
22945- c += 2; /* point the the start of the response */
22946- } else {
22947- /* no luck, no header found */
22948+ int have_content_length = 0;
22949+ int need_more = 0;
22950+ size_t i;
22951+
22952+ /* append the current packet to the chunk queue */
22953+ chunkqueue_append_buffer(hctx->http_rb, packet.b);
22954+ http_response_reset(p->resp);
22955+
22956+ switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
22957+ case PARSE_ERROR:
22958+ /* parsing the response header failed */
22959+
22960+ con->http_status = 502; /* Bad Gateway */
22961+
22962+ return 1;
22963+ case PARSE_NEED_MORE:
22964+ need_more = 1;
22965+ break; /* leave the loop */
22966+ case PARSE_SUCCESS:
22967 break;
22968+ default:
22969+ /* should not happen */
22970+ SEGFAULT();
22971 }
22972
22973- /* parse the response header */
22974- fcgi_response_parse(srv, con, p, hctx->response_header);
22975+ if (need_more) break;
22976
22977- con->file_started = 1;
22978+ chunkqueue_remove_finished_chunks(hctx->http_rb);
22979
22980- if (host->mode == FCGI_AUTHORIZER &&
22981- (con->http_status == 0 ||
22982- con->http_status == 200)) {
22983- /* a authorizer with approved the static request, ignore the content here */
22984- hctx->send_content_body = 0;
22985- }
22986-
22987- if (host->allow_xsendfile &&
22988- NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
22989- stat_cache_entry *sce;
22990-
22991- if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
22992- /* found */
22993-
22994- http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
22995- hctx->send_content_body = 0; /* ignore the content */
22996- joblist_append(srv, con);
22997+ con->http_status = p->resp->status;
22998+
22999+ /* handle the header fields */
23000+ if (host->mode == FCGI_AUTHORIZER) {
23001+ /* auth mode is a bit different */
23002+
23003+ if (con->http_status == 0 ||
23004+ con->http_status == 200) {
23005+ /* a authorizer with approved the static request, ignore the content here */
23006+ hctx->send_content_body = 0;
23007 }
23008 }
23009
23010+ /* copy the http-headers */
23011+ for (i = 0; i < p->resp->headers->used; i++) {
23012+ const char *ign[] = { "Status", NULL };
23013+ size_t j;
23014+ data_string *ds;
23015+
23016+ data_string *header = (data_string *)p->resp->headers->data[i];
23017+
23018+ /* ignore all headers in AUTHORIZER mode */
23019+ if (host->mode == FCGI_AUTHORIZER) continue;
23020+
23021+ /* some headers are ignored by default */
23022+ for (j = 0; ign[j]; j++) {
23023+ if (0 == strcasecmp(ign[j], header->key->ptr)) break;
23024+ }
23025+ if (ign[j]) continue;
23026+
23027+ if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
23028+ /* CGI/1.1 rev 03 - 7.2.1.2 */
23029+ con->http_status = 302;
23030+ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
23031+ have_content_length = 1;
23032+ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) ||
23033+ 0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
23034+
23035+ stat_cache_entry *sce;
23036
23037- if (hctx->send_content_body && blen > 1) {
23038- /* enable chunked-transfer-encoding */
23039+ if (host->allow_xsendfile &&
23040+ HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
23041+ http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
23042+ hctx->send_content_body = 0; /* ignore the content */
23043+
23044+ joblist_append(srv, con);
23045+ }
23046+
23047+ continue; /* ignore header */
23048+ }
23049+
23050+ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
23051+ ds = data_response_init();
23052+ }
23053+ buffer_copy_string_buffer(ds->key, header->key);
23054+ buffer_copy_string_buffer(ds->value, header->value);
23055+
23056+ array_insert_unique(con->response.headers, (data_unset *)ds);
23057+ }
23058+
23059+ /* header is complete ... go on with the body */
23060+
23061+ con->file_started = 1;
23062+
23063+ if (hctx->send_content_body) {
23064+ chunk *c = hctx->http_rb->first;
23065+
23066+ /* if we don't have a content-length enable chunked encoding
23067+ * if possible
23068+ *
23069+ * TODO: move this to a later stage in the filter-queue
23070+ * */
23071 if (con->request.http_version == HTTP_VERSION_1_1 &&
23072- !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23073+ !have_content_length) {
23074 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23075 }
23076
23077- http_chunk_append_mem(srv, con, c, blen);
23078+ /* copy the rest of the data */
23079+ for (c = hctx->http_rb->first; c; c = c->next) {
23080+ if (c->mem->used > 1) {
23081+ http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
23082+ c->offset = c->mem->used - 1;
23083+ }
23084+ }
23085+ chunkqueue_remove_finished_chunks(hctx->http_rb);
23086 joblist_append(srv, con);
23087 }
23088 } else if (hctx->send_content_body && packet.b->used > 1) {
23089- if (con->request.http_version == HTTP_VERSION_1_1 &&
23090- !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23091- /* enable chunked-transfer-encoding */
23092- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23093- }
23094-
23095 http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
23096 joblist_append(srv, con);
23097 }
23098 break;
23099 case FCGI_STDERR:
23100- log_error_write(srv, __FILE__, __LINE__, "sb",
23101+ log_error_write(srv, __FILE__, __LINE__, "sb",
23102 "FastCGI-stderr:", packet.b);
23103-
23104+
23105 break;
23106 case FCGI_END_REQUEST:
23107 con->file_finished = 1;
23108-
23109+
23110 if (host->mode != FCGI_AUTHORIZER ||
23111 !(con->http_status == 0 ||
23112 con->http_status == 200)) {
23113@@ -2547,39 +2460,39 @@
23114 http_chunk_append_mem(srv, con, NULL, 0);
23115 joblist_append(srv, con);
23116 }
23117-
23118+
23119 fin = 1;
23120 break;
23121 default:
23122- log_error_write(srv, __FILE__, __LINE__, "sd",
23123+ log_error_write(srv, __FILE__, __LINE__, "sd",
23124 "FastCGI: header.type not handled: ", packet.type);
23125 break;
23126 }
23127 buffer_free(packet.b);
23128 }
23129-
23130+
23131 return fin;
23132 }
23133
23134 static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
23135 fcgi_proc *proc;
23136-
23137+
23138 for (proc = host->first; proc; proc = proc->next) {
23139 int status;
23140
23141 if (p->conf.debug > 2) {
23142- log_error_write(srv, __FILE__, __LINE__, "sbdddd",
23143- "proc:",
23144+ log_error_write(srv, __FILE__, __LINE__, "sbdddd",
23145+ "proc:",
23146 proc->connection_name,
23147 proc->state,
23148 proc->is_local,
23149 proc->load,
23150 proc->pid);
23151 }
23152-
23153- /*
23154+
23155+ /*
23156 * if the remote side is overloaded, we check back after <n> seconds
23157- *
23158+ *
23159 */
23160 switch (proc->state) {
23161 case PROC_STATE_KILLED:
23162@@ -2592,13 +2505,13 @@
23163 break;
23164 case PROC_STATE_OVERLOADED:
23165 if (srv->cur_ts <= proc->disabled_until) break;
23166-
23167+
23168 proc->state = PROC_STATE_RUNNING;
23169 host->active_procs++;
23170-
23171- log_error_write(srv, __FILE__, __LINE__, "sbdb",
23172- "fcgi-server re-enabled:",
23173- host->host, host->port,
23174+
23175+ log_error_write(srv, __FILE__, __LINE__, "sbdb",
23176+ "fcgi-server re-enabled:",
23177+ host->host, host->port,
23178 host->unixsocket);
23179 break;
23180 case PROC_STATE_DIED_WAIT_FOR_PID:
23181@@ -2606,7 +2519,7 @@
23182 if (!proc->is_local) break;
23183
23184 /* the child should not terminate at all */
23185-
23186+#ifndef _WIN32
23187 switch(waitpid(proc->pid, &status, WNOHANG)) {
23188 case 0:
23189 /* child is still alive */
23190@@ -2616,45 +2529,45 @@
23191 default:
23192 if (WIFEXITED(status)) {
23193 #if 0
23194- log_error_write(srv, __FILE__, __LINE__, "sdsd",
23195+ log_error_write(srv, __FILE__, __LINE__, "sdsd",
23196 "child exited, pid:", proc->pid,
23197 "status:", WEXITSTATUS(status));
23198 #endif
23199 } else if (WIFSIGNALED(status)) {
23200- log_error_write(srv, __FILE__, __LINE__, "sd",
23201- "child signaled:",
23202+ log_error_write(srv, __FILE__, __LINE__, "sd",
23203+ "child signaled:",
23204 WTERMSIG(status));
23205 } else {
23206- log_error_write(srv, __FILE__, __LINE__, "sd",
23207- "child died somehow:",
23208+ log_error_write(srv, __FILE__, __LINE__, "sd",
23209+ "child died somehow:",
23210 status);
23211 }
23212-
23213+
23214 proc->state = PROC_STATE_DIED;
23215 break;
23216 }
23217-
23218+#endif
23219 /* fall through if we have a dead proc now */
23220 if (proc->state != PROC_STATE_DIED) break;
23221
23222 case PROC_STATE_DIED:
23223- /* local proc get restarted by us,
23224+ /* local proc get restarted by us,
23225 * remote ones hopefully by the admin */
23226-
23227+
23228 if (proc->is_local) {
23229 /* we still have connections bound to this proc,
23230 * let them terminate first */
23231 if (proc->load != 0) break;
23232-
23233+
23234 /* restart the child */
23235-
23236+
23237 if (p->conf.debug) {
23238 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23239 "--- fastcgi spawning",
23240 "\n\tsocket", proc->connection_name,
23241 "\n\tcurrent:", 1, "/", host->min_procs);
23242 }
23243-
23244+
23245 if (fcgi_spawn_connection(srv, p, host, proc)) {
23246 log_error_write(srv, __FILE__, __LINE__, "s",
23247 "ERROR: spawning fcgi failed.");
23248@@ -2662,18 +2575,18 @@
23249 }
23250 } else {
23251 if (srv->cur_ts <= proc->disabled_until) break;
23252-
23253+
23254 proc->state = PROC_STATE_RUNNING;
23255 host->active_procs++;
23256-
23257- log_error_write(srv, __FILE__, __LINE__, "sb",
23258- "fcgi-server re-enabled:",
23259+
23260+ log_error_write(srv, __FILE__, __LINE__, "sb",
23261+ "fcgi-server re-enabled:",
23262 proc->connection_name);
23263 }
23264 break;
23265 }
23266 }
23267-
23268+
23269 return 0;
23270 }
23271
23272@@ -2682,19 +2595,19 @@
23273 fcgi_extension_host *host= hctx->host;
23274 connection *con = hctx->remote_conn;
23275 fcgi_proc *proc;
23276-
23277+
23278 int ret;
23279
23280- /* sanity check */
23281+ /* sanity check */
23282 if (!host ||
23283 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
23284- log_error_write(srv, __FILE__, __LINE__, "sxddd",
23285+ log_error_write(srv, __FILE__, __LINE__, "sxddd",
23286 "write-req: error",
23287 host,
23288 host->host->used,
23289 host->port,
23290 host->unixsocket->used);
23291-
23292+
23293 hctx->proc->disabled_until = srv->cur_ts + 10;
23294 hctx->proc->state = PROC_STATE_DIED;
23295
23296@@ -2705,12 +2618,12 @@
23297 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23298 int socket_error;
23299 socklen_t socket_error_len = sizeof(socket_error);
23300-
23301+
23302 /* try to finish the connect() */
23303 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
23304- log_error_write(srv, __FILE__, __LINE__, "ss",
23305+ log_error_write(srv, __FILE__, __LINE__, "ss",
23306 "getsockopt failed:", strerror(errno));
23307-
23308+
23309 hctx->proc->disabled_until = srv->cur_ts + 10;
23310 hctx->proc->state = PROC_STATE_DIED;
23311
23312@@ -2719,12 +2632,12 @@
23313 if (socket_error != 0) {
23314 if (!hctx->proc->is_local || p->conf.debug) {
23315 /* local procs get restarted */
23316-
23317+
23318 log_error_write(srv, __FILE__, __LINE__, "sssb",
23319- "establishing connection failed:", strerror(socket_error),
23320+ "establishing connection failed:", strerror(socket_error),
23321 "socket:", hctx->proc->connection_name);
23322 }
23323-
23324+
23325 hctx->proc->disabled_until = srv->cur_ts + 5;
23326
23327 if (hctx->proc->is_local) {
23328@@ -2732,17 +2645,17 @@
23329 } else {
23330 hctx->proc->state = PROC_STATE_DIED;
23331 }
23332-
23333+
23334 hctx->proc->state = PROC_STATE_DIED;
23335-
23336+
23337 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23338 buffer_append_string(p->statuskey, ".died");
23339
23340 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23341-
23342+
23343 return HANDLER_ERROR;
23344 }
23345- /* go on with preparing the request */
23346+ /* go on with preparing the request */
23347 hctx->state = FCGI_STATE_PREPARE_WRITE;
23348 }
23349
23350@@ -2755,14 +2668,14 @@
23351 /* do we have a running process for this host (max-procs) ? */
23352 hctx->proc = NULL;
23353
23354- for (proc = hctx->host->first;
23355- proc && proc->state != PROC_STATE_RUNNING;
23356+ for (proc = hctx->host->first;
23357+ proc && proc->state != PROC_STATE_RUNNING;
23358 proc = proc->next);
23359-
23360+
23361 /* all childs are dead */
23362 if (proc == NULL) {
23363 hctx->fde_ndx = -1;
23364-
23365+
23366 return HANDLER_ERROR;
23367 }
23368
23369@@ -2775,50 +2688,50 @@
23370 }
23371
23372 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
23373-
23374+
23375 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
23376 if (errno == EMFILE ||
23377 errno == EINTR) {
23378- log_error_write(srv, __FILE__, __LINE__, "sd",
23379+ log_error_write(srv, __FILE__, __LINE__, "sd",
23380 "wait for fd at connection:", con->fd);
23381-
23382+
23383 return HANDLER_WAIT_FOR_FD;
23384 }
23385-
23386- log_error_write(srv, __FILE__, __LINE__, "ssdd",
23387+
23388+ log_error_write(srv, __FILE__, __LINE__, "ssdd",
23389 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
23390 return HANDLER_ERROR;
23391 }
23392 hctx->fde_ndx = -1;
23393-
23394+
23395 srv->cur_fds++;
23396-
23397+
23398 fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
23399-
23400+
23401 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
23402- log_error_write(srv, __FILE__, __LINE__, "ss",
23403+ log_error_write(srv, __FILE__, __LINE__, "ss",
23404 "fcntl failed:", strerror(errno));
23405-
23406+
23407 return HANDLER_ERROR;
23408 }
23409-
23410+
23411 if (hctx->proc->is_local) {
23412 hctx->pid = hctx->proc->pid;
23413 }
23414-
23415+
23416 switch (fcgi_establish_connection(srv, hctx)) {
23417 case CONNECTION_DELAYED:
23418 /* connection is in progress, wait for an event and call getsockopt() below */
23419-
23420+
23421 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23422-
23423+
23424 fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED);
23425 return HANDLER_WAIT_FOR_EVENT;
23426 case CONNECTION_OVERLOADED:
23427 /* cool down the backend, it is overloaded
23428 * -> EAGAIN */
23429
23430- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23431+ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23432 "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
23433 "reconnects:", hctx->reconnects,
23434 "load:", host->load);
23435@@ -2831,7 +2744,7 @@
23436 buffer_append_string(p->statuskey, ".overloaded");
23437
23438 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23439-
23440+
23441 return HANDLER_ERROR;
23442 case CONNECTION_DEAD:
23443 /* we got a hard error from the backend like
23444@@ -2840,19 +2753,19 @@
23445 *
23446 * for check if the host is back in 5 seconds
23447 * */
23448-
23449+
23450 hctx->proc->disabled_until = srv->cur_ts + 5;
23451 if (hctx->proc->is_local) {
23452 hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
23453 } else {
23454 hctx->proc->state = PROC_STATE_DIED;
23455 }
23456-
23457- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23458+
23459+ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23460 "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
23461 "reconnects:", hctx->reconnects,
23462 "load:", host->load);
23463-
23464+
23465 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23466 buffer_append_string(p->statuskey, ".died");
23467
23468@@ -2863,19 +2776,19 @@
23469 /* everything is ok, go on */
23470
23471 fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
23472-
23473+
23474 break;
23475 case CONNECTION_UNSET:
23476 break;
23477 }
23478-
23479+
23480 case FCGI_STATE_PREPARE_WRITE:
23481 /* ok, we have the connection */
23482-
23483+
23484 hctx->proc->load++;
23485 hctx->proc->last_used = srv->cur_ts;
23486 hctx->got_proc = 1;
23487-
23488+
23489 status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
23490 status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
23491
23492@@ -2898,9 +2811,9 @@
23493
23494 if (p->conf.debug) {
23495 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
23496- "got proc:",
23497- "pid:", hctx->proc->pid,
23498- "socket:", hctx->proc->connection_name,
23499+ "got proc:",
23500+ "pid:", hctx->proc->pid,
23501+ "socket:", hctx->proc->connection_name,
23502 "load:", hctx->proc->load);
23503 }
23504
23505@@ -2908,62 +2821,63 @@
23506 if (hctx->request_id == 0) {
23507 hctx->request_id = fcgi_requestid_new(srv, p);
23508 } else {
23509- log_error_write(srv, __FILE__, __LINE__, "sd",
23510+ log_error_write(srv, __FILE__, __LINE__, "sd",
23511 "fcgi-request is already in use:", hctx->request_id);
23512 }
23513-
23514+
23515 /* fall through */
23516 fcgi_create_env(srv, hctx, hctx->request_id);
23517-
23518+
23519 fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
23520-
23521+
23522 /* fall through */
23523 case FCGI_STATE_WRITE:
23524- ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
23525+ ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
23526
23527 chunkqueue_remove_finished_chunks(hctx->wb);
23528-
23529+
23530 if (ret < 0) {
23531 switch(errno) {
23532 case ENOTCONN:
23533- /* the connection got dropped after accept()
23534- *
23535- * this is most of the time a PHP which dies
23536+ /* the connection got dropped after accept()
23537+ *
23538+ * this is most of the time a PHP which dies
23539 * after PHP_FCGI_MAX_REQUESTS
23540- *
23541- */
23542+ *
23543+ */
23544 if (hctx->wb->bytes_out == 0 &&
23545 hctx->reconnects < 5) {
23546- usleep(10000); /* take away the load of the webserver
23547- * to let the php a chance to restart
23548+#ifndef _WIN32
23549+ usleep(10000); /* take away the load of the webserver
23550+ * to let the php a chance to restart
23551 */
23552-
23553+#endif
23554 fcgi_reconnect(srv, hctx);
23555-
23556+
23557 return HANDLER_WAIT_FOR_FD;
23558 }
23559-
23560+
23561 /* not reconnected ... why
23562- *
23563+ *
23564 * far@#lighttpd report this for FreeBSD
23565- *
23566+ *
23567 */
23568-
23569- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23570+
23571+ log_error_write(srv, __FILE__, __LINE__, "ssosd",
23572 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
23573 "write-offset:", hctx->wb->bytes_out,
23574 "reconnect attempts:", hctx->reconnects);
23575-
23576+
23577 return HANDLER_ERROR;
23578 case EAGAIN:
23579 case EINTR:
23580 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23581-
23582+
23583 return HANDLER_WAIT_FOR_EVENT;
23584 default:
23585- log_error_write(srv, __FILE__, __LINE__, "ssd",
23586+ log_error_write(srv, __FILE__, __LINE__, "ssd",
23587 "write failed:", strerror(errno), errno);
23588-
23589+
23590 return HANDLER_ERROR;
23591 }
23592 }
23593@@ -2975,7 +2889,7 @@
23594 fcgi_set_state(srv, hctx, FCGI_STATE_READ);
23595 } else {
23596 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23597-
23598+
23599 return HANDLER_WAIT_FOR_EVENT;
23600 }
23601
23602@@ -2987,7 +2901,7 @@
23603 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
23604 return HANDLER_ERROR;
23605 }
23606-
23607+
23608 return HANDLER_WAIT_FOR_EVENT;
23609 }
23610
23611@@ -2996,18 +2910,18 @@
23612 * */
23613 SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
23614 plugin_data *p = p_d;
23615-
23616+
23617 handler_ctx *hctx = con->plugin_ctx[p->id];
23618 fcgi_proc *proc;
23619 fcgi_extension_host *host;
23620-
23621+
23622 if (NULL == hctx) return HANDLER_GO_ON;
23623-
23624+
23625 /* not my job */
23626 if (con->mode != p->id) return HANDLER_GO_ON;
23627
23628 /* we don't have a host yet, choose one
23629- * -> this happens in the first round
23630+ * -> this happens in the first round
23631 * and when the host died and we have to select a new one */
23632 if (hctx->host == NULL) {
23633 size_t k;
23634@@ -3016,23 +2930,23 @@
23635 /* get best server */
23636 for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
23637 host = hctx->ext->hosts[k];
23638-
23639+
23640 /* we should have at least one proc that can do something */
23641 if (host->active_procs == 0) continue;
23642
23643 if (used == -1 || host->load < used) {
23644 used = host->load;
23645-
23646+
23647 ndx = k;
23648 }
23649 }
23650-
23651+
23652 /* found a server */
23653 if (ndx == -1) {
23654 /* all hosts are down */
23655
23656 fcgi_connection_close(srv, hctx);
23657-
23658+
23659 con->http_status = 500;
23660 con->mode = DIRECT;
23661
23662@@ -3040,16 +2954,16 @@
23663 }
23664
23665 host = hctx->ext->hosts[ndx];
23666-
23667- /*
23668- * if check-local is disabled, use the uri.path handler
23669- *
23670+
23671+ /*
23672+ * if check-local is disabled, use the uri.path handler
23673+ *
23674 */
23675-
23676+
23677 /* init handler-context */
23678 hctx->host = host;
23679
23680- /* we put a connection on this host, move the other new connections to other hosts
23681+ /* we put a connection on this host, move the other new connections to other hosts
23682 *
23683 * as soon as hctx->host is unassigned, decrease the load again */
23684 hctx->host->load++;
23685@@ -3063,7 +2977,7 @@
23686 case HANDLER_ERROR:
23687 proc = hctx->proc;
23688 host = hctx->host;
23689-
23690+
23691 if (hctx->state == FCGI_STATE_INIT ||
23692 hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23693 if (proc) host->active_procs--;
23694@@ -3078,7 +2992,7 @@
23695 return HANDLER_WAIT_FOR_FD;
23696 } else {
23697 fcgi_connection_close(srv, hctx);
23698-
23699+
23700 buffer_reset(con->physical.path);
23701 con->mode = DIRECT;
23702 con->http_status = 500;
23703@@ -3088,12 +3002,12 @@
23704 }
23705 } else {
23706 fcgi_connection_close(srv, hctx);
23707-
23708+
23709 buffer_reset(con->physical.path);
23710 con->mode = DIRECT;
23711 con->http_status = 503;
23712 joblist_append(srv, con); /* really ? */
23713-
23714+
23715 return HANDLER_FINISHED;
23716 }
23717 case HANDLER_WAIT_FOR_EVENT:
23718@@ -3115,7 +3029,7 @@
23719 handler_ctx *hctx = ctx;
23720 connection *con = hctx->remote_conn;
23721 plugin_data *p = hctx->plugin_data;
23722-
23723+
23724 fcgi_proc *proc = hctx->proc;
23725 fcgi_extension_host *host= hctx->host;
23726
23727@@ -3125,8 +3039,8 @@
23728 case 0:
23729 break;
23730 case 1:
23731-
23732- if (host->mode == FCGI_AUTHORIZER &&
23733+
23734+ if (host->mode == FCGI_AUTHORIZER &&
23735 (con->http_status == 200 ||
23736 con->http_status == 0)) {
23737 /*
23738@@ -3136,26 +3050,26 @@
23739 */
23740
23741 buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
23742-
23743+
23744 buffer_copy_string_buffer(con->physical.path, host->docroot);
23745 buffer_append_string_buffer(con->physical.path, con->uri.path);
23746 fcgi_connection_close(srv, hctx);
23747-
23748+
23749 con->mode = DIRECT;
23750 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
23751 } else {
23752 /* we are done */
23753 fcgi_connection_close(srv, hctx);
23754 }
23755-
23756+
23757 joblist_append(srv, con);
23758 return HANDLER_FINISHED;
23759 case -1:
23760 if (proc->pid && proc->state != PROC_STATE_DIED) {
23761 int status;
23762-
23763+
23764 /* only fetch the zombie if it is not already done */
23765-
23766+#ifndef _WIN32
23767 switch(waitpid(proc->pid, &status, WNOHANG)) {
23768 case 0:
23769 /* child is still alive */
23770@@ -3165,60 +3079,61 @@
23771 default:
23772 /* the child should not terminate at all */
23773 if (WIFEXITED(status)) {
23774- log_error_write(srv, __FILE__, __LINE__, "sdsd",
23775+ log_error_write(srv, __FILE__, __LINE__, "sdsd",
23776 "child exited, pid:", proc->pid,
23777 "status:", WEXITSTATUS(status));
23778 } else if (WIFSIGNALED(status)) {
23779- log_error_write(srv, __FILE__, __LINE__, "sd",
23780- "child signaled:",
23781+ log_error_write(srv, __FILE__, __LINE__, "sd",
23782+ "child signaled:",
23783 WTERMSIG(status));
23784 } else {
23785- log_error_write(srv, __FILE__, __LINE__, "sd",
23786- "child died somehow:",
23787+ log_error_write(srv, __FILE__, __LINE__, "sd",
23788+ "child died somehow:",
23789 status);
23790 }
23791-
23792+
23793 if (p->conf.debug) {
23794 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23795 "--- fastcgi spawning",
23796 "\n\tsocket", proc->connection_name,
23797 "\n\tcurrent:", 1, "/", host->min_procs);
23798 }
23799-
23800+
23801 if (fcgi_spawn_connection(srv, p, host, proc)) {
23802 /* respawning failed, retry later */
23803 proc->state = PROC_STATE_DIED;
23804
23805- log_error_write(srv, __FILE__, __LINE__, "s",
23806+ log_error_write(srv, __FILE__, __LINE__, "s",
23807 "respawning failed, will retry later");
23808 }
23809-
23810+
23811 break;
23812 }
23813+#endif
23814 }
23815
23816 if (con->file_started == 0) {
23817 /* nothing has been send out yet, try to use another child */
23818-
23819+
23820 if (hctx->wb->bytes_out == 0 &&
23821 hctx->reconnects < 5) {
23822 fcgi_reconnect(srv, hctx);
23823-
23824- log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23825+
23826+ log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23827 "response not received, request not sent",
23828- "on socket:", proc->connection_name,
23829+ "on socket:", proc->connection_name,
23830 "for", con->uri.path, ", reconnecting");
23831-
23832+
23833 return HANDLER_WAIT_FOR_FD;
23834 }
23835-
23836- log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
23837+
23838+ log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
23839 "response not received, request sent:", hctx->wb->bytes_out,
23840- "on socket:", proc->connection_name,
23841+ "on socket:", proc->connection_name,
23842 "for", con->uri.path, ", closing connection");
23843-
23844+
23845 fcgi_connection_close(srv, hctx);
23846-
23847+
23848 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
23849 buffer_reset(con->physical.path);
23850 con->http_status = 500;
23851@@ -3226,76 +3141,76 @@
23852 } else {
23853 /* response might have been already started, kill the connection */
23854 fcgi_connection_close(srv, hctx);
23855-
23856- log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23857+
23858+ log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23859 "response already sent out, but backend returned error",
23860- "on socket:", proc->connection_name,
23861+ "on socket:", proc->connection_name,
23862 "for", con->uri.path, ", terminating connection");
23863-
23864+
23865 connection_set_state(srv, con, CON_STATE_ERROR);
23866 }
23867
23868 /* */
23869-
23870-
23871+
23872+
23873 joblist_append(srv, con);
23874 return HANDLER_FINISHED;
23875 }
23876 }
23877-
23878+
23879 if (revents & FDEVENT_OUT) {
23880 if (hctx->state == FCGI_STATE_CONNECT_DELAYED ||
23881 hctx->state == FCGI_STATE_WRITE) {
23882 /* we are allowed to send something out
23883- *
23884+ *
23885 * 1. in a unfinished connect() call
23886 * 2. in a unfinished write() call (long POST request)
23887 */
23888 return mod_fastcgi_handle_subrequest(srv, con, p);
23889 } else {
23890- log_error_write(srv, __FILE__, __LINE__, "sd",
23891- "got a FDEVENT_OUT and didn't know why:",
23892+ log_error_write(srv, __FILE__, __LINE__, "sd",
23893+ "got a FDEVENT_OUT and didn't know why:",
23894 hctx->state);
23895 }
23896 }
23897-
23898+
23899 /* perhaps this issue is already handled */
23900 if (revents & FDEVENT_HUP) {
23901 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23902 /* getoptsock will catch this one (right ?)
23903- *
23904- * if we are in connect we might get a EINPROGRESS
23905- * in the first call and a FDEVENT_HUP in the
23906+ *
23907+ * if we are in connect we might get a EINPROGRESS
23908+ * in the first call and a FDEVENT_HUP in the
23909 * second round
23910- *
23911+ *
23912 * FIXME: as it is a bit ugly.
23913- *
23914+ *
23915 */
23916 return mod_fastcgi_handle_subrequest(srv, con, p);
23917 } else if (hctx->state == FCGI_STATE_READ &&
23918 hctx->proc->port == 0) {
23919 /* FIXME:
23920- *
23921+ *
23922 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
23923 * even if the FCGI_FIN packet is not received yet
23924 */
23925 } else {
23926- log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
23927- "error: unexpected close of fastcgi connection for",
23928+ log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
23929+ "error: unexpected close of fastcgi connection for",
23930 con->uri.path,
23931- "(no fastcgi process on host:",
23932+ "(no fastcgi process on host:",
23933 host->host,
23934- ", port: ",
23935+ ", port: ",
23936 host->port,
23937 " ?)",
23938 hctx->state);
23939-
23940+
23941 connection_set_state(srv, con, CON_STATE_ERROR);
23942 fcgi_connection_close(srv, hctx);
23943 joblist_append(srv, con);
23944 }
23945 } else if (revents & FDEVENT_ERR) {
23946- log_error_write(srv, __FILE__, __LINE__, "s",
23947+ log_error_write(srv, __FILE__, __LINE__, "s",
23948 "fcgi: got a FDEVENT_ERR. Don't know why.");
23949 /* kill all connections to the fastcgi process */
23950
23951@@ -3304,45 +3219,42 @@
23952 fcgi_connection_close(srv, hctx);
23953 joblist_append(srv, con);
23954 }
23955-
23956+
23957 return HANDLER_FINISHED;
23958 }
23959-#define PATCH(x) \
23960- p->conf.x = s->x;
23961+
23962 static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
23963 size_t i, j;
23964 plugin_config *s = p->config_storage[0];
23965-
23966- PATCH(exts);
23967- PATCH(debug);
23968- PATCH(ext_mapping);
23969-
23970+
23971+ PATCH_OPTION(exts);
23972+ PATCH_OPTION(debug);
23973+ PATCH_OPTION(ext_mapping);
23974+
23975 /* skip the first, the global context */
23976 for (i = 1; i < srv->config_context->used; i++) {
23977 data_config *dc = (data_config *)srv->config_context->data[i];
23978 s = p->config_storage[i];
23979-
23980+
23981 /* condition didn't match */
23982 if (!config_check_cond(srv, con, dc)) continue;
23983-
23984+
23985 /* merge config */
23986 for (j = 0; j < dc->value->used; j++) {
23987 data_unset *du = dc->value->data[j];
23988-
23989+
23990 if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
23991- PATCH(exts);
23992+ PATCH_OPTION(exts);
23993 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
23994- PATCH(debug);
23995+ PATCH_OPTION(debug);
23996 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
23997- PATCH(ext_mapping);
23998+ PATCH_OPTION(ext_mapping);
23999 }
24000 }
24001 }
24002-
24003+
24004 return 0;
24005 }
24006-#undef PATCH
24007-
24008
24009 static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
24010 plugin_data *p = p_d;
24011@@ -3351,16 +3263,16 @@
24012 buffer *fn;
24013 fcgi_extension *extension = NULL;
24014 fcgi_extension_host *host = NULL;
24015-
24016+
24017 /* Possibly, we processed already this request */
24018 if (con->file_started == 1) return HANDLER_GO_ON;
24019
24020 fn = uri_path_handler ? con->uri.path : con->physical.path;
24021
24022 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
24023-
24024+
24025 s_len = fn->used - 1;
24026-
24027+
24028 fcgi_patch_connection(srv, con, p);
24029
24030 /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
24031@@ -3368,24 +3280,24 @@
24032 * fastcgi.map-extensions = ( ".php3" => ".php" )
24033 *
24034 * fastcgi.server = ( ".php" => ... )
24035- *
24036+ *
24037 * */
24038
24039 /* check if extension-mapping matches */
24040 for (k = 0; k < p->conf.ext_mapping->used; k++) {
24041 data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
24042 size_t ct_len; /* length of the config entry */
24043-
24044+
24045 if (ds->key->used == 0) continue;
24046-
24047+
24048 ct_len = ds->key->used - 1;
24049-
24050+
24051 if (s_len < ct_len) continue;
24052-
24053+
24054 /* found a mapping */
24055 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
24056 /* check if we know the extension */
24057-
24058+
24059 /* we can reuse k here */
24060 for (k = 0; k < p->conf.exts->used; k++) {
24061 extension = p->conf.exts->exts[k];
24062@@ -3407,15 +3319,15 @@
24063 /* check if extension matches */
24064 for (k = 0; k < p->conf.exts->used; k++) {
24065 size_t ct_len; /* length of the config entry */
24066-
24067+
24068 extension = p->conf.exts->exts[k];
24069-
24070+
24071 if (extension->key->used == 0) continue;
24072-
24073+
24074 ct_len = extension->key->used - 1;
24075-
24076+
24077 if (s_len < ct_len) continue;
24078-
24079+
24080 /* check extension in the form "/fcgi_pattern" */
24081 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
24082 break;
24083@@ -3441,10 +3353,10 @@
24084 continue;
24085 }
24086
24087- /* we found one host that is alive */
24088+ /* we found one host that is alive */
24089 break;
24090 }
24091-
24092+
24093 if (!host) {
24094 /* sorry, we don't have a server alive for this ext */
24095 buffer_reset(con->physical.path);
24096@@ -3459,72 +3371,72 @@
24097 "on", extension->key,
24098 "are down.");
24099 }
24100-
24101+
24102 return HANDLER_FINISHED;
24103 }
24104
24105 /* a note about no handler is not sent yey */
24106 extension->note_is_sent = 0;
24107
24108- /*
24109- * if check-local is disabled, use the uri.path handler
24110- *
24111+ /*
24112+ * if check-local is disabled, use the uri.path handler
24113+ *
24114 */
24115-
24116+
24117 /* init handler-context */
24118 if (uri_path_handler) {
24119 if (host->check_local == 0) {
24120 handler_ctx *hctx;
24121 char *pathinfo;
24122-
24123+
24124 hctx = handler_ctx_init();
24125-
24126+
24127 hctx->remote_conn = con;
24128 hctx->plugin_data = p;
24129 hctx->proc = NULL;
24130 hctx->ext = extension;
24131-
24132+
24133
24134 hctx->conf.exts = p->conf.exts;
24135 hctx->conf.debug = p->conf.debug;
24136-
24137+
24138 con->plugin_ctx[p->id] = hctx;
24139-
24140+
24141 con->mode = p->id;
24142-
24143+
24144 if (con->conf.log_request_handling) {
24145- log_error_write(srv, __FILE__, __LINE__, "s",
24146+ log_error_write(srv, __FILE__, __LINE__, "s",
24147 "handling it in mod_fastcgi");
24148 }
24149-
24150- /* the prefix is the SCRIPT_NAME,
24151+
24152+ /* the prefix is the SCRIPT_NAME,
24153 * everthing from start to the next slash
24154 * this is important for check-local = "disable"
24155- *
24156+ *
24157 * if prefix = /admin.fcgi
24158- *
24159+ *
24160 * /admin.fcgi/foo/bar
24161- *
24162+ *
24163 * SCRIPT_NAME = /admin.fcgi
24164 * PATH_INFO = /foo/bar
24165- *
24166+ *
24167 * if prefix = /fcgi-bin/
24168- *
24169+ *
24170 * /fcgi-bin/foo/bar
24171- *
24172+ *
24173 * SCRIPT_NAME = /fcgi-bin/foo
24174 * PATH_INFO = /bar
24175- *
24176+ *
24177 */
24178-
24179+
24180 /* the rewrite is only done for /prefix/? matches */
24181 if (extension->key->ptr[0] == '/' &&
24182 con->uri.path->used > extension->key->used &&
24183 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
24184- /* rewrite uri.path and pathinfo */
24185-
24186+ /* rewrite uri.path and pathinfo */
24187+
24188 buffer_copy_string(con->request.pathinfo, pathinfo);
24189-
24190+
24191 con->uri.path->used -= con->request.pathinfo->used - 1;
24192 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
24193 }
24194@@ -3532,19 +3444,19 @@
24195 } else {
24196 handler_ctx *hctx;
24197 hctx = handler_ctx_init();
24198-
24199+
24200 hctx->remote_conn = con;
24201 hctx->plugin_data = p;
24202 hctx->proc = NULL;
24203 hctx->ext = extension;
24204-
24205+
24206 hctx->conf.exts = p->conf.exts;
24207 hctx->conf.debug = p->conf.debug;
24208-
24209+
24210 con->plugin_ctx[p->id] = hctx;
24211-
24212+
24213 con->mode = p->id;
24214-
24215+
24216 if (con->conf.log_request_handling) {
24217 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
24218 }
24219@@ -3566,19 +3478,19 @@
24220 JOBLIST_FUNC(mod_fastcgi_handle_joblist) {
24221 plugin_data *p = p_d;
24222 handler_ctx *hctx = con->plugin_ctx[p->id];
24223-
24224+
24225 if (hctx == NULL) return HANDLER_GO_ON;
24226
24227 if (hctx->fd != -1) {
24228 switch (hctx->state) {
24229 case FCGI_STATE_READ:
24230 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
24231-
24232+
24233 break;
24234 case FCGI_STATE_CONNECT_DELAYED:
24235 case FCGI_STATE_WRITE:
24236 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24237-
24238+
24239 break;
24240 case FCGI_STATE_INIT:
24241 /* at reconnect */
24242@@ -3595,7 +3507,7 @@
24243
24244 static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
24245 plugin_data *p = p_d;
24246-
24247+
24248 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
24249
24250 return HANDLER_GO_ON;
24251@@ -3604,16 +3516,39 @@
24252 TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
24253 plugin_data *p = p_d;
24254 size_t i, j, n;
24255-
24256-
24257+
24258+
24259 /* perhaps we should kill a connect attempt after 10-15 seconds
24260- *
24261+ *
24262 * currently we wait for the TCP timeout which is on Linux 180 seconds
24263- *
24264- *
24265- *
24266+ *
24267 */
24268
24269+ for (i = 0; i < srv->conns->used; i++) {
24270+ connection *con = srv->conns->ptr[i];
24271+ handler_ctx *hctx = con->plugin_ctx[p->id];
24272+
24273+ /* if a connection is ours and is in handle-req for more than max-request-time
24274+ * kill the connection */
24275+
24276+ if (con->mode != p->id) continue;
24277+ if (con->state != CON_STATE_HANDLE_REQUEST) continue;
24278+ if (srv->cur_ts < con->request_start + 60) continue;
24279+
24280+ /* the request is waiting for a FCGI_STDOUT since 60 seconds */
24281+
24282+ /* kill the connection */
24283+
24284+ log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
24285+
24286+ fcgi_connection_close(srv, hctx);
24287+
24288+ con->mode = DIRECT;
24289+ con->http_status = 500;
24290+
24291+ joblist_append(srv, con);
24292+ }
24293+
24294 /* check all childs if they are still up */
24295
24296 for (i = 0; i < srv->config_context->used; i++) {
24297@@ -3628,45 +3563,45 @@
24298 fcgi_extension *ex;
24299
24300 ex = exts->exts[j];
24301-
24302+
24303 for (n = 0; n < ex->used; n++) {
24304-
24305+
24306 fcgi_proc *proc;
24307 unsigned long sum_load = 0;
24308 fcgi_extension_host *host;
24309-
24310+
24311 host = ex->hosts[n];
24312-
24313+
24314 fcgi_restart_dead_procs(srv, p, host);
24315-
24316+
24317 for (proc = host->first; proc; proc = proc->next) {
24318 sum_load += proc->load;
24319 }
24320-
24321+
24322 if (host->num_procs &&
24323 host->num_procs < host->max_procs &&
24324 (sum_load / host->num_procs) > host->max_load_per_proc) {
24325 /* overload, spawn new child */
24326 if (p->conf.debug) {
24327- log_error_write(srv, __FILE__, __LINE__, "s",
24328+ log_error_write(srv, __FILE__, __LINE__, "s",
24329 "overload detected, spawning a new child");
24330 }
24331-
24332+
24333 for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
24334-
24335+
24336 if (proc) {
24337 if (proc == host->unused_procs) host->unused_procs = proc->next;
24338-
24339+
24340 if (proc->next) proc->next->prev = NULL;
24341-
24342+
24343 host->max_id++;
24344 } else {
24345 proc = fastcgi_process_init();
24346 proc->id = host->max_id++;
24347 }
24348-
24349+
24350 host->num_procs++;
24351-
24352+
24353 if (buffer_is_empty(host->unixsocket)) {
24354 proc->port = host->port + proc->id;
24355 } else {
24356@@ -3674,13 +3609,13 @@
24357 buffer_append_string(proc->unixsocket, "-");
24358 buffer_append_long(proc->unixsocket, proc->id);
24359 }
24360-
24361+
24362 if (fcgi_spawn_connection(srv, p, host, proc)) {
24363 log_error_write(srv, __FILE__, __LINE__, "s",
24364 "ERROR: spawning fcgi failed.");
24365 return HANDLER_ERROR;
24366 }
24367-
24368+
24369 proc->prev = NULL;
24370 proc->next = host->first;
24371 if (host->first) {
24372@@ -3688,56 +3623,56 @@
24373 }
24374 host->first = proc;
24375 }
24376-
24377+
24378 for (proc = host->first; proc; proc = proc->next) {
24379 if (proc->load != 0) break;
24380 if (host->num_procs <= host->min_procs) break;
24381 if (proc->pid == 0) continue;
24382-
24383+
24384 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
24385 /* a proc is idling for a long time now,
24386 * terminated it */
24387-
24388+
24389 if (p->conf.debug) {
24390- log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24391- "idle-timeout reached, terminating child:",
24392- "socket:", proc->connection_name,
24393+ log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24394+ "idle-timeout reached, terminating child:",
24395+ "socket:", proc->connection_name,
24396 "pid", proc->pid);
24397 }
24398-
24399-
24400+
24401+
24402 if (proc->next) proc->next->prev = proc->prev;
24403 if (proc->prev) proc->prev->next = proc->next;
24404-
24405+
24406 if (proc->prev == NULL) host->first = proc->next;
24407-
24408+
24409 proc->prev = NULL;
24410 proc->next = host->unused_procs;
24411-
24412+
24413 if (host->unused_procs) host->unused_procs->prev = proc;
24414 host->unused_procs = proc;
24415-
24416+
24417 kill(proc->pid, SIGTERM);
24418-
24419+
24420 proc->state = PROC_STATE_KILLED;
24421-
24422- log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24423- "killed:",
24424- "socket:", proc->connection_name,
24425+
24426+ log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24427+ "killed:",
24428+ "socket:", proc->connection_name,
24429 "pid", proc->pid);
24430-
24431+
24432 host->num_procs--;
24433-
24434+
24435 /* proc is now in unused, let the next second handle the next process */
24436 break;
24437- }
24438+ }
24439 }
24440-
24441+
24442 for (proc = host->unused_procs; proc; proc = proc->next) {
24443 int status;
24444-
24445+
24446 if (proc->pid == 0) continue;
24447-
24448+#ifndef _WIN32
24449 switch (waitpid(proc->pid, &status, WNOHANG)) {
24450 case 0:
24451 /* child still running after timeout, good */
24452@@ -3745,10 +3680,10 @@
24453 case -1:
24454 if (errno != EINTR) {
24455 /* no PID found ? should never happen */
24456- log_error_write(srv, __FILE__, __LINE__, "sddss",
24457+ log_error_write(srv, __FILE__, __LINE__, "sddss",
24458 "pid ", proc->pid, proc->state,
24459 "not found:", strerror(errno));
24460-
24461+
24462 #if 0
24463 if (errno == ECHILD) {
24464 /* someone else has cleaned up for us */
24465@@ -3762,25 +3697,26 @@
24466 /* the child should not terminate at all */
24467 if (WIFEXITED(status)) {
24468 if (proc->state != PROC_STATE_KILLED) {
24469- log_error_write(srv, __FILE__, __LINE__, "sdb",
24470- "child exited:",
24471+ log_error_write(srv, __FILE__, __LINE__, "sdb",
24472+ "child exited:",
24473 WEXITSTATUS(status), proc->connection_name);
24474 }
24475 } else if (WIFSIGNALED(status)) {
24476 if (WTERMSIG(status) != SIGTERM) {
24477- log_error_write(srv, __FILE__, __LINE__, "sd",
24478- "child signaled:",
24479+ log_error_write(srv, __FILE__, __LINE__, "sd",
24480+ "child signaled:",
24481 WTERMSIG(status));
24482 }
24483 } else {
24484- log_error_write(srv, __FILE__, __LINE__, "sd",
24485- "child died somehow:",
24486+ log_error_write(srv, __FILE__, __LINE__, "sd",
24487+ "child died somehow:",
24488 status);
24489 }
24490 proc->pid = 0;
24491 proc->state = PROC_STATE_UNSET;
24492 host->max_id--;
24493 }
24494+#endif
24495 }
24496 }
24497 }
24498@@ -3804,8 +3740,8 @@
24499 p->handle_subrequest = mod_fastcgi_handle_subrequest;
24500 p->handle_joblist = mod_fastcgi_handle_joblist;
24501 p->handle_trigger = mod_fastcgi_handle_trigger;
24502-
24503+
24504 p->data = NULL;
24505-
24506+
24507 return 0;
24508 }
1175ccec 24509--- ../lighttpd-1.4.11/src/mod_flv_streaming.c 2006-03-07 14:06:26.000000000 +0200
36e2a29e 24510+++ lighttpd-1.4.12/src/mod_flv_streaming.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
24511@@ -23,35 +23,35 @@
24512
24513 typedef struct {
24514 PLUGIN_DATA;
24515-
24516+
24517 buffer *query_str;
24518 array *get_params;
24519-
24520+
24521 plugin_config **config_storage;
24522-
24523- plugin_config conf;
24524+
24525+ plugin_config conf;
24526 } plugin_data;
24527
24528 /* init the plugin data */
24529 INIT_FUNC(mod_flv_streaming_init) {
24530 plugin_data *p;
24531-
24532+
24533 p = calloc(1, sizeof(*p));
24534-
24535+
24536 p->query_str = buffer_init();
24537 p->get_params = array_init();
24538-
24539+
24540 return p;
24541 }
24542
24543 /* detroy the plugin data */
24544 FREE_FUNC(mod_flv_streaming_free) {
24545 plugin_data *p = p_d;
24546-
24547+
24548 UNUSED(srv);
24549
24550 if (!p) return HANDLER_GO_ON;
24551-
24552+
24553 if (p->config_storage) {
24554 size_t i;
24555
24556@@ -59,19 +59,19 @@
24557 plugin_config *s = p->config_storage[i];
24558
24559 if (!s) continue;
24560-
24561+
24562 array_free(s->extensions);
24563-
24564+
24565 free(s);
24566 }
24567 free(p->config_storage);
24568 }
24569-
24570+
24571 buffer_free(p->query_str);
24572 array_free(p->get_params);
24573-
24574+
24575 free(p);
24576-
24577+
24578 return HANDLER_GO_ON;
24579 }
24580
24581@@ -80,83 +80,80 @@
24582 SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
24583 plugin_data *p = p_d;
24584 size_t i = 0;
24585-
24586- config_values_t cv[] = {
24587+
24588+ config_values_t cv[] = {
24589 { "flv-streaming.extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
24590 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
24591 };
24592-
24593+
24594 if (!p) return HANDLER_ERROR;
24595-
24596+
24597 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24598-
24599+
24600 for (i = 0; i < srv->config_context->used; i++) {
24601 plugin_config *s;
24602-
24603+
24604 s = calloc(1, sizeof(plugin_config));
24605 s->extensions = array_init();
24606-
24607+
24608 cv[0].destination = s->extensions;
24609-
24610+
24611 p->config_storage[i] = s;
24612-
24613+
24614 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24615 return HANDLER_ERROR;
24616 }
24617 }
24618-
24619+
24620 return HANDLER_GO_ON;
24621 }
24622
24623-#define PATCH(x) \
24624- p->conf.x = s->x;
24625 static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
24626 size_t i, j;
24627 plugin_config *s = p->config_storage[0];
24628-
24629- PATCH(extensions);
24630-
24631+
24632+ PATCH_OPTION(extensions);
24633+
24634 /* skip the first, the global context */
24635 for (i = 1; i < srv->config_context->used; i++) {
24636 data_config *dc = (data_config *)srv->config_context->data[i];
24637 s = p->config_storage[i];
24638-
24639+
24640 /* condition didn't match */
24641 if (!config_check_cond(srv, con, dc)) continue;
24642-
24643+
24644 /* merge config */
24645 for (j = 0; j < dc->value->used; j++) {
24646 data_unset *du = dc->value->data[j];
24647-
24648+
24649 if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
24650- PATCH(extensions);
24651+ PATCH_OPTION(extensions);
24652 }
24653 }
24654 }
24655-
24656+
24657 return 0;
24658 }
24659-#undef PATCH
24660
24661-static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
24662+static int split_get_params(array *get_params, buffer *qrystr) {
24663 size_t is_key = 1;
24664 size_t i;
24665 char *key = NULL, *val = NULL;
24666-
24667+
24668 key = qrystr->ptr;
24669-
24670+
24671 /* we need the \0 */
24672 for (i = 0; i < qrystr->used; i++) {
24673 switch(qrystr->ptr[i]) {
24674 case '=':
24675 if (is_key) {
24676 val = qrystr->ptr + i + 1;
24677-
24678+
24679 qrystr->ptr[i] = '\0';
24680-
24681+
24682 is_key = 0;
24683 }
24684-
24685+
24686 break;
24687 case '&':
24688 case '\0': /* fin symbol */
24689@@ -167,7 +164,7 @@
24690 /* terminate the value */
24691 qrystr->ptr[i] = '\0';
24692
24693- if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
24694+ if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
24695 ds = data_string_init();
24696 }
24697 buffer_copy_string_len(ds->key, key, strlen(key));
24698@@ -175,14 +172,14 @@
24699
24700 array_insert_unique(get_params, (data_unset *)ds);
24701 }
24702-
24703+
24704 key = qrystr->ptr + i + 1;
24705 val = NULL;
24706 is_key = 1;
24707 break;
24708 }
24709 }
24710-
24711+
24712 return 0;
24713 }
24714
24715@@ -190,34 +187,34 @@
24716 plugin_data *p = p_d;
24717 int s_len;
24718 size_t k;
24719-
24720+
24721 UNUSED(srv);
24722
24723 if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
24724-
24725+
24726 mod_flv_streaming_patch_connection(srv, con, p);
24727
24728 s_len = con->physical.path->used - 1;
24729-
24730+
24731 for (k = 0; k < p->conf.extensions->used; k++) {
24732 data_string *ds = (data_string *)p->conf.extensions->data[k];
24733 int ct_len = ds->value->used - 1;
24734-
24735+
24736 if (ct_len > s_len) continue;
24737 if (ds->value->used == 0) continue;
24738-
24739+
24740 if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
24741 data_string *get_param;
24742 stat_cache_entry *sce = NULL;
24743 buffer *b;
24744 int start;
24745 char *err = NULL;
24746- /* if there is a start=[0-9]+ in the header use it as start,
24747+ /* if there is a start=[0-9]+ in the header use it as start,
24748 * otherwise send the full file */
24749
24750 array_reset(p->get_params);
24751 buffer_copy_string_buffer(p->query_str, con->uri.query);
24752- split_get_params(srv, con, p->get_params, p->query_str);
24753+ split_get_params(p->get_params, p->query_str);
24754
24755 if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
24756 return HANDLER_GO_ON;
24757@@ -256,7 +253,7 @@
24758 return HANDLER_FINISHED;
24759 }
24760 }
24761-
24762+
24763 /* not found */
24764 return HANDLER_GO_ON;
24765 }
24766@@ -266,13 +263,13 @@
24767 int mod_flv_streaming_plugin_init(plugin *p) {
24768 p->version = LIGHTTPD_VERSION_ID;
24769 p->name = buffer_init_string("flv_streaming");
24770-
24771+
24772 p->init = mod_flv_streaming_init;
24773 p->handle_physical = mod_flv_streaming_path_handler;
24774 p->set_defaults = mod_flv_streaming_set_defaults;
24775 p->cleanup = mod_flv_streaming_free;
24776-
24777+
24778 p->data = NULL;
24779-
24780+
24781 return 0;
24782 }
1175ccec
ER
24783--- ../lighttpd-1.4.11/src/mod_indexfile.c 2005-09-30 01:08:53.000000000 +0300
24784+++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-15 22:43:21.000000000 +0300
24785@@ -12,6 +12,8 @@
24786
24787 #include "stat_cache.h"
24788
24789+#include "sys-strings.h"
24790+#include "sys-files.h"
24791 /* plugin config for all request/connections */
24792
24793 typedef struct {
24794@@ -20,51 +22,51 @@
2519e6e5
ER
24795
24796 typedef struct {
24797 PLUGIN_DATA;
24798-
24799+
24800 buffer *tmp_buf;
24801-
24802+
24803 plugin_config **config_storage;
24804-
24805- plugin_config conf;
24806+
24807+ plugin_config conf;
24808 } plugin_data;
24809
24810 /* init the plugin data */
24811 INIT_FUNC(mod_indexfile_init) {
24812 plugin_data *p;
24813-
24814+
24815 p = calloc(1, sizeof(*p));
24816-
24817+
24818 p->tmp_buf = buffer_init();
24819-
24820+
24821 return p;
24822 }
24823
24824 /* detroy the plugin data */
24825 FREE_FUNC(mod_indexfile_free) {
24826 plugin_data *p = p_d;
24827-
24828+
24829 UNUSED(srv);
24830
24831 if (!p) return HANDLER_GO_ON;
24832-
24833+
24834 if (p->config_storage) {
24835 size_t i;
24836 for (i = 0; i < srv->config_context->used; i++) {
24837 plugin_config *s = p->config_storage[i];
24838
24839 if (!s) continue;
24840-
24841+
24842 array_free(s->indexfiles);
24843-
24844+
24845 free(s);
24846 }
24847 free(p->config_storage);
24848 }
24849-
24850+
24851 buffer_free(p->tmp_buf);
24852-
24853+
24854 free(p);
24855-
24856+
24857 return HANDLER_GO_ON;
24858 }
24859
1175ccec 24860@@ -73,131 +75,139 @@
2519e6e5
ER
24861 SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
24862 plugin_data *p = p_d;
24863 size_t i = 0;
24864-
24865- config_values_t cv[] = {
24866+
24867+ config_values_t cv[] = {
24868 { "index-file.names", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
24869 { "server.indexfiles", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
24870 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
24871 };
24872-
24873+
24874 if (!p) return HANDLER_ERROR;
24875-
24876+
24877 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24878-
24879+
24880 for (i = 0; i < srv->config_context->used; i++) {
24881 plugin_config *s;
24882-
24883+
24884 s = calloc(1, sizeof(plugin_config));
24885 s->indexfiles = array_init();
24886-
24887+
24888 cv[0].destination = s->indexfiles;
24889 cv[1].destination = s->indexfiles; /* old name for [0] */
24890-
24891+
24892 p->config_storage[i] = s;
24893-
24894+
24895 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24896 return HANDLER_ERROR;
24897 }
24898 }
24899-
24900+
24901 return HANDLER_GO_ON;
24902 }
24903
24904-#define PATCH(x) \
24905- p->conf.x = s->x;
24906 static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
24907 size_t i, j;
24908 plugin_config *s = p->config_storage[0];
24909-
24910- PATCH(indexfiles);
24911-
24912+
24913+ PATCH_OPTION(indexfiles);
24914+
24915 /* skip the first, the global context */
24916 for (i = 1; i < srv->config_context->used; i++) {
24917 data_config *dc = (data_config *)srv->config_context->data[i];
24918 s = p->config_storage[i];
24919-
24920+
24921 /* condition didn't match */
24922 if (!config_check_cond(srv, con, dc)) continue;
24923-
24924+
24925 /* merge config */
24926 for (j = 0; j < dc->value->used; j++) {
24927 data_unset *du = dc->value->data[j];
24928-
24929+
24930 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
24931- PATCH(indexfiles);
24932+ PATCH_OPTION(indexfiles);
24933 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
24934- PATCH(indexfiles);
24935+ PATCH_OPTION(indexfiles);
24936 }
24937 }
24938 }
24939-
24940+
24941 return 0;
24942 }
24943-#undef PATCH
24944
24945 URIHANDLER_FUNC(mod_indexfile_subrequest) {
24946 plugin_data *p = p_d;
24947 size_t k;
24948 stat_cache_entry *sce = NULL;
24949-
24950+
24951 if (con->uri.path->used == 0) return HANDLER_GO_ON;
24952 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
24953-
24954+
24955 mod_indexfile_patch_connection(srv, con, p);
24956-
1175ccec
ER
24957+
24958+ /* is the physical-path really a dir ? */
24959+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
24960+ return HANDLER_GO_ON;
24961+ }
24962+
24963+ if (!S_ISDIR(sce->st.st_mode)) {
24964+ return HANDLER_GO_ON;
24965+ }
2519e6e5
ER
24966+
24967 if (con->conf.log_request_handling) {
24968 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Indexfile");
24969 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
24970 }
24971-
1175ccec 24972+
2519e6e5
ER
24973+
24974 /* indexfile */
24975 for (k = 0; k < p->conf.indexfiles->used; k++) {
24976 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
24977-
24978+
24979 if (ds->value && ds->value->ptr[0] == '/') {
24980- /* if the index-file starts with a prefix as use this file as
24981+ /* if the index-file starts with a prefix as use this file as
24982 * index-generator */
24983 buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
24984 } else {
24985 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
1175ccec 24986+ PATHNAME_APPEND_SLASH(p->tmp_buf);
2519e6e5
ER
24987 }
24988 buffer_append_string_buffer(p->tmp_buf, ds->value);
24989-
24990+
24991 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
24992 if (errno == EACCES) {
24993 con->http_status = 403;
24994 buffer_reset(con->physical.path);
24995-
24996+
24997 return HANDLER_FINISHED;
24998 }
24999-
25000+
25001 if (errno != ENOENT &&
25002 errno != ENOTDIR) {
25003 /* we have no idea what happend. let's tell the user so. */
25004-
25005+
25006 con->http_status = 500;
25007-
25008+
25009 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
25010 "file not found ... or so: ", strerror(errno),
25011 con->uri.path,
25012 "->", con->physical.path);
25013-
25014+
25015 buffer_reset(con->physical.path);
25016-
25017+
25018 return HANDLER_FINISHED;
25019 }
25020 continue;
25021 }
25022-
25023+
25024 /* rewrite uri.path to the real path (/ -> /index.php) */
25025 buffer_append_string_buffer(con->uri.path, ds->value);
25026 buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
25027-
25028+
25029 /* fce is already set up a few lines above */
25030-
25031+
25032 return HANDLER_GO_ON;
25033 }
25034-
25035+
25036 /* not found */
25037 return HANDLER_GO_ON;
25038 }
1175ccec 25039@@ -207,13 +217,13 @@
2519e6e5
ER
25040 int mod_indexfile_plugin_init(plugin *p) {
25041 p->version = LIGHTTPD_VERSION_ID;
25042 p->name = buffer_init_string("indexfile");
25043-
25044+
25045 p->init = mod_indexfile_init;
25046 p->handle_subrequest_start = mod_indexfile_subrequest;
25047 p->set_defaults = mod_indexfile_set_defaults;
25048 p->cleanup = mod_indexfile_free;
25049-
25050+
25051 p->data = NULL;
25052-
25053+
25054 return 0;
25055 }
1175ccec 25056--- ../lighttpd-1.4.11/src/mod_mysql_vhost.c 2006-01-14 20:35:10.000000000 +0200
36e2a29e 25057+++ lighttpd-1.4.12/src/mod_mysql_vhost.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
25058@@ -1,13 +1,18 @@
25059-#include <unistd.h>
25060 #include <stdio.h>
25061 #include <errno.h>
25062 #include <fcntl.h>
25063-#include <strings.h>
25064+#include <string.h>
25065
25066 #ifdef HAVE_CONFIG_H
25067 #include "config.h"
25068 #endif
25069
25070+#ifdef HAVE_MYSQL_H
25071+# ifdef HAVE_LIBMYSQL
25072+# define HAVE_MYSQL
25073+# endif
25074+#endif
25075+
25076 #ifdef HAVE_MYSQL
25077 #include <mysql.h>
25078 #endif
25079@@ -16,61 +21,40 @@
25080 #include "log.h"
25081
25082 #include "stat_cache.h"
25083-#ifdef DEBUG_MOD_MYSQL_VHOST
25084-#define DEBUG
25085-#endif
25086+#include "sys-files.h"
25087
25088-/*
25089- * Plugin for lighttpd to use MySQL
25090- * for domain to directory lookups,
25091- * i.e virtual hosts (vhosts).
25092- *
25093- * Optionally sets fcgi_offset and fcgi_arg
25094- * in preparation for fcgi.c to handle
25095- * per-user fcgi chroot jails.
25096- *
25097- * /ada@riksnet.se 2004-12-06
25098- */
25099+#include "mod_sql_vhost_core.h"
25100
25101 #ifdef HAVE_MYSQL
25102+
25103+#define CORE_PLUGIN "mod_sql_vhost_core"
25104+
25105 typedef struct {
25106 MYSQL *mysql;
25107-
25108- buffer *mydb;
25109- buffer *myuser;
25110- buffer *mypass;
25111- buffer *mysock;
25112-
25113- buffer *hostname;
25114- unsigned short port;
25115-
25116+
25117 buffer *mysql_pre;
25118 buffer *mysql_post;
25119+
25120+ mod_sql_vhost_core_plugin_config *core;
25121 } plugin_config;
25122
25123 /* global plugin data */
25124 typedef struct {
25125 PLUGIN_DATA;
25126-
25127+
25128 buffer *tmp_buf;
25129-
25130+
25131 plugin_config **config_storage;
25132-
25133- plugin_config conf;
25134+
25135+ plugin_config conf;
25136 } plugin_data;
25137
25138-/* per connection plugin data */
25139-typedef struct {
25140- buffer *server_name;
25141- buffer *document_root;
25142- buffer *fcgi_arg;
25143- unsigned fcgi_offset;
25144-} plugin_connection_data;
25145+SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost);
25146
25147 /* init the plugin data */
25148 INIT_FUNC(mod_mysql_vhost_init) {
25149 plugin_data *p;
25150-
25151+
25152 p = calloc(1, sizeof(*p));
25153
25154 p->tmp_buf = buffer_init();
25155@@ -83,144 +67,77 @@
25156 plugin_data *p = p_d;
25157
25158 UNUSED(srv);
25159-
25160-#ifdef DEBUG
25161- log_error_write(srv, __FILE__, __LINE__, "ss",
25162- "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
25163-#endif
25164+
25165 if (!p) return HANDLER_GO_ON;
25166-
25167+
25168 if (p->config_storage) {
25169 size_t i;
25170 for (i = 0; i < srv->config_context->used; i++) {
25171 plugin_config *s = p->config_storage[i];
25172
25173 if (!s) continue;
25174-
25175+
25176 mysql_close(s->mysql);
25177-
25178- buffer_free(s->mydb);
25179- buffer_free(s->myuser);
25180- buffer_free(s->mypass);
25181- buffer_free(s->mysock);
25182+
25183 buffer_free(s->mysql_pre);
25184 buffer_free(s->mysql_post);
25185-
25186+
25187 free(s);
25188 }
25189 free(p->config_storage);
25190 }
25191 buffer_free(p->tmp_buf);
25192-
25193- free(p);
25194
25195- return HANDLER_GO_ON;
25196-}
25197-
25198-/* handle the plugin per connection data */
25199-static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
25200-{
25201- plugin_data *p = p_d;
25202- plugin_connection_data *c = con->plugin_ctx[p->id];
25203-
25204- UNUSED(srv);
25205-
25206-#ifdef DEBUG
25207- log_error_write(srv, __FILE__, __LINE__, "ss",
25208- "mod_mysql_connection_data", c ? "old" : "NEW");
25209-#endif
25210-
25211- if (c) return c;
25212- c = calloc(1, sizeof(*c));
25213-
25214- c->server_name = buffer_init();
25215- c->document_root = buffer_init();
25216- c->fcgi_arg = buffer_init();
25217- c->fcgi_offset = 0;
25218-
25219- return con->plugin_ctx[p->id] = c;
25220-}
25221-
25222-/* destroy the plugin per connection data */
25223-CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
25224- plugin_data *p = p_d;
25225- plugin_connection_data *c = con->plugin_ctx[p->id];
25226-
25227- UNUSED(srv);
25228-
25229-#ifdef DEBUG
25230- log_error_write(srv, __FILE__, __LINE__, "ss",
25231- "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
25232-#endif
25233-
25234- if (!c) return HANDLER_GO_ON;
25235-
25236- buffer_free(c->server_name);
25237- buffer_free(c->document_root);
25238- buffer_free(c->fcgi_arg);
25239- c->fcgi_offset = 0;
25240-
25241- free(c);
25242+ free(p);
25243
25244- con->plugin_ctx[p->id] = NULL;
25245 return HANDLER_GO_ON;
25246 }
25247
25248 /* set configuration values */
25249 SERVER_FUNC(mod_mysql_vhost_set_defaults) {
25250 plugin_data *p = p_d;
25251+ mod_sql_vhost_core_plugin_data *core_config;
25252
25253- char *qmark;
25254 size_t i = 0;
25255
25256- config_values_t cv[] = {
25257- { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25258- { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25259- { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25260- { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25261- { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25262- { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
25263- { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER },
25264- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25265- };
25266-
25267+ /* our very own plugin storage, one entry for each conditional
25268+ *
25269+ * srv->config_context->used is the number of conditionals
25270+ * */
25271 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25272-
25273+
25274+ /* get the config of the core-plugin */
25275+ core_config = plugin_get_config(srv, CORE_PLUGIN);
25276+
25277+
25278+ /* walk through all conditionals and check for assignments */
25279 for (i = 0; i < srv->config_context->used; i++) {
25280 plugin_config *s;
25281 buffer *sel;
25282-
25283-
25284+ char *qmark;
25285+
25286+ /* get the config from the core plugin for this conditional-context */
25287 s = calloc(1, sizeof(plugin_config));
25288- s->mydb = buffer_init();
25289- s->myuser = buffer_init();
25290- s->mypass = buffer_init();
25291- s->mysock = buffer_init();
25292- s->hostname = buffer_init();
25293- s->port = 0; /* default port for mysql */
25294- sel = buffer_init();
25295- s->mysql = NULL;
25296+
25297+ s->core = core_config->config_storage[i];
25298
25299+ s->mysql = NULL;
25300+
25301 s->mysql_pre = buffer_init();
25302 s->mysql_post = buffer_init();
25303-
25304- cv[0].destination = s->mydb;
25305- cv[1].destination = s->myuser;
25306- cv[2].destination = s->mypass;
25307- cv[3].destination = s->mysock;
25308- cv[4].destination = sel;
25309- cv[5].destination = s->hostname;
25310- cv[6].destination = &(s->port);
25311-
25312+
25313 p->config_storage[i] = s;
25314-
25315- if (config_insert_values_global(srv,
25316- ((data_config *)srv->config_context->data[i])->value,
25317- cv)) return HANDLER_ERROR;
25318-
25319- s->mysql_pre = buffer_init();
25320- s->mysql_post = buffer_init();
25321-
25322+
25323+ /* check if we are the plugin for this backend */
25324+ if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
25325+
25326+ /* attach us to the core-plugin */
25327+ s->core->backend_data = p;
25328+ s->core->get_vhost = mod_mysql_vhost_get_vhost;
25329+
25330+ sel = buffer_init();
25331+ buffer_copy_string_buffer(sel, s->core->select_vhost);
25332+
25333 if (sel->used && (qmark = index(sel->ptr, '?'))) {
25334 *qmark = '\0';
25335 buffer_copy_string(s->mysql_pre, sel->ptr);
25336@@ -228,35 +145,35 @@
25337 } else {
25338 buffer_copy_string_buffer(s->mysql_pre, sel);
25339 }
25340-
25341+
25342 /* required:
25343 * - username
25344- * - database
25345- *
25346+ * - database
25347+ *
25348 * optional:
25349 * - password, default: empty
25350 * - socket, default: mysql default
25351 * - hostname, if set overrides socket
25352 * - port, default: 3306
25353 */
25354-
25355+
25356 /* all have to be set */
25357- if (!(buffer_is_empty(s->myuser) ||
25358- buffer_is_empty(s->mydb))) {
25359+ if (!(buffer_is_empty(s->core->user) ||
25360+ buffer_is_empty(s->core->db))) {
25361
25362 int fd;
25363-
25364+
25365 if (NULL == (s->mysql = mysql_init(NULL))) {
25366 log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
25367-
25368+
25369 return HANDLER_ERROR;
25370 }
25371-#define FOO(x) (s->x->used ? s->x->ptr : NULL)
25372-
25373- if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass),
25374- FOO(mydb), s->port, FOO(mysock), 0)) {
25375+#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
25376+
25377+ if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
25378+ FOO(db), s->core->port, FOO(sock), 0)) {
25379 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
25380-
25381+
25382 return HANDLER_ERROR;
25383 }
25384 #undef FOO
25385@@ -265,61 +182,47 @@
25386 /* otherwise we cannot be sure that mysql is fd i-1 */
25387 if (-1 == (fd = open("/dev/null", 0))) {
25388 close(fd);
25389- fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25390+ fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25391 }
25392 }
25393 }
25394-
25395-
25396+
25397+
25398
25399 return HANDLER_GO_ON;
25400 }
25401
25402-#define PATCH(x) \
25403- p->conf.x = s->x;
25404 static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
25405- size_t i, j;
25406+ size_t i;
25407 plugin_config *s = p->config_storage[0];
25408-
25409- PATCH(mysql_pre);
25410- PATCH(mysql_post);
25411-#ifdef HAVE_MYSQL
25412- PATCH(mysql);
25413-#endif
25414-
25415+
25416+ PATCH_OPTION(mysql_pre);
25417+ PATCH_OPTION(mysql_post);
25418+ PATCH_OPTION(mysql);
25419+
25420 /* skip the first, the global context */
25421 for (i = 1; i < srv->config_context->used; i++) {
25422 data_config *dc = (data_config *)srv->config_context->data[i];
25423 s = p->config_storage[i];
25424-
25425+
25426 /* condition didn't match */
25427 if (!config_check_cond(srv, con, dc)) continue;
25428-
25429- /* merge config */
25430- for (j = 0; j < dc->value->used; j++) {
25431- data_unset *du = dc->value->data[j];
25432-
25433- if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
25434- PATCH(mysql_pre);
25435- PATCH(mysql_post);
25436- }
25437- }
25438-
25439+
25440 if (s->mysql) {
25441- PATCH(mysql);
25442+ PATCH_OPTION(mysql);
25443+ PATCH_OPTION(mysql_pre);
25444+ PATCH_OPTION(mysql_post);
25445 }
25446 }
25447-
25448+
25449 return 0;
25450 }
25451-#undef PATCH
25452
25453-
25454-/* handle document root request */
25455-CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
25456+/**
25457+ * get the vhost info from the database
25458+ */
25459+SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
25460 plugin_data *p = p_d;
25461- plugin_connection_data *c;
25462- stat_cache_entry *sce;
25463
25464 unsigned cols;
25465 MYSQL_ROW row;
25466@@ -332,13 +235,6 @@
25467
25468 if (!p->conf.mysql) return HANDLER_GO_ON;
25469
25470- /* sets up connection data if not done yet */
25471- c = mod_mysql_vhost_connection_data(srv, con, p_d);
25472-
25473- /* check if cached this connection */
25474- if (c->server_name->used && /* con->uri.authority->used && */
25475- buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
25476-
25477 /* build and run SQL query */
25478 buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
25479 if (p->conf.mysql_post->used) {
25480@@ -347,77 +243,43 @@
25481 }
25482 if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
25483 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
25484- goto ERR500;
25485+
25486+ mysql_free_result(result);
25487+ return HANDLER_GO_ON;
25488 }
25489 result = mysql_store_result(p->conf.mysql);
25490 cols = mysql_num_fields(result);
25491 row = mysql_fetch_row(result);
25492+
25493 if (!row || cols < 1) {
25494 /* no such virtual host */
25495 mysql_free_result(result);
25496 return HANDLER_GO_ON;
25497 }
25498
25499- /* sanity check that really is a directory */
25500- buffer_copy_string(p->tmp_buf, row[0]);
25501- BUFFER_APPEND_SLASH(p->tmp_buf);
25502-
25503- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25504- log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
25505- goto ERR500;
25506- }
25507- if (!S_ISDIR(sce->st.st_mode)) {
25508- log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
25509- goto ERR500;
25510- }
25511+ buffer_copy_string(docroot, row[0]);
25512
25513- /* cache the data */
25514- buffer_copy_string_buffer(c->server_name, con->uri.authority);
25515- buffer_copy_string_buffer(c->document_root, p->tmp_buf);
25516-
25517- /* fcgi_offset and fcgi_arg are optional */
25518- if (cols > 1 && row[1]) {
25519- c->fcgi_offset = atoi(row[1]);
25520-
25521- if (cols > 2 && row[2]) {
25522- buffer_copy_string(c->fcgi_arg, row[2]);
25523- } else {
25524- c->fcgi_arg->used = 0;
25525- }
25526- } else {
25527- c->fcgi_offset = c->fcgi_arg->used = 0;
25528- }
25529 mysql_free_result(result);
25530
25531- /* fix virtual server and docroot */
25532-GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
25533- buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
25534-
25535-#ifdef DEBUG
25536- log_error_write(srv, __FILE__, __LINE__, "sbbdb",
25537- result ? "NOT CACHED" : "cached",
25538- con->server_name, con->physical.doc_root,
25539- c->fcgi_offset, c->fcgi_arg);
25540-#endif
25541- return HANDLER_GO_ON;
25542-
25543-ERR500: if (result) mysql_free_result(result);
25544- con->http_status = 500; /* Internal Error */
25545- return HANDLER_FINISHED;
25546+ return HANDLER_GO_ON;
25547 }
25548
25549 /* this function is called at dlopen() time and inits the callbacks */
25550 int mod_mysql_vhost_plugin_init(plugin *p) {
25551+ data_string *ds;
25552+
25553 p->version = LIGHTTPD_VERSION_ID;
25554 p->name = buffer_init_string("mysql_vhost");
25555
25556 p->init = mod_mysql_vhost_init;
25557 p->cleanup = mod_mysql_vhost_cleanup;
25558- p->handle_request_done = mod_mysql_vhost_handle_connection_close;
25559
25560 p->set_defaults = mod_mysql_vhost_set_defaults;
25561- p->handle_docroot = mod_mysql_vhost_handle_docroot;
25562
25563+ ds = data_string_init();
25564+ buffer_copy_string(ds->value, CORE_PLUGIN);
25565+ array_insert_unique(p->required_plugins, (data_unset *)ds);
25566+
25567 return 0;
25568 }
25569 #else
1175ccec
ER
25570--- ../lighttpd-1.4.11/src/mod_proxy.c 2006-01-31 13:01:22.000000000 +0200
25571+++ lighttpd-1.4.12/src/mod_proxy.c 2006-07-15 22:43:21.000000000 +0300
2519e6e5
ER
25572@@ -1,6 +1,5 @@
25573 #include <sys/types.h>
25574
25575-#include <unistd.h>
25576 #include <errno.h>
25577 #include <fcntl.h>
25578 #include <string.h>
25579@@ -23,6 +22,9 @@
25580
25581 #include "inet_ntop_cache.h"
25582 #include "crc32.h"
25583+#include "network.h"
25584+
25585+#include "http_resp.h"
25586
25587 #include <stdio.h>
25588
25589@@ -31,6 +33,8 @@
25590 #endif
25591
25592 #include "sys-socket.h"
25593+#include "sys-files.h"
25594+#include "sys-strings.h"
25595
25596 #define data_proxy data_fastcgi
25597 #define data_proxy_init data_fastcgi_init
1175ccec 25598@@ -38,22 +42,25 @@
2519e6e5
ER
25599 #define PROXY_RETRY_TIMEOUT 60
25600
25601 /**
25602- *
25603- * the proxy module is based on the fastcgi module
25604- *
25605+ *
25606+ * the proxy module is based on the fastcgi module
25607+ *
25608 * 28.06.2004 Jan Kneschke The first release
25609 * 01.07.2004 Evgeny Rodichev Several bugfixes and cleanups
25610 * - co-ordinate up- and downstream flows correctly (proxy_demux_response
25611 * and proxy_handle_fdevent)
25612 * - correctly transfer upstream http_response_status;
25613 * - some unused structures removed.
25614- *
25615+ *
25616 * TODO: - delay upstream read if write_queue is too large
25617 * (to prevent memory eating, like in apache). Shoud be
25618 * configurable).
1175ccec
ER
25619 * - persistent connection with upstream servers
25620 * - HTTP/1.1
25621 */
25622+
25623+
25624+
25625 typedef enum {
25626 PROXY_BALANCE_UNSET,
25627 PROXY_BALANCE_FAIR,
25628@@ -66,26 +73,33 @@
2519e6e5
ER
25629 int debug;
25630
25631 proxy_balance_t balance;
25632+
25633+ array *last_used_backends; /* "extension" : last_used_backend */
25634 } plugin_config;
25635
25636 typedef struct {
25637 PLUGIN_DATA;
25638-
25639+
25640 buffer *parse_response;
25641 buffer *balance_buf;
25642-
25643+
1175ccec
ER
25644+ http_resp *resp;
25645+
2519e6e5
ER
25646+ array *ignore_headers;
25647+
25648 plugin_config **config_storage;
25649-
25650+
25651 plugin_config conf;
25652 } plugin_data;
25653
25654-typedef enum {
25655- PROXY_STATE_INIT,
25656- PROXY_STATE_CONNECT,
25657- PROXY_STATE_PREPARE_WRITE,
25658- PROXY_STATE_WRITE,
25659- PROXY_STATE_READ,
25660- PROXY_STATE_ERROR
25661+typedef enum {
25662+ PROXY_STATE_INIT,
25663+ PROXY_STATE_CONNECT,
25664+ PROXY_STATE_PREPARE_WRITE,
25665+ PROXY_STATE_WRITE,
1175ccec
ER
25666+ PROXY_STATE_RESPONSE_HEADER,
25667+ PROXY_STATE_RESPONSE_CONTENT,
2519e6e5
ER
25668+ PROXY_STATE_ERROR
25669 } proxy_connection_state_t;
25670
25671 enum { PROXY_STDOUT, PROXY_END_REQUEST };
1175ccec 25672@@ -93,19 +107,17 @@
2519e6e5
ER
25673 typedef struct {
25674 proxy_connection_state_t state;
25675 time_t state_timestamp;
25676-
25677+
25678 data_proxy *host;
25679-
1175ccec
ER
25680- buffer *response;
25681- buffer *response_header;
2519e6e5
ER
25682
25683 chunkqueue *wb;
25684-
1175ccec 25685+ chunkqueue *rb;
2519e6e5
ER
25686+
25687 int fd; /* fd to the proxy process */
25688 int fde_ndx; /* index into the fd-event buffer */
25689
25690 size_t path_info_offset; /* start of path_info in uri.path */
25691-
25692+
25693 connection *remote_conn; /* dump pointer */
25694 plugin_data *plugin_data; /* dump pointer */
25695 } handler_ctx;
1175ccec 25696@@ -116,69 +128,88 @@
2519e6e5
ER
25697
25698 static handler_ctx * handler_ctx_init() {
25699 handler_ctx * hctx;
25700-
25701+
25702
25703 hctx = calloc(1, sizeof(*hctx));
25704-
25705+
25706 hctx->state = PROXY_STATE_INIT;
25707 hctx->host = NULL;
25708-
1175ccec
ER
25709- hctx->response = buffer_init();
25710- hctx->response_header = buffer_init();
2519e6e5
ER
25711
25712 hctx->wb = chunkqueue_init();
1175ccec 25713+ hctx->rb = chunkqueue_init();
2519e6e5
ER
25714
25715 hctx->fd = -1;
25716 hctx->fde_ndx = -1;
25717-
25718+
25719 return hctx;
25720 }
25721
1175ccec
ER
25722 static void handler_ctx_free(handler_ctx *hctx) {
25723- buffer_free(hctx->response);
25724- buffer_free(hctx->response_header);
2519e6e5
ER
25725 chunkqueue_free(hctx->wb);
25726-
1175ccec 25727+ chunkqueue_free(hctx->rb);
2519e6e5
ER
25728+
25729 free(hctx);
25730 }
25731
25732 INIT_FUNC(mod_proxy_init) {
25733 plugin_data *p;
25734-
25735+ size_t i;
25736+
25737+ char *hop2hop_headers[] = {
25738+ "Connection",
25739+ "Keep-Alive",
25740+ "Host",
25741+ NULL
25742+ };
25743+
25744 p = calloc(1, sizeof(*p));
25745-
1175ccec 25746- p->parse_response = buffer_init();
2519e6e5 25747+
2519e6e5
ER
25748 p->balance_buf = buffer_init();
25749-
25750+ p->ignore_headers = array_init();
1175ccec 25751+ p->resp = http_response_init();
2519e6e5
ER
25752+
25753+ for (i = 0; hop2hop_headers[i]; i++) {
25754+ data_string *ds;
25755+
1175ccec 25756+ if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
2519e6e5
ER
25757+ ds = data_string_init();
25758+ }
25759+
1175ccec 25760+ buffer_copy_string(ds->key, hop2hop_headers[i]);
2519e6e5
ER
25761+ buffer_copy_string(ds->value, hop2hop_headers[i]);
25762+ array_insert_unique(p->ignore_headers, (data_unset *)ds);
25763+ }
25764+
25765 return p;
25766 }
25767
25768
25769 FREE_FUNC(mod_proxy_free) {
25770 plugin_data *p = p_d;
25771-
25772+
25773 UNUSED(srv);
25774
1175ccec
ER
25775- buffer_free(p->parse_response);
25776- buffer_free(p->balance_buf);
2519e6e5 25777-
2519e6e5
ER
25778 if (p->config_storage) {
25779 size_t i;
25780 for (i = 0; i < srv->config_context->used; i++) {
25781 plugin_config *s = p->config_storage[i];
25782-
25783+
25784 if (s) {
25785-
25786 array_free(s->extensions);
25787-
25788+ array_free(s->last_used_backends);
25789+
25790 free(s);
25791 }
25792 }
25793 free(p->config_storage);
25794 }
25795-
25796+
1175ccec
ER
25797+ array_free(p->ignore_headers);
25798+ buffer_free(p->balance_buf);
25799+ http_response_free(p->resp);
2519e6e5
ER
25800+
25801 free(p);
25802-
25803+
25804 return HANDLER_GO_ON;
25805 }
25806
1175ccec 25807@@ -186,37 +217,38 @@
2519e6e5
ER
25808 plugin_data *p = p_d;
25809 data_unset *du;
25810 size_t i = 0;
25811-
25812- config_values_t cv[] = {
25813+
25814+ config_values_t cv[] = {
25815 { "proxy.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
25816 { "proxy.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
25817 { "proxy.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
25818 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25819 };
25820-
25821+
25822 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25823-
25824+
25825 for (i = 0; i < srv->config_context->used; i++) {
25826 plugin_config *s;
25827 array *ca;
25828-
25829+
25830 s = malloc(sizeof(plugin_config));
25831- s->extensions = array_init();
25832+ s->extensions = array_init();
25833+ s->last_used_backends = array_init();
25834 s->debug = 0;
25835-
25836+
25837 cv[0].destination = s->extensions;
25838 cv[1].destination = &(s->debug);
25839 cv[2].destination = p->balance_buf;
25840
25841 buffer_reset(p->balance_buf);
25842-
25843+
25844 p->config_storage[i] = s;
25845 ca = ((data_config *)srv->config_context->data[i])->value;
25846-
25847+
25848 if (0 != config_insert_values_global(srv, ca, cv)) {
25849 return HANDLER_ERROR;
25850 }
25851-
25852+
25853 if (buffer_is_empty(p->balance_buf)) {
25854 s->balance = PROXY_BALANCE_FAIR;
25855 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
1175ccec 25856@@ -226,99 +258,99 @@
2519e6e5
ER
25857 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
25858 s->balance = PROXY_BALANCE_HASH;
25859 } else {
25860- log_error_write(srv, __FILE__, __LINE__, "sb",
1175ccec 25861- "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
2519e6e5 25862+ log_error_write(srv, __FILE__, __LINE__, "sb",
1175ccec 25863+ "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
2519e6e5
ER
25864 return HANDLER_ERROR;
25865 }
1175ccec 25866
2519e6e5
ER
25867 if (NULL != (du = array_get_element(ca, "proxy.server"))) {
25868 size_t j;
25869 data_array *da = (data_array *)du;
25870-
25871+
25872 if (du->type != TYPE_ARRAY) {
25873- log_error_write(srv, __FILE__, __LINE__, "sss",
25874+ log_error_write(srv, __FILE__, __LINE__, "sss",
25875 "unexpected type for key: ", "proxy.server", "array of strings");
25876-
25877+
25878 return HANDLER_ERROR;
25879 }
25880-
25881- /*
25882+
25883+ /*
25884 * proxy.server = ( "<ext>" => ...,
25885 * "<ext>" => ... )
25886 */
25887-
25888+
25889 for (j = 0; j < da->value->used; j++) {
25890 data_array *da_ext = (data_array *)da->value->data[j];
25891 size_t n;
25892-
25893+
25894 if (da_ext->type != TYPE_ARRAY) {
25895- log_error_write(srv, __FILE__, __LINE__, "sssbs",
25896- "unexpected type for key: ", "proxy.server",
25897+ log_error_write(srv, __FILE__, __LINE__, "sssbs",
25898+ "unexpected type for key: ", "proxy.server",
25899 "[", da->value->data[j]->key, "](string)");
25900-
25901+
25902 return HANDLER_ERROR;
25903 }
25904-
25905- /*
25906- * proxy.server = ( "<ext>" =>
25907- * ( "<host>" => ( ... ),
25908+
25909+ /*
25910+ * proxy.server = ( "<ext>" =>
25911+ * ( "<host>" => ( ... ),
25912 * "<host>" => ( ... )
25913- * ),
25914+ * ),
25915 * "<ext>" => ... )
25916 */
25917-
25918+
25919 for (n = 0; n < da_ext->value->used; n++) {
25920 data_array *da_host = (data_array *)da_ext->value->data[n];
25921-
25922+
25923 data_proxy *df;
25924 data_array *dfa;
25925-
25926- config_values_t pcv[] = {
25927+
25928+ config_values_t pcv[] = {
25929 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
25930 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
25931 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25932 };
25933-
25934+
25935 if (da_host->type != TYPE_ARRAY) {
25936- log_error_write(srv, __FILE__, __LINE__, "ssSBS",
25937- "unexpected type for key:",
25938- "proxy.server",
25939+ log_error_write(srv, __FILE__, __LINE__, "ssSBS",
25940+ "unexpected type for key:",
25941+ "proxy.server",
25942 "[", da_ext->value->data[n]->key, "](string)");
25943-
25944+
25945 return HANDLER_ERROR;
25946 }
25947-
25948+
25949 df = data_proxy_init();
25950-
25951+
25952 df->port = 80;
25953-
25954+
25955 buffer_copy_string_buffer(df->key, da_host->key);
25956-
25957+
25958 pcv[0].destination = df->host;
25959 pcv[1].destination = &(df->port);
25960-
25961+
25962 if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
25963 return HANDLER_ERROR;
25964 }
25965-
25966+
25967 if (buffer_is_empty(df->host)) {
25968- log_error_write(srv, __FILE__, __LINE__, "sbbbs",
25969- "missing key (string):",
25970+ log_error_write(srv, __FILE__, __LINE__, "sbbbs",
25971+ "missing key (string):",
25972 da->key,
25973 da_ext->key,
25974 da_host->key,
25975 "host");
25976-
25977+
25978 return HANDLER_ERROR;
25979 }
25980-
25981+
25982 /* if extension already exists, take it */
25983-
25984+
25985 if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
25986 dfa = data_array_init();
25987-
25988+
25989 buffer_copy_string_buffer(dfa->key, da_ext->key);
25990-
25991+
25992 array_insert_unique(dfa->value, (data_unset *)df);
25993 array_insert_unique(s->extensions, (data_unset *)dfa);
25994 } else {
1175ccec 25995@@ -328,19 +360,19 @@
2519e6e5
ER
25996 }
25997 }
25998 }
25999-
26000+
26001 return HANDLER_GO_ON;
26002 }
26003
26004 void proxy_connection_close(server *srv, handler_ctx *hctx) {
26005 plugin_data *p;
26006 connection *con;
26007-
26008+
26009 if (NULL == hctx) return;
26010-
26011+
26012 p = hctx->plugin_data;
26013 con = hctx->remote_conn;
26014-
26015+
26016 if (hctx->fd != -1) {
26017 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26018 fdevent_unregister(srv->ev, hctx->fd);
1175ccec 26019@@ -348,47 +380,56 @@
2519e6e5
ER
26020 close(hctx->fd);
26021 srv->cur_fds--;
26022 }
26023-
26024+
26025 handler_ctx_free(hctx);
26026- con->plugin_ctx[p->id] = NULL;
26027+ con->plugin_ctx[p->id] = NULL;
26028 }
26029
26030 static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
26031 struct sockaddr *proxy_addr;
26032 struct sockaddr_in proxy_addr_in;
26033 socklen_t servlen;
26034-
26035+
26036 plugin_data *p = hctx->plugin_data;
26037 data_proxy *host= hctx->host;
26038 int proxy_fd = hctx->fd;
26039-
26040+
26041 memset(&proxy_addr, 0, sizeof(proxy_addr));
26042-
26043+
26044 proxy_addr_in.sin_family = AF_INET;
26045 proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr);
26046 proxy_addr_in.sin_port = htons(host->port);
26047 servlen = sizeof(proxy_addr_in);
26048-
26049+
26050 proxy_addr = (struct sockaddr *) &proxy_addr_in;
26051-
26052+
26053 if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
26054- if (errno == EINPROGRESS || errno == EALREADY) {
26055+#ifdef _WIN32
1175ccec 26056+ errno = WSAGetLastError();
2519e6e5 26057+#endif
1175ccec 26058+ switch(errno) {
2519e6e5 26059+#ifdef _WIN32
1175ccec 26060+ case WSAEWOULDBLOCK:
2519e6e5 26061+#endif
1175ccec
ER
26062+ case EINPROGRESS:
26063+ case EALREADY:
2519e6e5
ER
26064 if (p->conf.debug) {
26065- log_error_write(srv, __FILE__, __LINE__, "sd",
26066+ log_error_write(srv, __FILE__, __LINE__, "sd",
26067 "connect delayed:", proxy_fd);
26068 }
26069-
26070+
26071 return 1;
26072- } else {
26073-
26074- log_error_write(srv, __FILE__, __LINE__, "sdsd",
26075+ default:
26076+
26077+ log_error_write(srv, __FILE__, __LINE__, "sdsd",
26078 "connect failed:", proxy_fd, strerror(errno), errno);
26079-
26080+
26081 return -1;
26082 }
26083 }
1175ccec 26084+ fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
2519e6e5
ER
26085 if (p->conf.debug) {
26086- log_error_write(srv, __FILE__, __LINE__, "sd",
26087+ log_error_write(srv, __FILE__, __LINE__, "sd",
26088 "connect succeeded: ", proxy_fd);
26089 }
26090
1175ccec
ER
26091@@ -396,51 +437,52 @@
26092 }
26093
26094 void proxy_set_header(connection *con, const char *key, const char *value) {
26095- data_string *ds_dst;
26096+ data_string *ds_dst;
26097
26098- if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26099- ds_dst = data_string_init();
26100- }
26101-
26102- buffer_copy_string(ds_dst->key, key);
26103- buffer_copy_string(ds_dst->value, value);
26104- array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26105+ if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26106+ ds_dst = data_string_init();
26107+ }
26108+
26109+ buffer_copy_string(ds_dst->key, key);
26110+ buffer_copy_string(ds_dst->value, value);
26111+ array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26112 }
26113
26114 void proxy_append_header(connection *con, const char *key, const char *value) {
26115- data_string *ds_dst;
26116+ data_string *ds_dst;
26117
26118- if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26119- ds_dst = data_string_init();
26120- }
26121-
26122- buffer_copy_string(ds_dst->key, key);
26123- buffer_append_string(ds_dst->value, value);
26124- array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26125+ if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26126+ ds_dst = data_string_init();
26127+ }
26128+
26129+ buffer_copy_string(ds_dst->key, key);
26130+ buffer_append_string(ds_dst->value, value);
26131+ array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26132 }
26133
2519e6e5
ER
26134
26135 static int proxy_create_env(server *srv, handler_ctx *hctx) {
26136 size_t i;
26137-
26138+
26139 connection *con = hctx->remote_conn;
26140+ plugin_data *p = hctx->plugin_data;
26141 buffer *b;
26142-
26143+
26144 /* build header */
26145
26146 b = chunkqueue_get_append_buffer(hctx->wb);
26147-
26148+
26149 /* request line */
26150 buffer_copy_string(b, get_http_method_name(con->request.http_method));
26151 BUFFER_APPEND_STRING_CONST(b, " ");
26152-
26153+
26154 buffer_append_string_buffer(b, con->request.uri);
26155 BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
26156
26157 proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
26158- /* http_host is NOT is just a pointer to a buffer
26159+ /* http_host is NOT is just a pointer to a buffer
26160 * which is NULL if it is not set */
26161- if (con->request.http_host &&
26162+ if (con->request.http_host &&
26163 !buffer_is_empty(con->request.http_host)) {
26164 proxy_set_header(con, "X-Host", con->request.http_host->ptr);
26165 }
1175ccec 26166@@ -449,24 +491,25 @@
2519e6e5
ER
26167 /* request header */
26168 for (i = 0; i < con->request.headers->used; i++) {
26169 data_string *ds;
26170-
26171+
26172 ds = (data_string *)con->request.headers->data[i];
26173-
1175ccec 26174- if (ds->value->used && ds->key->used) {
2519e6e5
ER
26175- if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
26176-
1175ccec
ER
26177- buffer_append_string_buffer(b, ds->key);
26178- BUFFER_APPEND_STRING_CONST(b, ": ");
26179- buffer_append_string_buffer(b, ds->value);
26180- BUFFER_APPEND_STRING_CONST(b, "\r\n");
26181- }
2519e6e5 26182+
1175ccec 26183+ if (buffer_is_empty(ds->value) || buffer_is_empty(ds->key)) continue;
2519e6e5 26184+
1175ccec
ER
26185+ if (!buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
26186+ if (!buffer_is_equal_string(ds->key, CONST_STR_LEN("Keep-Alive"))) continue;
26187+
26188+ buffer_append_string_buffer(b, ds->key);
26189+ BUFFER_APPEND_STRING_CONST(b, ": ");
26190+ buffer_append_string_buffer(b, ds->value);
26191+ BUFFER_APPEND_STRING_CONST(b, "\r\n");
2519e6e5
ER
26192 }
26193-
26194+
26195 BUFFER_APPEND_STRING_CONST(b, "\r\n");
26196-
26197+
26198 hctx->wb->bytes_in += b->used - 1;
26199 /* body */
26200-
26201+
26202 if (con->request.content_length) {
26203 chunkqueue *req_cq = con->request_content_queue;
26204 chunk *req_c;
1175ccec 26205@@ -479,7 +522,7 @@
2519e6e5
ER
26206
26207 /* we announce toWrite octects
26208 * now take all the request_content chunk that we need to fill this request
26209- * */
26210+ * */
26211
26212 switch (req_c->type) {
26213 case FILE_CHUNK:
1175ccec 26214@@ -507,223 +550,161 @@
2519e6e5
ER
26215
26216 req_c->offset += weHave;
26217 req_cq->bytes_out += weHave;
26218-
26219+
26220 hctx->wb->bytes_in += weHave;
26221
26222 break;
26223 default:
26224 break;
26225 }
26226-
26227+
26228 offset += weHave;
26229 }
26230
26231 }
26232-
26233+
26234 return 0;
26235 }
26236
26237 static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) {
26238 hctx->state = state;
26239 hctx->state_timestamp = srv->cur_ts;
26240-
26241+
26242 return 0;
26243 }
26244
26245
26246-static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
26247- char *s, *ns;
26248- int http_response_status = -1;
26249-
26250- UNUSED(srv);
26251+static void chunkqueue_print(chunkqueue *cq) {
1175ccec 26252+ chunk *c;
2519e6e5
ER
26253
26254- /* \r\n -> \0\0 */
26255-
26256- buffer_copy_string_buffer(p->parse_response, in);
26257-
26258- for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
26259- char *key, *value;
26260- int key_len;
26261- data_string *ds;
26262- int copy_header;
26263-
26264- ns[0] = '\0';
26265- ns[1] = '\0';
26266-
26267- if (-1 == http_response_status) {
26268- /* The first line of a Response message is the Status-Line */
26269-
26270- for (key=s; *key && *key != ' '; key++);
26271-
26272- if (*key) {
26273- http_response_status = (int) strtol(key, NULL, 10);
26274- if (http_response_status <= 0) http_response_status = 502;
26275- } else {
26276- http_response_status = 502;
26277- }
26278-
26279- con->http_status = http_response_status;
26280- con->parsed_response |= HTTP_STATUS;
26281- continue;
26282- }
26283-
26284- if (NULL == (value = strchr(s, ':'))) {
26285- /* now we expect: "<key>: <value>\n" */
26286-
26287- continue;
26288- }
26289-
26290- key = s;
26291- key_len = value - key;
26292-
26293- value++;
26294- /* strip WS */
26295- while (*value == ' ' || *value == '\t') value++;
26296-
26297- copy_header = 1;
26298-
26299- switch(key_len) {
26300- case 4:
26301- if (0 == strncasecmp(key, "Date", key_len)) {
26302- con->parsed_response |= HTTP_DATE;
26303- }
26304- break;
26305- case 8:
26306- if (0 == strncasecmp(key, "Location", key_len)) {
26307- con->parsed_response |= HTTP_LOCATION;
26308- }
26309- break;
26310- case 10:
26311- if (0 == strncasecmp(key, "Connection", key_len)) {
26312- copy_header = 0;
26313- }
26314- break;
26315- case 14:
26316- if (0 == strncasecmp(key, "Content-Length", key_len)) {
26317- con->response.content_length = strtol(value, NULL, 10);
26318- con->parsed_response |= HTTP_CONTENT_LENGTH;
26319- }
26320- break;
26321- default:
26322- break;
26323- }
26324-
26325- if (copy_header) {
26326- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26327- ds = data_response_init();
26328- }
26329- buffer_copy_string_len(ds->key, key, key_len);
26330- buffer_copy_string(ds->value, value);
26331-
26332- array_insert_unique(con->response.headers, (data_unset *)ds);
26333- }
1175ccec
ER
26334+ for (c = cq->first; c; c = c->next) {
26335+ fprintf(stderr, "%s", c->mem->ptr + c->offset);
26336 }
2519e6e5
ER
26337-
26338- return 0;
1175ccec 26339+ fprintf(stderr, "\r\n");
2519e6e5
ER
26340 }
26341
26342-
26343 static int proxy_demux_response(server *srv, handler_ctx *hctx) {
26344- int fin = 0;
26345- int b;
26346- ssize_t r;
26347-
26348 plugin_data *p = hctx->plugin_data;
26349 connection *con = hctx->remote_conn;
26350 int proxy_fd = hctx->fd;
26351-
26352- /* check how much we have to read */
26353- if (ioctl(hctx->fd, FIONREAD, &b)) {
26354- log_error_write(srv, __FILE__, __LINE__, "sd",
26355- "ioctl failed: ",
26356- proxy_fd);
1175ccec
ER
26357+ chunkqueue *next_queue = NULL;
26358+ chunk *c = NULL;
26359+
26360+ switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
26361+ case NETWORK_STATUS_SUCCESS:
26362+ /* we got content */
26363+ break;
26364+ case NETWORK_STATUS_WAIT_FOR_EVENT:
26365+ /* the ioctl will return WAIT_FOR_EVENT on a read */
26366+ if (0 == con->file_started) return -1;
26367+ case NETWORK_STATUS_CONNECTION_CLOSE:
26368+ /* we are done, get out of here */
26369+ con->file_finished = 1;
26370+
26371+ /* close the chunk-queue with a empty chunk */
26372+
26373+ return 1;
26374+ default:
26375+ /* oops */
26376 return -1;
26377 }
26378
26379+ /* looks like we got some content
26380+ *
26381+ * split off the header from the incoming stream
26382+ */
2519e6e5
ER
26383
26384- if (p->conf.debug) {
26385- log_error_write(srv, __FILE__, __LINE__, "sd",
26386- "proxy - have to read:", b);
26387- }
1175ccec
ER
26388+ if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
26389+ size_t i;
26390+ int have_content_length = 0;
26391
2519e6e5
ER
26392- if (b > 0) {
26393- if (hctx->response->used == 0) {
26394- /* avoid too small buffer */
26395- buffer_prepare_append(hctx->response, b + 1);
26396- hctx->response->used = 1;
26397- } else {
26398- buffer_prepare_append(hctx->response, hctx->response->used + b);
26399- }
26400-
26401- if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
26402- log_error_write(srv, __FILE__, __LINE__, "sds",
26403- "unexpected end-of-file (perhaps the proxy process died):",
26404- proxy_fd, strerror(errno));
26405- return -1;
26406- }
26407-
26408- /* this should be catched by the b > 0 above */
26409- assert(r);
26410-
26411- hctx->response->used += r;
26412- hctx->response->ptr[hctx->response->used - 1] = '\0';
26413-
26414-#if 0
26415- log_error_write(srv, __FILE__, __LINE__, "sdsbs",
26416- "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
26417-#endif
1175ccec
ER
26418+ http_response_reset(p->resp);
26419
2519e6e5
ER
26420- if (0 == con->got_response) {
26421- con->got_response = 1;
26422- buffer_prepare_copy(hctx->response_header, 128);
26423- }
26424-
26425- if (0 == con->file_started) {
26426- char *c;
26427-
26428- /* search for the \r\n\r\n in the string */
26429- if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
26430- size_t hlen = c - hctx->response->ptr + 4;
26431- size_t blen = hctx->response->used - hlen - 1;
26432- /* found */
26433-
26434- buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
26435-#if 0
26436- log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
26437-#endif
26438- /* parse the response header */
26439- proxy_response_parse(srv, con, p, hctx->response_header);
26440-
26441- /* enable chunked-transfer-encoding */
26442- if (con->request.http_version == HTTP_VERSION_1_1 &&
26443- !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
26444- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
1175ccec
ER
26445+ /* the response header is not fully received yet,
26446+ *
26447+ * extract the http-response header from the rb-cq
26448+ */
26449+ switch (http_response_parse_cq(hctx->rb, p->resp)) {
26450+ case PARSE_ERROR:
26451+ /* parsing failed */
26452+
26453+ con->http_status = 502; /* Bad Gateway */
26454+ return 1;
26455+ case PARSE_NEED_MORE:
26456+ return 0;
26457+ case PARSE_SUCCESS:
26458+ con->http_status = p->resp->status;
26459+
26460+ chunkqueue_remove_finished_chunks(hctx->rb);
26461+
26462+ /* copy the http-headers */
26463+ for (i = 0; i < p->resp->headers->used; i++) {
26464+ const char *ign[] = { "Status", "Connection", NULL };
26465+ size_t j;
26466+ data_string *ds;
26467+
26468+ data_string *header = (data_string *)p->resp->headers->data[i];
26469+
26470+ /* some headers are ignored by default */
26471+ for (j = 0; ign[j]; j++) {
26472+ if (0 == strcasecmp(ign[j], header->key->ptr)) break;
26473 }
2519e6e5
ER
26474-
26475- con->file_started = 1;
26476- if (blen) {
26477- http_chunk_append_mem(srv, con, c + 4, blen + 1);
26478- joblist_append(srv, con);
1175ccec
ER
26479+ if (ign[j]) continue;
26480+
26481+ if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
26482+ /* CGI/1.1 rev 03 - 7.2.1.2 */
26483+ if (con->http_status == 0) con->http_status = 302;
26484+ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
26485+ have_content_length = 1;
26486 }
2519e6e5 26487- hctx->response->used = 0;
1175ccec
ER
26488+
26489+ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26490+ ds = data_response_init();
26491+ }
26492+ buffer_copy_string_buffer(ds->key, header->key);
26493+ buffer_copy_string_buffer(ds->value, header->value);
26494+
26495+ array_insert_unique(con->response.headers, (data_unset *)ds);
26496 }
2519e6e5
ER
26497- } else {
26498- http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
26499- joblist_append(srv, con);
26500- hctx->response->used = 0;
1175ccec
ER
26501+
26502+ con->file_started = 1;
26503+
26504+ if (con->request.http_version == HTTP_VERSION_1_1 &&
26505+ !have_content_length) {
26506+ con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26507+ }
26508+
26509+ hctx->state = PROXY_STATE_RESPONSE_CONTENT;
26510+ break;
26511 }
2519e6e5
ER
26512-
26513- } else {
26514- /* reading from upstream done */
1175ccec 26515- con->file_finished = 1;
2519e6e5 26516-
1175ccec
ER
26517- http_chunk_append_mem(srv, con, NULL, 0);
26518- joblist_append(srv, con);
2519e6e5
ER
26519-
26520- fin = 1;
1175ccec
ER
26521 }
26522-
26523- return fin;
2519e6e5 26524+
1175ccec
ER
26525+ /* FIXME: pass the response-header to the other plugins to
26526+ * setup the filter-queue
26527+ *
26528+ * - use next-queue instead of con->write_queue
26529+ */
2519e6e5 26530+
1175ccec 26531+ next_queue = con->write_queue;
2519e6e5 26532+
1175ccec 26533+ assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
2519e6e5 26534+
1175ccec
ER
26535+ /* FIXME: if we have a content-length or chunked-encoding
26536+ * handle it.
26537+ *
26538+ * for now we wait for EOF on the socket */
2519e6e5 26539+
1175ccec
ER
26540+ /* copy the content to the next cq */
26541+ for (c = hctx->rb->first; c; c = c->next) {
26542+ http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
2519e6e5 26543+
1175ccec
ER
26544+ c->offset = c->mem->used - 1;
26545+ }
2519e6e5 26546+
1175ccec
ER
26547+ chunkqueue_remove_finished_chunks(hctx->rb);
26548+ joblist_append(srv, con);
2519e6e5
ER
26549+
26550+ return 0;
26551 }
26552
26553
1175ccec 26554@@ -731,12 +712,12 @@
2519e6e5
ER
26555 data_proxy *host= hctx->host;
26556 plugin_data *p = hctx->plugin_data;
26557 connection *con = hctx->remote_conn;
26558-
26559+
26560 int ret;
26561-
26562- if (!host ||
1175ccec
ER
26563- (!host->host->used || !host->port)) return -1;
26564-
2519e6e5
ER
26565+
26566+ if (!host ||
1175ccec 26567+ (!host->host->used || !host->port)) return -1;
2519e6e5
ER
26568+
26569 switch(hctx->state) {
26570 case PROXY_STATE_INIT:
26571 if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
1175ccec 26572@@ -744,19 +725,19 @@
2519e6e5
ER
26573 return HANDLER_ERROR;
26574 }
26575 hctx->fde_ndx = -1;
26576-
26577+
26578 srv->cur_fds++;
26579-
26580+
26581 fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
26582-
26583+
26584 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
26585 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
26586-
26587+
26588 return HANDLER_ERROR;
26589 }
26590-
26591+
26592 /* fall through */
26593-
26594+
26595 case PROXY_STATE_CONNECT:
26596 /* try to finish the connect() */
26597 if (hctx->state == PROXY_STATE_INIT) {
1175ccec 26598@@ -764,16 +745,16 @@
2519e6e5
ER
26599 switch (proxy_establish_connection(srv, hctx)) {
26600 case 1:
26601 proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
26602-
26603+
26604 /* connection is in progress, wait for an event and call getsockopt() below */
26605-
26606+
26607 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26608-
26609+
26610 return HANDLER_WAIT_FOR_EVENT;
26611 case -1:
26612 /* if ECONNREFUSED choose another connection -> FIXME */
26613 hctx->fde_ndx = -1;
26614-
26615+
26616 return HANDLER_ERROR;
26617 default:
26618 /* everything is ok, go on */
1175ccec 26619@@ -782,152 +763,152 @@
2519e6e5
ER
26620 } else {
26621 int socket_error;
26622 socklen_t socket_error_len = sizeof(socket_error);
26623-
26624- /* we don't need it anymore */
26625+
26626+ /* we don't need it anymore */
26627 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26628
26629 /* try to finish the connect() */
26630 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
26631- log_error_write(srv, __FILE__, __LINE__, "ss",
26632+ log_error_write(srv, __FILE__, __LINE__, "ss",
26633 "getsockopt failed:", strerror(errno));
26634-
26635+
26636 return HANDLER_ERROR;
26637 }
26638 if (socket_error != 0) {
26639 log_error_write(srv, __FILE__, __LINE__, "ss",
26640- "establishing connection failed:", strerror(socket_error),
26641+ "establishing connection failed:", strerror(socket_error),
26642 "port:", hctx->host->port);
26643-
26644+
26645 return HANDLER_ERROR;
26646 }
26647 if (p->conf.debug) {
26648- log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
26649+ log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
26650 }
2519e6e5
ER
26651 }
26652-
26653+
26654 proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
26655 /* fall through */
26656 case PROXY_STATE_PREPARE_WRITE:
26657 proxy_create_env(srv, hctx);
26658-
26659+
26660 proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
26661-
26662+
26663 /* fall through */
26664 case PROXY_STATE_WRITE:;
26665- ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
26666+ ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
26667
26668 chunkqueue_remove_finished_chunks(hctx->wb);
26669
26670- if (-1 == ret) {
26671- if (errno != EAGAIN &&
26672- errno != EINTR) {
26673- log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26674-
26675- return HANDLER_ERROR;
26676- } else {
26677- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26678+ switch(ret) {
1175ccec 26679+ case NETWORK_STATUS_FATAL_ERROR:
2519e6e5
ER
26680+ log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26681
26682- return HANDLER_WAIT_FOR_EVENT;
26683- }
26684+ return HANDLER_ERROR;
1175ccec 26685+ case NETWORK_STATUS_WAIT_FOR_EVENT:
2519e6e5
ER
26686+
26687+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26688+
26689+ return HANDLER_WAIT_FOR_EVENT;
26690 }
26691
26692 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
26693- proxy_set_state(srv, hctx, PROXY_STATE_READ);
26694+ proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
26695
26696 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26697 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
26698 } else {
26699 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26700-
26701+
26702 return HANDLER_WAIT_FOR_EVENT;
26703 }
26704-
26705+
26706 return HANDLER_WAIT_FOR_EVENT;
26707- case PROXY_STATE_READ:
1175ccec 26708+ case PROXY_STATE_RESPONSE_CONTENT:
2519e6e5
ER
26709+ case PROXY_STATE_RESPONSE_HEADER:
26710 /* waiting for a response */
26711+
26712 return HANDLER_WAIT_FOR_EVENT;
26713 default:
26714 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
26715 return HANDLER_ERROR;
26716 }
26717-
26718+
26719 return HANDLER_GO_ON;
26720 }
26721
26722-#define PATCH(x) \
26723- p->conf.x = s->x;
26724 static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
26725 size_t i, j;
26726 plugin_config *s = p->config_storage[0];
26727-
26728- PATCH(extensions);
26729- PATCH(debug);
26730- PATCH(balance);
26731-
26732+
26733+ PATCH_OPTION(extensions);
26734+ PATCH_OPTION(debug);
26735+ PATCH_OPTION(balance);
26736+ PATCH_OPTION(last_used_backends);
26737+
26738 /* skip the first, the global context */
26739 for (i = 1; i < srv->config_context->used; i++) {
26740 data_config *dc = (data_config *)srv->config_context->data[i];
26741 s = p->config_storage[i];
26742-
26743+
26744 /* condition didn't match */
26745 if (!config_check_cond(srv, con, dc)) continue;
26746-
26747+
26748 /* merge config */
26749 for (j = 0; j < dc->value->used; j++) {
26750 data_unset *du = dc->value->data[j];
26751-
26752+
26753 if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
26754- PATCH(extensions);
26755+ PATCH_OPTION(extensions);
26756 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
26757- PATCH(debug);
26758+ PATCH_OPTION(debug);
26759 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
26760- PATCH(balance);
26761+ PATCH_OPTION(balance);
26762+ PATCH_OPTION(last_used_backends);
26763 }
26764 }
26765 }
26766-
26767+
26768 return 0;
26769 }
26770-#undef PATCH
26771
26772 SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
26773 plugin_data *p = p_d;
26774-
26775+
26776 handler_ctx *hctx = con->plugin_ctx[p->id];
26777 data_proxy *host;
26778-
26779+
26780 if (NULL == hctx) return HANDLER_GO_ON;
26781
26782 mod_proxy_patch_connection(srv, con, p);
26783-
26784+
26785 host = hctx->host;
26786-
26787+
26788 /* not my job */
26789 if (con->mode != p->id) return HANDLER_GO_ON;
26790-
26791+
26792 /* ok, create the request */
26793 switch(proxy_write_request(srv, hctx)) {
26794 case HANDLER_ERROR:
26795- log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
26796+ log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
26797 host->host,
26798 host->port,
26799 hctx->fd);
26800-
26801+
26802 /* disable this server */
26803 host->is_disabled = 1;
26804 host->disable_ts = srv->cur_ts;
26805-
26806+
26807 proxy_connection_close(srv, hctx);
26808-
26809- /* reset the enviroment and restart the sub-request */
26810+
26811+ /* reset the enviroment and restart the sub-request */
26812 buffer_reset(con->physical.path);
26813 con->mode = DIRECT;
26814
26815 joblist_append(srv, con);
26816
26817- /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26818- * and hope that the childs will be restarted
26819- *
26820+ /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26821+ * and hope that the childs will be restarted
26822+ *
26823 */
26824
26825 return HANDLER_WAIT_FOR_FD;
1175ccec 26826@@ -938,7 +919,7 @@
2519e6e5
ER
26827 default:
26828 break;
26829 }
26830-
26831+
26832 if (con->file_started == 1) {
26833 return HANDLER_FINISHED;
26834 } else {
1175ccec 26835@@ -951,13 +932,14 @@
2519e6e5
ER
26836 handler_ctx *hctx = ctx;
26837 connection *con = hctx->remote_conn;
26838 plugin_data *p = hctx->plugin_data;
26839-
26840-
26841+
26842+
26843 if ((revents & FDEVENT_IN) &&
26844- hctx->state == PROXY_STATE_READ) {
1175ccec
ER
26845+ (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
26846+ hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
2519e6e5
ER
26847
26848 if (p->conf.debug) {
26849- log_error_write(srv, __FILE__, __LINE__, "sd",
26850+ log_error_write(srv, __FILE__, __LINE__, "sd",
26851 "proxy: fdevent-in", hctx->state);
26852 }
26853
1175ccec
ER
26854@@ -965,11 +947,15 @@
26855 case 0:
2519e6e5
ER
26856 break;
26857 case 1:
1175ccec
ER
26858+ log_error_write(srv, __FILE__, __LINE__, "sd",
26859+ "proxy: request done", hctx->fd);
2519e6e5
ER
26860 hctx->host->usage--;
26861-
1175ccec
ER
26862+
26863+ http_chunk_append_mem(srv, con, NULL, 0);
2519e6e5
ER
26864+
26865 /* we are done */
26866 proxy_connection_close(srv, hctx);
26867-
26868+
26869 joblist_append(srv, con);
26870 return HANDLER_FINISHED;
26871 case -1:
1175ccec 26872@@ -982,53 +968,53 @@
2519e6e5
ER
26873 /* response might have been already started, kill the connection */
26874 connection_set_state(srv, con, CON_STATE_ERROR);
26875 }
26876-
26877+
26878 joblist_append(srv, con);
26879 return HANDLER_FINISHED;
26880 }
26881 }
26882-
26883+
26884 if (revents & FDEVENT_OUT) {
26885 if (p->conf.debug) {
26886- log_error_write(srv, __FILE__, __LINE__, "sd",
26887+ log_error_write(srv, __FILE__, __LINE__, "sd",
26888 "proxy: fdevent-out", hctx->state);
26889 }
26890
26891 if (hctx->state == PROXY_STATE_CONNECT ||
26892 hctx->state == PROXY_STATE_WRITE) {
26893 /* we are allowed to send something out
26894- *
26895+ *
26896 * 1. in a unfinished connect() call
26897 * 2. in a unfinished write() call (long POST request)
26898 */
26899 return mod_proxy_handle_subrequest(srv, con, p);
26900 } else {
26901- log_error_write(srv, __FILE__, __LINE__, "sd",
26902+ log_error_write(srv, __FILE__, __LINE__, "sd",
26903 "proxy: out", hctx->state);
26904 }
26905 }
26906-
26907+
26908 /* perhaps this issue is already handled */
26909 if (revents & FDEVENT_HUP) {
26910 if (p->conf.debug) {
26911- log_error_write(srv, __FILE__, __LINE__, "sd",
26912+ log_error_write(srv, __FILE__, __LINE__, "sd",
26913 "proxy: fdevent-hup", hctx->state);
26914 }
26915-
26916+
26917 if (hctx->state == PROXY_STATE_CONNECT) {
26918 /* connect() -> EINPROGRESS -> HUP */
26919-
26920+
26921 /**
26922- * what is proxy is doing if it can't reach the next hop ?
26923- *
26924+ * what is proxy is doing if it can't reach the next hop ?
26925+ *
26926 */
26927-
26928+
26929 proxy_connection_close(srv, hctx);
26930 joblist_append(srv, con);
26931-
26932+
26933 con->http_status = 503;
26934 con->mode = DIRECT;
26935-
26936+
26937 return HANDLER_FINISHED;
26938 }
26939
1175ccec 26940@@ -1038,13 +1024,13 @@
2519e6e5
ER
26941 joblist_append(srv, con);
26942 } else if (revents & FDEVENT_ERR) {
26943 /* kill all connections to the proxy process */
26944-
26945+
26946 log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
26947
26948 joblist_append(srv, con);
26949 proxy_connection_close(srv, hctx);
26950 }
26951-
26952+
26953 return HANDLER_FINISHED;
26954 }
26955
1175ccec 26956@@ -1058,44 +1044,48 @@
2519e6e5
ER
26957 buffer *fn;
26958 data_array *extension = NULL;
26959 size_t path_info_offset;
26960-
26961+ data_integer *last_used_backend;
26962+ data_proxy *host = NULL;
26963+ handler_ctx *hctx = NULL;
26964+
26965+ array *backends = NULL;
26966+
26967 /* Possibly, we processed already this request */
26968 if (con->file_started == 1) return HANDLER_GO_ON;
26969-
26970+
26971 mod_proxy_patch_connection(srv, con, p);
26972-
26973+
26974 fn = con->uri.path;
26975
26976 if (fn->used == 0) {
26977 return HANDLER_ERROR;
26978 }
26979-
26980+
26981 s_len = fn->used - 1;
26982-
26983-
2519e6e5
ER
26984+
26985 path_info_offset = 0;
26986
26987- if (p->conf.debug) {
26988+ if (p->conf.debug) {
26989 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - start");
26990 }
26991
26992 /* check if extension matches */
26993 for (k = 0; k < p->conf.extensions->used; k++) {
26994 size_t ct_len;
26995-
26996+
26997 extension = (data_array *)p->conf.extensions->data[k];
26998-
26999+
27000 if (extension->key->used == 0) continue;
27001-
27002+
27003 ct_len = extension->key->used - 1;
27004-
27005+
27006 if (s_len < ct_len) continue;
27007-
27008+
27009 /* check extension in the form "/proxy_pattern" */
27010 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
27011 if (s_len > ct_len + 1) {
27012 char *pi_offset;
27013-
27014+
27015 if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
27016 path_info_offset = pi_offset - fn->ptr;
27017 }
1175ccec 27018@@ -1106,12 +1096,14 @@
2519e6e5
ER
27019 break;
27020 }
27021 }
27022-
27023+
27024 if (k == p->conf.extensions->used) {
27025 return HANDLER_GO_ON;
27026 }
27027
27028- if (p->conf.debug) {
27029+ backends = extension->value;
27030+
27031+ if (p->conf.debug) {
27032 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found");
27033 }
27034
1175ccec 27035@@ -1120,34 +1112,34 @@
2519e6e5
ER
27036 /* hash balancing */
27037
27038 if (p->conf.debug) {
27039- log_error_write(srv, __FILE__, __LINE__, "sd",
27040- "proxy - used hash balancing, hosts:", extension->value->used);
27041+ log_error_write(srv, __FILE__, __LINE__, "sd",
27042+ "proxy - used hash balancing, hosts:", backends->used);
27043 }
27044
27045- for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
27046- data_proxy *host = (data_proxy *)extension->value->data[k];
27047+ for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
27048 unsigned long cur_max;
27049
27050- if (host->is_disabled) continue;
27051-
27052+ data_proxy *cur = (data_proxy *)backends->data[k];
27053+
27054+ if (cur->is_disabled) continue;
27055+
27056 cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
27057- generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
27058+ generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
27059 generate_crc32c(CONST_BUF_LEN(con->uri.authority));
27060-
27061+
27062 if (p->conf.debug) {
27063- log_error_write(srv, __FILE__, __LINE__, "sbbbd",
27064+ log_error_write(srv, __FILE__, __LINE__, "sbbbd",
27065 "proxy - election:",
27066 con->uri.path,
27067- host->host,
27068+ cur->host,
27069 con->uri.authority,
27070 cur_max);
27071 }
27072
27073- if ((last_max == ULONG_MAX) || /* first round */
27074- (cur_max > last_max)) {
27075+ if (host == NULL || (cur_max > last_max)) {
27076 last_max = cur_max;
27077
27078- ndx = k;
27079+ host = cur;
27080 }
27081 }
27082
1175ccec 27083@@ -1155,19 +1147,20 @@
2519e6e5
ER
27084 case PROXY_BALANCE_FAIR:
27085 /* fair balancing */
27086 if (p->conf.debug) {
27087- log_error_write(srv, __FILE__, __LINE__, "s",
27088+ log_error_write(srv, __FILE__, __LINE__, "s",
27089 "proxy - used fair balancing");
27090 }
27091
27092- for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27093- data_proxy *host = (data_proxy *)extension->value->data[k];
27094-
27095- if (host->is_disabled) continue;
27096-
27097- if (host->usage < max_usage) {
27098- max_usage = host->usage;
27099-
27100- ndx = k;
27101+ /* try to find the host with the lowest load */
27102+ for (k = 0, max_usage = 0; k < backends->used; k++) {
27103+ data_proxy *cur = (data_proxy *)backends->data[k];
27104+
27105+ if (cur->is_disabled) continue;
27106+
27107+ if (NULL == host || cur->usage < max_usage) {
27108+ max_usage = cur->usage;
27109+
27110+ host = cur;
27111 }
27112 }
27113
1175ccec 27114@@ -1175,89 +1168,100 @@
2519e6e5
ER
27115 case PROXY_BALANCE_RR:
27116 /* round robin */
27117 if (p->conf.debug) {
27118- log_error_write(srv, __FILE__, __LINE__, "s",
27119+ log_error_write(srv, __FILE__, __LINE__, "s",
27120 "proxy - used round-robin balancing");
27121 }
27122
27123 /* just to be sure */
27124- assert(extension->value->used < INT_MAX);
27125-
27126- for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27127- data_proxy *host = (data_proxy *)extension->value->data[k];
27128-
27129- if (host->is_disabled) continue;
27130-
27131- /* first usable ndx */
27132- if (max_usage == INT_MAX) {
27133- max_usage = k;
27134- }
27135+ assert(backends->used < INT_MAX);
27136
27137- /* get next ndx */
27138- if ((int)k > host->last_used_ndx) {
27139- ndx = k;
27140- host->last_used_ndx = k;
27141+ /* send each request to another host:
27142+ *
27143+ * e.g.:
27144+ *
27145+ * if we have three hosts it is
27146+ *
27147+ * 1 .. 2 .. 3 .. 1 .. 2 .. 3
27148+ *
27149+ **/
27150
27151- break;
27152- }
27153+ /* walk through the list */
27154+ last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
27155+
27156+ if (NULL == last_used_backend) {
27157+ last_used_backend = data_integer_init();
27158+
27159+ buffer_copy_string_buffer(last_used_backend->key, extension->key);
27160+ last_used_backend->value = 0;
27161+
27162+ array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
27163+ }
27164+
27165+ /* scan all but the last host to see if they are up
27166+ * take the first running host */
27167+ for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
27168+ data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
27169+
27170+ if (cur->is_disabled) continue;
27171+
27172+ host = cur;
27173+
27174+ last_used_backend->value = k;
27175+
27176+ break;
27177 }
27178-
27179- /* didn't found a higher id, wrap to the start */
27180- if (ndx != -1 && max_usage != INT_MAX) {
27181- ndx = max_usage;
27182+
27183+ if (NULL == host) {
27184+ /* we found nothing better, fallback to the last used backend
27185+ * and check if it is still up */
27186+ host = (data_proxy *)backends->data[last_used_backend->value];
27187+
27188+ if (host->is_disabled) host = NULL;
27189 }
27190
27191 break;
27192 default:
27193 break;
27194 }
27195-
27196- /* found a server */
27197- if (ndx != -1) {
27198- data_proxy *host = (data_proxy *)extension->value->data[ndx];
27199-
27200- /*
27201- * if check-local is disabled, use the uri.path handler
27202- *
27203- */
27204-
27205- /* init handler-context */
27206- handler_ctx *hctx;
27207- hctx = handler_ctx_init();
27208-
27209- hctx->path_info_offset = path_info_offset;
27210- hctx->remote_conn = con;
27211- hctx->plugin_data = p;
27212- hctx->host = host;
27213-
27214- con->plugin_ctx[p->id] = hctx;
27215-
27216- host->usage++;
27217-
27218- con->mode = p->id;
27219-
27220- if (p->conf.debug) {
27221- log_error_write(srv, __FILE__, __LINE__, "sbd",
27222- "proxy - found a host",
27223- host->host, host->port);
27224- }
27225
27226- return HANDLER_GO_ON;
27227- } else {
27228- /* no handler found */
27229+ /* we havn't found a host */
27230+ if (NULL == host) {
27231 con->http_status = 500;
27232-
27233- log_error_write(srv, __FILE__, __LINE__, "sb",
27234- "no proxy-handler found for:",
27235+
27236+ log_error_write(srv, __FILE__, __LINE__, "sb",
27237+ "no proxy-handler found for:",
27238 fn);
27239-
27240+
27241 return HANDLER_FINISHED;
27242 }
27243+
27244+ /* init handler-context */
27245+ hctx = handler_ctx_init();
27246+
27247+ hctx->path_info_offset = path_info_offset;
27248+ hctx->remote_conn = con;
27249+ hctx->plugin_data = p;
27250+ hctx->host = host;
27251+
27252+ con->plugin_ctx[p->id] = hctx;
27253+
27254+ host->usage++;
27255+
27256+ /* we handle this request */
27257+ con->mode = p->id;
27258+
27259+ if (p->conf.debug) {
27260+ log_error_write(srv, __FILE__, __LINE__, "sbd",
27261+ "proxy - found a host",
27262+ host->host, host->port);
27263+ }
27264+
27265 return HANDLER_GO_ON;
27266 }
27267
27268 static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
27269 plugin_data *p = p_d;
27270-
27271+
27272 proxy_connection_close(srv, con->plugin_ctx[p->id]);
27273
27274 return HANDLER_GO_ON;
1175ccec 27275@@ -1276,11 +1280,11 @@
2519e6e5
ER
27276 size_t i, n, k;
27277 for (i = 0; i < srv->config_context->used; i++) {
27278 plugin_config *s = p->config_storage[i];
27279-
27280- if (!s) continue;
27281+
27282+ if (!s) continue;
27283
27284 /* get the extensions for all configs */
27285-
27286+
27287 for (k = 0; k < s->extensions->used; k++) {
27288 data_array *extension = (data_array *)s->extensions->data[k];
27289
1175ccec 27290@@ -1290,8 +1294,8 @@
2519e6e5
ER
27291
27292 if (!host->is_disabled ||
27293 srv->cur_ts - host->disable_ts < 5) continue;
27294-
27295- log_error_write(srv, __FILE__, __LINE__, "sbd",
27296+
27297+ log_error_write(srv, __FILE__, __LINE__, "sbd",
27298 "proxy - re-enabled:",
27299 host->host, host->port);
27300
1175ccec 27301@@ -1317,8 +1321,8 @@
2519e6e5
ER
27302 p->handle_uri_clean = mod_proxy_check_extension;
27303 p->handle_subrequest = mod_proxy_handle_subrequest;
27304 p->handle_trigger = mod_proxy_trigger;
27305-
27306+
27307 p->data = NULL;
27308-
27309+
27310 return 0;
27311 }
1175ccec 27312--- ../lighttpd-1.4.11/src/mod_redirect.c 2006-02-08 15:38:06.000000000 +0200
36e2a29e 27313+++ lighttpd-1.4.12/src/mod_redirect.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
27314@@ -22,35 +22,35 @@
27315 PLUGIN_DATA;
27316 buffer *match_buf;
27317 buffer *location;
27318-
27319+
27320 plugin_config **config_storage;
27321-
27322- plugin_config conf;
27323+
27324+ plugin_config conf;
27325 } plugin_data;
27326
27327 INIT_FUNC(mod_redirect_init) {
27328 plugin_data *p;
27329-
27330+
27331 p = calloc(1, sizeof(*p));
27332-
27333+
27334 p->match_buf = buffer_init();
27335 p->location = buffer_init();
27336-
27337+
27338 return p;
27339 }
27340
27341 FREE_FUNC(mod_redirect_free) {
27342 plugin_data *p = p_d;
27343-
27344+
27345 if (!p) return HANDLER_GO_ON;
27346
27347 if (p->config_storage) {
27348 size_t i;
27349 for (i = 0; i < srv->config_context->used; i++) {
27350 plugin_config *s = p->config_storage[i];
27351-
27352+
27353 pcre_keyvalue_buffer_free(s->redirect);
27354-
27355+
27356 free(s);
27357 }
27358 free(p->config_storage);
27359@@ -59,9 +59,9 @@
27360
27361 buffer_free(p->match_buf);
27362 buffer_free(p->location);
27363-
27364+
27365 free(p);
27366-
27367+
27368 return HANDLER_GO_ON;
27369 }
27370
27371@@ -69,195 +69,137 @@
27372 plugin_data *p = p_d;
27373 data_unset *du;
27374 size_t i = 0;
27375-
27376- config_values_t cv[] = {
27377+
27378+ config_values_t cv[] = {
27379 { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27380 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27381 };
27382-
27383+
27384 if (!p) return HANDLER_ERROR;
27385-
27386+
27387 /* 0 */
27388 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27389-
27390+
27391 for (i = 0; i < srv->config_context->used; i++) {
27392 plugin_config *s;
27393 size_t j;
27394 array *ca;
27395 data_array *da = (data_array *)du;
27396-
27397+
27398 s = calloc(1, sizeof(plugin_config));
27399 s->redirect = pcre_keyvalue_buffer_init();
27400-
27401+
27402 cv[0].destination = s->redirect;
27403-
27404+
27405 p->config_storage[i] = s;
27406 ca = ((data_config *)srv->config_context->data[i])->value;
27407-
27408+
27409 if (0 != config_insert_values_global(srv, ca, cv)) {
27410 return HANDLER_ERROR;
27411 }
27412-
27413+
27414 if (NULL == (du = array_get_element(ca, "url.redirect"))) {
27415 /* no url.redirect defined */
27416 continue;
27417 }
27418-
27419+
27420 if (du->type != TYPE_ARRAY) {
27421- log_error_write(srv, __FILE__, __LINE__, "sss",
27422+ log_error_write(srv, __FILE__, __LINE__, "sss",
27423 "unexpected type for key: ", "url.redirect", "array of strings");
27424-
27425+
27426 return HANDLER_ERROR;
27427 }
27428-
27429+
27430 da = (data_array *)du;
27431-
27432+
27433 for (j = 0; j < da->value->used; j++) {
27434 if (da->value->data[j]->type != TYPE_STRING) {
27435- log_error_write(srv, __FILE__, __LINE__, "sssbs",
27436- "unexpected type for key: ",
27437- "url.redirect",
27438+ log_error_write(srv, __FILE__, __LINE__, "sssbs",
27439+ "unexpected type for key: ",
27440+ "url.redirect",
27441 "[", da->value->data[j]->key, "](string)");
27442-
27443+
27444 return HANDLER_ERROR;
27445 }
27446-
27447- if (0 != pcre_keyvalue_buffer_append(s->redirect,
27448+
27449+ if (0 != pcre_keyvalue_buffer_append(s->redirect,
27450 ((data_string *)(da->value->data[j]))->key->ptr,
27451 ((data_string *)(da->value->data[j]))->value->ptr)) {
27452-
27453- log_error_write(srv, __FILE__, __LINE__, "sb",
27454+
27455+ log_error_write(srv, __FILE__, __LINE__, "sb",
27456 "pcre-compile failed for", da->value->data[j]->key);
27457 }
27458 }
27459 }
27460-
27461+
27462 return HANDLER_GO_ON;
27463 }
27464 #ifdef HAVE_PCRE_H
27465 static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
27466 size_t i, j;
27467 plugin_config *s = p->config_storage[0];
27468-
27469+
27470 p->conf.redirect = s->redirect;
27471-
27472+
27473 /* skip the first, the global context */
27474 for (i = 1; i < srv->config_context->used; i++) {
27475 data_config *dc = (data_config *)srv->config_context->data[i];
27476 s = p->config_storage[i];
27477-
27478+
27479 /* condition didn't match */
27480 if (!config_check_cond(srv, con, dc)) continue;
27481-
27482+
27483 /* merge config */
27484 for (j = 0; j < dc->value->used; j++) {
27485 data_unset *du = dc->value->data[j];
27486-
27487+
27488 if (0 == strcmp(du->key->ptr, "url.redirect")) {
27489 p->conf.redirect = s->redirect;
27490 p->conf.context = dc;
27491 }
27492 }
27493 }
27494-
27495+
27496 return 0;
27497 }
27498 #endif
27499 static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
27500 #ifdef HAVE_PCRE_H
27501 plugin_data *p = p_data;
27502- size_t i;
27503+ int i;
27504
27505- /*
27506+ /*
27507 * REWRITE URL
27508- *
27509+ *
27510 * e.g. redirect /base/ to /index.php?section=base
27511- *
27512+ *
27513 */
27514-
27515+
27516 mod_redirect_patch_connection(srv, con, p);
27517-
27518+
27519 buffer_copy_string_buffer(p->match_buf, con->request.uri);
27520-
27521- for (i = 0; i < p->conf.redirect->used; i++) {
27522- pcre *match;
27523- pcre_extra *extra;
27524- const char *pattern;
27525- size_t pattern_len;
27526- int n;
27527- pcre_keyvalue *kv = p->conf.redirect->kv[i];
27528-# define N 10
27529- int ovec[N * 3];
27530-
27531- match = kv->key;
27532- extra = kv->key_extra;
27533- pattern = kv->value->ptr;
27534- pattern_len = kv->value->used - 1;
27535-
27536- if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
27537- if (n != PCRE_ERROR_NOMATCH) {
27538- log_error_write(srv, __FILE__, __LINE__, "sd",
27539- "execution error while matching: ", n);
27540- return HANDLER_ERROR;
27541- }
27542- } else {
27543- const char **list;
27544- size_t start, end;
27545- size_t k;
27546-
27547- /* it matched */
27548- pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
27549-
27550- /* search for $[0-9] */
27551-
27552- buffer_reset(p->location);
27553-
27554- start = 0; end = pattern_len;
27555- for (k = 0; k < pattern_len; k++) {
27556- if ((pattern[k] == '$' || pattern[k] == '%') &&
27557- isdigit((unsigned char)pattern[k + 1])) {
27558- /* got one */
27559-
27560- size_t num = pattern[k + 1] - '0';
27561-
27562- end = k;
27563-
27564- buffer_append_string_len(p->location, pattern + start, end - start);
27565-
27566- if (pattern[k] == '$') {
27567- /* n is always > 0 */
27568- if (num < (size_t)n) {
27569- buffer_append_string(p->location, list[num]);
27570- }
27571- } else {
27572- config_append_cond_match_buffer(con, p->conf.context, p->location, num);
27573- }
27574-
27575- k++;
27576- start = k + 1;
27577- }
27578- }
27579-
27580- buffer_append_string_len(p->location, pattern + start, pattern_len - start);
27581-
27582- pcre_free(list);
27583-
27584- response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27585-
27586- con->http_status = 301;
27587- con->file_finished = 1;
27588-
27589- return HANDLER_FINISHED;
27590- }
27591+ i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
27592+
27593+ if (i >= 0) {
27594+ response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27595+
27596+ con->http_status = 301;
27597+ con->file_finished = 1;
27598+
27599+ return HANDLER_FINISHED;
27600+ }
27601+ else if (i != PCRE_ERROR_NOMATCH) {
27602+ log_error_write(srv, __FILE__, __LINE__, "s",
27603+ "execution error while matching", i);
27604 }
27605 #undef N
27606-
27607+
27608 #else
27609 UNUSED(srv);
27610 UNUSED(con);
27611 UNUSED(p_data);
27612 #endif
27613-
27614+
27615 return HANDLER_GO_ON;
27616 }
27617
27618@@ -265,13 +207,13 @@
27619 int mod_redirect_plugin_init(plugin *p) {
27620 p->version = LIGHTTPD_VERSION_ID;
27621 p->name = buffer_init_string("redirect");
27622-
27623+
27624 p->init = mod_redirect_init;
27625 p->handle_uri_clean = mod_redirect_uri_handler;
27626 p->set_defaults = mod_redirect_set_defaults;
27627 p->cleanup = mod_redirect_free;
27628-
27629+
27630 p->data = NULL;
27631-
27632+
27633 return 0;
27634 }
1175ccec 27635--- ../lighttpd-1.4.11/src/mod_rewrite.c 2005-09-29 20:59:10.000000000 +0300
36e2a29e 27636+++ lighttpd-1.4.12/src/mod_rewrite.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
27637@@ -13,24 +13,8 @@
27638 #endif
27639
27640 typedef struct {
27641-#ifdef HAVE_PCRE_H
27642- pcre *key;
27643-#endif
27644-
27645- buffer *value;
27646-
27647- int once;
27648-} rewrite_rule;
27649-
27650-typedef struct {
27651- rewrite_rule **ptr;
27652-
27653- size_t used;
27654- size_t size;
27655-} rewrite_rule_buffer;
27656-
27657-typedef struct {
27658- rewrite_rule_buffer *rewrite;
27659+ pcre_keyvalue_buffer *rewrite;
27660+ buffer *once;
27661 data_config *context; /* to which apply me */
27662 } plugin_config;
27663
27664@@ -42,20 +26,20 @@
27665 typedef struct {
27666 PLUGIN_DATA;
27667 buffer *match_buf;
27668-
27669+
27670 plugin_config **config_storage;
27671-
27672- plugin_config conf;
27673+
27674+ plugin_config conf;
27675 } plugin_data;
27676
27677 static handler_ctx * handler_ctx_init() {
27678 handler_ctx * hctx;
27679-
27680+
27681 hctx = calloc(1, sizeof(*hctx));
27682-
27683+
27684 hctx->state = REWRITE_STATE_UNSET;
27685 hctx->loops = 0;
27686-
27687+
27688 return hctx;
27689 }
27690
27691@@ -63,207 +47,136 @@
27692 free(hctx);
27693 }
27694
27695-rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
27696- rewrite_rule_buffer *kvb;
27697-
27698- kvb = calloc(1, sizeof(*kvb));
27699-
27700- return kvb;
27701-}
27702-
27703-int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
27704-#ifdef HAVE_PCRE_H
27705- size_t i;
27706- const char *errptr;
27707- int erroff;
27708-
27709- if (!key) return -1;
27710-
27711- if (kvb->size == 0) {
27712- kvb->size = 4;
27713- kvb->used = 0;
27714-
27715- kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
27716-
27717- for(i = 0; i < kvb->size; i++) {
27718- kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27719- }
27720- } else if (kvb->used == kvb->size) {
27721- kvb->size += 4;
27722-
27723- kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
27724-
27725- for(i = kvb->used; i < kvb->size; i++) {
27726- kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27727- }
27728- }
27729-
27730- if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
27731- 0, &errptr, &erroff, NULL))) {
27732-
27733- return -1;
27734- }
27735-
27736- kvb->ptr[kvb->used]->value = buffer_init();
27737- buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
27738- kvb->ptr[kvb->used]->once = once;
27739-
27740- kvb->used++;
27741-
27742- return 0;
27743-#else
27744- UNUSED(kvb);
27745- UNUSED(value);
27746- UNUSED(once);
27747- UNUSED(key);
27748-
27749- return -1;
27750-#endif
27751-}
27752-
27753-void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
27754-#ifdef HAVE_PCRE_H
27755- size_t i;
27756-
27757- for (i = 0; i < kvb->size; i++) {
27758- if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
27759- if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
27760- free(kvb->ptr[i]);
27761- }
27762-
27763- if (kvb->ptr) free(kvb->ptr);
27764-#endif
27765-
27766- free(kvb);
27767-}
27768-
27769
27770 INIT_FUNC(mod_rewrite_init) {
27771 plugin_data *p;
27772-
27773+
27774 p = calloc(1, sizeof(*p));
27775-
27776+
27777 p->match_buf = buffer_init();
27778-
27779+
27780 return p;
27781 }
27782
27783 FREE_FUNC(mod_rewrite_free) {
27784 plugin_data *p = p_d;
27785-
27786+
27787 UNUSED(srv);
27788
27789 if (!p) return HANDLER_GO_ON;
27790-
27791+
27792 buffer_free(p->match_buf);
27793 if (p->config_storage) {
27794 size_t i;
27795 for (i = 0; i < srv->config_context->used; i++) {
27796 plugin_config *s = p->config_storage[i];
27797- rewrite_rule_buffer_free(s->rewrite);
27798-
27799+ pcre_keyvalue_buffer_free(s->rewrite);
27800+ buffer_free(s->once);
27801+
27802 free(s);
27803 }
27804 free(p->config_storage);
27805 }
27806-
27807+
27808 free(p);
27809-
27810+
27811 return HANDLER_GO_ON;
27812 }
27813
27814 static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
27815 data_unset *du;
27816-
27817+
27818 if (NULL != (du = array_get_element(ca, option))) {
27819 data_array *da = (data_array *)du;
27820 size_t j;
27821-
27822+
27823 if (du->type != TYPE_ARRAY) {
27824- log_error_write(srv, __FILE__, __LINE__, "sss",
27825+ log_error_write(srv, __FILE__, __LINE__, "sss",
27826 "unexpected type for key: ", option, "array of strings");
27827-
27828+
27829 return HANDLER_ERROR;
27830 }
27831-
27832+
27833 da = (data_array *)du;
27834-
27835+
27836 for (j = 0; j < da->value->used; j++) {
27837 if (da->value->data[j]->type != TYPE_STRING) {
27838- log_error_write(srv, __FILE__, __LINE__, "sssbs",
27839- "unexpected type for key: ",
27840- option,
27841+ log_error_write(srv, __FILE__, __LINE__, "sssbs",
27842+ "unexpected type for key: ",
27843+ option,
27844 "[", da->value->data[j]->key, "](string)");
27845-
27846+
27847 return HANDLER_ERROR;
27848 }
27849-
27850- if (0 != rewrite_rule_buffer_append(s->rewrite,
27851- ((data_string *)(da->value->data[j]))->key,
27852- ((data_string *)(da->value->data[j]))->value,
27853- once)) {
27854+
27855+ if (0 != pcre_keyvalue_buffer_append(s->rewrite,
27856+ ((data_string *)(da->value->data[j]))->key->ptr,
27857+ ((data_string *)(da->value->data[j]))->value->ptr)) {
27858 #ifdef HAVE_PCRE_H
27859- log_error_write(srv, __FILE__, __LINE__, "sb",
27860+ log_error_write(srv, __FILE__, __LINE__, "sb",
27861 "pcre-compile failed for", da->value->data[j]->key);
27862 #else
27863- log_error_write(srv, __FILE__, __LINE__, "s",
27864+ log_error_write(srv, __FILE__, __LINE__, "s",
27865 "pcre support is missing, please install libpcre and the headers");
27866 #endif
27867 }
27868+
27869+ if (once) {
27870+ buffer_append_string_len(s->once, CONST_STR_LEN("1"));
27871+ } else {
27872+ buffer_append_string_len(s->once, CONST_STR_LEN("0"));
27873+ }
27874 }
27875 }
27876-
27877+
27878 return 0;
27879 }
27880
27881 SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
27882 plugin_data *p = p_d;
27883 size_t i = 0;
27884-
27885- config_values_t cv[] = {
27886+
27887+ config_values_t cv[] = {
27888 { "url.rewrite-repeat", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27889 { "url.rewrite-once", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
27890-
27891- /* old names, still supported
27892- *
27893+
27894+ /* old names, still supported
27895+ *
27896 * url.rewrite remapped to url.rewrite-once
27897 * url.rewrite-final is url.rewrite-once
27898- *
27899+ *
27900 */
27901 { "url.rewrite", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
27902 { "url.rewrite-final", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
27903 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27904 };
27905-
27906+
27907 if (!p) return HANDLER_ERROR;
27908-
27909+
27910 /* 0 */
27911 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27912-
27913+
27914 for (i = 0; i < srv->config_context->used; i++) {
27915 plugin_config *s;
27916 array *ca;
27917-
27918+
27919 s = calloc(1, sizeof(plugin_config));
27920- s->rewrite = rewrite_rule_buffer_init();
27921-
27922- cv[0].destination = s->rewrite;
27923- cv[1].destination = s->rewrite;
27924- cv[2].destination = s->rewrite;
27925-
27926+ s->rewrite = pcre_keyvalue_buffer_init();
27927+ s->once = buffer_init();
27928+
27929 p->config_storage[i] = s;
27930 ca = ((data_config *)srv->config_context->data[i])->value;
27931-
27932+
27933 if (0 != config_insert_values_global(srv, ca, cv)) {
27934 return HANDLER_ERROR;
27935 }
27936-
27937+
27938 parse_config_entry(srv, s, ca, "url.rewrite-once", 1);
27939 parse_config_entry(srv, s, ca, "url.rewrite-final", 1);
27940 parse_config_entry(srv, s, ca, "url.rewrite", 1);
27941 parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
27942 }
27943-
27944+
27945 return HANDLER_GO_ON;
27946 }
27947 #ifdef HAVE_PCRE_H
27948@@ -271,157 +184,107 @@
27949 size_t i, j;
27950 plugin_config *s = p->config_storage[0];
27951 p->conf.rewrite = s->rewrite;
27952-
27953+ p->conf.once = s->once;
27954+
27955 /* skip the first, the global context */
27956 for (i = 1; i < srv->config_context->used; i++) {
27957 data_config *dc = (data_config *)srv->config_context->data[i];
27958 s = p->config_storage[i];
27959-
27960+
27961 if (COMP_HTTP_URL == dc->comp) continue;
27962-
27963+
27964 /* condition didn't match */
27965 if (!config_check_cond(srv, con, dc)) continue;
27966-
27967+
27968 /* merge config */
27969 for (j = 0; j < dc->value->used; j++) {
27970 data_unset *du = dc->value->data[j];
27971-
27972+
27973 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
27974 p->conf.rewrite = s->rewrite;
27975+ p->conf.once = s->once;
27976 p->conf.context = dc;
27977 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
27978 p->conf.rewrite = s->rewrite;
27979+ p->conf.once = s->once;
27980 p->conf.context = dc;
27981 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
27982 p->conf.rewrite = s->rewrite;
27983+ p->conf.once = s->once;
27984 p->conf.context = dc;
27985 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
27986 p->conf.rewrite = s->rewrite;
27987+ p->conf.once = s->once;
27988 p->conf.context = dc;
27989 }
27990 }
27991 }
27992-
27993+
27994 return 0;
27995 }
27996 #endif
27997 URIHANDLER_FUNC(mod_rewrite_con_reset) {
27998 plugin_data *p = p_d;
27999-
28000+
28001 UNUSED(srv);
28002-
28003+
28004 if (con->plugin_ctx[p->id]) {
28005 handler_ctx_free(con->plugin_ctx[p->id]);
28006 con->plugin_ctx[p->id] = NULL;
28007 }
28008-
28009+
28010 return HANDLER_GO_ON;
28011 }
28012
28013 URIHANDLER_FUNC(mod_rewrite_uri_handler) {
28014 #ifdef HAVE_PCRE_H
28015 plugin_data *p = p_d;
28016- size_t i;
28017+ int i;
28018 handler_ctx *hctx;
28019
28020- /*
28021+ /*
28022 * REWRITE URL
28023- *
28024+ *
28025 * e.g. rewrite /base/ to /index.php?section=base
28026- *
28027+ *
28028 */
28029-
28030+
28031 if (con->plugin_ctx[p->id]) {
28032 hctx = con->plugin_ctx[p->id];
28033-
28034+
28035 if (hctx->loops++ > 100) {
28036- log_error_write(srv, __FILE__, __LINE__, "s",
28037+ log_error_write(srv, __FILE__, __LINE__, "s",
28038 "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
28039-
28040+
28041 return HANDLER_ERROR;
28042 }
28043-
28044+
28045 if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
28046 }
28047-
28048+
28049 mod_rewrite_patch_connection(srv, con, p);
28050
28051 if (!p->conf.rewrite) return HANDLER_GO_ON;
28052-
28053+
28054 buffer_copy_string_buffer(p->match_buf, con->request.uri);
28055-
28056- for (i = 0; i < p->conf.rewrite->used; i++) {
28057- pcre *match;
28058- const char *pattern;
28059- size_t pattern_len;
28060- int n;
28061- rewrite_rule *rule = p->conf.rewrite->ptr[i];
28062-# define N 10
28063- int ovec[N * 3];
28064-
28065- match = rule->key;
28066- pattern = rule->value->ptr;
28067- pattern_len = rule->value->used - 1;
28068-
28069- if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
28070- if (n != PCRE_ERROR_NOMATCH) {
28071- log_error_write(srv, __FILE__, __LINE__, "sd",
28072- "execution error while matching: ", n);
28073- return HANDLER_ERROR;
28074- }
28075- } else {
28076- const char **list;
28077- size_t start, end;
28078- size_t k;
28079-
28080- /* it matched */
28081- pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
28082-
28083- /* search for $[0-9] */
28084-
28085- buffer_reset(con->request.uri);
28086-
28087- start = 0; end = pattern_len;
28088- for (k = 0; k < pattern_len; k++) {
28089- if ((pattern[k] == '$' || pattern[k] == '%') &&
28090- isdigit((unsigned char)pattern[k + 1])) {
28091- /* got one */
28092-
28093- size_t num = pattern[k + 1] - '0';
28094-
28095- end = k;
28096-
28097- buffer_append_string_len(con->request.uri, pattern + start, end - start);
28098-
28099- if (pattern[k] == '$') {
28100- /* n is always > 0 */
28101- if (num < (size_t)n) {
28102- buffer_append_string(con->request.uri, list[num]);
28103- }
28104- } else {
28105- config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
28106- }
28107-
28108- k++;
28109- start = k + 1;
28110- }
28111- }
28112-
28113- buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
28114-
28115- pcre_free(list);
28116-
28117- hctx = handler_ctx_init();
28118-
28119- con->plugin_ctx[p->id] = hctx;
28120-
28121- if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
28122-
28123- return HANDLER_COMEBACK;
28124- }
28125+ i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
28126+
28127+ if (i >= 0) {
28128+ hctx = handler_ctx_init();
28129+
28130+ con->plugin_ctx[p->id] = hctx;
28131+
28132+ if (p->conf.once->ptr[i] == '1')
28133+ hctx->state = REWRITE_STATE_FINISHED;
28134+
28135+ return HANDLER_COMEBACK;
28136+ }
28137+ else if (i != PCRE_ERROR_NOMATCH) {
28138+ log_error_write(srv, __FILE__, __LINE__, "s",
28139+ "execution error while matching", i);
28140 }
28141 #undef N
28142-
28143+
28144 #else
28145 UNUSED(srv);
28146 UNUSED(con);
28147@@ -434,17 +297,17 @@
28148 int mod_rewrite_plugin_init(plugin *p) {
28149 p->version = LIGHTTPD_VERSION_ID;
28150 p->name = buffer_init_string("rewrite");
28151-
28152+
28153 p->init = mod_rewrite_init;
28154 /* it has to stay _raw as we are matching on uri + querystring
28155 */
28156-
28157+
28158 p->handle_uri_raw = mod_rewrite_uri_handler;
28159 p->set_defaults = mod_rewrite_set_defaults;
28160 p->cleanup = mod_rewrite_free;
28161 p->connection_reset = mod_rewrite_con_reset;
28162-
28163+
28164 p->data = NULL;
28165-
28166+
28167 return 0;
28168 }
1175ccec 28169--- ../lighttpd-1.4.11/src/mod_rrdtool.c 2005-08-22 01:52:24.000000000 +0300
36e2a29e 28170+++ lighttpd-1.4.12/src/mod_rrdtool.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
28171@@ -5,7 +5,6 @@
28172 #include <stdlib.h>
28173 #include <stdio.h>
28174 #include <string.h>
28175-#include <unistd.h>
28176 #include <errno.h>
28177 #include <time.h>
28178
28179@@ -20,10 +19,14 @@
28180 /* no need for waitpid if we don't have fork */
28181 #include <sys/wait.h>
28182 #endif
28183+
28184+#include "sys-files.h"
28185+#include "sys-process.h"
28186+
28187 typedef struct {
28188 buffer *path_rrdtool_bin;
28189 buffer *path_rrd;
28190-
28191+
28192 double requests, *requests_ptr;
28193 double bytes_written, *bytes_written_ptr;
28194 double bytes_read, *bytes_read_ptr;
28195@@ -31,84 +34,84 @@
28196
28197 typedef struct {
28198 PLUGIN_DATA;
28199-
28200+
28201 buffer *cmd;
28202 buffer *resp;
28203-
28204+
28205 int read_fd, write_fd;
28206 pid_t rrdtool_pid;
28207-
28208+
28209 int rrdtool_running;
28210-
28211+
28212 plugin_config **config_storage;
28213 plugin_config conf;
28214 } plugin_data;
28215
28216 INIT_FUNC(mod_rrd_init) {
28217 plugin_data *p;
28218-
28219+
28220 p = calloc(1, sizeof(*p));
28221-
28222+
28223 p->resp = buffer_init();
28224 p->cmd = buffer_init();
28225-
28226+
28227 return p;
28228 }
28229
28230 FREE_FUNC(mod_rrd_free) {
28231 plugin_data *p = p_d;
28232 size_t i;
28233-
28234+
28235 if (!p) return HANDLER_GO_ON;
28236-
28237+
28238 if (p->config_storage) {
28239 for (i = 0; i < srv->config_context->used; i++) {
28240 plugin_config *s = p->config_storage[i];
28241-
28242+
28243 buffer_free(s->path_rrdtool_bin);
28244 buffer_free(s->path_rrd);
28245-
28246+
28247 free(s);
28248 }
28249 }
28250 buffer_free(p->cmd);
28251 buffer_free(p->resp);
28252-
28253+
28254 free(p->config_storage);
28255-
28256+
28257 if (p->rrdtool_pid) {
28258 int status;
28259 close(p->read_fd);
28260 close(p->write_fd);
28261-#ifdef HAVE_FORK
28262+#ifdef HAVE_FORK
28263 /* collect status */
28264 waitpid(p->rrdtool_pid, &status, 0);
28265 #endif
28266 }
28267-
28268+
28269 free(p);
28270-
28271+
28272 return HANDLER_GO_ON;
28273 }
28274
28275 int mod_rrd_create_pipe(server *srv, plugin_data *p) {
28276 pid_t pid;
28277-
28278+
28279 int to_rrdtool_fds[2];
28280 int from_rrdtool_fds[2];
28281-#ifdef HAVE_FORK
28282+#ifdef HAVE_FORK
28283 if (pipe(to_rrdtool_fds)) {
28284- log_error_write(srv, __FILE__, __LINE__, "ss",
28285+ log_error_write(srv, __FILE__, __LINE__, "ss",
28286 "pipe failed: ", strerror(errno));
28287 return -1;
28288 }
28289-
28290+
28291 if (pipe(from_rrdtool_fds)) {
28292- log_error_write(srv, __FILE__, __LINE__, "ss",
28293+ log_error_write(srv, __FILE__, __LINE__, "ss",
28294 "pipe failed: ", strerror(errno));
28295 return -1;
28296 }
28297-
28298+
28299 /* fork, execve */
28300 switch (pid = fork()) {
28301 case 0: {
28302@@ -117,33 +120,33 @@
28303 int argc;
28304 int i = 0;
28305 char *dash = "-";
28306-
28307+
28308 /* move stdout to from_rrdtool_fd[1] */
28309 close(STDOUT_FILENO);
28310 dup2(from_rrdtool_fds[1], STDOUT_FILENO);
28311 close(from_rrdtool_fds[1]);
28312 /* not needed */
28313 close(from_rrdtool_fds[0]);
28314-
28315+
28316 /* move the stdin to to_rrdtool_fd[0] */
28317 close(STDIN_FILENO);
28318 dup2(to_rrdtool_fds[0], STDIN_FILENO);
28319 close(to_rrdtool_fds[0]);
28320 /* not needed */
28321 close(to_rrdtool_fds[1]);
28322-
28323+
28324 close(STDERR_FILENO);
28325-
28326+
28327 if (srv->errorlog_mode == ERRORLOG_FILE) {
28328 dup2(srv->errorlog_fd, STDERR_FILENO);
28329 close(srv->errorlog_fd);
28330 }
28331-
28332+
28333 /* set up args */
28334 argc = 3;
28335 args = malloc(sizeof(*args) * argc);
28336 i = 0;
28337-
28338+
28339 args[i++] = p->conf.path_rrdtool_bin->ptr;
28340 args[i++] = dash;
28341 args[i++] = NULL;
28342@@ -152,12 +155,12 @@
28343 for (i = 3; i < 256; i++) {
28344 close(i);
28345 }
28346-
28347+
28348 /* exec the cgi */
28349 execv(args[0], args);
28350-
28351+
28352 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
28353-
28354+
28355 /* */
28356 SEGFAULT();
28357 break;
28358@@ -168,19 +171,19 @@
28359 break;
28360 default: {
28361 /* father */
28362-
28363+
28364 close(from_rrdtool_fds[1]);
28365 close(to_rrdtool_fds[0]);
28366-
28367+
28368 /* register PID and wait for them asyncronously */
28369 p->write_fd = to_rrdtool_fds[1];
28370 p->read_fd = from_rrdtool_fds[0];
28371 p->rrdtool_pid = pid;
28372-
28373+
28374 break;
28375 }
28376 }
28377-
28378+
28379 return 0;
28380 #else
28381 return -1;
28382@@ -189,19 +192,19 @@
28383
28384 static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
28385 struct stat st;
28386-
28387+
28388 /* check if DB already exists */
28389 if (0 == stat(s->path_rrd->ptr, &st)) {
28390 /* check if it is plain file */
28391 if (!S_ISREG(st.st_mode)) {
28392- log_error_write(srv, __FILE__, __LINE__, "sb",
28393+ log_error_write(srv, __FILE__, __LINE__, "sb",
28394 "not a regular file:", s->path_rrd);
28395 return HANDLER_ERROR;
28396 }
28397 } else {
28398 int r ;
28399 /* create a new one */
28400-
28401+
28402 BUFFER_COPY_STRING_CONST(p->cmd, "create ");
28403 buffer_append_string_buffer(p->cmd, s->path_rrd);
28404 buffer_append_string(p->cmd, " --step 60 ");
28405@@ -220,158 +223,155 @@
28406 buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
28407 buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
28408 buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
28409-
28410+
28411 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28412- log_error_write(srv, __FILE__, __LINE__, "ss",
28413+ log_error_write(srv, __FILE__, __LINE__, "ss",
28414 "rrdtool-write: failed", strerror(errno));
28415-
28416+
28417 return HANDLER_ERROR;
28418 }
28419-
28420+
28421 buffer_prepare_copy(p->resp, 4096);
28422 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28423- log_error_write(srv, __FILE__, __LINE__, "ss",
28424+ log_error_write(srv, __FILE__, __LINE__, "ss",
28425 "rrdtool-read: failed", strerror(errno));
28426-
28427+
28428 return HANDLER_ERROR;
28429 }
28430-
28431+
28432 p->resp->used = r;
28433-
28434+
28435 if (p->resp->ptr[0] != 'O' ||
28436 p->resp->ptr[1] != 'K') {
28437- log_error_write(srv, __FILE__, __LINE__, "sbb",
28438+ log_error_write(srv, __FILE__, __LINE__, "sbb",
28439 "rrdtool-response:", p->cmd, p->resp);
28440-
28441+
28442 return HANDLER_ERROR;
28443 }
28444 }
28445-
28446+
28447 return HANDLER_GO_ON;
28448 }
28449
28450-#define PATCH(x) \
28451- p->conf.x = s->x;
28452 static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
28453 size_t i, j;
28454 plugin_config *s = p->config_storage[0];
28455-
28456- PATCH(path_rrdtool_bin);
28457- PATCH(path_rrd);
28458-
28459+
28460+ PATCH_OPTION(path_rrdtool_bin);
28461+ PATCH_OPTION(path_rrd);
28462+
28463 p->conf.bytes_written_ptr = &(s->bytes_written);
28464 p->conf.bytes_read_ptr = &(s->bytes_read);
28465 p->conf.requests_ptr = &(s->requests);
28466-
28467+
28468 /* skip the first, the global context */
28469 for (i = 1; i < srv->config_context->used; i++) {
28470 data_config *dc = (data_config *)srv->config_context->data[i];
28471 s = p->config_storage[i];
28472-
28473+
28474 /* condition didn't match */
28475 if (!config_check_cond(srv, con, dc)) continue;
28476-
28477+
28478 /* merge config */
28479 for (j = 0; j < dc->value->used; j++) {
28480 data_unset *du = dc->value->data[j];
28481-
28482+
28483 if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
28484- PATCH(path_rrd);
28485+ PATCH_OPTION(path_rrd);
28486 /* get pointers to double values */
28487-
28488+
28489 p->conf.bytes_written_ptr = &(s->bytes_written);
28490 p->conf.bytes_read_ptr = &(s->bytes_read);
28491 p->conf.requests_ptr = &(s->requests);
28492 }
28493 }
28494 }
28495-
28496+
28497 return 0;
28498 }
28499-#undef PATCH
28500
28501 SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
28502 plugin_data *p = p_d;
28503 size_t i;
28504-
28505- config_values_t cv[] = {
28506+
28507+ config_values_t cv[] = {
28508 { "rrdtool.binary", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
28509 { "rrdtool.db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
28510 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
28511 };
28512-
28513+
28514 if (!p) return HANDLER_ERROR;
28515-
28516+
28517 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28518-
28519+
28520 for (i = 0; i < srv->config_context->used; i++) {
28521 plugin_config *s;
28522-
28523+
28524 s = calloc(1, sizeof(plugin_config));
28525 s->path_rrdtool_bin = buffer_init();
28526 s->path_rrd = buffer_init();
28527 s->requests = 0;
28528 s->bytes_written = 0;
28529 s->bytes_read = 0;
28530-
28531+
28532 cv[0].destination = s->path_rrdtool_bin;
28533 cv[1].destination = s->path_rrd;
28534-
28535+
28536 p->config_storage[i] = s;
28537-
28538+
28539 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
28540 return HANDLER_ERROR;
28541 }
28542-
28543+
28544 if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
28545 /* path_rrdtool_bin is a global option */
28546-
28547- log_error_write(srv, __FILE__, __LINE__, "s",
28548+
28549+ log_error_write(srv, __FILE__, __LINE__, "s",
28550 "rrdtool.binary can only be set as a global option.");
28551-
28552+
28553 return HANDLER_ERROR;
28554 }
28555-
28556+
28557 }
28558-
28559+
28560 p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
28561 p->rrdtool_running = 0;
28562-
28563+
28564 /* check for dir */
28565-
28566+
28567 if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
28568- log_error_write(srv, __FILE__, __LINE__, "s",
28569+ log_error_write(srv, __FILE__, __LINE__, "s",
28570 "rrdtool.binary has to be set");
28571 return HANDLER_ERROR;
28572 }
28573-
28574+
28575 /* open the pipe to rrdtool */
28576 if (mod_rrd_create_pipe(srv, p)) {
28577 return HANDLER_ERROR;
28578 }
28579-
28580+
28581 p->rrdtool_running = 1;
28582-
28583+
28584 return HANDLER_GO_ON;
28585 }
28586
28587 TRIGGER_FUNC(mod_rrd_trigger) {
28588 plugin_data *p = p_d;
28589 size_t i;
28590-
28591+
28592 if (!p->rrdtool_running) return HANDLER_GO_ON;
28593 if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
28594-
28595+
28596 for (i = 0; i < srv->config_context->used; i++) {
28597 plugin_config *s = p->config_storage[i];
28598 int r;
28599-
28600+
28601 if (buffer_is_empty(s->path_rrd)) continue;
28602-
28603+
28604 /* write the data down every minute */
28605-
28606+
28607 if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
28608-
28609+
28610 BUFFER_COPY_STRING_CONST(p->cmd, "update ");
28611 buffer_append_string_buffer(p->cmd, s->path_rrd);
28612 BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
28613@@ -381,69 +381,69 @@
28614 BUFFER_APPEND_STRING_CONST(p->cmd, ":");
28615 buffer_append_long(p->cmd, s->requests);
28616 BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
28617-
28618+
28619 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28620 p->rrdtool_running = 0;
28621-
28622- log_error_write(srv, __FILE__, __LINE__, "ss",
28623+
28624+ log_error_write(srv, __FILE__, __LINE__, "ss",
28625 "rrdtool-write: failed", strerror(errno));
28626-
28627+
28628 return HANDLER_ERROR;
28629 }
28630-
28631+
28632 buffer_prepare_copy(p->resp, 4096);
28633 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28634 p->rrdtool_running = 0;
28635-
28636- log_error_write(srv, __FILE__, __LINE__, "ss",
28637+
28638+ log_error_write(srv, __FILE__, __LINE__, "ss",
28639 "rrdtool-read: failed", strerror(errno));
28640-
28641+
28642 return HANDLER_ERROR;
28643 }
28644-
28645+
28646 p->resp->used = r;
28647-
28648+
28649 if (p->resp->ptr[0] != 'O' ||
28650 p->resp->ptr[1] != 'K') {
28651 p->rrdtool_running = 0;
28652-
28653- log_error_write(srv, __FILE__, __LINE__, "sbb",
28654+
28655+ log_error_write(srv, __FILE__, __LINE__, "sbb",
28656 "rrdtool-response:", p->cmd, p->resp);
28657-
28658+
28659 return HANDLER_ERROR;
28660 }
28661 s->requests = 0;
28662 s->bytes_written = 0;
28663 s->bytes_read = 0;
28664 }
28665-
28666+
28667 return HANDLER_GO_ON;
28668 }
28669
28670 REQUESTDONE_FUNC(mod_rrd_account) {
28671 plugin_data *p = p_d;
28672-
28673+
28674 mod_rrd_patch_connection(srv, con, p);
28675-
28676+
28677 *(p->conf.requests_ptr) += 1;
28678 *(p->conf.bytes_written_ptr) += con->bytes_written;
28679 *(p->conf.bytes_read_ptr) += con->bytes_read;
28680-
28681+
28682 return HANDLER_GO_ON;
28683 }
28684
28685 int mod_rrdtool_plugin_init(plugin *p) {
28686 p->version = LIGHTTPD_VERSION_ID;
28687 p->name = buffer_init_string("rrd");
28688-
28689+
28690 p->init = mod_rrd_init;
28691 p->cleanup = mod_rrd_free;
28692 p->set_defaults= mod_rrd_set_defaults;
28693-
28694+
28695 p->handle_trigger = mod_rrd_trigger;
28696 p->handle_request_done = mod_rrd_account;
28697-
28698+
28699 p->data = NULL;
28700-
28701+
28702 return 0;
28703 }
1175ccec 28704--- ../lighttpd-1.4.11/src/mod_scgi.c 2006-03-04 17:15:26.000000000 +0200
36e2a29e 28705+++ lighttpd-1.4.12/src/mod_scgi.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
28706@@ -1,5 +1,4 @@
28707 #include <sys/types.h>
28708-#include <unistd.h>
28709 #include <errno.h>
28710 #include <fcntl.h>
28711 #include <string.h>
28712@@ -30,7 +29,9 @@
28713 #endif
28714
28715 #include "sys-socket.h"
28716-
28717+#include "sys-files.h"
28718+#include "sys-strings.h"
28719+#include "sys-process.h"
28720
28721 #ifndef UNIX_PATH_MAX
28722 # define UNIX_PATH_MAX 108
28723@@ -46,30 +47,29 @@
28724 enum {EOL_UNSET, EOL_N, EOL_RN};
28725
28726 /*
28727- *
28728+ *
28729 * TODO:
28730- *
28731+ *
28732 * - add timeout for a connect to a non-scgi process
28733 * (use state_timestamp + state)
28734- *
28735+ *
28736 */
28737
28738 typedef struct scgi_proc {
28739 size_t id; /* id will be between 1 and max_procs */
28740 buffer *socket; /* config.socket + "-" + id */
28741 unsigned port; /* config.port + pno */
28742-
28743- pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
28744
28745+ pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
28746
28747 size_t load; /* number of requests waiting on this process */
28748
28749 time_t last_used; /* see idle_timeout */
28750 size_t requests; /* see max_requests */
28751 struct scgi_proc *prev, *next; /* see first */
28752-
28753+
28754 time_t disable_ts; /* replace by host->something */
28755-
28756+
28757 int is_local;
28758
28759 enum { PROC_STATE_UNSET, /* init-phase */
28760@@ -78,7 +78,7 @@
28761 PROC_STATE_KILLED, /* was killed as we don't have the load anymore */
28762 PROC_STATE_DIED, /* marked as dead, should be restarted */
28763 PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
28764- } state;
28765+ } state;
28766 } scgi_proc;
28767
28768 typedef struct {
28769@@ -86,20 +86,20 @@
28770 * sorted by lowest load
28771 *
28772 * whenever a job is done move it up in the list
28773- * until it is sorted, move it down as soon as the
28774+ * until it is sorted, move it down as soon as the
28775 * job is started
28776 */
28777- scgi_proc *first;
28778- scgi_proc *unused_procs;
28779+ scgi_proc *first;
28780+ scgi_proc *unused_procs;
28781
28782- /*
28783+ /*
28784 * spawn at least min_procs, at max_procs.
28785 *
28786- * as soon as the load of the first entry
28787+ * as soon as the load of the first entry
28788 * is max_load_per_proc we spawn a new one
28789- * and add it to the first entry and give it
28790+ * and add it to the first entry and give it
28791 * the load
28792- *
28793+ *
28794 */
28795
28796 unsigned short min_procs;
28797@@ -111,44 +111,44 @@
28798
28799 /*
28800 * kick the process from the list if it was not
28801- * used for idle_timeout until min_procs is
28802+ * used for idle_timeout until min_procs is
28803 * reached. this helps to get the processlist
28804 * small again we had a small peak load.
28805 *
28806 */
28807-
28808+
28809 unsigned short idle_timeout;
28810-
28811+
28812 /*
28813 * time after a disabled remote connection is tried to be re-enabled
28814- *
28815- *
28816+ *
28817+ *
28818 */
28819-
28820+
28821 unsigned short disable_time;
28822
28823 /*
28824 * same scgi processes get a little bit larger
28825- * than wanted. max_requests_per_proc kills a
28826+ * than wanted. max_requests_per_proc kills a
28827 * process after a number of handled requests.
28828 *
28829 */
28830 size_t max_requests_per_proc;
28831-
28832+
28833
28834 /* config */
28835
28836- /*
28837- * host:port
28838+ /*
28839+ * host:port
28840 *
28841- * if host is one of the local IP adresses the
28842+ * if host is one of the local IP adresses the
28843 * whole connection is local
28844 *
28845 * if tcp/ip should be used host AND port have
28846- * to be specified
28847- *
28848- */
28849- buffer *host;
28850+ * to be specified
28851+ *
28852+ */
28853+ buffer *host;
28854 unsigned short port;
28855
28856 /*
28857@@ -161,7 +161,7 @@
28858 */
28859 buffer *unixsocket;
28860
28861- /* if socket is local we can start the scgi
28862+ /* if socket is local we can start the scgi
28863 * process ourself
28864 *
28865 * bin-path is the path to the binary
28866@@ -169,19 +169,19 @@
28867 * check min_procs and max_procs for the number
28868 * of process to start-up
28869 */
28870- buffer *bin_path;
28871-
28872- /* bin-path is set bin-environment is taken to
28873+ buffer *bin_path;
28874+
28875+ /* bin-path is set bin-environment is taken to
28876 * create the environement before starting the
28877 * FastCGI process
28878- *
28879+ *
28880 */
28881 array *bin_env;
28882-
28883+
28884 array *bin_env_copy;
28885-
28886+
28887 /*
28888- * docroot-translation between URL->phys and the
28889+ * docroot-translation between URL->phys and the
28890 * remote host
28891 *
28892 * reasons:
28893@@ -192,7 +192,7 @@
28894 buffer *docroot;
28895
28896 /*
28897- * check_local tell you if the phys file is stat()ed
28898+ * check_local tell you if the phys file is stat()ed
28899 * or not. FastCGI doesn't care if the service is
28900 * remote. If the web-server side doesn't contain
28901 * the scgi-files we should not stat() for them
28902@@ -202,33 +202,33 @@
28903
28904 /*
28905 * append PATH_INFO to SCRIPT_FILENAME
28906- *
28907+ *
28908 * php needs this if cgi.fix_pathinfo is provied
28909- *
28910+ *
28911 */
28912-
28913+
28914 ssize_t load; /* replace by host->load */
28915
28916 size_t max_id; /* corresponds most of the time to
28917 num_procs.
28918-
28919+
28920 only if a process is killed max_id waits for the process itself
28921 to die and decrements its afterwards */
28922 } scgi_extension_host;
28923
28924 /*
28925 * one extension can have multiple hosts assigned
28926- * one host can spawn additional processes on the same
28927+ * one host can spawn additional processes on the same
28928 * socket (if we control it)
28929 *
28930 * ext -> host -> procs
28931 * 1:n 1:n
28932 *
28933- * if the scgi process is remote that whole goes down
28934+ * if the scgi process is remote that whole goes down
28935 * to
28936 *
28937 * ext -> host -> procs
28938- * 1:n 1:1
28939+ * 1:n 1:1
28940 *
28941 * in case of PHP and FCGI_CHILDREN we have again a procs
28942 * but we don't control it directly.
28943@@ -239,7 +239,7 @@
28944 buffer *key; /* like .php */
28945
28946 scgi_extension_host **hosts;
28947-
28948+
28949 size_t used;
28950 size_t size;
28951 } scgi_extension;
28952@@ -253,14 +253,14 @@
28953
28954
28955 typedef struct {
28956- scgi_exts *exts;
28957-
28958+ scgi_exts *exts;
28959+
28960 int debug;
28961 } plugin_config;
28962
28963 typedef struct {
28964 char **ptr;
28965-
28966+
28967 size_t size;
28968 size_t used;
28969 } char_array;
28970@@ -268,52 +268,51 @@
28971 /* generic plugin data, shared between all connections */
28972 typedef struct {
28973 PLUGIN_DATA;
28974-
28975+
28976 buffer *scgi_env;
28977-
28978+
28979 buffer *path;
28980 buffer *parse_response;
28981-
28982+
28983 plugin_config **config_storage;
28984-
28985+
28986 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
28987 } plugin_data;
28988
28989 /* connection specific data */
28990-typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
28991- FCGI_STATE_WRITE, FCGI_STATE_READ
28992+typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
28993+ FCGI_STATE_WRITE, FCGI_STATE_READ
28994 } scgi_connection_state_t;
28995
28996 typedef struct {
28997- buffer *response;
28998+ buffer *response;
28999 size_t response_len;
29000 int response_type;
29001 int response_padding;
29002-
29003+
29004 scgi_proc *proc;
29005 scgi_extension_host *host;
29006-
29007+
29008 scgi_connection_state_t state;
29009 time_t state_timestamp;
29010-
29011+
29012 int reconnects; /* number of reconnect attempts */
29013-
29014+
29015 read_buffer *rb;
29016 chunkqueue *wb;
29017-
29018+
29019 buffer *response_header;
29020-
29021+
29022 int delayed; /* flag to mark that the connect() is delayed */
29023-
29024+
29025 size_t request_id;
29026 int fd; /* fd to the scgi process */
29027 int fde_ndx; /* index into the fd-event buffer */
29028-
29029 pid_t pid;
29030 int got_proc;
29031-
29032+
29033 plugin_config conf;
29034-
29035+
29036 connection *remote_conn; /* dumb pointer */
29037 plugin_data *plugin_data; /* dumb pointer */
29038 } handler_ctx;
29039@@ -328,28 +327,28 @@
29040
29041 static handler_ctx * handler_ctx_init() {
29042 handler_ctx * hctx;
29043-
29044+
29045 hctx = calloc(1, sizeof(*hctx));
29046 assert(hctx);
29047-
29048+
29049 hctx->fde_ndx = -1;
29050-
29051+
29052 hctx->response = buffer_init();
29053 hctx->response_header = buffer_init();
29054-
29055+
29056 hctx->request_id = 0;
29057 hctx->state = FCGI_STATE_INIT;
29058 hctx->proc = NULL;
29059-
29060+
29061 hctx->response_len = 0;
29062 hctx->response_type = 0;
29063 hctx->response_padding = 0;
29064 hctx->fd = -1;
29065-
29066+
29067 hctx->reconnects = 0;
29068
29069 hctx->wb = chunkqueue_init();
29070-
29071+
29072 return hctx;
29073 }
29074
29075@@ -358,12 +357,12 @@
29076 buffer_free(hctx->response_header);
29077
29078 chunkqueue_free(hctx->wb);
29079-
29080+
29081 if (hctx->rb) {
29082 if (hctx->rb->ptr) free(hctx->rb->ptr);
29083 free(hctx->rb);
29084 }
29085-
29086+
29087 free(hctx);
29088 }
29089
29090@@ -372,20 +371,20 @@
29091
29092 f = calloc(1, sizeof(*f));
29093 f->socket = buffer_init();
29094-
29095+
29096 f->prev = NULL;
29097 f->next = NULL;
29098-
29099+
29100 return f;
29101 }
29102
29103 void scgi_process_free(scgi_proc *f) {
29104 if (!f) return;
29105-
29106+
29107 scgi_process_free(f->next);
29108-
29109+
29110 buffer_free(f->socket);
29111-
29112+
29113 free(f);
29114 }
29115
29116@@ -400,62 +399,62 @@
29117 f->bin_path = buffer_init();
29118 f->bin_env = array_init();
29119 f->bin_env_copy = array_init();
29120-
29121+
29122 return f;
29123 }
29124
29125 void scgi_host_free(scgi_extension_host *h) {
29126 if (!h) return;
29127-
29128+
29129 buffer_free(h->host);
29130 buffer_free(h->unixsocket);
29131 buffer_free(h->docroot);
29132 buffer_free(h->bin_path);
29133 array_free(h->bin_env);
29134 array_free(h->bin_env_copy);
29135-
29136+
29137 scgi_process_free(h->first);
29138 scgi_process_free(h->unused_procs);
29139-
29140+
29141 free(h);
29142-
29143+
29144 }
29145
29146 scgi_exts *scgi_extensions_init() {
29147 scgi_exts *f;
29148
29149 f = calloc(1, sizeof(*f));
29150-
29151+
29152 return f;
29153 }
29154
29155 void scgi_extensions_free(scgi_exts *f) {
29156 size_t i;
29157-
29158+
29159 if (!f) return;
29160-
29161+
29162 for (i = 0; i < f->used; i++) {
29163 scgi_extension *fe;
29164 size_t j;
29165-
29166+
29167 fe = f->exts[i];
29168-
29169+
29170 for (j = 0; j < fe->used; j++) {
29171 scgi_extension_host *h;
29172-
29173+
29174 h = fe->hosts[j];
29175-
29176+
29177 scgi_host_free(h);
29178 }
29179-
29180+
29181 buffer_free(fe->key);
29182 free(fe->hosts);
29183-
29184+
29185 free(fe);
29186 }
29187-
29188+
29189 free(f->exts);
29190-
29191+
29192 free(f);
29193 }
29194
29195@@ -504,99 +503,103 @@
29196 assert(fe->hosts);
29197 }
29198
29199- fe->hosts[fe->used++] = fh;
29200+ fe->hosts[fe->used++] = fh;
29201
29202 return 0;
29203-
29204+
29205 }
29206
29207 INIT_FUNC(mod_scgi_init) {
29208 plugin_data *p;
29209-
29210+
29211 p = calloc(1, sizeof(*p));
29212-
29213+
29214 p->scgi_env = buffer_init();
29215-
29216+
29217 p->path = buffer_init();
29218 p->parse_response = buffer_init();
29219-
29220+
29221 return p;
29222 }
29223
29224
29225 FREE_FUNC(mod_scgi_free) {
29226 plugin_data *p = p_d;
29227-
29228+
29229 UNUSED(srv);
29230
29231 buffer_free(p->scgi_env);
29232 buffer_free(p->path);
29233 buffer_free(p->parse_response);
29234-
29235+
29236 if (p->config_storage) {
29237 size_t i, j, n;
29238 for (i = 0; i < srv->config_context->used; i++) {
29239 plugin_config *s = p->config_storage[i];
29240 scgi_exts *exts;
29241-
29242+
29243 if (!s) continue;
29244-
29245+
29246 exts = s->exts;
29247
29248 for (j = 0; j < exts->used; j++) {
29249 scgi_extension *ex;
29250-
29251+
29252 ex = exts->exts[j];
29253-
29254+
29255 for (n = 0; n < ex->used; n++) {
29256 scgi_proc *proc;
29257 scgi_extension_host *host;
29258-
29259+
29260 host = ex->hosts[n];
29261-
29262+
29263 for (proc = host->first; proc; proc = proc->next) {
29264+#ifndef _WIN32
29265 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29266-
29267- if (proc->is_local &&
29268+#endif
29269+
29270+ if (proc->is_local &&
29271 !buffer_is_empty(proc->socket)) {
29272 unlink(proc->socket->ptr);
29273 }
29274 }
29275-
29276+
29277 for (proc = host->unused_procs; proc; proc = proc->next) {
29278+#ifndef _WIN32
29279 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29280-
29281- if (proc->is_local &&
29282+#endif
29283+
29284+ if (proc->is_local &&
29285 !buffer_is_empty(proc->socket)) {
29286 unlink(proc->socket->ptr);
29287 }
29288 }
29289 }
29290 }
29291-
29292+
29293 scgi_extensions_free(s->exts);
29294-
29295+
29296 free(s);
29297 }
29298 free(p->config_storage);
29299 }
29300-
29301+
29302 free(p);
29303-
29304+
29305 return HANDLER_GO_ON;
29306 }
29307
29308 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
29309 char *dst;
29310-
29311+
29312 if (!key || !val) return -1;
29313-
29314+
29315 dst = malloc(key_len + val_len + 3);
29316 memcpy(dst, key, key_len);
29317 dst[key_len] = '=';
29318 /* add the \0 from the value */
29319 memcpy(dst + key_len + 1, val, val_len + 1);
29320-
29321+
29322 if (env->size == 0) {
29323 env->size = 16;
29324 env->ptr = malloc(env->size * sizeof(*env->ptr));
29325@@ -604,13 +607,13 @@
29326 env->size += 16;
29327 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
29328 }
29329-
29330+
29331 env->ptr[env->used++] = dst;
29332-
29333+
29334 return 0;
29335 }
29336
29337-static int scgi_spawn_connection(server *srv,
29338+static int scgi_spawn_connection(server *srv,
29339 plugin_data *p,
29340 scgi_extension_host *host,
29341 scgi_proc *proc) {
29342@@ -622,31 +625,27 @@
29343 #endif
29344 struct sockaddr_in scgi_addr_in;
29345 struct sockaddr *scgi_addr;
29346-
29347+
29348 socklen_t servlen;
29349-
29350+
29351 #ifndef HAVE_FORK
29352 return -1;
29353 #endif
29354-
29355+
29356 if (p->conf.debug) {
29357 log_error_write(srv, __FILE__, __LINE__, "sdb",
29358 "new proc, socket:", proc->port, proc->socket);
29359 }
29360-
29361+
29362 if (!buffer_is_empty(proc->socket)) {
29363 memset(&scgi_addr, 0, sizeof(scgi_addr));
29364-
29365+
29366 #ifdef HAVE_SYS_UN_H
29367 scgi_addr_un.sun_family = AF_UNIX;
29368 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
29369-
29370-#ifdef SUN_LEN
29371+
29372 servlen = SUN_LEN(&scgi_addr_un);
29373-#else
29374- /* stevens says: */
29375- servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
29376-#endif
29377+
29378 socket_type = AF_UNIX;
29379 scgi_addr = (struct sockaddr *) &scgi_addr_un;
29380 #else
29381@@ -656,115 +655,115 @@
29382 #endif
29383 } else {
29384 scgi_addr_in.sin_family = AF_INET;
29385-
29386+
29387 if (buffer_is_empty(host->host)) {
29388 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29389 } else {
29390 struct hostent *he;
29391-
29392+
29393 /* set a usefull default */
29394 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29395-
29396-
29397+
29398+
29399 if (NULL == (he = gethostbyname(host->host->ptr))) {
29400- log_error_write(srv, __FILE__, __LINE__,
29401- "sdb", "gethostbyname failed: ",
29402+ log_error_write(srv, __FILE__, __LINE__,
29403+ "sdb", "gethostbyname failed: ",
29404 h_errno, host->host);
29405 return -1;
29406 }
29407-
29408+
29409 if (he->h_addrtype != AF_INET) {
29410 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
29411 return -1;
29412 }
29413-
29414+
29415 if (he->h_length != sizeof(struct in_addr)) {
29416 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
29417 return -1;
29418 }
29419-
29420+
29421 memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
29422-
29423+
29424 }
29425 scgi_addr_in.sin_port = htons(proc->port);
29426 servlen = sizeof(scgi_addr_in);
29427-
29428+
29429 socket_type = AF_INET;
29430 scgi_addr = (struct sockaddr *) &scgi_addr_in;
29431 }
29432-
29433+
29434 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29435- log_error_write(srv, __FILE__, __LINE__, "ss",
29436+ log_error_write(srv, __FILE__, __LINE__, "ss",
29437 "failed:", strerror(errno));
29438 return -1;
29439 }
29440-
29441+
29442 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
29443 /* server is not up, spawn in */
29444 pid_t child;
29445 int val;
29446-
29447+
29448 if (!buffer_is_empty(proc->socket)) {
29449 unlink(proc->socket->ptr);
29450 }
29451-
29452+
29453 close(scgi_fd);
29454-
29455+
29456 /* reopen socket */
29457 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29458- log_error_write(srv, __FILE__, __LINE__, "ss",
29459+ log_error_write(srv, __FILE__, __LINE__, "ss",
29460 "socket failed:", strerror(errno));
29461 return -1;
29462 }
29463-
29464+
29465 val = 1;
29466 if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
29467- log_error_write(srv, __FILE__, __LINE__, "ss",
29468+ log_error_write(srv, __FILE__, __LINE__, "ss",
29469 "socketsockopt failed:", strerror(errno));
29470 return -1;
29471 }
29472-
29473+
29474 /* create socket */
29475 if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
29476- log_error_write(srv, __FILE__, __LINE__, "sbds",
29477- "bind failed for:",
29478- proc->socket,
29479- proc->port,
29480+ log_error_write(srv, __FILE__, __LINE__, "sbds",
29481+ "bind failed for:",
29482+ proc->socket,
29483+ proc->port,
29484 strerror(errno));
29485 return -1;
29486 }
29487-
29488+
29489 if (-1 == listen(scgi_fd, 1024)) {
29490- log_error_write(srv, __FILE__, __LINE__, "ss",
29491+ log_error_write(srv, __FILE__, __LINE__, "ss",
29492 "listen failed:", strerror(errno));
29493 return -1;
29494 }
29495-
29496-#ifdef HAVE_FORK
29497+
29498+#ifdef HAVE_FORK
29499 switch ((child = fork())) {
29500 case 0: {
29501 buffer *b;
29502 size_t i = 0;
29503 int fd = 0;
29504 char_array env;
29505-
29506-
29507+
29508+
29509 /* create environment */
29510 env.ptr = NULL;
29511 env.size = 0;
29512 env.used = 0;
29513-
29514+
29515 /* we don't need the client socket */
29516 for (fd = 3; fd < 256; fd++) {
29517 if (fd != 2 && fd != scgi_fd) close(fd);
29518 }
29519-
29520+
29521 /* build clean environment */
29522 if (host->bin_env_copy->used) {
29523 for (i = 0; i < host->bin_env_copy->used; i++) {
29524 data_string *ds = (data_string *)host->bin_env_copy->data[i];
29525 char *ge;
29526-
29527+
29528 if (NULL != (ge = getenv(ds->value->ptr))) {
29529 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
29530 }
29531@@ -772,44 +771,44 @@
29532 } else {
29533 for (i = 0; environ[i]; i++) {
29534 char *eq;
29535-
29536+
29537 if (NULL != (eq = strchr(environ[i], '='))) {
29538 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
29539 }
29540 }
29541 }
29542-
29543+
29544 /* create environment */
29545 for (i = 0; i < host->bin_env->used; i++) {
29546 data_string *ds = (data_string *)host->bin_env->data[i];
29547-
29548+
29549 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
29550 }
29551-
29552+
29553 for (i = 0; i < env.used; i++) {
29554 /* search for PHP_FCGI_CHILDREN */
29555 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
29556 }
29557-
29558+
29559 /* not found, add a default */
29560 if (i == env.used) {
29561 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
29562 }
29563-
29564+
29565 env.ptr[env.used] = NULL;
29566-
29567+
29568 b = buffer_init();
29569 buffer_copy_string(b, "exec ");
29570 buffer_append_string_buffer(b, host->bin_path);
29571-
29572+
29573 /* exec the cgi */
29574 execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
29575-
29576- log_error_write(srv, __FILE__, __LINE__, "sbs",
29577+
29578+ log_error_write(srv, __FILE__, __LINE__, "sbs",
29579 "execl failed for:", host->bin_path, strerror(errno));
29580-
29581+
29582 exit(errno);
29583-
29584+
29585 break;
29586 }
29587 case -1:
29588@@ -817,32 +816,32 @@
29589 break;
29590 default:
29591 /* father */
29592-
29593+
29594 /* wait */
29595 select(0, NULL, NULL, NULL, &tv);
29596-
29597+
29598 switch (waitpid(child, &status, WNOHANG)) {
29599 case 0:
29600 /* child still running after timeout, good */
29601 break;
29602 case -1:
29603 /* no PID found ? should never happen */
29604- log_error_write(srv, __FILE__, __LINE__, "ss",
29605+ log_error_write(srv, __FILE__, __LINE__, "ss",
29606 "pid not found:", strerror(errno));
29607 return -1;
29608 default:
29609 /* the child should not terminate at all */
29610 if (WIFEXITED(status)) {
29611- log_error_write(srv, __FILE__, __LINE__, "sd",
29612- "child exited (is this a SCGI binary ?):",
29613+ log_error_write(srv, __FILE__, __LINE__, "sd",
29614+ "child exited (is this a SCGI binary ?):",
29615 WEXITSTATUS(status));
29616 } else if (WIFSIGNALED(status)) {
29617- log_error_write(srv, __FILE__, __LINE__, "sd",
29618- "child signaled:",
29619+ log_error_write(srv, __FILE__, __LINE__, "sd",
29620+ "child signaled:",
29621 WTERMSIG(status));
29622 } else {
29623- log_error_write(srv, __FILE__, __LINE__, "sd",
29624- "child died somehow:",
29625+ log_error_write(srv, __FILE__, __LINE__, "sd",
29626+ "child died somehow:",
29627 status);
29628 }
29629 return -1;
29630@@ -852,26 +851,26 @@
29631 proc->pid = child;
29632 proc->last_used = srv->cur_ts;
29633 proc->is_local = 1;
29634-
29635+
29636 break;
29637 }
29638 #endif
29639 } else {
29640 proc->is_local = 0;
29641 proc->pid = 0;
29642-
29643+
29644 if (p->conf.debug) {
29645 log_error_write(srv, __FILE__, __LINE__, "sb",
29646 "(debug) socket is already used, won't spawn:",
29647 proc->socket);
29648 }
29649 }
29650-
29651+
29652 proc->state = PROC_STATE_RUNNING;
29653 host->active_procs++;
29654-
29655+
29656 close(scgi_fd);
29657-
29658+
29659 return 0;
29660 }
29661
29662@@ -880,89 +879,89 @@
29663 plugin_data *p = p_d;
29664 data_unset *du;
29665 size_t i = 0;
29666-
29667- config_values_t cv[] = {
29668+
29669+ config_values_t cv[] = {
29670 { "scgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
29671 { "scgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
29672 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29673 };
29674-
29675+
29676 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
29677-
29678+
29679 for (i = 0; i < srv->config_context->used; i++) {
29680 plugin_config *s;
29681 array *ca;
29682-
29683+
29684 s = malloc(sizeof(plugin_config));
29685 s->exts = scgi_extensions_init();
29686 s->debug = 0;
29687-
29688+
29689 cv[0].destination = s->exts;
29690 cv[1].destination = &(s->debug);
29691-
29692+
29693 p->config_storage[i] = s;
29694 ca = ((data_config *)srv->config_context->data[i])->value;
29695-
29696+
29697 if (0 != config_insert_values_global(srv, ca, cv)) {
29698 return HANDLER_ERROR;
29699 }
29700-
29701- /*
29702+
29703+ /*
29704 * <key> = ( ... )
29705 */
29706-
29707+
29708 if (NULL != (du = array_get_element(ca, "scgi.server"))) {
29709 size_t j;
29710 data_array *da = (data_array *)du;
29711-
29712+
29713 if (du->type != TYPE_ARRAY) {
29714- log_error_write(srv, __FILE__, __LINE__, "sss",
29715+ log_error_write(srv, __FILE__, __LINE__, "sss",
29716 "unexpected type for key: ", "scgi.server", "array of strings");
29717-
29718+
29719 return HANDLER_ERROR;
29720 }
29721-
29722-
29723- /*
29724- * scgi.server = ( "<ext>" => ( ... ),
29725+
29726+
29727+ /*
29728+ * scgi.server = ( "<ext>" => ( ... ),
29729 * "<ext>" => ( ... ) )
29730 */
29731-
29732+
29733 for (j = 0; j < da->value->used; j++) {
29734 size_t n;
29735 data_array *da_ext = (data_array *)da->value->data[j];
29736-
29737+
29738 if (da->value->data[j]->type != TYPE_ARRAY) {
29739- log_error_write(srv, __FILE__, __LINE__, "sssbs",
29740- "unexpected type for key: ", "scgi.server",
29741+ log_error_write(srv, __FILE__, __LINE__, "sssbs",
29742+ "unexpected type for key: ", "scgi.server",
29743 "[", da->value->data[j]->key, "](string)");
29744-
29745+
29746 return HANDLER_ERROR;
29747 }
29748-
29749- /*
29750- * da_ext->key == name of the extension
29751+
29752+ /*
29753+ * da_ext->key == name of the extension
29754 */
29755-
29756- /*
29757- * scgi.server = ( "<ext>" =>
29758- * ( "<host>" => ( ... ),
29759+
29760+ /*
29761+ * scgi.server = ( "<ext>" =>
29762+ * ( "<host>" => ( ... ),
29763 * "<host>" => ( ... )
29764- * ),
29765+ * ),
29766 * "<ext>" => ... )
29767 */
29768-
29769+
29770 for (n = 0; n < da_ext->value->used; n++) {
29771 data_array *da_host = (data_array *)da_ext->value->data[n];
29772-
29773+
29774 scgi_extension_host *df;
29775-
29776- config_values_t fcv[] = {
29777+
29778+ config_values_t fcv[] = {
29779 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
29780 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
29781 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
29782 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
29783-
29784+
29785 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
29786 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
29787 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
29788@@ -970,37 +969,37 @@
29789 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
29790 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
29791 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
29792-
29793+
29794 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
29795 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
29796-
29797-
29798+
29799+
29800 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29801 };
29802-
29803+
29804 if (da_host->type != TYPE_ARRAY) {
29805- log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29806- "unexpected type for key:",
29807- "scgi.server",
29808+ log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29809+ "unexpected type for key:",
29810+ "scgi.server",
29811 "[", da_host->key, "](string)");
29812-
29813+
29814 return HANDLER_ERROR;
29815 }
29816-
29817+
29818 df = scgi_host_init();
29819-
29820+
29821 df->check_local = 1;
29822 df->min_procs = 4;
29823 df->max_procs = 4;
29824 df->max_load_per_proc = 1;
29825 df->idle_timeout = 60;
29826 df->disable_time = 60;
29827-
29828+
29829 fcv[0].destination = df->host;
29830 fcv[1].destination = df->docroot;
29831 fcv[2].destination = df->unixsocket;
29832 fcv[3].destination = df->bin_path;
29833-
29834+
29835 fcv[4].destination = &(df->check_local);
29836 fcv[5].destination = &(df->port);
29837 fcv[6].destination = &(df->min_procs);
29838@@ -1008,47 +1007,47 @@
29839 fcv[8].destination = &(df->max_load_per_proc);
29840 fcv[9].destination = &(df->idle_timeout);
29841 fcv[10].destination = &(df->disable_time);
29842-
29843+
29844 fcv[11].destination = df->bin_env;
29845 fcv[12].destination = df->bin_env_copy;
29846-
29847-
29848+
29849+
29850 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
29851 return HANDLER_ERROR;
29852 }
29853-
29854- if ((!buffer_is_empty(df->host) || df->port) &&
29855+
29856+ if ((!buffer_is_empty(df->host) || df->port) &&
29857 !buffer_is_empty(df->unixsocket)) {
29858- log_error_write(srv, __FILE__, __LINE__, "s",
29859+ log_error_write(srv, __FILE__, __LINE__, "s",
29860 "either host+port or socket");
29861-
29862+
29863 return HANDLER_ERROR;
29864 }
29865-
29866+
29867 if (!buffer_is_empty(df->unixsocket)) {
29868 /* unix domain socket */
29869-
29870+
29871 if (df->unixsocket->used > UNIX_PATH_MAX - 2) {
29872- log_error_write(srv, __FILE__, __LINE__, "s",
29873+ log_error_write(srv, __FILE__, __LINE__, "s",
29874 "path of the unixdomain socket is too large");
29875 return HANDLER_ERROR;
29876 }
29877 } else {
29878 /* tcp/ip */
29879-
29880- if (buffer_is_empty(df->host) &&
29881+
29882+ if (buffer_is_empty(df->host) &&
29883 buffer_is_empty(df->bin_path)) {
29884- log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29885- "missing key (string):",
29886+ log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29887+ "missing key (string):",
29888 da->key,
29889 da_ext->key,
29890 da_host->key,
29891 "host");
29892-
29893+
29894 return HANDLER_ERROR;
29895 } else if (df->port == 0) {
29896- log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29897- "missing key (short):",
29898+ log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29899+ "missing key (short):",
29900 da->key,
29901 da_ext->key,
29902 da_host->key,
29903@@ -1056,14 +1055,14 @@
29904 return HANDLER_ERROR;
29905 }
29906 }
29907-
29908- if (!buffer_is_empty(df->bin_path)) {
29909+
29910+ if (!buffer_is_empty(df->bin_path)) {
29911 /* a local socket + self spawning */
29912 size_t pno;
29913-
29914+
29915 if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
29916 if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
29917-
29918+
29919 if (s->debug) {
29920 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
29921 "--- scgi spawning local",
29922@@ -1073,7 +1072,7 @@
29923 "\n\tmin-procs:", df->min_procs,
29924 "\n\tmax-procs:", df->max_procs);
29925 }
29926-
29927+
29928 for (pno = 0; pno < df->min_procs; pno++) {
29929 scgi_proc *proc;
29930
29931@@ -1088,7 +1087,7 @@
29932 buffer_append_string(proc->socket, "-");
29933 buffer_append_long(proc->socket, pno);
29934 }
29935-
29936+
29937 if (s->debug) {
29938 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
29939 "--- scgi spawning",
29940@@ -1096,53 +1095,53 @@
29941 "\n\tsocket", df->unixsocket,
29942 "\n\tcurrent:", pno, "/", df->min_procs);
29943 }
29944-
29945+
29946 if (scgi_spawn_connection(srv, p, df, proc)) {
29947 log_error_write(srv, __FILE__, __LINE__, "s",
29948 "[ERROR]: spawning fcgi failed.");
29949 return HANDLER_ERROR;
29950 }
29951-
29952+
29953 proc->next = df->first;
29954 if (df->first) df->first->prev = proc;
29955-
29956+
29957 df->first = proc;
29958 }
29959 } else {
29960 scgi_proc *fp;
29961-
29962+
29963 fp = scgi_process_init();
29964 fp->id = df->num_procs++;
29965 df->max_id++;
29966 df->active_procs++;
29967 fp->state = PROC_STATE_RUNNING;
29968-
29969+
29970 if (buffer_is_empty(df->unixsocket)) {
29971 fp->port = df->port;
29972 } else {
29973 buffer_copy_string_buffer(fp->socket, df->unixsocket);
29974 }
29975-
29976+
29977 df->first = fp;
29978-
29979+
29980 df->min_procs = 1;
29981 df->max_procs = 1;
29982 }
29983-
29984+
29985 /* if extension already exists, take it */
29986 scgi_extension_insert(s->exts, da_ext->key, df);
29987 }
29988 }
29989 }
29990 }
29991-
29992+
29993 return HANDLER_GO_ON;
29994 }
29995
29996 static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) {
29997 hctx->state = state;
29998 hctx->state_timestamp = srv->cur_ts;
29999-
30000+
30001 return 0;
30002 }
30003
30004@@ -1150,34 +1149,34 @@
30005 void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
30006 plugin_data *p;
30007 connection *con;
30008-
30009+
30010 if (NULL == hctx) return;
30011-
30012+
30013 p = hctx->plugin_data;
30014 con = hctx->remote_conn;
30015-
30016+
30017 if (con->mode != p->id) {
30018 WP();
30019 return;
30020 }
30021-
30022+
30023 if (hctx->fd != -1) {
30024 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30025 fdevent_unregister(srv->ev, hctx->fd);
30026 close(hctx->fd);
30027 srv->cur_fds--;
30028 }
30029-
30030+
30031 if (hctx->host && hctx->proc) {
30032 hctx->host->load--;
30033-
30034+
30035 if (hctx->got_proc) {
30036 /* after the connect the process gets a load */
30037 hctx->proc->load--;
30038-
30039+
30040 if (p->conf.debug) {
30041 log_error_write(srv, __FILE__, __LINE__, "sddb",
30042- "release proc:",
30043+ "release proc:",
30044 hctx->fd,
30045 hctx->proc->pid, hctx->proc->socket);
30046 }
30047@@ -1186,87 +1185,87 @@
30048 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30049 }
30050
30051-
30052+
30053 handler_ctx_free(hctx);
30054- con->plugin_ctx[p->id] = NULL;
30055+ con->plugin_ctx[p->id] = NULL;
30056 }
30057
30058 static int scgi_reconnect(server *srv, handler_ctx *hctx) {
30059 plugin_data *p = hctx->plugin_data;
30060-
30061- /* child died
30062- *
30063- * 1.
30064- *
30065+
30066+ /* child died
30067+ *
30068+ * 1.
30069+ *
30070 * connect was ok, connection was accepted
30071 * but the php accept loop checks after the accept if it should die or not.
30072- *
30073- * if yes we can only detect it at a write()
30074- *
30075+ *
30076+ * if yes we can only detect it at a write()
30077+ *
30078 * next step is resetting this attemp and setup a connection again
30079- *
30080+ *
30081 * if we have more then 5 reconnects for the same request, die
30082- *
30083- * 2.
30084- *
30085+ *
30086+ * 2.
30087+ *
30088 * we have a connection but the child died by some other reason
30089- *
30090+ *
30091 */
30092-
30093+
30094 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30095 fdevent_unregister(srv->ev, hctx->fd);
30096 close(hctx->fd);
30097 srv->cur_fds--;
30098-
30099+
30100 scgi_set_state(srv, hctx, FCGI_STATE_INIT);
30101-
30102+
30103 hctx->request_id = 0;
30104 hctx->reconnects++;
30105-
30106+
30107 if (p->conf.debug) {
30108 log_error_write(srv, __FILE__, __LINE__, "sddb",
30109- "release proc:",
30110+ "release proc:",
30111 hctx->fd,
30112 hctx->proc->pid, hctx->proc->socket);
30113 }
30114-
30115+
30116 hctx->proc->load--;
30117 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30118-
30119+
30120 return 0;
30121 }
30122
30123
30124 static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
30125 plugin_data *p = p_d;
30126-
30127+
30128 scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
30129-
30130+
30131 return HANDLER_GO_ON;
30132 }
30133
30134
30135 static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
30136 size_t len;
30137-
30138+
30139 if (!key || !val) return -1;
30140-
30141+
30142 len = key_len + val_len + 2;
30143-
30144+
30145 buffer_prepare_append(env, len);
30146
30147- /* include the NUL */
30148+ /* include the NUL */
30149 memcpy(env->ptr + env->used, key, key_len + 1);
30150 env->used += key_len + 1;
30151 memcpy(env->ptr + env->used, val, val_len + 1);
30152 env->used += val_len + 1;
30153-
30154+
30155 return 0;
30156 }
30157
30158
30159 /**
30160- *
30161+ *
30162 * returns
30163 * -1 error
30164 * 0 connected
30165@@ -1280,24 +1279,21 @@
30166 struct sockaddr_un scgi_addr_un;
30167 #endif
30168 socklen_t servlen;
30169-
30170+
30171 scgi_extension_host *host = hctx->host;
30172 scgi_proc *proc = hctx->proc;
30173 int scgi_fd = hctx->fd;
30174-
30175+
30176 memset(&scgi_addr, 0, sizeof(scgi_addr));
30177-
30178+
30179 if (!buffer_is_empty(proc->socket)) {
30180 #ifdef HAVE_SYS_UN_H
30181 /* use the unix domain socket */
30182 scgi_addr_un.sun_family = AF_UNIX;
30183 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
30184-#ifdef SUN_LEN
30185+
30186 servlen = SUN_LEN(&scgi_addr_un);
30187-#else
30188- /* stevens says: */
30189- servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
30190-#endif
30191+
30192 scgi_addr = (struct sockaddr *) &scgi_addr_un;
30193 #else
30194 return -1;
30195@@ -1305,105 +1301,105 @@
30196 } else {
30197 scgi_addr_in.sin_family = AF_INET;
30198 if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) {
30199- log_error_write(srv, __FILE__, __LINE__, "sbs",
30200- "converting IP-adress failed for", host->host,
30201+ log_error_write(srv, __FILE__, __LINE__, "sbs",
30202+ "converting IP-adress failed for", host->host,
30203 "\nBe sure to specify an IP address here");
30204-
30205+
30206 return -1;
30207 }
30208 scgi_addr_in.sin_port = htons(proc->port);
30209 servlen = sizeof(scgi_addr_in);
30210-
30211+
30212 scgi_addr = (struct sockaddr *) &scgi_addr_in;
30213 }
30214-
30215+
30216 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
30217- if (errno == EINPROGRESS ||
30218+ if (errno == EINPROGRESS ||
30219 errno == EALREADY ||
30220 errno == EINTR) {
30221 if (hctx->conf.debug) {
30222- log_error_write(srv, __FILE__, __LINE__, "sd",
30223+ log_error_write(srv, __FILE__, __LINE__, "sd",
30224 "connect delayed, will continue later:", scgi_fd);
30225 }
30226-
30227+
30228 return 1;
30229 } else {
30230- log_error_write(srv, __FILE__, __LINE__, "sdsddb",
30231- "connect failed:", scgi_fd,
30232+ log_error_write(srv, __FILE__, __LINE__, "sdsddb",
30233+ "connect failed:", scgi_fd,
30234 strerror(errno), errno,
30235 proc->port, proc->socket);
30236
30237 if (errno == EAGAIN) {
30238 /* this is Linux only */
30239-
30240- log_error_write(srv, __FILE__, __LINE__, "s",
30241+
30242+ log_error_write(srv, __FILE__, __LINE__, "s",
30243 "If this happend on Linux: You have been run out of local ports. "
30244 "Check the manual, section Performance how to handle this.");
30245- }
30246-
30247+ }
30248+
30249 return -1;
30250 }
30251 }
30252 if (hctx->conf.debug > 1) {
30253- log_error_write(srv, __FILE__, __LINE__, "sd",
30254+ log_error_write(srv, __FILE__, __LINE__, "sd",
30255 "connect succeeded: ", scgi_fd);
30256 }
30257
30258
30259-
30260+
30261 return 0;
30262 }
30263
30264 static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
30265 size_t i;
30266-
30267+
30268 for (i = 0; i < con->request.headers->used; i++) {
30269 data_string *ds;
30270-
30271+
30272 ds = (data_string *)con->request.headers->data[i];
30273-
30274+
30275 if (ds->value->used && ds->key->used) {
30276 size_t j;
30277 buffer_reset(srv->tmp_buf);
30278-
30279+
30280 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
30281 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
30282 srv->tmp_buf->used--;
30283 }
30284-
30285+
30286 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30287 for (j = 0; j < ds->key->used - 1; j++) {
30288- srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30289- light_isalpha(ds->key->ptr[j]) ?
30290+ srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30291+ light_isalpha(ds->key->ptr[j]) ?
30292 ds->key->ptr[j] & ~32 : '_';
30293 }
30294 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30295-
30296+
30297 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30298 }
30299 }
30300-
30301+
30302 for (i = 0; i < con->environment->used; i++) {
30303 data_string *ds;
30304-
30305+
30306 ds = (data_string *)con->environment->data[i];
30307-
30308+
30309 if (ds->value->used && ds->key->used) {
30310 size_t j;
30311 buffer_reset(srv->tmp_buf);
30312-
30313+
30314 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30315 for (j = 0; j < ds->key->used - 1; j++) {
30316- srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30317- isalpha((unsigned char)ds->key->ptr[j]) ?
30318+ srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30319+ isalpha((unsigned char)ds->key->ptr[j]) ?
30320 toupper((unsigned char)ds->key->ptr[j]) : '_';
30321 }
30322 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30323-
30324+
30325 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30326 }
30327 }
30328-
30329+
30330 return 0;
30331 }
30332
30333@@ -1415,20 +1411,20 @@
30334 char b2[INET6_ADDRSTRLEN + 1];
30335 #endif
30336 buffer *b;
30337-
30338+
30339 plugin_data *p = hctx->plugin_data;
30340 scgi_extension_host *host= hctx->host;
30341
30342 connection *con = hctx->remote_conn;
30343 server_socket *srv_sock = con->srv_socket;
30344-
30345+
30346 sock_addr our_addr;
30347 socklen_t our_addr_len;
30348-
30349+
30350 buffer_prepare_copy(p->scgi_env, 1024);
30351
30352 /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
30353-
30354+
30355 /* request.content_length < SSIZE_MAX, see request.c */
30356 ltostr(buf, con->request.content_length);
30357 scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
30358@@ -1436,13 +1432,13 @@
30359
30360
30361 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
30362-
30363+
30364 if (con->server_name->used) {
30365 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
30366 } else {
30367 #ifdef HAVE_IPV6
30368- s = inet_ntop(srv_sock->addr.plain.sa_family,
30369- srv_sock->addr.plain.sa_family == AF_INET6 ?
30370+ s = inet_ntop(srv_sock->addr.plain.sa_family,
30371+ srv_sock->addr.plain.sa_family == AF_INET6 ?
30372 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
30373 (const void *) &(srv_sock->addr.ipv4.sin_addr),
30374 b2, sizeof(b2)-1);
30375@@ -1451,47 +1447,47 @@
30376 #endif
30377 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
30378 }
30379-
30380+
30381 scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
30382-
30383- ltostr(buf,
30384+
30385+ ltostr(buf,
30386 #ifdef HAVE_IPV6
30387 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
30388 #else
30389 ntohs(srv_sock->addr.ipv4.sin_port)
30390 #endif
30391 );
30392-
30393+
30394 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
30395-
30396+
30397 /* get the server-side of the connection to the client */
30398 our_addr_len = sizeof(our_addr);
30399-
30400+
30401 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
30402 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
30403 } else {
30404 s = inet_ntop_cache_get_ip(srv, &(our_addr));
30405 }
30406 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
30407-
30408- ltostr(buf,
30409+
30410+ ltostr(buf,
30411 #ifdef HAVE_IPV6
30412 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
30413 #else
30414 ntohs(con->dst_addr.ipv4.sin_port)
30415 #endif
30416 );
30417-
30418+
30419 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
30420-
30421+
30422 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
30423 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
30424-
30425+
30426 if (!buffer_is_empty(con->authed_user)) {
30427 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
30428 CONST_BUF_LEN(con->authed_user));
30429 }
30430-
30431+
30432
30433 /*
30434 * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
30435@@ -1500,12 +1496,12 @@
30436 */
30437
30438 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
30439-
30440+
30441 if (!buffer_is_empty(con->request.pathinfo)) {
30442 scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
30443-
30444+
30445 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
30446-
30447+
30448 if (!buffer_is_empty(host->docroot)) {
30449 buffer_copy_string_buffer(p->path, host->docroot);
30450 } else {
30451@@ -1526,19 +1522,19 @@
30452 */
30453
30454 if (!buffer_is_empty(host->docroot)) {
30455- /*
30456- * rewrite SCRIPT_FILENAME
30457- *
30458+ /*
30459+ * rewrite SCRIPT_FILENAME
30460+ *
30461 */
30462-
30463+
30464 buffer_copy_string_buffer(p->path, host->docroot);
30465 buffer_append_string_buffer(p->path, con->uri.path);
30466-
30467+
30468 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30469 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
30470 } else {
30471 buffer_copy_string_buffer(p->path, con->physical.path);
30472-
30473+
30474 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30475 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
30476 }
30477@@ -1551,30 +1547,30 @@
30478 } else {
30479 scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
30480 }
30481-
30482+
30483 s = get_http_method_name(con->request.http_method);
30484 scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
30485 scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
30486 s = get_http_version_name(con->request.http_version);
30487 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
30488-
30489+
30490 #ifdef USE_OPENSSL
30491 if (srv_sock->is_ssl) {
30492 scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
30493 }
30494 #endif
30495-
30496+
30497 scgi_env_add_request_headers(srv, con, p);
30498
30499 b = chunkqueue_get_append_buffer(hctx->wb);
30500-
30501+
30502 buffer_append_long(b, p->scgi_env->used);
30503 buffer_append_string_len(b, CONST_STR_LEN(":"));
30504 buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used);
30505 buffer_append_string_len(b, CONST_STR_LEN(","));
30506
30507 hctx->wb->bytes_in += b->used - 1;
30508-
30509+
30510 if (con->request.content_length) {
30511 chunkqueue *req_cq = con->request_content_queue;
30512 chunk *req_c;
30513@@ -1587,7 +1583,7 @@
30514
30515 /* we announce toWrite octects
30516 * now take all the request_content chunk that we need to fill this request
30517- * */
30518+ * */
30519
30520 switch (req_c->type) {
30521 case FILE_CHUNK:
30522@@ -1615,32 +1611,32 @@
30523
30524 req_c->offset += weHave;
30525 req_cq->bytes_out += weHave;
30526-
30527+
30528 hctx->wb->bytes_in += weHave;
30529
30530 break;
30531 default:
30532 break;
30533 }
30534-
30535+
30536 offset += weHave;
30537 }
30538 }
30539-
30540+
30541 #if 0
30542 for (i = 0; i < hctx->write_buffer->used; i++) {
30543 fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]);
30544 if ((i+1) % 16 == 0) {
30545 size_t j;
30546 for (j = i-15; j <= i; j++) {
30547- fprintf(stderr, "%c",
30548+ fprintf(stderr, "%c",
30549 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
30550 }
30551 fprintf(stderr, "\n");
30552 }
30553 }
30554 #endif
30555-
30556+
30557 return 0;
30558 }
30559
30560@@ -1648,32 +1644,32 @@
30561 char *ns;
30562 const char *s;
30563 int line = 0;
30564-
30565+
30566 UNUSED(srv);
30567-
30568+
30569 buffer_copy_string_buffer(p->parse_response, in);
30570-
30571- for (s = p->parse_response->ptr;
30572- NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
30573+
30574+ for (s = p->parse_response->ptr;
30575+ NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
30576 s = ns + (eol == EOL_RN ? 2 : 1), line++) {
30577 const char *key, *value;
30578 int key_len;
30579 data_string *ds;
30580-
30581+
30582 ns[0] = '\0';
30583-
30584- if (line == 0 &&
30585+
30586+ if (line == 0 &&
30587 0 == strncmp(s, "HTTP/1.", 7)) {
30588 /* non-parsed header ... we parse them anyway */
30589-
30590+
30591 if ((s[7] == '1' ||
30592 s[7] == '0') &&
30593 s[8] == ' ') {
30594 int status;
30595 /* after the space should be a status code for us */
30596-
30597+
30598 status = strtol(s+9, NULL, 10);
30599-
30600+
30601 if (con->http_status >= 100 &&
30602 con->http_status < 1000) {
30603 /* we expected 3 digits and didn't got them */
30604@@ -1682,27 +1678,27 @@
30605 }
30606 }
30607 } else {
30608-
30609+
30610 key = s;
30611 if (NULL == (value = strchr(s, ':'))) {
30612 /* we expect: "<key>: <value>\r\n" */
30613 continue;
30614 }
30615-
30616+
30617 key_len = value - key;
30618 value += 1;
30619-
30620+
30621 /* skip LWS */
30622 while (*value == ' ' || *value == '\t') value++;
30623-
30624+
30625 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
30626 ds = data_response_init();
30627 }
30628 buffer_copy_string_len(ds->key, key, key_len);
30629 buffer_copy_string(ds->value, value);
30630-
30631+
30632 array_insert_unique(con->response.headers, (data_unset *)ds);
30633-
30634+
30635 switch(key_len) {
30636 case 4:
30637 if (0 == strncasecmp(key, "Date", key_len)) {
30638@@ -1737,13 +1733,13 @@
30639 }
30640 }
30641 }
30642-
30643+
30644 /* CGI/1.1 rev 03 - 7.2.1.2 */
30645 if ((con->parsed_response & HTTP_LOCATION) &&
30646 !(con->parsed_response & HTTP_STATUS)) {
30647 con->http_status = 302;
30648 }
30649-
30650+
30651 return 0;
30652 }
30653
30654@@ -1751,10 +1747,10 @@
30655 static int scgi_demux_response(server *srv, handler_ctx *hctx) {
30656 plugin_data *p = hctx->plugin_data;
30657 connection *con = hctx->remote_conn;
30658-
30659+
30660 while(1) {
30661 int n;
30662-
30663+
30664 buffer_prepare_copy(hctx->response, 1024);
30665 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
30666 if (errno == EAGAIN || errno == EINTR) {
30667@@ -1765,143 +1761,143 @@
30668 log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
30669 return -1;
30670 }
30671-
30672+
30673 if (n == 0) {
30674 /* read finished */
30675-
30676+
30677 con->file_finished = 1;
30678-
30679+
30680 /* send final chunk */
30681 http_chunk_append_mem(srv, con, NULL, 0);
30682 joblist_append(srv, con);
30683-
30684+
30685 return 1;
30686 }
30687-
30688+
30689 hctx->response->ptr[n] = '\0';
30690 hctx->response->used = n+1;
30691-
30692+
30693 /* split header from body */
30694-
30695+
30696 if (con->file_started == 0) {
30697 char *c;
30698 int in_header = 0;
30699 int header_end = 0;
30700 int cp, eol = EOL_UNSET;
30701 size_t used = 0;
30702-
30703+
30704 buffer_append_string_buffer(hctx->response_header, hctx->response);
30705-
30706+
30707 /* nph (non-parsed headers) */
30708 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
30709-
30710+
30711 /* search for the \r\n\r\n or \n\n in the string */
30712 for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
30713 if (*c == ':') in_header = 1;
30714 else if (*c == '\n') {
30715 if (in_header == 0) {
30716 /* got a response without a response header */
30717-
30718+
30719 c = NULL;
30720 header_end = 1;
30721 break;
30722 }
30723-
30724+
30725 if (eol == EOL_UNSET) eol = EOL_N;
30726-
30727+
30728 if (*(c+1) == '\n') {
30729 header_end = 1;
30730 break;
30731 }
30732-
30733+
30734 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
30735 if (in_header == 0) {
30736 /* got a response without a response header */
30737-
30738+
30739 c = NULL;
30740 header_end = 1;
30741 break;
30742 }
30743-
30744+
30745 if (eol == EOL_UNSET) eol = EOL_RN;
30746-
30747+
30748 if (used > 3 &&
30749- *(c+2) == '\r' &&
30750+ *(c+2) == '\r' &&
30751 *(c+3) == '\n') {
30752 header_end = 1;
30753 break;
30754 }
30755-
30756+
30757 /* skip the \n */
30758 c++;
30759 cp++;
30760 used--;
30761 }
30762 }
30763-
30764+
30765 if (header_end) {
30766 if (c == NULL) {
30767 /* no header, but a body */
30768-
30769+
30770 if (con->request.http_version == HTTP_VERSION_1_1) {
30771 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30772 }
30773-
30774+
30775 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
30776 joblist_append(srv, con);
30777 } else {
30778 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
30779 size_t blen = hctx->response_header->used - hlen - 1;
30780-
30781+
30782 /* a small hack: terminate after at the second \r */
30783 hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
30784 hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
30785-
30786+
30787 /* parse the response header */
30788 scgi_response_parse(srv, con, p, hctx->response_header, eol);
30789-
30790+
30791 /* enable chunked-transfer-encoding */
30792 if (con->request.http_version == HTTP_VERSION_1_1 &&
30793 !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
30794 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30795 }
30796-
30797+
30798 if ((hctx->response->used != hlen) && blen > 0) {
30799 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
30800 joblist_append(srv, con);
30801 }
30802 }
30803-
30804+
30805 con->file_started = 1;
30806 }
30807 } else {
30808 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
30809 joblist_append(srv, con);
30810 }
30811-
30812-#if 0
30813+
30814+#if 0
30815 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
30816 #endif
30817 }
30818-
30819+
30820 return 0;
30821 }
30822
30823
30824 int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30825 scgi_proc *p;
30826-
30827+
30828 UNUSED(srv);
30829-
30830- /* we have been the smallest of the current list
30831- * and we want to insert the node sorted as soon
30832+
30833+ /* we have been the smallest of the current list
30834+ * and we want to insert the node sorted as soon
30835 * possible
30836 *
30837- * 1 0 0 0 1 1 1
30838- * | ^
30839+ * 1 0 0 0 1 1 1
30840+ * | ^
30841 * | |
30842 * +------+
30843- *
30844+ *
30845 */
30846
30847 /* nothing to sort, only one element */
30848@@ -1909,9 +1905,9 @@
30849
30850 for (p = proc; p->next && p->next->load < proc->load; p = p->next);
30851
30852- /* no need to move something
30853+ /* no need to move something
30854 *
30855- * 1 2 2 2 3 3 3
30856+ * 1 2 2 2 3 3 3
30857 * ^
30858 * |
30859 * +
30860@@ -1930,16 +1926,16 @@
30861
30862 if (proc->prev) proc->prev->next = proc->next;
30863 if (proc->next) proc->next->prev = proc->prev;
30864-
30865+
30866 /* proc should be right of p */
30867-
30868+
30869 proc->next = p->next;
30870 proc->prev = p;
30871 if (p->next) p->next->prev = proc;
30872 p->next = proc;
30873 #if 0
30874 for(p = host->first; p; p = p->next) {
30875- log_error_write(srv, __FILE__, __LINE__, "dd",
30876+ log_error_write(srv, __FILE__, __LINE__, "dd",
30877 p->pid, p->load);
30878 }
30879 #else
30880@@ -1951,21 +1947,21 @@
30881
30882 int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30883 scgi_proc *p;
30884-
30885+
30886 UNUSED(srv);
30887-
30888- /* we have been the smallest of the current list
30889- * and we want to insert the node sorted as soon
30890+
30891+ /* we have been the smallest of the current list
30892+ * and we want to insert the node sorted as soon
30893 * possible
30894 *
30895- * 0 0 0 0 1 0 1
30896+ * 0 0 0 0 1 0 1
30897 * ^ |
30898 * | |
30899 * +----------+
30900 *
30901 *
30902 * the basic is idea is:
30903- * - the last active scgi process should be still
30904+ * - the last active scgi process should be still
30905 * in ram and is not swapped out yet
30906 * - processes that are not reused will be killed
30907 * after some time by the trigger-handler
30908@@ -1975,7 +1971,7 @@
30909 * ice-cold processes are propably unused since more
30910 * than 'unused-timeout', are swaped out and won't be
30911 * reused in the next seconds anyway.
30912- *
30913+ *
30914 */
30915
30916 /* nothing to sort, only one element */
30917@@ -1984,16 +1980,16 @@
30918 for (p = host->first; p != proc && p->load < proc->load; p = p->next);
30919
30920
30921- /* no need to move something
30922+ /* no need to move something
30923 *
30924- * 1 2 2 2 3 3 3
30925+ * 1 2 2 2 3 3 3
30926 * ^
30927 * |
30928 * +
30929 *
30930 */
30931 if (p == proc) return 0;
30932-
30933+
30934 /* we have to move left. If we are already the first element
30935 * we are done */
30936 if (host->first == proc) return 0;
30937@@ -2009,9 +2005,9 @@
30938 p->prev = proc;
30939
30940 if (proc->prev == NULL) host->first = proc;
30941-#if 0
30942+#if 0
30943 for(p = host->first; p; p = p->next) {
30944- log_error_write(srv, __FILE__, __LINE__, "dd",
30945+ log_error_write(srv, __FILE__, __LINE__, "dd",
30946 p->pid, p->load);
30947 }
30948 #else
30949@@ -2023,41 +2019,42 @@
30950
30951 static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
30952 scgi_proc *proc;
30953-
30954+
30955 for (proc = host->first; proc; proc = proc->next) {
30956 if (p->conf.debug) {
30957- log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
30958- "proc:",
30959- host->host, proc->port,
30960+ log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
30961+ "proc:",
30962+ host->host, proc->port,
30963 proc->socket,
30964 proc->state,
30965 proc->is_local,
30966 proc->load,
30967 proc->pid);
30968 }
30969-
30970+
30971 if (0 == proc->is_local) {
30972- /*
30973- * external servers might get disabled
30974- *
30975- * enable the server again, perhaps it is back again
30976+ /*
30977+ * external servers might get disabled
30978+ *
30979+ * enable the server again, perhaps it is back again
30980 */
30981-
30982+
30983 if ((proc->state == PROC_STATE_DISABLED) &&
30984 (srv->cur_ts - proc->disable_ts > host->disable_time)) {
30985 proc->state = PROC_STATE_RUNNING;
30986 host->active_procs++;
30987-
30988- log_error_write(srv, __FILE__, __LINE__, "sbdb",
30989- "fcgi-server re-enabled:",
30990- host->host, host->port,
30991+
30992+ log_error_write(srv, __FILE__, __LINE__, "sbdb",
30993+ "fcgi-server re-enabled:",
30994+ host->host, host->port,
30995 host->unixsocket);
30996 }
30997 } else {
30998 /* the child should not terminate at all */
30999 int status;
31000-
31001+
31002 if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
31003+#ifndef _WIN32
31004 switch(waitpid(proc->pid, &status, WNOHANG)) {
31005 case 0:
31006 /* child is still alive */
31007@@ -2067,33 +2064,34 @@
31008 default:
31009 if (WIFEXITED(status)) {
31010 #if 0
31011- log_error_write(srv, __FILE__, __LINE__, "sdsd",
31012+ log_error_write(srv, __FILE__, __LINE__, "sdsd",
31013 "child exited, pid:", proc->pid,
31014 "status:", WEXITSTATUS(status));
31015 #endif
31016 } else if (WIFSIGNALED(status)) {
31017- log_error_write(srv, __FILE__, __LINE__, "sd",
31018- "child signaled:",
31019+ log_error_write(srv, __FILE__, __LINE__, "sd",
31020+ "child signaled:",
31021 WTERMSIG(status));
31022 } else {
31023- log_error_write(srv, __FILE__, __LINE__, "sd",
31024- "child died somehow:",
31025+ log_error_write(srv, __FILE__, __LINE__, "sd",
31026+ "child died somehow:",
31027 status);
31028 }
31029-
31030+
31031 proc->state = PROC_STATE_DIED;
31032 break;
31033 }
31034+#endif
31035 }
31036-
31037- /*
31038+
31039+ /*
31040 * local servers might died, but we restart them
31041- *
31042+ *
31043 */
31044 if (proc->state == PROC_STATE_DIED &&
31045 proc->load == 0) {
31046 /* restart the child */
31047-
31048+
31049 if (p->conf.debug) {
31050 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31051 "--- scgi spawning",
31052@@ -2101,18 +2099,18 @@
31053 "\n\tsocket", host->unixsocket,
31054 "\n\tcurrent:", 1, "/", host->min_procs);
31055 }
31056-
31057+
31058 if (scgi_spawn_connection(srv, p, host, proc)) {
31059 log_error_write(srv, __FILE__, __LINE__, "s",
31060 "ERROR: spawning fcgi failed.");
31061 return HANDLER_ERROR;
31062 }
31063-
31064+
31065 scgi_proclist_sort_down(srv, host, proc);
31066 }
31067 }
31068 }
31069-
31070+
31071 return 0;
31072 }
31073
31074@@ -2121,13 +2119,13 @@
31075 plugin_data *p = hctx->plugin_data;
31076 scgi_extension_host *host= hctx->host;
31077 connection *con = hctx->remote_conn;
31078-
31079+
31080 int ret;
31081
31082- /* sanity check */
31083+ /* sanity check */
31084 if (!host ||
31085 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
31086- log_error_write(srv, __FILE__, __LINE__, "sxddd",
31087+ log_error_write(srv, __FILE__, __LINE__, "sxddd",
31088 "write-req: error",
31089 host,
31090 host->host->used,
31091@@ -2135,179 +2133,180 @@
31092 host->unixsocket->used);
31093 return HANDLER_ERROR;
31094 }
31095-
31096+
31097
31098 switch(hctx->state) {
31099 case FCGI_STATE_INIT:
31100 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
31101-
31102+
31103 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
31104 if (errno == EMFILE ||
31105 errno == EINTR) {
31106- log_error_write(srv, __FILE__, __LINE__, "sd",
31107+ log_error_write(srv, __FILE__, __LINE__, "sd",
31108 "wait for fd at connection:", con->fd);
31109-
31110+
31111 return HANDLER_WAIT_FOR_FD;
31112 }
31113-
31114- log_error_write(srv, __FILE__, __LINE__, "ssdd",
31115+
31116+ log_error_write(srv, __FILE__, __LINE__, "ssdd",
31117 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
31118 return HANDLER_ERROR;
31119 }
31120 hctx->fde_ndx = -1;
31121-
31122+
31123 srv->cur_fds++;
31124-
31125+
31126 fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
31127-
31128+
31129 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
31130- log_error_write(srv, __FILE__, __LINE__, "ss",
31131+ log_error_write(srv, __FILE__, __LINE__, "ss",
31132 "fcntl failed: ", strerror(errno));
31133-
31134+
31135 return HANDLER_ERROR;
31136 }
31137-
31138+
31139 /* fall through */
31140 case FCGI_STATE_CONNECT:
31141 if (hctx->state == FCGI_STATE_INIT) {
31142- for (hctx->proc = hctx->host->first;
31143- hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
31144+ for (hctx->proc = hctx->host->first;
31145+ hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
31146 hctx->proc = hctx->proc->next);
31147-
31148+
31149 /* all childs are dead */
31150 if (hctx->proc == NULL) {
31151 hctx->fde_ndx = -1;
31152-
31153+
31154 return HANDLER_ERROR;
31155 }
31156-
31157+
31158 if (hctx->proc->is_local) {
31159 hctx->pid = hctx->proc->pid;
31160 }
31161-
31162+
31163 switch (scgi_establish_connection(srv, hctx)) {
31164 case 1:
31165 scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
31166-
31167+
31168 /* connection is in progress, wait for an event and call getsockopt() below */
31169-
31170+
31171 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31172-
31173+
31174 return HANDLER_WAIT_FOR_EVENT;
31175 case -1:
31176 /* if ECONNREFUSED choose another connection -> FIXME */
31177 hctx->fde_ndx = -1;
31178-
31179+
31180 return HANDLER_ERROR;
31181 default:
31182 /* everything is ok, go on */
31183 break;
31184 }
31185
31186-
31187+
31188 } else {
31189 int socket_error;
31190 socklen_t socket_error_len = sizeof(socket_error);
31191-
31192+
31193 /* try to finish the connect() */
31194 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
31195- log_error_write(srv, __FILE__, __LINE__, "ss",
31196+ log_error_write(srv, __FILE__, __LINE__, "ss",
31197 "getsockopt failed:", strerror(errno));
31198-
31199+
31200 return HANDLER_ERROR;
31201 }
31202 if (socket_error != 0) {
31203 if (!hctx->proc->is_local || p->conf.debug) {
31204 /* local procs get restarted */
31205-
31206+
31207 log_error_write(srv, __FILE__, __LINE__, "ss",
31208- "establishing connection failed:", strerror(socket_error),
31209+ "establishing connection failed:", strerror(socket_error),
31210 "port:", hctx->proc->port);
31211 }
31212-
31213+
31214 return HANDLER_ERROR;
31215 }
31216 }
31217-
31218+
31219 /* ok, we have the connection */
31220-
31221+
31222 hctx->proc->load++;
31223 hctx->proc->last_used = srv->cur_ts;
31224 hctx->got_proc = 1;
31225-
31226+
31227 if (p->conf.debug) {
31228 log_error_write(srv, __FILE__, __LINE__, "sddbdd",
31229- "got proc:",
31230+ "got proc:",
31231 hctx->fd,
31232- hctx->proc->pid,
31233- hctx->proc->socket,
31234+ hctx->proc->pid,
31235+ hctx->proc->socket,
31236 hctx->proc->port,
31237 hctx->proc->load);
31238 }
31239
31240 /* move the proc-list entry down the list */
31241 scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
31242-
31243+
31244 scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
31245 /* fall through */
31246 case FCGI_STATE_PREPARE_WRITE:
31247 scgi_create_env(srv, hctx);
31248-
31249+
31250 scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
31251-
31252+
31253 /* fall through */
31254 case FCGI_STATE_WRITE:
31255- ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
31256+ ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
31257
31258 chunkqueue_remove_finished_chunks(hctx->wb);
31259-
31260+
31261 if (-1 == ret) {
31262 if (errno == ENOTCONN) {
31263- /* the connection got dropped after accept()
31264- *
31265- * this is most of the time a PHP which dies
31266+ /* the connection got dropped after accept()
31267+ *
31268+ * this is most of the time a PHP which dies
31269 * after PHP_FCGI_MAX_REQUESTS
31270- *
31271- */
31272+ *
31273+ */
31274 if (hctx->wb->bytes_out == 0 &&
31275 hctx->reconnects < 5) {
31276- usleep(10000); /* take away the load of the webserver
31277- * to let the php a chance to restart
31278+#ifndef _WIN32
31279+ usleep(10000); /* take away the load of the webserver
31280+ * to let the php a chance to restart
31281 */
31282-
31283+#endif
31284 scgi_reconnect(srv, hctx);
31285-
31286+
31287 return HANDLER_WAIT_FOR_FD;
31288 }
31289-
31290+
31291 /* not reconnected ... why
31292- *
31293+ *
31294 * far@#lighttpd report this for FreeBSD
31295- *
31296+ *
31297 */
31298-
31299- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31300+
31301+ log_error_write(srv, __FILE__, __LINE__, "ssosd",
31302 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
31303 "write-offset:", hctx->wb->bytes_out,
31304 "reconnect attempts:", hctx->reconnects);
31305-
31306+
31307 return HANDLER_ERROR;
31308 }
31309-
31310+
31311 if ((errno != EAGAIN) &&
31312 (errno != EINTR)) {
31313-
31314- log_error_write(srv, __FILE__, __LINE__, "ssd",
31315+
31316+ log_error_write(srv, __FILE__, __LINE__, "ssd",
31317 "write failed:", strerror(errno), errno);
31318-
31319+
31320 return HANDLER_ERROR;
31321 } else {
31322 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31323-
31324+
31325 return HANDLER_WAIT_FOR_EVENT;
31326 }
31327 }
31328-
31329+
31330 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
31331 /* we don't need the out event anymore */
31332 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
31333@@ -2315,10 +2314,10 @@
31334 scgi_set_state(srv, hctx, FCGI_STATE_READ);
31335 } else {
31336 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31337-
31338+
31339 return HANDLER_WAIT_FOR_EVENT;
31340 }
31341-
31342+
31343 break;
31344 case FCGI_STATE_READ:
31345 /* waiting for a response */
31346@@ -2327,67 +2326,67 @@
31347 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
31348 return HANDLER_ERROR;
31349 }
31350-
31351+
31352 return HANDLER_WAIT_FOR_EVENT;
31353 }
31354
31355 SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
31356 plugin_data *p = p_d;
31357-
31358+
31359 handler_ctx *hctx = con->plugin_ctx[p->id];
31360 scgi_proc *proc;
31361 scgi_extension_host *host;
31362-
31363+
31364 if (NULL == hctx) return HANDLER_GO_ON;
31365-
31366+
31367 /* not my job */
31368 if (con->mode != p->id) return HANDLER_GO_ON;
31369-
31370+
31371 /* ok, create the request */
31372 switch(scgi_write_request(srv, hctx)) {
31373 case HANDLER_ERROR:
31374 proc = hctx->proc;
31375 host = hctx->host;
31376-
31377- if (proc &&
31378+
31379+ if (proc &&
31380 0 == proc->is_local &&
31381 proc->state != PROC_STATE_DISABLED) {
31382 /* only disable remote servers as we don't manage them*/
31383-
31384- log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
31385+
31386+ log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
31387 host->host,
31388 proc->port,
31389 proc->socket);
31390-
31391+
31392 /* disable this server */
31393 proc->disable_ts = srv->cur_ts;
31394 proc->state = PROC_STATE_DISABLED;
31395 host->active_procs--;
31396 }
31397-
31398+
31399 if (hctx->state == FCGI_STATE_INIT ||
31400 hctx->state == FCGI_STATE_CONNECT) {
31401- /* connect() or getsockopt() failed,
31402- * restart the request-handling
31403+ /* connect() or getsockopt() failed,
31404+ * restart the request-handling
31405 */
31406 if (proc && proc->is_local) {
31407
31408 if (p->conf.debug) {
31409- log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
31410+ log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
31411 host->host,
31412 proc->port,
31413 proc->socket);
31414 }
31415
31416- /*
31417+ /*
31418 * several hctx might reference the same proc
31419- *
31420+ *
31421 * Only one of them should mark the proc as dead all the other
31422 * ones should just take a new one.
31423- *
31424+ *
31425 * If a new proc was started with the old struct this might lead
31426 * the mark a perfect proc as dead otherwise
31427- *
31428+ *
31429 */
31430 if (proc->state == PROC_STATE_RUNNING &&
31431 hctx->pid == proc->pid) {
31432@@ -2395,25 +2394,25 @@
31433 }
31434 }
31435 scgi_restart_dead_procs(srv, p, host);
31436-
31437+
31438 scgi_connection_cleanup(srv, hctx);
31439-
31440+
31441 buffer_reset(con->physical.path);
31442 con->mode = DIRECT;
31443 joblist_append(srv, con);
31444-
31445- /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31446- * and hope that the childs will be restarted
31447- *
31448+
31449+ /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31450+ * and hope that the childs will be restarted
31451+ *
31452 */
31453 return HANDLER_WAIT_FOR_FD;
31454 } else {
31455 scgi_connection_cleanup(srv, hctx);
31456-
31457+
31458 buffer_reset(con->physical.path);
31459 con->mode = DIRECT;
31460 con->http_status = 503;
31461-
31462+
31463 return HANDLER_FINISHED;
31464 }
31465 case HANDLER_WAIT_FOR_EVENT:
31466@@ -2433,23 +2432,23 @@
31467 static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
31468 plugin_data *p;
31469 connection *con;
31470-
31471+
31472 if (NULL == hctx) return HANDLER_GO_ON;
31473-
31474+
31475 p = hctx->plugin_data;
31476 con = hctx->remote_conn;
31477-
31478+
31479 if (con->mode != p->id) return HANDLER_GO_ON;
31480-
31481- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31482- "emergency exit: scgi:",
31483+
31484+ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31485+ "emergency exit: scgi:",
31486 "connection-fd:", con->fd,
31487 "fcgi-fd:", hctx->fd);
31488-
31489-
31490-
31491+
31492+
31493+
31494 scgi_connection_cleanup(srv, hctx);
31495-
31496+
31497 return HANDLER_FINISHED;
31498 }
31499
31500@@ -2459,7 +2458,7 @@
31501 handler_ctx *hctx = ctx;
31502 connection *con = hctx->remote_conn;
31503 plugin_data *p = hctx->plugin_data;
31504-
31505+
31506 scgi_proc *proc = hctx->proc;
31507 scgi_extension_host *host= hctx->host;
31508
31509@@ -2471,15 +2470,15 @@
31510 case 1:
31511 /* we are done */
31512 scgi_connection_cleanup(srv, hctx);
31513-
31514+
31515 joblist_append(srv, con);
31516 return HANDLER_FINISHED;
31517 case -1:
31518 if (proc->pid && proc->state != PROC_STATE_DIED) {
31519 int status;
31520-
31521+
31522 /* only fetch the zombie if it is not already done */
31523-
31524+#ifndef _WIN32
31525 switch(waitpid(proc->pid, &status, WNOHANG)) {
31526 case 0:
31527 /* child is still alive */
31528@@ -2489,19 +2488,19 @@
31529 default:
31530 /* the child should not terminate at all */
31531 if (WIFEXITED(status)) {
31532- log_error_write(srv, __FILE__, __LINE__, "sdsd",
31533+ log_error_write(srv, __FILE__, __LINE__, "sdsd",
31534 "child exited, pid:", proc->pid,
31535 "status:", WEXITSTATUS(status));
31536 } else if (WIFSIGNALED(status)) {
31537- log_error_write(srv, __FILE__, __LINE__, "sd",
31538- "child signaled:",
31539+ log_error_write(srv, __FILE__, __LINE__, "sd",
31540+ "child signaled:",
31541 WTERMSIG(status));
31542 } else {
31543- log_error_write(srv, __FILE__, __LINE__, "sd",
31544- "child died somehow:",
31545+ log_error_write(srv, __FILE__, __LINE__, "sd",
31546+ "child died somehow:",
31547 status);
31548 }
31549-
31550+
31551 if (p->conf.debug) {
31552 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31553 "--- scgi spawning",
31554@@ -2509,40 +2508,41 @@
31555 "\n\tsocket", host->unixsocket,
31556 "\n\tcurrent:", 1, "/", host->min_procs);
31557 }
31558-
31559+
31560 if (scgi_spawn_connection(srv, p, host, proc)) {
31561 /* child died */
31562 proc->state = PROC_STATE_DIED;
31563 } else {
31564 scgi_proclist_sort_down(srv, host, proc);
31565 }
31566-
31567+
31568 break;
31569 }
31570+#endif
31571 }
31572
31573 if (con->file_started == 0) {
31574 /* nothing has been send out yet, try to use another child */
31575-
31576+
31577 if (hctx->wb->bytes_out == 0 &&
31578 hctx->reconnects < 5) {
31579 scgi_reconnect(srv, hctx);
31580-
31581- log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31582+
31583+ log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31584 "response not sent, request not sent, reconnection.",
31585 "connection-fd:", con->fd,
31586 "fcgi-fd:", hctx->fd);
31587-
31588+
31589 return HANDLER_WAIT_FOR_FD;
31590 }
31591-
31592- log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31593+
31594+ log_error_write(srv, __FILE__, __LINE__, "sosdsd",
31595 "response not sent, request sent:", hctx->wb->bytes_out,
31596 "connection-fd:", con->fd,
31597 "fcgi-fd:", hctx->fd);
31598-
31599+
31600 scgi_connection_cleanup(srv, hctx);
31601-
31602+
31603 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
31604 buffer_reset(con->physical.path);
31605 con->http_status = 500;
31606@@ -2550,76 +2550,76 @@
31607 } else {
31608 /* response might have been already started, kill the connection */
31609 scgi_connection_cleanup(srv, hctx);
31610-
31611- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31612+
31613+ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31614 "response already sent out, termination connection",
31615 "connection-fd:", con->fd,
31616 "fcgi-fd:", hctx->fd);
31617-
31618+
31619 connection_set_state(srv, con, CON_STATE_ERROR);
31620 }
31621
31622 /* */
31623-
31624-
31625+
31626+
31627 joblist_append(srv, con);
31628 return HANDLER_FINISHED;
31629 }
31630 }
31631-
31632+
31633 if (revents & FDEVENT_OUT) {
31634 if (hctx->state == FCGI_STATE_CONNECT ||
31635 hctx->state == FCGI_STATE_WRITE) {
31636 /* we are allowed to send something out
31637- *
31638+ *
31639 * 1. in a unfinished connect() call
31640 * 2. in a unfinished write() call (long POST request)
31641 */
31642 return mod_scgi_handle_subrequest(srv, con, p);
31643 } else {
31644- log_error_write(srv, __FILE__, __LINE__, "sd",
31645- "got a FDEVENT_OUT and didn't know why:",
31646+ log_error_write(srv, __FILE__, __LINE__, "sd",
31647+ "got a FDEVENT_OUT and didn't know why:",
31648 hctx->state);
31649 }
31650 }
31651-
31652+
31653 /* perhaps this issue is already handled */
31654 if (revents & FDEVENT_HUP) {
31655 if (hctx->state == FCGI_STATE_CONNECT) {
31656 /* getoptsock will catch this one (right ?)
31657- *
31658- * if we are in connect we might get a EINPROGRESS
31659- * in the first call and a FDEVENT_HUP in the
31660+ *
31661+ * if we are in connect we might get a EINPROGRESS
31662+ * in the first call and a FDEVENT_HUP in the
31663 * second round
31664- *
31665+ *
31666 * FIXME: as it is a bit ugly.
31667- *
31668+ *
31669 */
31670 return mod_scgi_handle_subrequest(srv, con, p);
31671 } else if (hctx->state == FCGI_STATE_READ &&
31672 hctx->proc->port == 0) {
31673 /* FIXME:
31674- *
31675+ *
31676 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
31677 * even if the FCGI_FIN packet is not received yet
31678 */
31679 } else {
31680- log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
31681- "error: unexpected close of scgi connection for",
31682+ log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
31683+ "error: unexpected close of scgi connection for",
31684 con->uri.path,
31685- "(no scgi process on host: ",
31686+ "(no scgi process on host: ",
31687 host->host,
31688- ", port: ",
31689+ ", port: ",
31690 host->port,
31691 " ?)",
31692 hctx->state);
31693-
31694+
31695 connection_set_state(srv, con, CON_STATE_ERROR);
31696 scgi_connection_close(srv, hctx);
31697 joblist_append(srv, con);
31698 }
31699 } else if (revents & FDEVENT_ERR) {
31700- log_error_write(srv, __FILE__, __LINE__, "s",
31701+ log_error_write(srv, __FILE__, __LINE__, "s",
31702 "fcgi: got a FDEVENT_ERR. Don't know why.");
31703 /* kill all connections to the scgi process */
31704
31705@@ -2628,42 +2628,39 @@
31706 scgi_connection_close(srv, hctx);
31707 joblist_append(srv, con);
31708 }
31709-
31710+
31711 return HANDLER_FINISHED;
31712 }
31713-#define PATCH(x) \
31714- p->conf.x = s->x;
31715+
31716 static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
31717 size_t i, j;
31718 plugin_config *s = p->config_storage[0];
31719-
31720- PATCH(exts);
31721- PATCH(debug);
31722-
31723+
31724+ PATCH_OPTION(exts);
31725+ PATCH_OPTION(debug);
31726+
31727 /* skip the first, the global context */
31728 for (i = 1; i < srv->config_context->used; i++) {
31729 data_config *dc = (data_config *)srv->config_context->data[i];
31730 s = p->config_storage[i];
31731-
31732+
31733 /* condition didn't match */
31734 if (!config_check_cond(srv, con, dc)) continue;
31735-
31736+
31737 /* merge config */
31738 for (j = 0; j < dc->value->used; j++) {
31739 data_unset *du = dc->value->data[j];
31740-
31741+
31742 if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
31743- PATCH(exts);
31744+ PATCH_OPTION(exts);
31745 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
31746- PATCH(debug);
31747+ PATCH_OPTION(debug);
31748 }
31749 }
31750 }
31751-
31752+
31753 return 0;
31754 }
31755-#undef PATCH
31756-
31757
31758 static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
31759 plugin_data *p = p_d;
31760@@ -2673,30 +2670,30 @@
31761 size_t k;
31762 buffer *fn;
31763 scgi_extension *extension = NULL;
31764-
31765+
31766 /* Possibly, we processed already this request */
31767 if (con->file_started == 1) return HANDLER_GO_ON;
31768-
31769+
31770 fn = uri_path_handler ? con->uri.path : con->physical.path;
31771
31772 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
31773
31774 s_len = fn->used - 1;
31775-
31776+
31777 scgi_patch_connection(srv, con, p);
31778
31779 /* check if extension matches */
31780 for (k = 0; k < p->conf.exts->used; k++) {
31781 size_t ct_len;
31782-
31783+
31784 extension = p->conf.exts->exts[k];
31785-
31786+
31787 if (extension->key->used == 0) continue;
31788-
31789+
31790 ct_len = extension->key->used - 1;
31791-
31792+
31793 if (s_len < ct_len) continue;
31794-
31795+
31796 /* check extension in the form "/scgi_pattern" */
31797 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
31798 break;
31799@@ -2710,17 +2707,17 @@
31800 if (k == p->conf.exts->used) {
31801 return HANDLER_GO_ON;
31802 }
31803-
31804+
31805 /* get best server */
31806 for (k = 0, ndx = -1; k < extension->used; k++) {
31807 scgi_extension_host *host = extension->hosts[k];
31808-
31809+
31810 /* we should have at least one proc that can do somthing */
31811 if (host->active_procs == 0) continue;
31812
31813 if (used == -1 || host->load < used) {
31814 used = host->load;
31815-
31816+
31817 ndx = k;
31818 }
31819 }
31820@@ -2728,12 +2725,12 @@
31821 /* found a server */
31822 if (ndx != -1) {
31823 scgi_extension_host *host = extension->hosts[ndx];
31824-
31825- /*
31826- * if check-local is disabled, use the uri.path handler
31827- *
31828+
31829+ /*
31830+ * if check-local is disabled, use the uri.path handler
31831+ *
31832 */
31833-
31834+
31835 /* init handler-context */
31836 if (uri_path_handler) {
31837 if (host->check_local == 0) {
31838@@ -2741,7 +2738,7 @@
31839 char *pathinfo;
31840
31841 hctx = handler_ctx_init();
31842-
31843+
31844 hctx->remote_conn = con;
31845 hctx->plugin_data = p;
31846 hctx->host = host;
31847@@ -2749,45 +2746,45 @@
31848
31849 hctx->conf.exts = p->conf.exts;
31850 hctx->conf.debug = p->conf.debug;
31851-
31852+
31853 con->plugin_ctx[p->id] = hctx;
31854-
31855+
31856 host->load++;
31857-
31858+
31859 con->mode = p->id;
31860
31861 if (con->conf.log_request_handling) {
31862 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
31863 }
31864
31865- /* the prefix is the SCRIPT_NAME,
31866+ /* the prefix is the SCRIPT_NAME,
31867 * everthing from start to the next slash
31868 * this is important for check-local = "disable"
31869- *
31870+ *
31871 * if prefix = /admin.fcgi
31872- *
31873+ *
31874 * /admin.fcgi/foo/bar
31875- *
31876+ *
31877 * SCRIPT_NAME = /admin.fcgi
31878 * PATH_INFO = /foo/bar
31879- *
31880+ *
31881 * if prefix = /fcgi-bin/
31882- *
31883+ *
31884 * /fcgi-bin/foo/bar
31885- *
31886+ *
31887 * SCRIPT_NAME = /fcgi-bin/foo
31888 * PATH_INFO = /bar
31889- *
31890+ *
31891 */
31892-
31893+
31894 /* the rewrite is only done for /prefix/? matches */
31895 if (extension->key->ptr[0] == '/' &&
31896 con->uri.path->used > extension->key->used &&
31897 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
31898- /* rewrite uri.path and pathinfo */
31899-
31900+ /* rewrite uri.path and pathinfo */
31901+
31902 buffer_copy_string(con->request.pathinfo, pathinfo);
31903-
31904+
31905 con->uri.path->used -= con->request.pathinfo->used - 1;
31906 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
31907 }
31908@@ -2796,21 +2793,21 @@
31909 } else {
31910 handler_ctx *hctx;
31911 hctx = handler_ctx_init();
31912-
31913+
31914 hctx->remote_conn = con;
31915 hctx->plugin_data = p;
31916 hctx->host = host;
31917 hctx->proc = NULL;
31918-
31919+
31920 hctx->conf.exts = p->conf.exts;
31921 hctx->conf.debug = p->conf.debug;
31922-
31923+
31924 con->plugin_ctx[p->id] = hctx;
31925-
31926+
31927 host->load++;
31928-
31929+
31930 con->mode = p->id;
31931-
31932+
31933 if (con->conf.log_request_handling) {
31934 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
31935 }
31936@@ -2821,11 +2818,11 @@
31937 /* no handler found */
31938 buffer_reset(con->physical.path);
31939 con->http_status = 500;
31940-
31941- log_error_write(srv, __FILE__, __LINE__, "sb",
31942- "no fcgi-handler found for:",
31943+
31944+ log_error_write(srv, __FILE__, __LINE__, "sb",
31945+ "no fcgi-handler found for:",
31946 fn);
31947-
31948+
31949 return HANDLER_FINISHED;
31950 }
31951 return HANDLER_GO_ON;
31952@@ -2844,19 +2841,19 @@
31953 JOBLIST_FUNC(mod_scgi_handle_joblist) {
31954 plugin_data *p = p_d;
31955 handler_ctx *hctx = con->plugin_ctx[p->id];
31956-
31957+
31958 if (hctx == NULL) return HANDLER_GO_ON;
31959
31960 if (hctx->fd != -1) {
31961 switch (hctx->state) {
31962 case FCGI_STATE_READ:
31963 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
31964-
31965+
31966 break;
31967 case FCGI_STATE_CONNECT:
31968 case FCGI_STATE_WRITE:
31969 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31970-
31971+
31972 break;
31973 case FCGI_STATE_INIT:
31974 /* at reconnect */
31975@@ -2873,21 +2870,21 @@
31976
31977 static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
31978 plugin_data *p = p_d;
31979-
31980+
31981 return scgi_connection_close(srv, con->plugin_ctx[p->id]);
31982 }
31983
31984 TRIGGER_FUNC(mod_scgi_handle_trigger) {
31985 plugin_data *p = p_d;
31986 size_t i, j, n;
31987-
31988-
31989+
31990+
31991 /* perhaps we should kill a connect attempt after 10-15 seconds
31992- *
31993+ *
31994 * currently we wait for the TCP timeout which is on Linux 180 seconds
31995- *
31996- *
31997- *
31998+ *
31999+ *
32000+ *
32001 */
32002
32003 /* check all childs if they are still up */
32004@@ -2904,47 +2901,47 @@
32005 scgi_extension *ex;
32006
32007 ex = exts->exts[j];
32008-
32009+
32010 for (n = 0; n < ex->used; n++) {
32011-
32012+
32013 scgi_proc *proc;
32014 unsigned long sum_load = 0;
32015 scgi_extension_host *host;
32016-
32017+
32018 host = ex->hosts[n];
32019-
32020+
32021 scgi_restart_dead_procs(srv, p, host);
32022-
32023+
32024 for (proc = host->first; proc; proc = proc->next) {
32025 sum_load += proc->load;
32026 }
32027-
32028+
32029 if (host->num_procs &&
32030 host->num_procs < host->max_procs &&
32031 (sum_load / host->num_procs) > host->max_load_per_proc) {
32032 /* overload, spawn new child */
32033 scgi_proc *fp = NULL;
32034-
32035+
32036 if (p->conf.debug) {
32037- log_error_write(srv, __FILE__, __LINE__, "s",
32038+ log_error_write(srv, __FILE__, __LINE__, "s",
32039 "overload detected, spawning a new child");
32040 }
32041-
32042+
32043 for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
32044-
32045+
32046 if (fp) {
32047 if (fp == host->unused_procs) host->unused_procs = fp->next;
32048-
32049+
32050 if (fp->next) fp->next->prev = NULL;
32051-
32052+
32053 host->max_id++;
32054 } else {
32055 fp = scgi_process_init();
32056 fp->id = host->max_id++;
32057 }
32058-
32059+
32060 host->num_procs++;
32061-
32062+
32063 if (buffer_is_empty(host->unixsocket)) {
32064 fp->port = host->port + fp->id;
32065 } else {
32066@@ -2952,13 +2949,13 @@
32067 buffer_append_string(fp->socket, "-");
32068 buffer_append_long(fp->socket, fp->id);
32069 }
32070-
32071+
32072 if (scgi_spawn_connection(srv, p, host, fp)) {
32073 log_error_write(srv, __FILE__, __LINE__, "s",
32074 "ERROR: spawning fcgi failed.");
32075 return HANDLER_ERROR;
32076 }
32077-
32078+
32079 fp->prev = NULL;
32080 fp->next = host->first;
32081 if (host->first) {
32082@@ -2966,56 +2963,57 @@
32083 }
32084 host->first = fp;
32085 }
32086-
32087+
32088 for (proc = host->first; proc; proc = proc->next) {
32089 if (proc->load != 0) break;
32090 if (host->num_procs <= host->min_procs) break;
32091 if (proc->pid == 0) continue;
32092-
32093+#ifndef _WIN32
32094 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
32095 /* a proc is idling for a long time now,
32096 * terminated it */
32097-
32098+
32099 if (p->conf.debug) {
32100- log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32101- "idle-timeout reached, terminating child:",
32102- "socket:", proc->socket,
32103+ log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32104+ "idle-timeout reached, terminating child:",
32105+ "socket:", proc->socket,
32106 "pid", proc->pid);
32107 }
32108-
32109-
32110+
32111+
32112 if (proc->next) proc->next->prev = proc->prev;
32113 if (proc->prev) proc->prev->next = proc->next;
32114-
32115+
32116 if (proc->prev == NULL) host->first = proc->next;
32117-
32118+
32119 proc->prev = NULL;
32120 proc->next = host->unused_procs;
32121-
32122+
32123 if (host->unused_procs) host->unused_procs->prev = proc;
32124 host->unused_procs = proc;
32125-
32126+
32127 kill(proc->pid, SIGTERM);
32128-
32129+
32130 proc->state = PROC_STATE_KILLED;
32131-
32132- log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32133- "killed:",
32134- "socket:", proc->socket,
32135+
32136+ log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32137+ "killed:",
32138+ "socket:", proc->socket,
32139 "pid", proc->pid);
32140-
32141+
32142 host->num_procs--;
32143-
32144+
32145 /* proc is now in unused, let the next second handle the next process */
32146 break;
32147- }
32148+ }
32149+#endif
32150 }
32151-
32152+
32153 for (proc = host->unused_procs; proc; proc = proc->next) {
32154 int status;
32155-
32156+
32157 if (proc->pid == 0) continue;
32158-
32159+#ifndef _WIN32
32160 switch (waitpid(proc->pid, &status, WNOHANG)) {
32161 case 0:
32162 /* child still running after timeout, good */
32163@@ -3023,10 +3021,10 @@
32164 case -1:
32165 if (errno != EINTR) {
32166 /* no PID found ? should never happen */
32167- log_error_write(srv, __FILE__, __LINE__, "sddss",
32168+ log_error_write(srv, __FILE__, __LINE__, "sddss",
32169 "pid ", proc->pid, proc->state,
32170 "not found:", strerror(errno));
32171-
32172+
32173 #if 0
32174 if (errno == ECHILD) {
32175 /* someone else has cleaned up for us */
32176@@ -3040,25 +3038,26 @@
32177 /* the child should not terminate at all */
32178 if (WIFEXITED(status)) {
32179 if (proc->state != PROC_STATE_KILLED) {
32180- log_error_write(srv, __FILE__, __LINE__, "sdb",
32181- "child exited:",
32182+ log_error_write(srv, __FILE__, __LINE__, "sdb",
32183+ "child exited:",
32184 WEXITSTATUS(status), proc->socket);
32185 }
32186 } else if (WIFSIGNALED(status)) {
32187 if (WTERMSIG(status) != SIGTERM) {
32188- log_error_write(srv, __FILE__, __LINE__, "sd",
32189- "child signaled:",
32190+ log_error_write(srv, __FILE__, __LINE__, "sd",
32191+ "child signaled:",
32192 WTERMSIG(status));
32193 }
32194 } else {
32195- log_error_write(srv, __FILE__, __LINE__, "sd",
32196- "child died somehow:",
32197+ log_error_write(srv, __FILE__, __LINE__, "sd",
32198+ "child died somehow:",
32199 status);
32200 }
32201 proc->pid = 0;
32202 proc->state = PROC_STATE_UNSET;
32203 host->max_id--;
32204 }
32205+#endif
32206 }
32207 }
32208 }
32209@@ -3082,8 +3081,8 @@
32210 p->handle_subrequest = mod_scgi_handle_subrequest;
32211 p->handle_joblist = mod_scgi_handle_joblist;
32212 p->handle_trigger = mod_scgi_handle_trigger;
32213-
32214+
32215 p->data = NULL;
32216-
32217+
32218 return 0;
32219 }
1175ccec 32220--- ../lighttpd-1.4.11/src/mod_secure_download.c 2005-12-14 14:37:29.000000000 +0200
36e2a29e 32221+++ lighttpd-1.4.12/src/mod_secure_download.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
32222@@ -25,7 +25,7 @@
32223 #ifdef USE_OPENSSL
32224 #define IN const
32225 #else
32226-#define IN
32227+#define IN
32228 #endif
32229 #define OUT
32230
32231@@ -36,28 +36,28 @@
32232 buffer *doc_root;
32233 buffer *secret;
32234 buffer *uri_prefix;
32235-
32236+
32237 unsigned short timeout;
32238 } plugin_config;
32239
32240 typedef struct {
32241 PLUGIN_DATA;
32242-
32243+
32244 buffer *md5;
32245-
32246+
32247 plugin_config **config_storage;
32248-
32249- plugin_config conf;
32250+
32251+ plugin_config conf;
32252 } plugin_data;
32253
32254 /* init the plugin data */
32255 INIT_FUNC(mod_secdownload_init) {
32256 plugin_data *p;
32257-
32258+
32259 p = calloc(1, sizeof(*p));
32260-
32261+
32262 p->md5 = buffer_init();
32263-
32264+
32265 return p;
32266 }
32267
32268@@ -65,27 +65,27 @@
32269 FREE_FUNC(mod_secdownload_free) {
32270 plugin_data *p = p_d;
32271 UNUSED(srv);
32272-
32273+
32274 if (!p) return HANDLER_GO_ON;
32275-
32276+
32277 if (p->config_storage) {
32278 size_t i;
32279 for (i = 0; i < srv->config_context->used; i++) {
32280 plugin_config *s = p->config_storage[i];
32281-
32282+
32283 buffer_free(s->secret);
32284 buffer_free(s->doc_root);
32285 buffer_free(s->uri_prefix);
32286-
32287+
32288 free(s);
32289 }
32290 free(p->config_storage);
32291 }
32292-
32293+
32294 buffer_free(p->md5);
32295-
32296+
32297 free(p);
32298-
32299+
32300 return HANDLER_GO_ON;
32301 }
32302
32303@@ -94,107 +94,103 @@
32304 SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
32305 plugin_data *p = p_d;
32306 size_t i = 0;
32307-
32308- config_values_t cv[] = {
32309+
32310+ config_values_t cv[] = {
32311 { "secdownload.secret", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
32312 { "secdownload.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
32313 { "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
32314 { "secdownload.timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
32315 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32316 };
32317-
32318+
32319 if (!p) return HANDLER_ERROR;
32320-
32321+
32322 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32323-
32324+
32325 for (i = 0; i < srv->config_context->used; i++) {
32326 plugin_config *s;
32327-
32328+
32329 s = calloc(1, sizeof(plugin_config));
32330 s->secret = buffer_init();
32331 s->doc_root = buffer_init();
32332 s->uri_prefix = buffer_init();
32333 s->timeout = 60;
32334-
32335+
32336 cv[0].destination = s->secret;
32337 cv[1].destination = s->doc_root;
32338 cv[2].destination = s->uri_prefix;
32339 cv[3].destination = &(s->timeout);
32340-
32341+
32342 p->config_storage[i] = s;
32343-
32344+
32345 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32346 return HANDLER_ERROR;
32347 }
32348 }
32349-
32350+
32351 return HANDLER_GO_ON;
32352 }
32353
32354 /**
32355 * checks if the supplied string is a MD5 string
32356- *
32357+ *
32358 * @param str a possible MD5 string
32359 * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
32360 */
32361
32362 int is_hex_len(const char *str, size_t len) {
32363 size_t i;
32364-
32365+
32366 if (NULL == str) return 0;
32367-
32368+
32369 for (i = 0; i < len && *str; i++, str++) {
32370 /* illegal characters */
32371 if (!((*str >= '0' && *str <= '9') ||
32372 (*str >= 'a' && *str <= 'f') ||
32373- (*str >= 'A' && *str <= 'F'))
32374+ (*str >= 'A' && *str <= 'F'))
32375 ) {
32376 return 0;
32377 }
32378 }
32379-
32380+
32381 return i == len;
32382 }
32383
32384-#define PATCH(x) \
32385- p->conf.x = s->x;
32386 static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
32387 size_t i, j;
32388 plugin_config *s = p->config_storage[0];
32389-
32390- PATCH(secret);
32391- PATCH(doc_root);
32392- PATCH(uri_prefix);
32393- PATCH(timeout);
32394-
32395+
32396+ PATCH_OPTION(secret);
32397+ PATCH_OPTION(doc_root);
32398+ PATCH_OPTION(uri_prefix);
32399+ PATCH_OPTION(timeout);
32400+
32401 /* skip the first, the global context */
32402 for (i = 1; i < srv->config_context->used; i++) {
32403 data_config *dc = (data_config *)srv->config_context->data[i];
32404 s = p->config_storage[i];
32405-
32406+
32407 /* condition didn't match */
32408 if (!config_check_cond(srv, con, dc)) continue;
32409-
32410+
32411 /* merge config */
32412 for (j = 0; j < dc->value->used; j++) {
32413 data_unset *du = dc->value->data[j];
32414-
32415+
32416 if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
32417- PATCH(secret);
32418+ PATCH_OPTION(secret);
32419 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
32420- PATCH(doc_root);
32421+ PATCH_OPTION(doc_root);
32422 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
32423- PATCH(uri_prefix);
32424+ PATCH_OPTION(uri_prefix);
32425 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
32426- PATCH(timeout);
32427+ PATCH_OPTION(timeout);
32428 }
32429 }
32430 }
32431-
32432+
32433 return 0;
32434 }
32435-#undef PATCH
32436-
32437
32438 URIHANDLER_FUNC(mod_secdownload_uri_handler) {
32439 plugin_data *p = p_d;
32440@@ -203,88 +199,88 @@
32441 const char *rel_uri, *ts_str, *md5_str;
32442 time_t ts = 0;
32443 size_t i;
32444-
32445+
32446 if (con->uri.path->used == 0) return HANDLER_GO_ON;
32447-
32448+
32449 mod_secdownload_patch_connection(srv, con, p);
32450
32451 if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
32452-
32453+
32454 if (buffer_is_empty(p->conf.secret)) {
32455 log_error_write(srv, __FILE__, __LINE__, "s",
32456 "secdownload.secret has to be set");
32457 return HANDLER_ERROR;
32458 }
32459-
32460+
32461 if (buffer_is_empty(p->conf.doc_root)) {
32462 log_error_write(srv, __FILE__, __LINE__, "s",
32463 "secdownload.document-root has to be set");
32464 return HANDLER_ERROR;
32465 }
32466-
32467- /*
32468+
32469+ /*
32470 * /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
32471 */
32472-
32473+
32474 if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
32475-
32476+
32477 md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
32478-
32479+
32480 if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
32481 if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
32482-
32483+
32484 ts_str = md5_str + 32 + 1;
32485-
32486+
32487 if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
32488 if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
32489-
32490+
32491 for (i = 0; i < 8; i++) {
32492 ts = (ts << 4) + hex2int(*(ts_str + i));
32493 }
32494-
32495+
32496 /* timed-out */
32497- if (srv->cur_ts - ts > p->conf.timeout ||
32498+ if (srv->cur_ts - ts > p->conf.timeout ||
32499 srv->cur_ts - ts < -p->conf.timeout) {
32500 con->http_status = 408;
32501-
32502+
32503 return HANDLER_FINISHED;
32504 }
32505-
32506+
32507 rel_uri = ts_str + 8;
32508-
32509- /* checking MD5
32510- *
32511+
32512+ /* checking MD5
32513+ *
32514 * <secret><rel-path><timestamp-hex>
32515 */
32516-
32517+
32518 buffer_copy_string_buffer(p->md5, p->conf.secret);
32519 buffer_append_string(p->md5, rel_uri);
32520 buffer_append_string_len(p->md5, ts_str, 8);
32521-
32522+
32523 MD5_Init(&Md5Ctx);
32524 MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
32525 MD5_Final(HA1, &Md5Ctx);
32526-
32527+
32528 buffer_copy_string_hex(p->md5, (char *)HA1, 16);
32529-
32530+
32531 if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
32532 con->http_status = 403;
32533-
32534- log_error_write(srv, __FILE__, __LINE__, "sss",
32535+
32536+ log_error_write(srv, __FILE__, __LINE__, "sss",
32537 "md5 invalid:",
32538 md5_str, p->md5->ptr);
32539-
32540+
32541 return HANDLER_FINISHED;
32542 }
32543-
32544+
32545 /* starting with the last / we should have relative-path to the docroot
32546 */
32547-
32548+
32549 buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
32550 buffer_copy_string(con->physical.rel_path, rel_uri);
32551 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
32552 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
32553-
32554+
32555 return HANDLER_GO_ON;
32556 }
32557
32558@@ -293,13 +289,13 @@
32559 int mod_secdownload_plugin_init(plugin *p) {
32560 p->version = LIGHTTPD_VERSION_ID;
32561 p->name = buffer_init_string("secdownload");
32562-
32563+
32564 p->init = mod_secdownload_init;
32565 p->handle_physical = mod_secdownload_uri_handler;
32566 p->set_defaults = mod_secdownload_set_defaults;
32567 p->cleanup = mod_secdownload_free;
32568-
32569+
32570 p->data = NULL;
32571-
32572+
32573 return 0;
32574 }
1175ccec 32575--- ../lighttpd-1.4.11/src/mod_setenv.c 2006-01-14 20:33:12.000000000 +0200
36e2a29e 32576+++ lighttpd-1.4.12/src/mod_setenv.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
32577@@ -18,25 +18,25 @@
32578 typedef struct {
32579 array *request_header;
32580 array *response_header;
32581-
32582+
32583 array *environment;
32584 } plugin_config;
32585
32586 typedef struct {
32587 PLUGIN_DATA;
32588-
32589+
32590 plugin_config **config_storage;
32591-
32592- plugin_config conf;
32593+
32594+ plugin_config conf;
32595 } plugin_data;
32596
32597 static handler_ctx * handler_ctx_init() {
32598 handler_ctx * hctx;
32599-
32600+
32601 hctx = calloc(1, sizeof(*hctx));
32602-
32603+
32604 hctx->handled = 0;
32605-
32606+
32607 return hctx;
32608 }
32609
32610@@ -48,36 +48,36 @@
32611 /* init the plugin data */
32612 INIT_FUNC(mod_setenv_init) {
32613 plugin_data *p;
32614-
32615+
32616 p = calloc(1, sizeof(*p));
32617-
32618+
32619 return p;
32620 }
32621
32622 /* detroy the plugin data */
32623 FREE_FUNC(mod_setenv_free) {
32624 plugin_data *p = p_d;
32625-
32626+
32627 UNUSED(srv);
32628
32629 if (!p) return HANDLER_GO_ON;
32630-
32631+
32632 if (p->config_storage) {
32633 size_t i;
32634 for (i = 0; i < srv->config_context->used; i++) {
32635 plugin_config *s = p->config_storage[i];
32636-
32637+
32638 array_free(s->request_header);
32639 array_free(s->response_header);
32640 array_free(s->environment);
32641-
32642+
32643 free(s);
32644 }
32645 free(p->config_storage);
32646 }
32647-
32648+
32649 free(p);
32650-
32651+
32652 return HANDLER_GO_ON;
32653 }
32654
32655@@ -86,86 +86,83 @@
32656 SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
32657 plugin_data *p = p_d;
32658 size_t i = 0;
32659-
32660- config_values_t cv[] = {
32661+
32662+ config_values_t cv[] = {
32663 { "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
32664 { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
32665 { "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
32666 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32667 };
32668-
32669+
32670 if (!p) return HANDLER_ERROR;
32671-
32672+
32673 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32674-
32675+
32676 for (i = 0; i < srv->config_context->used; i++) {
32677 plugin_config *s;
32678-
32679+
32680 s = calloc(1, sizeof(plugin_config));
32681 s->request_header = array_init();
32682 s->response_header = array_init();
32683 s->environment = array_init();
32684-
32685+
32686 cv[0].destination = s->request_header;
32687 cv[1].destination = s->response_header;
32688 cv[2].destination = s->environment;
32689-
32690+
32691 p->config_storage[i] = s;
32692-
32693+
32694 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32695 return HANDLER_ERROR;
32696 }
32697 }
32698-
32699+
32700 return HANDLER_GO_ON;
32701 }
32702
32703-#define PATCH(x) \
32704- p->conf.x = s->x;
32705 static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
32706 size_t i, j;
32707 plugin_config *s = p->config_storage[0];
32708-
32709- PATCH(request_header);
32710- PATCH(response_header);
32711- PATCH(environment);
32712-
32713+
32714+ PATCH_OPTION(request_header);
32715+ PATCH_OPTION(response_header);
32716+ PATCH_OPTION(environment);
32717+
32718 /* skip the first, the global context */
32719 for (i = 1; i < srv->config_context->used; i++) {
32720 data_config *dc = (data_config *)srv->config_context->data[i];
32721 s = p->config_storage[i];
32722-
32723+
32724 /* condition didn't match */
32725 if (!config_check_cond(srv, con, dc)) continue;
32726-
32727+
32728 /* merge config */
32729 for (j = 0; j < dc->value->used; j++) {
32730 data_unset *du = dc->value->data[j];
32731-
32732+
32733 if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
32734- PATCH(request_header);
32735+ PATCH_OPTION(request_header);
32736 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
32737- PATCH(response_header);
32738+ PATCH_OPTION(response_header);
32739 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
f26f9fd5
ER
32740- PATCH(environment);
32741+ PATCH_OPTION(environment);
32742 }
32743 }
32744 }
2519e6e5
ER
32745-
32746+
32747 return 0;
32748 }
32749-#undef PATCH
32750
32751 URIHANDLER_FUNC(mod_setenv_uri_handler) {
32752 plugin_data *p = p_d;
32753 size_t k;
32754 handler_ctx *hctx;
32755-
32756+
32757 if (con->plugin_ctx[p->id]) {
32758 hctx = con->plugin_ctx[p->id];
32759 } else {
32760 hctx = handler_ctx_init();
32761-
32762+
32763 con->plugin_ctx[p->id] = hctx;
32764 }
32765
32766@@ -180,52 +177,52 @@
32767 for (k = 0; k < p->conf.request_header->used; k++) {
32768 data_string *ds = (data_string *)p->conf.request_header->data[k];
32769 data_string *ds_dst;
32770-
32771+
32772 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
32773 ds_dst = data_string_init();
32774 }
32775-
32776+
32777 buffer_copy_string_buffer(ds_dst->key, ds->key);
32778 buffer_copy_string_buffer(ds_dst->value, ds->value);
32779-
32780+
32781 array_insert_unique(con->request.headers, (data_unset *)ds_dst);
32782 }
32783-
32784+
32785 for (k = 0; k < p->conf.environment->used; k++) {
32786 data_string *ds = (data_string *)p->conf.environment->data[k];
32787 data_string *ds_dst;
32788-
32789+
32790 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
32791 ds_dst = data_string_init();
32792 }
32793-
32794+
32795 buffer_copy_string_buffer(ds_dst->key, ds->key);
32796 buffer_copy_string_buffer(ds_dst->value, ds->value);
32797-
32798+
32799 array_insert_unique(con->environment, (data_unset *)ds_dst);
32800 }
32801-
32802+
32803 for (k = 0; k < p->conf.response_header->used; k++) {
32804 data_string *ds = (data_string *)p->conf.response_header->data[k];
32805-
32806+
32807 response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
32808 }
32809-
32810+
32811 /* not found */
32812 return HANDLER_GO_ON;
32813 }
32814
32815 REQUESTDONE_FUNC(mod_setenv_reset) {
32816 plugin_data *p = p_d;
32817-
32818+
32819 UNUSED(srv);
32820-
32821+
32822 if (con->plugin_ctx[p->id]) {
32823 handler_ctx_free(con->plugin_ctx[p->id]);
32824 con->plugin_ctx[p->id] = NULL;
32825 }
32826
32827- return HANDLER_GO_ON;
32828+ return HANDLER_GO_ON;
32829 }
32830
32831 /* this function is called at dlopen() time and inits the callbacks */
32832@@ -233,15 +230,15 @@
32833 int mod_setenv_plugin_init(plugin *p) {
32834 p->version = LIGHTTPD_VERSION_ID;
32835 p->name = buffer_init_string("setenv");
32836-
32837+
32838 p->init = mod_setenv_init;
32839 p->handle_uri_clean = mod_setenv_uri_handler;
32840 p->set_defaults = mod_setenv_set_defaults;
32841 p->cleanup = mod_setenv_free;
32842-
32843+
32844 p->handle_request_done = mod_setenv_reset;
32845
32846 p->data = NULL;
32847-
32848+
32849 return 0;
32850 }
1175ccec 32851--- ../lighttpd-1.4.11/src/mod_simple_vhost.c 2005-11-18 15:16:13.000000000 +0200
36e2a29e 32852+++ lighttpd-1.4.12/src/mod_simple_vhost.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
32853@@ -10,6 +10,8 @@
32854
32855 #include "plugin.h"
32856
32857+#include "sys-files.h"
32858+
32859 #ifdef HAVE_CONFIG_H
32860 #include "config.h"
32861 #endif
32862@@ -18,7 +20,7 @@
32863 buffer *server_root;
32864 buffer *default_host;
32865 buffer *document_root;
32866-
32867+
32868 buffer *docroot_cache_key;
32869 buffer *docroot_cache_value;
32870 buffer *docroot_cache_servername;
32871@@ -28,138 +30,138 @@
32872
32873 typedef struct {
32874 PLUGIN_DATA;
32875-
32876+
32877 buffer *doc_root;
32878-
32879+
32880 plugin_config **config_storage;
32881- plugin_config conf;
32882+ plugin_config conf;
32883 } plugin_data;
32884
32885 INIT_FUNC(mod_simple_vhost_init) {
32886 plugin_data *p;
32887-
32888+
32889 p = calloc(1, sizeof(*p));
32890-
32891+
32892 p->doc_root = buffer_init();
32893-
32894+
32895 return p;
32896 }
32897
32898 FREE_FUNC(mod_simple_vhost_free) {
32899 plugin_data *p = p_d;
32900-
32901+
32902 UNUSED(srv);
32903
32904 if (!p) return HANDLER_GO_ON;
32905-
32906+
32907 if (p->config_storage) {
32908 size_t i;
32909 for (i = 0; i < srv->config_context->used; i++) {
32910 plugin_config *s = p->config_storage[i];
32911-
32912+
32913 buffer_free(s->document_root);
32914 buffer_free(s->default_host);
32915 buffer_free(s->server_root);
32916-
32917+
32918 buffer_free(s->docroot_cache_key);
32919 buffer_free(s->docroot_cache_value);
32920 buffer_free(s->docroot_cache_servername);
32921-
32922+
32923 free(s);
32924 }
32925-
32926+
32927 free(p->config_storage);
32928 }
32929-
32930+
32931 buffer_free(p->doc_root);
32932-
32933+
32934 free(p);
32935-
32936+
32937 return HANDLER_GO_ON;
32938 }
32939
32940 SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
32941 plugin_data *p = p_d;
32942 size_t i;
32943-
32944- config_values_t cv[] = {
32945+
32946+ config_values_t cv[] = {
32947 { "simple-vhost.server-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
32948 { "simple-vhost.default-host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
32949 { "simple-vhost.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
32950 { "simple-vhost.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
32951 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32952 };
32953-
32954+
32955 if (!p) return HANDLER_ERROR;
32956-
32957+
32958 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32959-
32960+
32961 for (i = 0; i < srv->config_context->used; i++) {
32962 plugin_config *s;
32963-
32964+
32965 s = calloc(1, sizeof(plugin_config));
32966-
32967+
32968 s->server_root = buffer_init();
32969 s->default_host = buffer_init();
32970 s->document_root = buffer_init();
32971-
32972+
32973 s->docroot_cache_key = buffer_init();
32974 s->docroot_cache_value = buffer_init();
32975 s->docroot_cache_servername = buffer_init();
32976
32977 s->debug = 0;
32978-
32979+
32980 cv[0].destination = s->server_root;
32981 cv[1].destination = s->default_host;
32982 cv[2].destination = s->document_root;
32983 cv[3].destination = &(s->debug);
32984-
32985-
32986+
32987+
32988 p->config_storage[i] = s;
32989-
32990+
32991 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32992 return HANDLER_ERROR;
32993 }
32994 }
32995-
32996+
32997 return HANDLER_GO_ON;
32998 }
32999
33000 static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
33001 stat_cache_entry *sce = NULL;
33002-
33003+
33004 buffer_prepare_copy(out, 128);
33005
33006 if (p->conf.server_root->used) {
33007 buffer_copy_string_buffer(out, p->conf.server_root);
33008-
33009+
33010 if (host->used) {
33011 /* a hostname has to start with a alpha-numerical character
33012 * and must not contain a slash "/"
33013 */
33014 char *dp;
33015-
33016- BUFFER_APPEND_SLASH(out);
33017-
33018+
33019+ PATHNAME_APPEND_SLASH(out);
33020+
33021 if (NULL == (dp = strchr(host->ptr, ':'))) {
33022 buffer_append_string_buffer(out, host);
33023 } else {
33024 buffer_append_string_len(out, host->ptr, dp - host->ptr);
33025 }
33026 }
33027- BUFFER_APPEND_SLASH(out);
33028-
33029+ PATHNAME_APPEND_SLASH(out);
33030+
33031 if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
33032 buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
33033 } else {
33034 buffer_append_string_buffer(out, p->conf.document_root);
33035- BUFFER_APPEND_SLASH(out);
33036+ PATHNAME_APPEND_SLASH(out);
33037 }
33038 } else {
33039 buffer_copy_string_buffer(out, con->conf.document_root);
33040- BUFFER_APPEND_SLASH(out);
33041+ PATHNAME_APPEND_SLASH(out);
33042 }
33043-
33044+
33045 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
33046 if (p->conf.debug) {
33047 log_error_write(srv, __FILE__, __LINE__, "sb",
33048@@ -169,57 +171,53 @@
33049 } else if (!S_ISDIR(sce->st.st_mode)) {
33050 return -1;
33051 }
33052-
33053+
33054 return 0;
33055 }
33056
33057-
33058-#define PATCH(x) \
33059- p->conf.x = s->x;
33060 static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
33061 size_t i, j;
33062 plugin_config *s = p->config_storage[0];
33063-
33064- PATCH(server_root);
33065- PATCH(default_host);
33066- PATCH(document_root);
33067-
33068- PATCH(docroot_cache_key);
33069- PATCH(docroot_cache_value);
33070- PATCH(docroot_cache_servername);
33071
33072- PATCH(debug);
33073-
33074+ PATCH_OPTION(server_root);
33075+ PATCH_OPTION(default_host);
33076+ PATCH_OPTION(document_root);
33077+
33078+ PATCH_OPTION(docroot_cache_key);
33079+ PATCH_OPTION(docroot_cache_value);
33080+ PATCH_OPTION(docroot_cache_servername);
33081+
33082+ PATCH_OPTION(debug);
33083+
33084 /* skip the first, the global context */
33085 for (i = 1; i < srv->config_context->used; i++) {
33086 data_config *dc = (data_config *)srv->config_context->data[i];
33087 s = p->config_storage[i];
33088-
33089+
33090 /* condition didn't match */
33091 if (!config_check_cond(srv, con, dc)) continue;
33092-
33093+
33094 /* merge config */
33095 for (j = 0; j < dc->value->used; j++) {
33096 data_unset *du = dc->value->data[j];
33097-
33098+
33099 if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
33100- PATCH(server_root);
33101- PATCH(docroot_cache_key);
33102- PATCH(docroot_cache_value);
33103- PATCH(docroot_cache_servername);
33104+ PATCH_OPTION(server_root);
33105+ PATCH_OPTION(docroot_cache_key);
33106+ PATCH_OPTION(docroot_cache_value);
33107+ PATCH_OPTION(docroot_cache_servername);
33108 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
33109- PATCH(default_host);
33110+ PATCH_OPTION(default_host);
33111 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
33112- PATCH(document_root);
33113+ PATCH_OPTION(document_root);
33114 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
33115- PATCH(debug);
33116+ PATCH_OPTION(debug);
33117 }
33118 }
33119 }
33120-
33121+
33122 return 0;
33123 }
33124-#undef PATCH
33125
33126 static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
33127 plugin_data *p = p_data;
33128@@ -227,12 +225,12 @@
33129 /*
33130 * cache the last successfull translation from hostname (authority) to docroot
33131 * - this saves us a stat() call
33132- *
33133+ *
33134 */
33135-
33136+
33137 mod_simple_vhost_patch_connection(srv, con, p);
33138-
33139- if (p->conf.docroot_cache_key->used &&
33140+
33141+ if (p->conf.docroot_cache_key->used &&
33142 con->uri.authority->used &&
33143 buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
33144 /* cache hit */
33145@@ -243,8 +241,8 @@
33146 if ((con->uri.authority->used == 0) ||
33147 build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
33148 /* not found, fallback the default-host */
33149- if (build_doc_root(srv, con, p,
33150- p->doc_root,
33151+ if (build_doc_root(srv, con, p,
33152+ p->doc_root,
33153 p->conf.default_host)) {
33154 return HANDLER_GO_ON;
33155 } else {
33156@@ -253,15 +251,15 @@
33157 } else {
33158 buffer_copy_string_buffer(con->server_name, con->uri.authority);
33159 }
33160-
33161+
33162 /* copy to cache */
33163 buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority);
33164 buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root);
33165 buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
33166-
33167+
33168 buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
33169 }
33170-
33171+
33172 return HANDLER_GO_ON;
33173 }
33174
33175@@ -269,13 +267,13 @@
33176 int mod_simple_vhost_plugin_init(plugin *p) {
33177 p->version = LIGHTTPD_VERSION_ID;
33178 p->name = buffer_init_string("simple_vhost");
33179-
33180+
33181 p->init = mod_simple_vhost_init;
33182 p->set_defaults = mod_simple_vhost_set_defaults;
33183 p->handle_docroot = mod_simple_vhost_docroot;
33184 p->cleanup = mod_simple_vhost_free;
33185-
33186+
33187 p->data = NULL;
33188-
33189+
33190 return 0;
33191 }
1175ccec 33192--- ../lighttpd-1.4.11/src/mod_skeleton.c 2005-10-02 18:30:51.000000000 +0300
36e2a29e 33193+++ lighttpd-1.4.12/src/mod_skeleton.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
33194@@ -14,13 +14,13 @@
33195
33196 /**
33197 * this is a skeleton for a lighttpd plugin
33198- *
33199+ *
33200 * just replaces every occurance of 'skeleton' by your plugin name
33201- *
33202+ *
33203 * e.g. in vim:
33204- *
33205+ *
33206 * :%s/skeleton/myhandler/
33207- *
33208+ *
33209 */
33210
33211
33212@@ -33,12 +33,12 @@
33213
33214 typedef struct {
33215 PLUGIN_DATA;
33216-
33217+
33218 buffer *match_buf;
33219-
33220+
33221 plugin_config **config_storage;
33222-
33223- plugin_config conf;
33224+
33225+ plugin_config conf;
33226 } plugin_data;
33227
33228 typedef struct {
33229@@ -47,36 +47,36 @@
33230
33231 static handler_ctx * handler_ctx_init() {
33232 handler_ctx * hctx;
33233-
33234+
33235 hctx = calloc(1, sizeof(*hctx));
33236-
33237+
33238 return hctx;
33239 }
33240
33241 static void handler_ctx_free(handler_ctx *hctx) {
33242-
33243+
33244 free(hctx);
33245 }
33246
33247 /* init the plugin data */
33248 INIT_FUNC(mod_skeleton_init) {
33249 plugin_data *p;
33250-
33251+
33252 p = calloc(1, sizeof(*p));
33253-
33254+
33255 p->match_buf = buffer_init();
33256-
33257+
33258 return p;
33259 }
33260
33261 /* detroy the plugin data */
33262 FREE_FUNC(mod_skeleton_free) {
33263 plugin_data *p = p_d;
33264-
33265+
33266 UNUSED(srv);
33267
33268 if (!p) return HANDLER_GO_ON;
33269-
33270+
33271 if (p->config_storage) {
33272 size_t i;
33273
33274@@ -84,18 +84,18 @@
33275 plugin_config *s = p->config_storage[i];
33276
33277 if (!s) continue;
33278-
33279+
33280 array_free(s->match);
33281-
33282+
33283 free(s);
33284 }
33285 free(p->config_storage);
33286 }
33287-
33288+
33289 buffer_free(p->match_buf);
33290-
33291+
33292 free(p);
33293-
33294+
33295 return HANDLER_GO_ON;
33296 }
33297
33298@@ -104,91 +104,88 @@
33299 SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
33300 plugin_data *p = p_d;
33301 size_t i = 0;
33302-
33303- config_values_t cv[] = {
33304+
33305+ config_values_t cv[] = {
33306 { "skeleton.array", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
33307 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33308 };
33309-
33310+
33311 if (!p) return HANDLER_ERROR;
33312-
33313+
33314 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33315-
33316+
33317 for (i = 0; i < srv->config_context->used; i++) {
33318 plugin_config *s;
33319-
33320+
33321 s = calloc(1, sizeof(plugin_config));
33322 s->match = array_init();
33323-
33324+
33325 cv[0].destination = s->match;
33326-
33327+
33328 p->config_storage[i] = s;
33329-
33330+
33331 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33332 return HANDLER_ERROR;
33333 }
33334 }
33335-
33336+
33337 return HANDLER_GO_ON;
33338 }
33339
33340-#define PATCH(x) \
33341- p->conf.x = s->x;
33342 static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
33343 size_t i, j;
33344 plugin_config *s = p->config_storage[0];
33345-
33346- PATCH(match);
33347-
33348+
33349+ PATCH_OPTION(match);
33350+
33351 /* skip the first, the global context */
33352 for (i = 1; i < srv->config_context->used; i++) {
33353 data_config *dc = (data_config *)srv->config_context->data[i];
33354 s = p->config_storage[i];
33355-
33356+
33357 /* condition didn't match */
33358 if (!config_check_cond(srv, con, dc)) continue;
33359-
33360+
33361 /* merge config */
33362 for (j = 0; j < dc->value->used; j++) {
33363 data_unset *du = dc->value->data[j];
33364-
33365+
33366 if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
33367- PATCH(match);
33368+ PATCH_OPTION(match);
33369 }
33370 }
33371 }
33372-
33373+
33374 return 0;
33375 }
33376-#undef PATCH
33377
33378 URIHANDLER_FUNC(mod_skeleton_uri_handler) {
33379 plugin_data *p = p_d;
33380 int s_len;
33381 size_t k, i;
33382-
33383+
33384 UNUSED(srv);
33385
33386 if (con->uri.path->used == 0) return HANDLER_GO_ON;
33387-
33388+
33389 mod_skeleton_patch_connection(srv, con, p);
33390
33391 s_len = con->uri.path->used - 1;
33392-
33393+
33394 for (k = 0; k < p->conf.match->used; k++) {
33395 data_string *ds = (data_string *)p->conf.match->data[k];
33396 int ct_len = ds->value->used - 1;
33397-
33398+
33399 if (ct_len > s_len) continue;
33400 if (ds->value->used == 0) continue;
33401-
33402+
33403 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
33404 con->http_status = 403;
33405-
33406+
33407 return HANDLER_FINISHED;
33408 }
33409 }
33410-
33411+
33412 /* not found */
33413 return HANDLER_GO_ON;
33414 }
33415@@ -198,13 +195,13 @@
33416 int mod_skeleton_plugin_init(plugin *p) {
33417 p->version = LIGHTTPD_VERSION_ID;
33418 p->name = buffer_init_string("skeleton");
33419-
33420+
33421 p->init = mod_skeleton_init;
33422 p->handle_uri_clean = mod_skeleton_uri_handler;
33423 p->set_defaults = mod_skeleton_set_defaults;
33424 p->cleanup = mod_skeleton_free;
33425-
33426+
33427 p->data = NULL;
33428-
33429+
33430 return 0;
33431 }
1175ccec 33432--- ../lighttpd-1.4.11/src/mod_sql_vhost_core.c 1970-01-01 03:00:00.000000000 +0300
36e2a29e 33433+++ lighttpd-1.4.12/src/mod_sql_vhost_core.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
33434@@ -0,0 +1,209 @@
33435+#include <stdio.h>
33436+#include <errno.h>
33437+#include <fcntl.h>
33438+#include <string.h>
33439+
33440+#ifdef HAVE_CONFIG_H
33441+#include "config.h"
33442+#endif
33443+
33444+#include "plugin.h"
33445+#include "log.h"
33446+
33447+#include "stat_cache.h"
33448+
33449+#include "mod_sql_vhost_core.h"
33450+
33451+#define plugin_data mod_sql_vhost_core_plugin_data
33452+#define plugin_config mod_sql_vhost_core_plugin_config
33453+
33454+/* init the plugin data */
33455+INIT_FUNC(mod_sql_vhost_core_init) {
33456+ plugin_data *p;
33457+
33458+ p = calloc(1, sizeof(*p));
33459+
33460+ p->docroot = buffer_init();
33461+ p->host = buffer_init();
33462+
33463+ return p;
33464+}
33465+
33466+/* cleanup the plugin data */
33467+SERVER_FUNC(mod_sql_vhost_core_cleanup) {
33468+ plugin_data *p = p_d;
33469+
33470+ UNUSED(srv);
33471+
33472+ if (!p) return HANDLER_GO_ON;
33473+
33474+ if (p->config_storage) {
33475+ size_t i;
33476+ for (i = 0; i < srv->config_context->used; i++) {
33477+ plugin_config *s = p->config_storage[i];
33478+
33479+ if (!s) continue;
33480+
33481+ buffer_free(s->db);
33482+ buffer_free(s->user);
33483+ buffer_free(s->pass);
33484+ buffer_free(s->sock);
33485+ buffer_free(s->backend);
33486+
33487+ free(s);
33488+ }
33489+ free(p->config_storage);
33490+ }
33491+ buffer_free(p->docroot);
33492+ buffer_free(p->host);
33493+
33494+ free(p);
33495+
33496+ return HANDLER_GO_ON;
33497+}
33498+
33499+/* set configuration values */
33500+SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
33501+ plugin_data *p = p_d;
33502+
33503+ size_t i = 0;
33504+
33505+ config_values_t cv[] = {
33506+ { "sql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
33507+ { "sql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
33508+ { "sql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
33509+ { "sql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
33510+ { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
33511+ { "sql-vhost.hostname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
33512+ { "sql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
33513+ { "sql-vhost.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
33514+
33515+ /* backward compat */
33516+ { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
33517+ { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
33518+ { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
33519+ { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
33520+ { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
33521+ { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
33522+ { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
33523+
33524+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33525+ };
33526+
33527+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33528+
33529+ for (i = 0; i < srv->config_context->used; i++) {
33530+ plugin_config *s;
33531+
33532+ s = calloc(1, sizeof(plugin_config));
33533+ s->db = buffer_init();
33534+ s->user = buffer_init();
33535+ s->pass = buffer_init();
33536+ s->sock = buffer_init();
33537+ s->hostname = buffer_init();
33538+ s->backend = buffer_init();
33539+ s->port = 0; /* default port for mysql */
33540+ s->select_vhost = buffer_init();
33541+ s->backend_data = NULL;
33542+
33543+ cv[0].destination = s->db;
33544+ cv[1].destination = s->user;
33545+ cv[2].destination = s->pass;
33546+ cv[3].destination = s->sock;
33547+ cv[4].destination = s->select_vhost;
33548+ cv[5].destination = s->hostname;
33549+ cv[6].destination = &(s->port);
33550+ cv[7].destination = s->backend;
33551+
33552+ /* backend compat */
33553+ cv[8].destination = cv[0].destination;
33554+ cv[9].destination = cv[1].destination;
33555+ cv[10].destination = cv[2].destination;
33556+ cv[11].destination = cv[3].destination;
33557+ cv[12].destination = cv[4].destination;
33558+ cv[13].destination = cv[5].destination;
33559+ cv[14].destination = cv[6].destination;
33560+
33561+ p->config_storage[i] = s;
33562+
33563+ if (config_insert_values_global(srv,
33564+ ((data_config *)srv->config_context->data[i])->value,
33565+ cv)) return HANDLER_ERROR;
33566+
33567+ /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
33568+ }
33569+
33570+ return HANDLER_GO_ON;
33571+}
33572+
33573+static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
33574+ size_t i;
33575+ plugin_config *s = p->config_storage[0];
33576+
33577+ PATCH_OPTION(backend_data);
33578+ PATCH_OPTION(get_vhost);
33579+
33580+ /* skip the first, the global context */
33581+ for (i = 1; i < srv->config_context->used; i++) {
33582+ data_config *dc = (data_config *)srv->config_context->data[i];
33583+ s = p->config_storage[i];
33584+
33585+ /* condition didn't match */
33586+ if (!config_check_cond(srv, con, dc)) continue;
33587+
33588+ if (s->backend_data) {
33589+ PATCH_OPTION(backend_data);
33590+ PATCH_OPTION(get_vhost);
33591+ }
33592+ }
33593+
33594+ return 0;
33595+}
33596+
33597+/* handle document root request */
33598+CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
33599+ plugin_data *p = p_d;
33600+ stat_cache_entry *sce;
33601+
33602+ /* no host specified? */
33603+ if (!con->uri.authority->used) return HANDLER_GO_ON;
33604+
33605+ mod_sql_vhost_core_patch_connection(srv, con, p);
33606+
33607+ /* do we have backend ? */
33608+ if (!p->conf.get_vhost) return HANDLER_GO_ON;
33609+
33610+ /* ask the backend for the data */
33611+ if (0 != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
33612+ return HANDLER_GO_ON;
33613+ }
33614+
33615+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
33616+ log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->docroot);
33617+ return HANDLER_GO_ON;
33618+ }
33619+ if (!S_ISDIR(sce->st.st_mode)) {
33620+ log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->docroot);
33621+ return HANDLER_GO_ON;
33622+ }
33623+
33624+ buffer_copy_string_buffer(con->server_name, p->host);
33625+ buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
33626+
33627+ return HANDLER_GO_ON;
33628+}
33629+
33630+/* this function is called at dlopen() time and inits the callbacks */
33631+int mod_sql_vhost_core_plugin_init(plugin *p) {
33632+ p->version = LIGHTTPD_VERSION_ID;
33633+ p->name = buffer_init_string("mod_sql_vhost_core");
33634+
33635+ p->init = mod_sql_vhost_core_init;
33636+ p->cleanup = mod_sql_vhost_core_cleanup;
33637+
33638+ p->set_defaults = mod_sql_vhost_core_set_defaults;
33639+ p->handle_docroot = mod_sql_vhost_core_handle_docroot;
33640+
33641+ return 0;
33642+}
33643+
1175ccec 33644--- ../lighttpd-1.4.11/src/mod_sql_vhost_core.h 1970-01-01 03:00:00.000000000 +0300
36e2a29e 33645+++ lighttpd-1.4.12/src/mod_sql_vhost_core.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
33646@@ -0,0 +1,49 @@
33647+#ifndef _MOD_SQL_VHOST_CORE_H_
33648+#define _MOD_SQL_VHOST_CORE_H_
33649+
33650+#include "buffer.h"
33651+#include "plugin.h"
33652+
33653+#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
33654+ (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
33655+
33656+#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
33657+
33658+#define SQLVHOST_BACKEND_GETVHOST(name) \
33659+ SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
33660+
33661+#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
33662+ SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
33663+
33664+typedef struct {
33665+ buffer *db;
33666+ buffer *user;
33667+ buffer *pass;
33668+ buffer *sock;
33669+
33670+ buffer *hostname;
33671+ unsigned short port;
33672+
33673+ buffer *backend;
33674+ void *backend_data;
33675+
33676+ buffer *select_vhost;
33677+
33678+ SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
33679+} mod_sql_vhost_core_plugin_config;
33680+
33681+/* global plugin data */
33682+typedef struct {
33683+ PLUGIN_DATA;
33684+
33685+ buffer *docroot;
33686+ buffer *host;
33687+
33688+ mod_sql_vhost_core_plugin_config **config_storage;
33689+
33690+ mod_sql_vhost_core_plugin_config conf;
33691+} mod_sql_vhost_core_plugin_data;
33692+
33693+
33694+
33695+#endif
1175ccec 33696--- ../lighttpd-1.4.11/src/mod_ssi.c 2006-03-04 17:09:48.000000000 +0200
36e2a29e 33697+++ lighttpd-1.4.12/src/mod_ssi.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
33698@@ -6,7 +6,6 @@
33699 #include <string.h>
33700 #include <errno.h>
33701 #include <time.h>
33702-#include <unistd.h>
33703
33704 #include "base.h"
33705 #include "log.h"
33706@@ -23,6 +22,8 @@
33707 #include "inet_ntop_cache.h"
33708
33709 #include "sys-socket.h"
33710+#include "sys-strings.h"
33711+#include "sys-files.h"
33712
33713 #ifdef HAVE_PWD_H
33714 #include <pwd.h>
33715@@ -39,15 +40,15 @@
33716 /* init the plugin data */
33717 INIT_FUNC(mod_ssi_init) {
33718 plugin_data *p;
33719-
33720+
33721 p = calloc(1, sizeof(*p));
33722-
33723+
33724 p->timefmt = buffer_init();
33725 p->stat_fn = buffer_init();
33726-
33727+
33728 p->ssi_vars = array_init();
33729 p->ssi_cgi_env = array_init();
33730-
33731+
33732 return p;
33733 }
33734
33735@@ -55,21 +56,21 @@
33736 FREE_FUNC(mod_ssi_free) {
33737 plugin_data *p = p_d;
33738 UNUSED(srv);
33739-
33740+
33741 if (!p) return HANDLER_GO_ON;
33742-
33743+
33744 if (p->config_storage) {
33745 size_t i;
33746 for (i = 0; i < srv->config_context->used; i++) {
33747 plugin_config *s = p->config_storage[i];
33748-
33749+
33750 array_free(s->ssi_extension);
33751-
33752+
33753 free(s);
33754 }
33755 free(p->config_storage);
33756 }
33757-
33758+
33759 array_free(p->ssi_vars);
33760 array_free(p->ssi_cgi_env);
33761 #ifdef HAVE_PCRE_H
33762@@ -77,9 +78,9 @@
33763 #endif
33764 buffer_free(p->timefmt);
33765 buffer_free(p->stat_fn);
33766-
33767+
33768 free(p);
33769-
33770+
33771 return HANDLER_GO_ON;
33772 }
33773
33774@@ -92,36 +93,36 @@
33775 const char *errptr;
33776 int erroff;
33777 #endif
33778-
33779- config_values_t cv[] = {
33780+
33781+ config_values_t cv[] = {
33782 { "ssi.extension", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
33783 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33784 };
33785-
33786+
33787 if (!p) return HANDLER_ERROR;
33788-
33789+
33790 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33791-
33792+
33793 for (i = 0; i < srv->config_context->used; i++) {
33794 plugin_config *s;
33795-
33796+
33797 s = calloc(1, sizeof(plugin_config));
33798 s->ssi_extension = array_init();
33799-
33800+
33801 cv[0].destination = s->ssi_extension;
33802-
33803+
33804 p->config_storage[i] = s;
33805-
33806+
33807 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33808 return HANDLER_ERROR;
33809 }
33810 }
33811-
33812+
33813 #ifdef HAVE_PCRE_H
33814 /* allow 2 params */
33815 if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
33816 log_error_write(srv, __FILE__, __LINE__, "sds",
33817- "ssi: pcre ",
33818+ "ssi: pcre ",
33819 erroff, errptr);
33820 return HANDLER_ERROR;
33821 }
33822@@ -130,52 +131,52 @@
33823 "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
33824 return HANDLER_ERROR;
33825 #endif
33826-
33827+
33828 return HANDLER_GO_ON;
33829 }
33830
33831 int ssi_env_add(array *env, const char *key, const char *val) {
33832 data_string *ds;
33833-
33834+
33835 if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
33836 ds = data_string_init();
33837 }
33838 buffer_copy_string(ds->key, key);
33839 buffer_copy_string(ds->value, val);
33840-
33841+
33842 array_insert_unique(env, (data_unset *)ds);
33843-
33844+
33845 return 0;
33846 }
33847
33848 /**
33849 *
33850 * the next two functions are take from fcgi.c
33851- *
33852+ *
33853 */
33854
33855 static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
33856 size_t i;
33857-
33858+
33859 for (i = 0; i < con->request.headers->used; i++) {
33860 data_string *ds;
33861-
33862+
33863 ds = (data_string *)con->request.headers->data[i];
33864-
33865+
33866 if (ds->value->used && ds->key->used) {
33867 size_t j;
33868 buffer_reset(srv->tmp_buf);
33869-
33870+
33871 /* don't forward the Authorization: Header */
33872 if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
33873 continue;
33874 }
33875-
33876+
33877 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
33878 buffer_copy_string(srv->tmp_buf, "HTTP_");
33879 srv->tmp_buf->used--;
33880 }
33881-
33882+
33883 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
33884 for (j = 0; j < ds->key->used - 1; j++) {
33885 char c = '_';
33886@@ -189,33 +190,33 @@
33887 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
33888 }
33889 srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
33890-
33891+
33892 ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
33893 }
33894 }
33895-
33896+
33897 return 0;
33898 }
33899
33900 static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
33901 char buf[32];
33902-
33903+
33904 server_socket *srv_sock = con->srv_socket;
33905-
33906+
33907 #ifdef HAVE_IPV6
33908 char b2[INET6_ADDRSTRLEN + 1];
33909 #endif
33910
33911 #define CONST_STRING(x) \
33912 x
33913-
33914+
33915 array_reset(p->ssi_cgi_env);
33916-
33917+
33918 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
33919 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
33920 #ifdef HAVE_IPV6
33921- inet_ntop(srv_sock->addr.plain.sa_family,
33922- srv_sock->addr.plain.sa_family == AF_INET6 ?
33923+ inet_ntop(srv_sock->addr.plain.sa_family,
33924+ srv_sock->addr.plain.sa_family == AF_INET6 ?
33925 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
33926 (const void *) &(srv_sock->addr.ipv4.sin_addr),
33927 b2, sizeof(b2)-1)
33928@@ -224,28 +225,28 @@
33929 #endif
33930 );
33931 ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
33932-
33933- ltostr(buf,
33934+
33935+ ltostr(buf,
33936 #ifdef HAVE_IPV6
33937 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
33938 #else
33939 ntohs(srv_sock->addr.ipv4.sin_port)
33940 #endif
33941 );
33942-
33943+
33944 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
33945-
33946+
33947 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
33948 inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
33949-
33950+
33951 if (con->authed_user->used) {
33952 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
33953 con->authed_user->ptr);
33954 }
33955-
33956+
33957 if (con->request.content_length > 0) {
33958 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
33959-
33960+
33961 /* request.content_length < SSIZE_MAX, see request.c */
33962 ltostr(buf, con->request.content_length);
33963 ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
33964@@ -271,30 +272,30 @@
33965 if (con->request.pathinfo->used) {
33966 ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
33967 }
33968-
33969+
33970 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
33971 ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
33972-
33973+
33974 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
33975 ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
33976 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
33977 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
33978 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
33979-
33980+
33981 ssi_env_add_request_headers(srv, con, p);
33982-
33983+
33984 return 0;
33985 }
33986
33987-static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
33988+static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
33989 const char **l, size_t n) {
33990 size_t i, ssicmd = 0;
33991 char buf[255];
33992 buffer *b = NULL;
33993-
33994- struct {
33995+
33996+ struct {
33997 const char *var;
33998- enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
33999+ enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
34000 SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
34001 SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
34002 } ssicmds[] = {
34003@@ -310,27 +311,27 @@
34004 { "endif", SSI_ENDIF },
34005 { "else", SSI_ELSE },
34006 { "exec", SSI_EXEC },
34007-
34008+
34009 { NULL, SSI_UNSET }
34010 };
34011-
34012+
34013 for (i = 0; ssicmds[i].var; i++) {
34014 if (0 == strcmp(l[1], ssicmds[i].var)) {
34015 ssicmd = ssicmds[i].type;
34016 break;
34017 }
34018 }
34019-
34020+
34021 switch(ssicmd) {
34022 case SSI_ECHO: {
34023 /* echo */
34024 int var = 0, enc = 0;
34025 const char *var_val = NULL;
34026 stat_cache_entry *sce = NULL;
34027-
34028- struct {
34029+
34030+ struct {
34031 const char *var;
34032- enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
34033+ enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
34034 SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
34035 } echovars[] = {
34036 { "DATE_GMT", SSI_ECHO_DATE_GMT },
34037@@ -339,27 +340,27 @@
34038 { "DOCUMENT_URI", SSI_ECHO_DOCUMENT_URI },
34039 { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
34040 { "USER_NAME", SSI_ECHO_USER_NAME },
34041-
34042+
34043 { NULL, SSI_ECHO_UNSET }
34044 };
34045-
34046- struct {
34047+
34048+ struct {
34049 const char *var;
34050 enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
34051 } encvars[] = {
34052 { "url", SSI_ENC_URL },
34053 { "none", SSI_ENC_NONE },
34054 { "entity", SSI_ENC_ENTITY },
34055-
34056+
34057 { NULL, SSI_ENC_UNSET }
34058 };
34059-
34060+
34061 for (i = 2; i < n; i += 2) {
34062 if (0 == strcmp(l[i], "var")) {
34063 int j;
34064-
34065+
34066 var_val = l[i+1];
34067-
34068+
34069 for (j = 0; echovars[j].var; j++) {
34070 if (0 == strcmp(l[i+1], echovars[j].var)) {
34071 var = echovars[j].type;
34072@@ -368,7 +369,7 @@
34073 }
34074 } else if (0 == strcmp(l[i], "encoding")) {
34075 int j;
34076-
34077+
34078 for (j = 0; encvars[j].var; j++) {
34079 if (0 == strcmp(l[i+1], encvars[j].var)) {
34080 enc = encvars[j].type;
34081@@ -377,26 +378,26 @@
34082 }
34083 } else {
34084 log_error_write(srv, __FILE__, __LINE__, "sss",
34085- "ssi: unknow attribute for ",
34086+ "ssi: unknow attribute for ",
34087 l[1], l[i]);
34088 }
34089 }
34090-
34091+
34092 if (p->if_is_false) break;
34093-
34094+
34095 if (!var_val) {
34096 log_error_write(srv, __FILE__, __LINE__, "sss",
34097- "ssi: ",
34098+ "ssi: ",
34099 l[1], "var is missing");
34100 break;
34101 }
34102
34103 stat_cache_get_entry(srv, con, con->physical.path, &sce);
34104-
34105+
34106 switch(var) {
34107 case SSI_ECHO_USER_NAME: {
34108 struct passwd *pw;
34109-
34110+
34111 b = chunkqueue_get_append_buffer(con->write_queue);
34112 #ifdef HAVE_PWD_H
34113 if (NULL == (pw = getpwuid(sce->st.st_uid))) {
34114@@ -411,7 +412,7 @@
34115 }
34116 case SSI_ECHO_LAST_MODIFIED: {
34117 time_t t = sce->st.st_mtime;
34118-
34119+
34120 b = chunkqueue_get_append_buffer(con->write_queue);
34121 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34122 buffer_copy_string(b, "(none)");
34123@@ -422,7 +423,7 @@
34124 }
34125 case SSI_ECHO_DATE_LOCAL: {
34126 time_t t = time(NULL);
34127-
34128+
34129 b = chunkqueue_get_append_buffer(con->write_queue);
34130 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34131 buffer_copy_string(b, "(none)");
34132@@ -433,7 +434,7 @@
34133 }
34134 case SSI_ECHO_DATE_GMT: {
34135 time_t t = time(NULL);
34136-
34137+
34138 b = chunkqueue_get_append_buffer(con->write_queue);
34139 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
34140 buffer_copy_string(b, "(none)");
34141@@ -444,7 +445,7 @@
34142 }
34143 case SSI_ECHO_DOCUMENT_NAME: {
34144 char *sl;
34145-
34146+
34147 b = chunkqueue_get_append_buffer(con->write_queue);
34148 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34149 buffer_copy_string_buffer(b, con->physical.path);
34150@@ -461,15 +462,15 @@
34151 default: {
34152 data_string *ds;
34153 /* check if it is a cgi-var */
34154-
34155+
34156 b = chunkqueue_get_append_buffer(con->write_queue);
34157-
34158+
34159 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
34160 buffer_copy_string_buffer(b, ds->value);
34161 } else {
34162 buffer_copy_string(b, "(none)");
34163 }
34164-
34165+
34166 break;
34167 }
34168 }
34169@@ -481,7 +482,7 @@
34170 const char * file_path = NULL, *virt_path = NULL;
34171 struct stat st;
34172 char *sl;
34173-
34174+
34175 for (i = 2; i < n; i += 2) {
34176 if (0 == strcmp(l[i], "file")) {
34177 file_path = l[i+1];
34178@@ -489,28 +490,28 @@
34179 virt_path = l[i+1];
34180 } else {
34181 log_error_write(srv, __FILE__, __LINE__, "sss",
34182- "ssi: unknow attribute for ",
34183+ "ssi: unknow attribute for ",
34184 l[1], l[i]);
34185 }
34186 }
34187-
34188+
34189 if (!file_path && !virt_path) {
34190 log_error_write(srv, __FILE__, __LINE__, "sss",
34191- "ssi: ",
34192+ "ssi: ",
34193 l[1], "file or virtual are missing");
34194 break;
34195 }
34196-
34197+
34198 if (file_path && virt_path) {
34199 log_error_write(srv, __FILE__, __LINE__, "sss",
34200- "ssi: ",
34201+ "ssi: ",
34202 l[1], "only one of file and virtual is allowed here");
34203 break;
34204 }
34205-
34206-
34207+
34208+
34209 if (p->if_is_false) break;
34210-
34211+
34212 if (file_path) {
34213 /* current doc-root */
34214 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34215@@ -519,46 +520,46 @@
34216 buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
34217 }
34218
34219- buffer_copy_string(srv->tmp_buf, file_path);
34220+ buffer_copy_string(srv->tmp_buf, file_path);
34221 buffer_urldecode_path(srv->tmp_buf);
34222- buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
34223- buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34224+ buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
34225+ buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34226 } else {
34227 /* virtual */
34228-
34229+
34230 if (virt_path[0] == '/') {
34231 buffer_copy_string(p->stat_fn, virt_path);
34232 } else {
34233 /* there is always a / */
34234 sl = strrchr(con->uri.path->ptr, '/');
34235-
34236+
34237 buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
34238 buffer_append_string(p->stat_fn, virt_path);
34239 }
34240-
34241+
34242 buffer_urldecode_path(p->stat_fn);
34243 buffer_path_simplify(srv->tmp_buf, p->stat_fn);
34244-
34245+
34246 /* we have an uri */
34247-
34248+
34249 buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
34250 buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34251 }
34252-
34253+
34254 if (0 == stat(p->stat_fn->ptr, &st)) {
34255 time_t t = st.st_mtime;
34256-
34257+
34258 switch (ssicmd) {
34259 case SSI_FSIZE:
34260 b = chunkqueue_get_append_buffer(con->write_queue);
34261 if (p->sizefmt) {
34262 int j = 0;
34263 const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
34264-
34265+
34266 off_t s = st.st_size;
34267-
34268+
34269 for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
34270-
34271+
34272 buffer_copy_off_t(b, s);
34273 buffer_append_string(b, abr[j]);
34274 } else {
34275@@ -579,7 +580,7 @@
34276 }
34277 } else {
34278 log_error_write(srv, __FILE__, __LINE__, "sbs",
34279- "ssi: stating failed ",
34280+ "ssi: stating failed ",
34281 p->stat_fn, strerror(errno));
34282 }
34283 break;
34284@@ -593,33 +594,33 @@
34285 val = l[i+1];
34286 } else {
34287 log_error_write(srv, __FILE__, __LINE__, "sss",
34288- "ssi: unknow attribute for ",
34289+ "ssi: unknow attribute for ",
34290 l[1], l[i]);
34291 }
34292 }
34293-
34294+
34295 if (p->if_is_false) break;
34296-
34297+
34298 if (key && val) {
34299 data_string *ds;
34300-
34301+
34302 if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
34303 ds = data_string_init();
34304 }
34305 buffer_copy_string(ds->key, key);
34306 buffer_copy_string(ds->value, val);
34307-
34308+
34309 array_insert_unique(p->ssi_vars, (data_unset *)ds);
34310 } else {
34311 log_error_write(srv, __FILE__, __LINE__, "sss",
34312- "ssi: var and value have to be set in",
34313+ "ssi: var and value have to be set in",
34314 l[0], l[1]);
34315 }
34316 break;
34317 }
34318- case SSI_CONFIG:
34319+ case SSI_CONFIG:
34320 if (p->if_is_false) break;
34321-
34322+
34323 for (i = 2; i < n; i += 2) {
34324 if (0 == strcmp(l[i], "timefmt")) {
34325 buffer_copy_string(p->timefmt, l[i+1]);
34326@@ -632,63 +633,65 @@
34327 log_error_write(srv, __FILE__, __LINE__, "sssss",
34328 "ssi: unknow value for attribute '",
34329 l[i],
34330- "' for ",
34331+ "' for ",
34332 l[1], l[i+1]);
34333 }
34334 } else {
34335 log_error_write(srv, __FILE__, __LINE__, "sss",
34336- "ssi: unknow attribute for ",
34337+ "ssi: unknow attribute for ",
34338 l[1], l[i]);
34339 }
34340 }
34341 break;
34342 case SSI_PRINTENV:
34343 if (p->if_is_false) break;
34344-
34345+
34346 b = chunkqueue_get_append_buffer(con->write_queue);
34347 buffer_copy_string(b, "<pre>");
34348 for (i = 0; i < p->ssi_vars->used; i++) {
34349 data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
34350-
34351+
34352 buffer_append_string_buffer(b, ds->key);
34353 buffer_append_string(b, ": ");
34354 buffer_append_string_buffer(b, ds->value);
34355 buffer_append_string(b, "<br />");
34356-
34357+
34358 }
34359 buffer_append_string(b, "</pre>");
34360-
34361+
34362 break;
34363 case SSI_EXEC: {
34364+#ifndef _WIN32
34365+
34366 const char *cmd = NULL;
34367 pid_t pid;
34368 int from_exec_fds[2];
34369-
34370+
34371 for (i = 2; i < n; i += 2) {
34372 if (0 == strcmp(l[i], "cmd")) {
34373 cmd = l[i+1];
34374 } else {
34375 log_error_write(srv, __FILE__, __LINE__, "sss",
34376- "ssi: unknow attribute for ",
34377+ "ssi: unknow attribute for ",
34378 l[1], l[i]);
34379 }
34380 }
34381-
34382+
34383 if (p->if_is_false) break;
34384-
34385+
34386 /* create a return pipe and send output to the html-page
34387- *
34388- * as exec is assumed evil it is implemented synchronously
34389+ *
34390+ * as exec is assumed evil it is implemented synchronously
34391 */
34392-
34393+
34394 if (!cmd) break;
34395-#ifdef HAVE_FORK
34396+
34397 if (pipe(from_exec_fds)) {
34398- log_error_write(srv, __FILE__, __LINE__, "ss",
34399+ log_error_write(srv, __FILE__, __LINE__, "ss",
34400 "pipe failed: ", strerror(errno));
34401 return -1;
34402 }
34403-
34404+
34405 /* fork, execve */
34406 switch (pid = fork()) {
34407 case 0: {
34408@@ -698,14 +701,14 @@
34409 close(from_exec_fds[1]);
34410 /* not needed */
34411 close(from_exec_fds[0]);
34412-
34413+
34414 /* close stdin */
34415 close(STDIN_FILENO);
34416-
34417+
34418 execl("/bin/sh", "sh", "-c", cmd, NULL);
34419-
34420+
34421 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
34422-
34423+
34424 /* */
34425 SEGFAULT();
34426 break;
34427@@ -718,9 +721,9 @@
34428 /* father */
34429 int status;
34430 ssize_t r;
34431-
34432+
34433 close(from_exec_fds[1]);
34434-
34435+
34436 /* wait for the client to end */
34437 if (-1 == waitpid(pid, &status, 0)) {
34438 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
34439@@ -730,7 +733,7 @@
34440
34441 while(1) {
34442 if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
34443- log_error_write(srv, __FILE__, __LINE__, "s",
34444+ log_error_write(srv, __FILE__, __LINE__, "s",
34445 "unexpected end-of-file (perhaps the ssi-exec process died)");
34446 return -1;
34447 }
34448@@ -738,10 +741,10 @@
34449 if (toread > 0) {
34450 b = chunkqueue_get_append_buffer(con->write_queue);
34451
34452- buffer_prepare_copy(b, toread + 1);
34453+ buffer_prepare_copy(b, toread + 1);
34454
34455 if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
34456- /* read failed */
34457+ /* read failed */
34458 break;
34459 } else {
34460 b->used = r;
34461@@ -755,59 +758,58 @@
34462 log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
34463 }
34464 close(from_exec_fds[0]);
34465-
34466+
34467 break;
34468 }
34469 }
34470 #else
34471-
34472 return -1;
34473 #endif
34474-
34475+
34476 break;
34477 }
34478 case SSI_IF: {
34479 const char *expr = NULL;
34480-
34481+
34482 for (i = 2; i < n; i += 2) {
34483 if (0 == strcmp(l[i], "expr")) {
34484 expr = l[i+1];
34485 } else {
34486 log_error_write(srv, __FILE__, __LINE__, "sss",
34487- "ssi: unknow attribute for ",
34488+ "ssi: unknow attribute for ",
34489 l[1], l[i]);
34490 }
34491 }
34492-
34493+
34494 if (!expr) {
34495 log_error_write(srv, __FILE__, __LINE__, "sss",
34496- "ssi: ",
34497+ "ssi: ",
34498 l[1], "expr missing");
34499 break;
34500 }
34501-
34502+
34503 if ((!p->if_is_false) &&
34504- ((p->if_is_false_level == 0) ||
34505+ ((p->if_is_false_level == 0) ||
34506 (p->if_level < p->if_is_false_level))) {
34507 switch (ssi_eval_expr(srv, con, p, expr)) {
34508 case -1:
34509- case 0:
34510- p->if_is_false = 1;
34511+ case 0:
34512+ p->if_is_false = 1;
34513 p->if_is_false_level = p->if_level;
34514 break;
34515- case 1:
34516- p->if_is_false = 0;
34517+ case 1:
34518+ p->if_is_false = 0;
34519 break;
34520 }
34521 }
34522-
34523+
34524 p->if_level++;
34525-
34526+
34527 break;
34528 }
34529 case SSI_ELSE:
34530 p->if_level--;
34531-
34532+
34533 if (p->if_is_false) {
34534 if ((p->if_level == p->if_is_false_level) &&
34535 (p->if_is_false_endif == 0)) {
34536@@ -815,11 +817,11 @@
34537 }
34538 } else {
34539 p->if_is_false = 1;
34540-
34541+
34542 p->if_is_false_level = p->if_level;
34543 }
34544 p->if_level++;
34545-
34546+
34547 break;
34548 case SSI_ELIF: {
34549 const char *expr = NULL;
34550@@ -828,52 +830,52 @@
34551 expr = l[i+1];
34552 } else {
34553 log_error_write(srv, __FILE__, __LINE__, "sss",
34554- "ssi: unknow attribute for ",
34555+ "ssi: unknow attribute for ",
34556 l[1], l[i]);
34557 }
34558 }
34559-
34560+
34561 if (!expr) {
34562 log_error_write(srv, __FILE__, __LINE__, "sss",
34563- "ssi: ",
34564+ "ssi: ",
34565 l[1], "expr missing");
34566 break;
34567 }
34568-
34569+
34570 p->if_level--;
34571-
34572+
34573 if (p->if_level == p->if_is_false_level) {
34574 if ((p->if_is_false) &&
34575 (p->if_is_false_endif == 0)) {
34576 switch (ssi_eval_expr(srv, con, p, expr)) {
34577 case -1:
34578- case 0:
34579- p->if_is_false = 1;
34580+ case 0:
34581+ p->if_is_false = 1;
34582 p->if_is_false_level = p->if_level;
34583 break;
34584- case 1:
34585- p->if_is_false = 0;
34586+ case 1:
34587+ p->if_is_false = 0;
34588 break;
34589 }
34590 } else {
34591- p->if_is_false = 1;
34592+ p->if_is_false = 1;
34593 p->if_is_false_level = p->if_level;
34594 p->if_is_false_endif = 1;
34595 }
34596 }
34597-
34598+
34599 p->if_level++;
34600-
34601+
34602 break;
34603 }
34604 case SSI_ENDIF:
34605 p->if_level--;
34606-
34607+
34608 if (p->if_level == p->if_is_false_level) {
34609 p->if_is_false = 0;
34610 p->if_is_false_endif = 0;
34611 }
34612-
34613+
34614 break;
34615 default:
34616 log_error_write(srv, __FILE__, __LINE__, "ss",
34617@@ -881,41 +883,41 @@
34618 l[1]);
34619 break;
34620 }
34621-
34622+
34623 return 0;
34624-
34625+
34626 }
34627
34628 static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
34629 stream s;
34630 #ifdef HAVE_PCRE_H
34631 int i, n;
34632-
34633+
34634 #define N 10
34635 int ovec[N * 3];
34636 #endif
34637-
34638+
34639 /* get a stream to the file */
34640-
34641+
34642 array_reset(p->ssi_vars);
34643 array_reset(p->ssi_cgi_env);
34644 buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z");
34645 p->sizefmt = 0;
34646 build_ssi_cgi_vars(srv, con, p);
34647 p->if_is_false = 0;
34648-
34649+
34650 if (-1 == stream_open(&s, con->physical.path)) {
34651 log_error_write(srv, __FILE__, __LINE__, "sb",
34652 "stream-open: ", con->physical.path);
34653 return -1;
34654 }
34655-
34656-
34657+
34658+
34659 /**
34660- * <!--#element attribute=value attribute=value ... -->
34661- *
34662+ * <!--#element attribute=value attribute=value ... -->
34663+ *
34664 * config DONE
34665- * errmsg -- missing
34666+ * errmsg -- missing
34667 * sizefmt DONE
34668 * timefmt DONE
34669 * echo DONE
34670@@ -937,13 +939,13 @@
34671 * set DONE
34672 * var DONE
34673 * value DONE
34674- *
34675+ *
34676 * if DONE
34677 * elif DONE
34678 * else DONE
34679 * endif DONE
34680- *
34681- *
34682+ *
34683+ *
34684 * expressions
34685 * AND, OR DONE
34686 * comp DONE
34687@@ -951,118 +953,115 @@
34688 * $... DONE
34689 * '...' DONE
34690 * ( ... ) DONE
34691- *
34692- *
34693- *
34694+ *
34695+ *
34696+ *
34697 * ** all DONE **
34698- * DATE_GMT
34699- * The current date in Greenwich Mean Time.
34700- * DATE_LOCAL
34701- * The current date in the local time zone.
34702- * DOCUMENT_NAME
34703- * The filename (excluding directories) of the document requested by the user.
34704- * DOCUMENT_URI
34705- * The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document.
34706- * LAST_MODIFIED
34707- * The last modification date of the document requested by the user.
34708- * USER_NAME
34709+ * DATE_GMT
34710+ * The current date in Greenwich Mean Time.
34711+ * DATE_LOCAL
34712+ * The current date in the local time zone.
34713+ * DOCUMENT_NAME
34714+ * The filename (excluding directories) of the document requested by the user.
34715+ * DOCUMENT_URI
34716+ * The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document.
34717+ * LAST_MODIFIED
34718+ * The last modification date of the document requested by the user.
34719+ * USER_NAME
34720 * Contains the owner of the file which included it.
34721- *
34722+ *
34723 */
34724-#ifdef HAVE_PCRE_H
34725+#ifdef HAVE_PCRE_H
34726 for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
34727 const char **l;
34728 /* take everything from last offset to current match pos */
34729-
34730+
34731 if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
34732-
34733+
34734 pcre_get_substring_list(s.start, ovec, n, &l);
34735 process_ssi_stmt(srv, con, p, l, n);
34736 pcre_free_substring_list(l);
34737 }
34738-
34739+
34740 switch(n) {
34741 case PCRE_ERROR_NOMATCH:
34742 /* copy everything/the rest */
34743 chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
34744-
34745+
34746 break;
34747 default:
34748 log_error_write(srv, __FILE__, __LINE__, "sd",
34749 "execution error while matching: ", n);
34750 break;
34751 }
34752-#endif
34753-
34754-
34755+#endif
34756+
34757+
34758 stream_close(&s);
34759-
34760+
34761 con->file_started = 1;
34762 con->file_finished = 1;
34763-
34764+
34765 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
34766-
34767+
34768 /* reset physical.path */
34769 buffer_reset(con->physical.path);
34770-
34771+
34772 return 0;
34773 }
34774
34775-#define PATCH(x) \
34776- p->conf.x = s->x;
34777 static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
34778 size_t i, j;
34779 plugin_config *s = p->config_storage[0];
34780-
34781- PATCH(ssi_extension);
34782-
34783+
34784+ PATCH_OPTION(ssi_extension);
34785+
34786 /* skip the first, the global context */
34787 for (i = 1; i < srv->config_context->used; i++) {
34788 data_config *dc = (data_config *)srv->config_context->data[i];
34789 s = p->config_storage[i];
34790-
34791+
34792 /* condition didn't match */
34793 if (!config_check_cond(srv, con, dc)) continue;
34794-
34795+
34796 /* merge config */
34797 for (j = 0; j < dc->value->used; j++) {
34798 data_unset *du = dc->value->data[j];
34799-
34800+
34801 if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
34802- PATCH(ssi_extension);
34803+ PATCH_OPTION(ssi_extension);
34804 }
34805 }
34806 }
34807-
34808+
34809 return 0;
34810 }
34811-#undef PATCH
34812
34813 URIHANDLER_FUNC(mod_ssi_physical_path) {
34814 plugin_data *p = p_d;
34815 size_t k;
34816-
34817+
34818 if (con->physical.path->used == 0) return HANDLER_GO_ON;
34819-
34820+
34821 mod_ssi_patch_connection(srv, con, p);
34822-
34823+
34824 for (k = 0; k < p->conf.ssi_extension->used; k++) {
34825 data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
34826-
34827+
34828 if (ds->value->used == 0) continue;
34829-
34830+
34831 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
34832 /* handle ssi-request */
34833-
34834+
34835 if (mod_ssi_handle_request(srv, con, p)) {
34836 /* on error */
34837 con->http_status = 500;
34838 }
34839-
34840+
34841 return HANDLER_FINISHED;
34842 }
34843 }
34844-
34845+
34846 /* not found */
34847 return HANDLER_GO_ON;
34848 }
34849@@ -1072,13 +1071,13 @@
34850 int mod_ssi_plugin_init(plugin *p) {
34851 p->version = LIGHTTPD_VERSION_ID;
34852 p->name = buffer_init_string("ssi");
34853-
34854+
34855 p->init = mod_ssi_init;
34856 p->handle_subrequest_start = mod_ssi_physical_path;
34857 p->set_defaults = mod_ssi_set_defaults;
34858 p->cleanup = mod_ssi_free;
34859-
34860+
34861 p->data = NULL;
34862-
34863+
34864 return 0;
34865 }
1175ccec 34866--- ../lighttpd-1.4.11/src/mod_ssi.h 2005-08-11 01:26:39.000000000 +0300
36e2a29e 34867+++ lighttpd-1.4.12/src/mod_ssi.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
34868@@ -19,23 +19,23 @@
34869
34870 typedef struct {
34871 PLUGIN_DATA;
34872-
34873-#ifdef HAVE_PCRE_H
34874+
34875+#ifdef HAVE_PCRE_H
34876 pcre *ssi_regex;
34877-#endif
34878+#endif
34879 buffer *timefmt;
34880 int sizefmt;
34881-
34882+
34883 buffer *stat_fn;
34884-
34885+
34886 array *ssi_vars;
34887 array *ssi_cgi_env;
34888-
34889+
34890 int if_level, if_is_false_level, if_is_false, if_is_false_endif;
34891-
34892+
34893 plugin_config **config_storage;
34894-
34895- plugin_config conf;
34896+
34897+ plugin_config conf;
34898 } plugin_data;
34899
34900 int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
1175ccec 34901--- ../lighttpd-1.4.11/src/mod_ssi_expr.c 2005-08-11 01:26:48.000000000 +0300
36e2a29e 34902+++ lighttpd-1.4.12/src/mod_ssi_expr.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
34903@@ -11,9 +11,9 @@
34904 const char *input;
34905 size_t offset;
34906 size_t size;
34907-
34908+
34909 int line_pos;
34910-
34911+
34912 int in_key;
34913 int in_brace;
34914 int in_cond;
34915@@ -21,15 +21,15 @@
34916
34917 ssi_val_t *ssi_val_init() {
34918 ssi_val_t *s;
34919-
34920+
34921 s = calloc(1, sizeof(*s));
34922-
34923+
34924 return s;
34925 }
34926
34927 void ssi_val_free(ssi_val_t *s) {
34928 if (s->str) buffer_free(s->str);
34929-
34930+
34931 free(s);
34932 }
34933
34934@@ -45,175 +45,175 @@
34935 ssi_tokenizer_t *t, int *token_id, buffer *token) {
34936 int tid = 0;
34937 size_t i;
34938-
34939+
34940 UNUSED(con);
34941
34942 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
34943 char c = t->input[t->offset];
34944 data_string *ds;
34945-
34946+
34947 switch (c) {
34948- case '=':
34949+ case '=':
34950 tid = TK_EQ;
34951-
34952+
34953 t->offset++;
34954 t->line_pos++;
34955-
34956+
34957 buffer_copy_string(token, "(=)");
34958-
34959+
34960 break;
34961 case '>':
34962 if (t->input[t->offset + 1] == '=') {
34963 t->offset += 2;
34964 t->line_pos += 2;
34965-
34966+
34967 tid = TK_GE;
34968-
34969+
34970 buffer_copy_string(token, "(>=)");
34971 } else {
34972 t->offset += 1;
34973 t->line_pos += 1;
34974-
34975+
34976 tid = TK_GT;
34977-
34978+
34979 buffer_copy_string(token, "(>)");
34980 }
34981-
34982+
34983 break;
34984 case '<':
34985 if (t->input[t->offset + 1] == '=') {
34986 t->offset += 2;
34987 t->line_pos += 2;
34988-
34989+
34990 tid = TK_LE;
34991-
34992+
34993 buffer_copy_string(token, "(<=)");
34994 } else {
34995 t->offset += 1;
34996 t->line_pos += 1;
34997-
34998+
34999 tid = TK_LT;
35000-
35001+
35002 buffer_copy_string(token, "(<)");
35003 }
35004-
35005+
35006 break;
35007-
35008+
35009 case '!':
35010 if (t->input[t->offset + 1] == '=') {
35011 t->offset += 2;
35012 t->line_pos += 2;
35013-
35014+
35015 tid = TK_NE;
35016-
35017+
35018 buffer_copy_string(token, "(!=)");
35019 } else {
35020 t->offset += 1;
35021 t->line_pos += 1;
35022-
35023+
35024 tid = TK_NOT;
35025-
35026+
35027 buffer_copy_string(token, "(!)");
35028 }
35029-
35030+
35031 break;
35032 case '&':
35033 if (t->input[t->offset + 1] == '&') {
35034 t->offset += 2;
35035 t->line_pos += 2;
35036-
35037+
35038 tid = TK_AND;
35039-
35040+
35041 buffer_copy_string(token, "(&&)");
35042 } else {
35043- log_error_write(srv, __FILE__, __LINE__, "sds",
35044- "pos:", t->line_pos,
35045+ log_error_write(srv, __FILE__, __LINE__, "sds",
35046+ "pos:", t->line_pos,
35047 "missing second &");
35048 return -1;
35049 }
35050-
35051+
35052 break;
35053 case '|':
35054 if (t->input[t->offset + 1] == '|') {
35055 t->offset += 2;
35056 t->line_pos += 2;
35057-
35058+
35059 tid = TK_OR;
35060-
35061+
35062 buffer_copy_string(token, "(||)");
35063 } else {
35064- log_error_write(srv, __FILE__, __LINE__, "sds",
35065- "pos:", t->line_pos,
35066+ log_error_write(srv, __FILE__, __LINE__, "sds",
35067+ "pos:", t->line_pos,
35068 "missing second |");
35069 return -1;
35070 }
35071-
35072+
35073 break;
35074 case '\t':
35075 case ' ':
35076 t->offset++;
35077 t->line_pos++;
35078 break;
35079-
35080+
35081 case '\'':
35082 /* search for the terminating " */
35083 for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
35084-
35085+
35086 if (t->input[t->offset + i]) {
35087 tid = TK_VALUE;
35088-
35089+
35090 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35091-
35092+
35093 t->offset += i + 1;
35094 t->line_pos += i + 1;
35095 } else {
35096 /* ERROR */
35097-
35098- log_error_write(srv, __FILE__, __LINE__, "sds",
35099- "pos:", t->line_pos,
35100+
35101+ log_error_write(srv, __FILE__, __LINE__, "sds",
35102+ "pos:", t->line_pos,
35103 "missing closing quote");
35104-
35105+
35106 return -1;
35107 }
35108-
35109+
35110 break;
35111 case '(':
35112 t->offset++;
35113 t->in_brace++;
35114-
35115+
35116 tid = TK_LPARAN;
35117-
35118+
35119 buffer_copy_string(token, "(");
35120 break;
35121 case ')':
35122 t->offset++;
35123 t->in_brace--;
35124-
35125+
35126 tid = TK_RPARAN;
35127-
35128+
35129 buffer_copy_string(token, ")");
35130 break;
35131 case '$':
35132 if (t->input[t->offset + 1] == '{') {
35133 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
35134-
35135+
35136 if (t->input[t->offset + i] != '}') {
35137- log_error_write(srv, __FILE__, __LINE__, "sds",
35138- "pos:", t->line_pos,
35139+ log_error_write(srv, __FILE__, __LINE__, "sds",
35140+ "pos:", t->line_pos,
35141 "missing closing quote");
35142-
35143+
35144 return -1;
35145 }
35146-
35147+
35148 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
35149 } else {
35150 for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_'; i++);
35151-
35152+
35153 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35154 }
35155-
35156+
35157 tid = TK_VALUE;
35158-
35159+
35160 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
35161 buffer_copy_string_buffer(token, ds->value);
35162 } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
35163@@ -221,16 +221,16 @@
35164 } else {
35165 buffer_copy_string(token, "");
35166 }
35167-
35168+
35169 t->offset += i;
35170 t->line_pos += i;
35171-
35172+
35173 break;
35174 default:
35175 for (i = 0; isgraph(t->input[t->offset + i]); i++) {
35176 char d = t->input[t->offset + i];
35177 switch(d) {
35178- case ' ':
35179+ case ' ':
35180 case '\t':
35181 case ')':
35182 case '(':
35183@@ -244,25 +244,25 @@
35184 break;
35185 }
35186 }
35187-
35188+
35189 tid = TK_VALUE;
35190-
35191+
35192 buffer_copy_string_len(token, t->input + t->offset, i);
35193-
35194+
35195 t->offset += i;
35196 t->line_pos += i;
35197-
35198+
35199 break;
35200 }
35201 }
35202-
35203+
35204 if (tid) {
35205 *token_id = tid;
35206-
35207+
35208 return 1;
35209 } else if (t->offset < t->size) {
35210- log_error_write(srv, __FILE__, __LINE__, "sds",
35211- "pos:", t->line_pos,
35212+ log_error_write(srv, __FILE__, __LINE__, "sds",
35213+ "pos:", t->line_pos,
35214 "foobar");
35215 }
35216 return 0;
35217@@ -275,50 +275,50 @@
35218 buffer *token;
35219 ssi_ctx_t context;
35220 int ret;
35221-
35222+
35223 t.input = expr;
35224 t.offset = 0;
35225 t.size = strlen(expr);
35226 t.line_pos = 1;
35227-
35228+
35229 t.in_key = 1;
35230 t.in_brace = 0;
35231 t.in_cond = 0;
35232-
35233+
35234 context.ok = 1;
35235 context.srv = srv;
35236-
35237+
35238 /* default context */
35239-
35240+
35241 pParser = ssiexprparserAlloc( malloc );
35242 token = buffer_init();
35243 while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
35244 ssiexprparser(pParser, token_id, token, &context);
35245-
35246+
35247 token = buffer_init();
35248 }
35249 ssiexprparser(pParser, 0, token, &context);
35250 ssiexprparserFree(pParser, free );
35251-
35252+
35253 buffer_free(token);
35254-
35255+
35256 if (ret == -1) {
35257- log_error_write(srv, __FILE__, __LINE__, "s",
35258+ log_error_write(srv, __FILE__, __LINE__, "s",
35259 "expr parser failed");
35260 return -1;
35261 }
35262-
35263+
35264 if (context.ok == 0) {
35265- log_error_write(srv, __FILE__, __LINE__, "sds",
35266- "pos:", t.line_pos,
35267+ log_error_write(srv, __FILE__, __LINE__, "sds",
35268+ "pos:", t.line_pos,
35269 "parser failed somehow near here");
35270 return -1;
35271 }
35272 #if 0
35273- log_error_write(srv, __FILE__, __LINE__, "ssd",
35274+ log_error_write(srv, __FILE__, __LINE__, "ssd",
35275 "expr: ",
35276 expr,
35277 context.val.bo);
35278-#endif
35279+#endif
35280 return context.val.bo;
35281 }
1175ccec 35282--- ../lighttpd-1.4.11/src/mod_ssi_expr.h 2005-08-11 01:26:48.000000000 +0300
36e2a29e 35283+++ lighttpd-1.4.12/src/mod_ssi_expr.h 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
35284@@ -5,16 +5,16 @@
35285
35286 typedef struct {
35287 enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
35288-
35289+
35290 buffer *str;
35291 int bo;
35292 } ssi_val_t;
35293
35294 typedef struct {
35295 int ok;
35296-
35297+
35298 ssi_val_t val;
35299-
35300+
35301 void *srv;
35302 } ssi_ctx_t;
35303
1175ccec 35304--- ../lighttpd-1.4.11/src/mod_ssi_exprparser.c 2005-10-03 00:40:25.000000000 +0300
36e2a29e 35305+++ lighttpd-1.4.12/src/mod_ssi_exprparser.c 2006-07-11 22:08:02.000000000 +0300
2519e6e5
ER
35306@@ -18,10 +18,10 @@
35307 /* Next is all token values, in a form suitable for use by makeheaders.
35308 ** This section will be null unless lemon is run with the -m switch.
35309 */
35310-/*
35311+/*
35312 ** These constants (all generated automatically by the parser generator)
35313 ** specify the various kinds of tokens (terminals) that the parser
35314-** understands.
35315+** understands.
35316 **
35317 ** Each symbol here is a terminal symbol in the grammar.
35318 */
35319@@ -38,7 +38,7 @@
35320 ** and nonterminals. "int" is used otherwise.
35321 ** YYNOCODE is a number of type YYCODETYPE which corresponds
35322 ** to no legal terminal or nonterminal number. This
35323-** number is used to fill in empty slots of the hash
35324+** number is used to fill in empty slots of the hash
35325 ** table.
35326 ** YYFALLBACK If defined, this indicates that one or more tokens
35327 ** have fall-back values which should be used if the
35328@@ -47,7 +47,7 @@
35329 ** and nonterminal numbers. "unsigned char" is
35330 ** used if there are fewer than 250 rules and
35331 ** states combined. "int" is used otherwise.
35332-** ssiexprparserTOKENTYPE is the data type used for minor tokens given
35333+** ssiexprparserTOKENTYPE is the data type used for minor tokens given
35334 ** directly to the parser from the tokenizer.
35335 ** YYMINORTYPE is the data type used for all minor tokens.
35336 ** This is typically a union of many types, one of
35337@@ -91,7 +91,7 @@
35338 /* Next are that tables used to determine what action to take based on the
35339 ** current state and lookahead token. These tables are used to implement
35340 ** functions that take a state number and lookahead value and return an
35341-** action integer.
35342+** action integer.
35343 **
35344 ** Suppose the action integer is N. Then the action is determined as
35345 ** follows
35346@@ -116,7 +116,7 @@
35347 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
35348 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
35349 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
35350-** and that yy_default[S] should be used instead.
35351+** and that yy_default[S] should be used instead.
35352 **
35353 ** The formula above is for computing the action when the lookahead is
35354 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
35355@@ -168,7 +168,7 @@
35356
35357 /* The next table maps tokens into fallback tokens. If a construct
35358 ** like the following:
35359-**
35360+**
35361 ** %fallback ID X Y Z.
35362 **
35363 ** appears in the grammer, then ID becomes a fallback token for X, Y,
35364@@ -219,10 +219,10 @@
35365 #endif /* NDEBUG */
35366
35367 #ifndef NDEBUG
35368-/*
35369+/*
35370 ** Turn parser tracing on by giving a stream to which to write the trace
35371 ** and a prompt to preface each trace message. Tracing is turned off
35372-** by making either argument NULL
35373+** by making either argument NULL
35374 **
35375 ** Inputs:
35376 ** <ul>
35377@@ -247,7 +247,7 @@
35378 #ifndef NDEBUG
35379 /* For tracing shifts, the names of all terminals and nonterminals
35380 ** are required. The following table supplies these names */
35381-static const char *yyTokenName[] = {
35382+static const char *yyTokenName[] = {
35383 "$", "AND", "OR", "EQ",
35384 "NE", "GT", "GE", "LT",
35385 "LE", "NOT", "LPARAN", "RPARAN",
35386@@ -295,7 +295,7 @@
35387 #endif
35388 }
35389
35390-/*
35391+/*
35392 ** This function allocates a new parser.
35393 ** The only argument is a pointer to a function which works like
35394 ** malloc.
35395@@ -326,7 +326,7 @@
35396 /* Here is inserted the actions which take place when a
35397 ** terminal or non-terminal is destroyed. This can happen
35398 ** when the symbol is popped from the stack during a
35399- ** reduce or during error processing or when a parser is
35400+ ** reduce or during error processing or when a parser is
35401 ** being destroyed before it is finished parsing.
35402 **
35403 ** Note: during a reduce, the only symbols destroyed are those
35404@@ -379,7 +379,7 @@
35405 return yymajor;
35406 }
35407
35408-/*
35409+/*
35410 ** Deallocate and destroy a parser. Destructors are all called for
35411 ** all stack elements before shutting the parser down.
35412 **
35413@@ -415,7 +415,7 @@
35414 ){
35415 int i;
35416 int stateno = pParser->yystack[pParser->yyidx].stateno;
35417-
35418+
35419 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
35420 i = yy_shift_ofst[stateno];
35421 if( i==YY_SHIFT_USE_DFLT ){
35422@@ -459,7 +459,7 @@
35423 ){
35424 int i;
35425 int stateno = pParser->yystack[pParser->yyidx].stateno;
35426-
35427+
35428 i = yy_reduce_ofst[stateno];
35429 if( i==YY_REDUCE_USE_DFLT ){
35430 return yy_default[stateno];
35431@@ -559,7 +559,7 @@
35432 ssiexprparserARG_FETCH;
35433 yymsp = &yypParser->yystack[yypParser->yyidx];
35434 #ifndef NDEBUG
35435- if( yyTraceFILE && yyruleno>=0
35436+ if( yyTraceFILE && yyruleno>=0
35437 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
35438 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
35439 yyRuleName[yyruleno]);
35440@@ -872,7 +872,7 @@
35441 #ifdef YYERRORSYMBOL
35442 /* A syntax error has occurred.
35443 ** The response to an error depends upon whether or not the
35444- ** grammar defines an error token "ERROR".
35445+ ** grammar defines an error token "ERROR".
35446 **
35447 ** This is what we do if the grammar does define ERROR:
35448 **
1175ccec 35449--- ../lighttpd-1.4.11/src/mod_staticfile.c 2006-02-15 14:31:14.000000000 +0200
36e2a29e 35450+++ lighttpd-1.4.12/src/mod_staticfile.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
35451@@ -14,9 +14,11 @@
35452 #include "http_chunk.h"
35453 #include "response.h"
35454
35455+#include "sys-files.h"
35456+#include "sys-strings.h"
35457 /**
35458 * this is a staticfile for a lighttpd plugin
35459- *
35460+ *
35461 */
35462
35463
35464@@ -29,48 +31,48 @@
35465
35466 typedef struct {
35467 PLUGIN_DATA;
35468-
35469+
35470 buffer *range_buf;
35471-
35472+
35473 plugin_config **config_storage;
35474-
35475- plugin_config conf;
35476+
35477+ plugin_config conf;
35478 } plugin_data;
35479
35480 /* init the plugin data */
35481 INIT_FUNC(mod_staticfile_init) {
35482 plugin_data *p;
35483-
35484+
35485 p = calloc(1, sizeof(*p));
35486-
35487+
35488 p->range_buf = buffer_init();
35489-
35490+
35491 return p;
35492 }
35493
35494-/* detroy the plugin data */
35495+/* destroy the plugin data */
35496 FREE_FUNC(mod_staticfile_free) {
35497 plugin_data *p = p_d;
35498-
35499+
35500 UNUSED(srv);
35501
35502 if (!p) return HANDLER_GO_ON;
35503-
35504+
35505 if (p->config_storage) {
35506 size_t i;
35507 for (i = 0; i < srv->config_context->used; i++) {
35508 plugin_config *s = p->config_storage[i];
35509-
35510+
35511 array_free(s->exclude_ext);
35512-
35513+
35514 free(s);
35515 }
35516 free(p->config_storage);
35517 }
35518 buffer_free(p->range_buf);
35519-
35520+
35521 free(p);
35522-
35523+
35524 return HANDLER_GO_ON;
35525 }
35526
35527@@ -79,63 +81,60 @@
35528 SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
35529 plugin_data *p = p_d;
35530 size_t i = 0;
35531-
35532- config_values_t cv[] = {
35533+
35534+ config_values_t cv[] = {
35535 { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
35536 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
35537 };
35538-
35539+
35540 if (!p) return HANDLER_ERROR;
35541-
35542+
35543 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
35544-
35545+
35546 for (i = 0; i < srv->config_context->used; i++) {
35547 plugin_config *s;
35548-
35549+
35550 s = calloc(1, sizeof(plugin_config));
35551 s->exclude_ext = array_init();
35552-
35553+
35554 cv[0].destination = s->exclude_ext;
35555-
35556+
35557 p->config_storage[i] = s;
35558-
35559+
35560 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
35561 return HANDLER_ERROR;
35562 }
35563 }
35564-
35565+
35566 return HANDLER_GO_ON;
35567 }
35568
35569-#define PATCH(x) \
35570- p->conf.x = s->x;
35571 static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
35572 size_t i, j;
35573 plugin_config *s = p->config_storage[0];
35574-
35575- PATCH(exclude_ext);
35576-
35577+
35578+ PATCH_OPTION(exclude_ext);
35579+
35580 /* skip the first, the global context */
35581 for (i = 1; i < srv->config_context->used; i++) {
35582 data_config *dc = (data_config *)srv->config_context->data[i];
35583 s = p->config_storage[i];
35584-
35585+
35586 /* condition didn't match */
35587 if (!config_check_cond(srv, con, dc)) continue;
35588-
35589+
35590 /* merge config */
35591 for (j = 0; j < dc->value->used; j++) {
35592 data_unset *du = dc->value->data[j];
35593-
35594+
35595 if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
35596- PATCH(exclude_ext);
35597+ PATCH_OPTION(exclude_ext);
35598 }
35599 }
35600 }
35601-
35602+
35603 return 0;
35604 }
35605-#undef PATCH
35606
35607 static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
35608 int multipart = 0;
35609@@ -146,69 +145,69 @@
35610 data_string *ds;
35611 stat_cache_entry *sce = NULL;
35612 buffer *content_type = NULL;
35613-
35614+
35615 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35616 SEGFAULT();
35617 }
35618-
35619+
35620 start = 0;
35621 end = sce->st.st_size - 1;
35622-
35623+
35624 con->response.content_length = 0;
35625-
35626+
35627 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
35628 content_type = ds->value;
35629 }
35630-
35631+
35632 for (s = con->request.http_range, error = 0;
35633 !error && *s && NULL != (minus = strchr(s, '-')); ) {
35634 char *err;
35635 off_t la, le;
35636-
35637+
35638 if (s == minus) {
35639 /* -<stop> */
35640-
35641+
35642 le = strtoll(s, &err, 10);
35643-
35644+
35645 if (le == 0) {
35646 /* RFC 2616 - 14.35.1 */
35647-
35648+
35649 con->http_status = 416;
35650 error = 1;
35651 } else if (*err == '\0') {
35652 /* end */
35653 s = err;
35654-
35655+
35656 end = sce->st.st_size - 1;
35657 start = sce->st.st_size + le;
35658 } else if (*err == ',') {
35659 multipart = 1;
35660 s = err + 1;
35661-
35662+
35663 end = sce->st.st_size - 1;
35664 start = sce->st.st_size + le;
35665 } else {
35666 error = 1;
35667 }
35668-
35669+
35670 } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
35671 /* <start>- */
35672-
35673+
35674 la = strtoll(s, &err, 10);
35675-
35676+
35677 if (err == minus) {
35678 /* ok */
35679-
35680+
35681 if (*(err + 1) == '\0') {
35682 s = err + 1;
35683-
35684+
35685 end = sce->st.st_size - 1;
35686 start = la;
35687-
35688+
35689 } else if (*(err + 1) == ',') {
35690 multipart = 1;
35691 s = err + 2;
35692-
35693+
35694 end = sce->st.st_size - 1;
35695 start = la;
35696 } else {
35697@@ -220,64 +219,64 @@
35698 }
35699 } else {
35700 /* <start>-<stop> */
35701-
35702+
35703 la = strtoll(s, &err, 10);
35704-
35705+
35706 if (err == minus) {
35707 le = strtoll(minus+1, &err, 10);
35708-
35709+
35710 /* RFC 2616 - 14.35.1 */
35711 if (la > le) {
35712 error = 1;
35713 }
35714-
35715+
35716 if (*err == '\0') {
35717 /* ok, end*/
35718 s = err;
35719-
35720+
35721 end = le;
35722 start = la;
35723 } else if (*err == ',') {
35724 multipart = 1;
35725 s = err + 1;
35726-
35727+
35728 end = le;
35729 start = la;
35730 } else {
35731 /* error */
35732-
35733+
35734 error = 1;
35735 }
35736 } else {
35737 /* error */
35738-
35739+
35740 error = 1;
35741 }
35742 }
35743-
35744+
35745 if (!error) {
35746 if (start < 0) start = 0;
35747-
35748+
35749 /* RFC 2616 - 14.35.1 */
35750 if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
35751-
35752+
35753 if (start > sce->st.st_size - 1) {
35754 error = 1;
35755-
35756+
35757 con->http_status = 416;
35758 }
35759 }
35760-
35761+
35762 if (!error) {
35763 if (multipart) {
35764 /* write boundary-header */
35765 buffer *b;
35766-
35767+
35768 b = chunkqueue_get_append_buffer(con->write_queue);
35769-
35770+
35771 buffer_copy_string(b, "\r\n--");
35772 buffer_append_string(b, boundary);
35773-
35774+
35775 /* write Content-Range */
35776 buffer_append_string(b, "\r\nContent-Range: bytes ");
35777 buffer_append_off_t(b, start);
35778@@ -285,54 +284,54 @@
35779 buffer_append_off_t(b, end);
35780 buffer_append_string(b, "/");
35781 buffer_append_off_t(b, sce->st.st_size);
35782-
35783+
35784 buffer_append_string(b, "\r\nContent-Type: ");
35785 buffer_append_string_buffer(b, content_type);
35786-
35787+
35788 /* write END-OF-HEADER */
35789 buffer_append_string(b, "\r\n\r\n");
35790-
35791+
35792 con->response.content_length += b->used - 1;
35793-
35794+
35795 }
35796-
35797+
35798 chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
35799 con->response.content_length += end - start + 1;
35800 }
35801 }
35802-
35803+
35804 /* something went wrong */
35805 if (error) return -1;
35806-
35807+
35808 if (multipart) {
35809 /* add boundary end */
35810 buffer *b;
35811-
35812+
35813 b = chunkqueue_get_append_buffer(con->write_queue);
35814-
35815+
35816 buffer_copy_string_len(b, "\r\n--", 4);
35817 buffer_append_string(b, boundary);
35818 buffer_append_string_len(b, "--\r\n", 4);
35819-
35820+
35821 con->response.content_length += b->used - 1;
35822-
35823+
35824 /* set header-fields */
35825-
35826+
35827 buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
35828 buffer_append_string(p->range_buf, boundary);
35829-
35830+
35831 /* overwrite content-type */
35832 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
35833 } else {
35834 /* add Content-Range-header */
35835-
35836+
35837 buffer_copy_string(p->range_buf, "bytes ");
35838 buffer_append_off_t(p->range_buf, start);
35839 buffer_append_string(p->range_buf, "-");
35840 buffer_append_off_t(p->range_buf, end);
35841 buffer_append_string(p->range_buf, "/");
35842 buffer_append_off_t(p->range_buf, sce->st.st_size);
35843-
35844+
35845 response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
35846 }
35847
35848@@ -347,12 +346,12 @@
35849 stat_cache_entry *sce = NULL;
35850 buffer *mtime;
35851 data_string *ds;
35852-
35853+
35854 /* someone else has done a decision for us */
35855 if (con->http_status != 0) return HANDLER_GO_ON;
35856 if (con->uri.path->used == 0) return HANDLER_GO_ON;
35857 if (con->physical.path->used == 0) return HANDLER_GO_ON;
35858-
35859+
35860 /* someone else has handled this request */
35861 if (con->mode != DIRECT) return HANDLER_GO_ON;
35862
35863@@ -365,52 +364,52 @@
35864 default:
35865 return HANDLER_GO_ON;
35866 }
35867-
35868+
35869 mod_staticfile_patch_connection(srv, con, p);
35870-
35871+
35872 s_len = con->uri.path->used - 1;
35873-
35874+
35875 /* ignore certain extensions */
35876 for (k = 0; k < p->conf.exclude_ext->used; k++) {
35877- ds = (data_string *)p->conf.exclude_ext->data[k];
35878-
35879+ ds = (data_string *)p->conf.exclude_ext->data[k];
35880+
35881 if (ds->value->used == 0) continue;
35882
35883 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
35884 return HANDLER_GO_ON;
35885 }
35886 }
35887-
35888+
35889
35890 if (con->conf.log_request_handling) {
35891 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling file as static file");
35892 }
35893-
35894+
35895 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35896 con->http_status = 403;
35897-
35898+
35899 log_error_write(srv, __FILE__, __LINE__, "sbsb",
35900 "not a regular file:", con->uri.path,
35901 "->", con->physical.path);
35902-
35903+
35904 return HANDLER_FINISHED;
35905 }
35906-
35907- /* we only handline regular files */
35908+
35909+ /* we only handle regular files */
35910 if (!S_ISREG(sce->st.st_mode)) {
35911 con->http_status = 404;
35912-
35913+
35914 if (con->conf.log_file_not_found) {
35915 log_error_write(srv, __FILE__, __LINE__, "sbsb",
35916 "not a regular file:", con->uri.path,
35917 "->", sce->name);
35918 }
35919-
35920+
35921 return HANDLER_FINISHED;
35922 }
35923
35924- /* mod_compress might set several data directly, don't overwrite them */
35925-
35926+ /* mod_compress might set several parameters directly; don't overwrite them */
35927+
35928 /* set response content-type, if not set already */
35929
35930 if (NULL == array_get_element(con->response.headers, "Content-Type")) {
35931@@ -420,15 +419,15 @@
35932 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
35933 }
35934 }
35935-
35936+
35937 if (NULL == array_get_element(con->response.headers, "ETag")) {
35938 /* generate e-tag */
35939 etag_mutate(con->physical.etag, sce->etag);
35940-
35941+
35942 response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
35943 }
35944 response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
35945-
35946+
35947 /* prepare header */
35948 if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
35949 mtime = strftime_cache_get(srv, sce->st.st_mtime);
35950@@ -444,34 +443,34 @@
35951 /* check if we have a conditional GET */
35952
35953 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) {
35954- /* if the value is the same as our ETag, we do a Range-request,
35955+ /* if the value is the same as our ETag, we do a Range-request,
35956 * otherwise a full 200 */
35957
35958 if (!buffer_is_equal(ds->value, con->physical.etag)) {
35959 do_range_request = 0;
35960 }
35961 }
35962-
35963+
35964 if (do_range_request) {
35965 /* content prepared, I'm done */
35966 con->file_finished = 1;
35967-
35968+
35969 if (0 == http_response_parse_range(srv, con, p)) {
35970 con->http_status = 206;
35971 }
35972 return HANDLER_FINISHED;
35973 }
35974 }
35975-
35976+
35977 /* if we are still here, prepare body */
35978-
35979- /* we add it here for all requests
35980- * the HEAD request will drop it afterwards again
35981+
35982+ /* we add it here for all requests
35983+ * the HEAD request will drop it afterwards again
35984 */
35985 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
35986-
35987+
35988 con->file_finished = 1;
35989-
35990+
35991 return HANDLER_FINISHED;
35992 }
35993
35994@@ -480,13 +479,13 @@
35995 int mod_staticfile_plugin_init(plugin *p) {
35996 p->version = LIGHTTPD_VERSION_ID;
35997 p->name = buffer_init_string("staticfile");
35998-
35999+
36000 p->init = mod_staticfile_init;
36001 p->handle_subrequest_start = mod_staticfile_subrequest;
36002 p->set_defaults = mod_staticfile_set_defaults;
36003 p->cleanup = mod_staticfile_free;
36004-
36005+
36006 p->data = NULL;
36007-
36008+
36009 return 0;
36010 }
1175ccec 36011--- ../lighttpd-1.4.11/src/mod_status.c 2006-01-10 21:45:32.000000000 +0200
36e2a29e 36012+++ lighttpd-1.4.12/src/mod_status.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
36013@@ -4,7 +4,6 @@
36014 #include <fcntl.h>
36015 #include <stdlib.h>
36016 #include <string.h>
36017-#include <unistd.h>
36018 #include <errno.h>
36019 #include <time.h>
36020 #include <stdio.h>
36021@@ -29,114 +28,114 @@
36022
36023 typedef struct {
36024 PLUGIN_DATA;
36025-
36026+
36027 double traffic_out;
36028 double requests;
36029-
36030+
36031 double mod_5s_traffic_out[5];
36032 double mod_5s_requests[5];
36033 size_t mod_5s_ndx;
36034-
36035+
36036 double rel_traffic_out;
36037 double rel_requests;
36038-
36039+
36040 double abs_traffic_out;
36041 double abs_requests;
36042-
36043+
36044 double bytes_written;
36045-
36046+
36047 buffer *module_list;
36048-
36049+
36050 plugin_config **config_storage;
36051-
36052- plugin_config conf;
36053+
36054+ plugin_config conf;
36055 } plugin_data;
36056
36057 INIT_FUNC(mod_status_init) {
36058 plugin_data *p;
36059 size_t i;
36060-
36061+
36062 p = calloc(1, sizeof(*p));
36063-
36064+
36065 p->traffic_out = p->requests = 0;
36066 p->rel_traffic_out = p->rel_requests = 0;
36067 p->abs_traffic_out = p->abs_requests = 0;
36068 p->bytes_written = 0;
36069 p->module_list = buffer_init();
36070-
36071+
36072 for (i = 0; i < 5; i++) {
36073 p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
36074 }
36075-
36076+
36077 return p;
36078 }
36079
36080 FREE_FUNC(mod_status_free) {
36081 plugin_data *p = p_d;
36082-
36083+
36084 UNUSED(srv);
36085
36086 if (!p) return HANDLER_GO_ON;
36087-
36088+
36089 buffer_free(p->module_list);
36090-
36091+
36092 if (p->config_storage) {
36093 size_t i;
36094 for (i = 0; i < srv->config_context->used; i++) {
36095 plugin_config *s = p->config_storage[i];
36096-
36097+
36098 buffer_free(s->status_url);
36099 buffer_free(s->statistics_url);
36100 buffer_free(s->config_url);
36101-
36102+
36103 free(s);
36104 }
36105 free(p->config_storage);
36106 }
36107-
36108-
36109+
36110+
36111 free(p);
36112-
36113+
36114 return HANDLER_GO_ON;
36115 }
36116
36117 SETDEFAULTS_FUNC(mod_status_set_defaults) {
36118 plugin_data *p = p_d;
36119 size_t i;
36120-
36121- config_values_t cv[] = {
36122+
36123+ config_values_t cv[] = {
36124 { "status.status-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36125 { "status.config-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36126 { "status.enable-sort", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
36127 { "status.statistics-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36128 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36129 };
36130-
36131+
36132 if (!p) return HANDLER_ERROR;
36133-
36134+
36135 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36136-
36137+
36138 for (i = 0; i < srv->config_context->used; i++) {
36139 plugin_config *s;
36140-
36141+
36142 s = calloc(1, sizeof(plugin_config));
36143 s->config_url = buffer_init();
36144 s->status_url = buffer_init();
36145 s->sort = 1;
36146 s->statistics_url = buffer_init();
36147-
36148+
36149 cv[0].destination = s->status_url;
36150 cv[1].destination = s->config_url;
36151 cv[2].destination = &(s->sort);
36152 cv[3].destination = s->statistics_url;
36153-
36154+
36155 p->config_storage[i] = s;
36156-
36157+
36158 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36159 return HANDLER_ERROR;
36160 }
36161 }
36162-
36163+
36164 return HANDLER_GO_ON;
36165 }
36166
36167@@ -151,7 +150,7 @@
36168 buffer_append_string(b, value);
36169 BUFFER_APPEND_STRING_CONST(b, "</td>\n");
36170 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
36171-
36172+
36173 return 0;
36174 }
36175
36176@@ -161,13 +160,13 @@
36177 buffer_append_string(b, key);
36178 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36179 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
36180-
36181+
36182 return 0;
36183 }
36184
36185 static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
36186 plugin_data *p = p_d;
36187-
36188+
36189 if (p->conf.sort) {
36190 BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">");
36191 buffer_append_string(b, key);
36192@@ -177,13 +176,13 @@
36193 buffer_append_string(b, key);
36194 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36195 }
36196-
36197+
36198 return 0;
36199 }
36200
36201 static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
36202 *multiplier = ' ';
36203-
36204+
36205 if (*avg > size) { *avg /= size; *multiplier = 'k'; }
36206 if (*avg > size) { *avg /= size; *multiplier = 'M'; }
36207 if (*avg > size) { *avg /= size; *multiplier = 'G'; }
36208@@ -202,21 +201,21 @@
36209 size_t j;
36210 double avg;
36211 char multiplier = '\0';
36212- char buf[32];
36213+ char buf[128];
36214 time_t ts;
36215-
36216+
36217 int days, hours, mins, seconds;
36218-
36219+
36220 b = chunkqueue_get_append_buffer(con->write_queue);
36221
36222- BUFFER_COPY_STRING_CONST(b,
36223+ BUFFER_COPY_STRING_CONST(b,
36224 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36225 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36226 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36227 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
36228 " <head>\n"
36229 " <title>Status</title>\n");
36230-
36231+
36232 BUFFER_APPEND_STRING_CONST(b,
36233 " <style type=\"text/css\">\n"
36234 " table.status { border: black solid thin; }\n"
36235@@ -226,14 +225,14 @@
36236 " a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
36237 " span.sortarrow { color: white; text-decoration: none; }\n"
36238 " </style>\n");
36239-
36240+
36241 if (p->conf.sort) {
36242 BUFFER_APPEND_STRING_CONST(b,
36243 "<script type=\"text/javascript\">\n"
36244 "// <!--\n"
36245 "var sort_column;\n"
36246 "var prev_span = null;\n");
36247-
36248+
36249 BUFFER_APPEND_STRING_CONST(b,
36250 "function get_inner_text(el) {\n"
36251 " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
36252@@ -251,7 +250,7 @@
36253 " }\n"
36254 " return str;\n"
36255 "}\n");
36256-
36257+
36258 BUFFER_APPEND_STRING_CONST(b,
36259 "function sortfn(a,b) {\n"
36260 " var at = get_inner_text(a.cells[sort_column]);\n"
36261@@ -266,7 +265,7 @@
36262 " else return 1;\n"
36263 " }\n"
36264 "}\n");
36265-
36266+
36267 BUFFER_APPEND_STRING_CONST(b,
36268 "function resort(lnk) {\n"
36269 " var span = lnk.childNodes[1];\n"
36270@@ -276,7 +275,7 @@
36271 " rows[j-1] = table.rows[j];\n"
36272 " sort_column = lnk.parentNode.cellIndex;\n"
36273 " rows.sort(sortfn);\n");
36274-
36275+
36276 BUFFER_APPEND_STRING_CONST(b,
36277 " if (prev_span != null) prev_span.innerHTML = '';\n"
36278 " if (span.getAttribute('sortdir')=='down') {\n"
36279@@ -294,175 +293,175 @@
36280 "// -->\n"
36281 "</script>\n");
36282 }
36283-
36284- BUFFER_APPEND_STRING_CONST(b,
36285+
36286+ BUFFER_APPEND_STRING_CONST(b,
36287 " </head>\n"
36288 " <body>\n");
36289-
36290-
36291-
36292+
36293+
36294+
36295 /* connection listing */
36296 BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
36297-
36298- BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
36299- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
36300+
36301+ BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
36302+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
36303 buffer_append_string_buffer(b, con->uri.authority);
36304- BUFFER_APPEND_STRING_CONST(b, " (");
36305+ BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
36306 buffer_append_string_buffer(b, con->server_name);
36307- BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
36308- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
36309-
36310+ BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
36311+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
36312+
36313 ts = srv->cur_ts - srv->startup_ts;
36314-
36315+
36316 days = ts / (60 * 60 * 24);
36317 ts %= (60 * 60 * 24);
36318-
36319+
36320 hours = ts / (60 * 60);
36321 ts %= (60 * 60);
36322-
36323+
36324 mins = ts / (60);
36325 ts %= (60);
36326-
36327+
36328 seconds = ts;
36329-
36330+
36331 if (days) {
36332 buffer_append_long(b, days);
36333 BUFFER_APPEND_STRING_CONST(b, " days ");
36334 }
36335-
36336+
36337 if (hours) {
36338 buffer_append_long(b, hours);
36339 BUFFER_APPEND_STRING_CONST(b, " hours ");
36340 }
36341-
36342+
36343 if (mins) {
36344 buffer_append_long(b, mins);
36345 BUFFER_APPEND_STRING_CONST(b, " min ");
36346 }
36347-
36348+
36349 buffer_append_long(b, seconds);
36350 BUFFER_APPEND_STRING_CONST(b, " s");
36351-
36352+
36353 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36354 BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
36355-
36356+
36357 ts = srv->startup_ts;
36358-
36359- strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
36360+
36361+ strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
36362 buffer_append_string(b, buf);
36363 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36364-
36365-
36366+
36367+
36368 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
36369-
36370- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36371+
36372+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
36373 avg = p->abs_requests;
36374
36375 mod_status_get_multiplier(&avg, &multiplier, 1000);
36376-
36377+
36378 buffer_append_long(b, avg);
36379- BUFFER_APPEND_STRING_CONST(b, " ");
36380+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
36381 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36382- BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
36383-
36384- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36385+ BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
36386+
36387+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
36388 avg = p->abs_traffic_out;
36389
36390 mod_status_get_multiplier(&avg, &multiplier, 1024);
36391
36392 sprintf(buf, "%.2f", avg);
36393 buffer_append_string(b, buf);
36394- BUFFER_APPEND_STRING_CONST(b, " ");
36395+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_mult\">");
36396 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36397- BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
36398+ BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
36399
36400
36401
36402 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
36403-
36404- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36405+
36406+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
36407 avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
36408
36409 mod_status_get_multiplier(&avg, &multiplier, 1000);
36410
36411 buffer_append_long(b, avg);
36412- BUFFER_APPEND_STRING_CONST(b, " ");
36413+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
36414 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36415- BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36416-
36417- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36418+ BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36419+
36420+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
36421 avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
36422
36423 mod_status_get_multiplier(&avg, &multiplier, 1024);
36424
36425 sprintf(buf, "%.2f", avg);
36426 buffer_append_string(b, buf);
36427- BUFFER_APPEND_STRING_CONST(b, " ");
36428+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
36429 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36430- BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36431+ BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36432+
36433+
36434
36435-
36436-
36437 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n");
36438 for (j = 0, avg = 0; j < 5; j++) {
36439 avg += p->mod_5s_requests[j];
36440 }
36441-
36442+
36443 avg /= 5;
36444-
36445- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36446+
36447+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
36448
36449 mod_status_get_multiplier(&avg, &multiplier, 1000);
36450
36451 buffer_append_long(b, avg);
36452- BUFFER_APPEND_STRING_CONST(b, " ");
36453+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
36454 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36455-
36456- BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36457-
36458+
36459+ BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36460+
36461 for (j = 0, avg = 0; j < 5; j++) {
36462 avg += p->mod_5s_traffic_out[j];
36463 }
36464-
36465+
36466 avg /= 5;
36467-
36468- BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36469+
36470+ BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
36471
36472 mod_status_get_multiplier(&avg, &multiplier, 1024);
36473
36474 sprintf(buf, "%.2f", avg);
36475 buffer_append_string(b, buf);
36476- BUFFER_APPEND_STRING_CONST(b, " ");
36477+ BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
36478 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36479- BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36480-
36481+ BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36482+
36483 BUFFER_APPEND_STRING_CONST(b, "</table>\n");
36484-
36485-
36486+
36487+
36488 BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n");
36489 BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n");
36490 BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n");
36491 BUFFER_APPEND_STRING_CONST(b, "q = request-start, Q = request-end\n");
36492 BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
36493-
36494- BUFFER_APPEND_STRING_CONST(b, "<b>");
36495+
36496+ BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
36497 buffer_append_long(b, srv->conns->used);
36498- BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
36499-
36500+ BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
36501+
36502 for (j = 0; j < srv->conns->used; j++) {
36503 connection *c = srv->conns->ptr[j];
36504 const char *state = connection_get_short_state(c->state);
36505-
36506+
36507 buffer_append_string_len(b, state, 1);
36508-
36509+
36510 if (((j + 1) % 50) == 0) {
36511 BUFFER_APPEND_STRING_CONST(b, "\n");
36512 }
36513 }
36514-
36515+
36516 BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
36517-
36518- BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
36519+
36520+ BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
36521 BUFFER_APPEND_STRING_CONST(b, "<tr>");
36522 mod_status_header_append_sort(b, p_d, "Client IP");
36523 mod_status_header_append_sort(b, p_d, "Read");
36524@@ -473,16 +472,16 @@
36525 mod_status_header_append_sort(b, p_d, "URI");
36526 mod_status_header_append_sort(b, p_d, "File");
36527 BUFFER_APPEND_STRING_CONST(b, "</tr>\n");
36528-
36529+
36530 for (j = 0; j < srv->conns->used; j++) {
36531 connection *c = srv->conns->ptr[j];
36532-
36533- BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
36534-
36535+
36536+ BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
36537+
36538 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
36539-
36540- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36541-
36542+
36543+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
36544+
36545 if (con->request.content_length) {
36546 buffer_append_long(b, c->request_content_queue->bytes_in);
36547 BUFFER_APPEND_STRING_CONST(b, "/");
36548@@ -490,55 +489,55 @@
36549 } else {
36550 BUFFER_APPEND_STRING_CONST(b, "0/0");
36551 }
36552-
36553- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36554-
36555+
36556+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
36557+
36558 buffer_append_off_t(b, chunkqueue_written(c->write_queue));
36559 BUFFER_APPEND_STRING_CONST(b, "/");
36560 buffer_append_off_t(b, chunkqueue_length(c->write_queue));
36561-
36562- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36563-
36564+
36565+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
36566+
36567 buffer_append_string(b, connection_get_state(c->state));
36568-
36569- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36570-
36571+
36572+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
36573+
36574 buffer_append_long(b, srv->cur_ts - c->request_start);
36575-
36576- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36577-
36578+
36579+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
36580+
36581 if (buffer_is_empty(c->server_name)) {
36582 buffer_append_string_buffer(b, c->uri.authority);
36583 }
36584 else {
36585 buffer_append_string_buffer(b, c->server_name);
36586 }
36587-
36588- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36589-
36590+
36591+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
36592+
36593 if (!buffer_is_empty(c->uri.path)) {
36594 buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
36595 }
36596-
36597- BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36598-
36599+
36600+ BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
36601+
36602 buffer_append_string_buffer(b, c->physical.path);
36603-
36604+
36605 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36606 }
36607-
36608-
36609- BUFFER_APPEND_STRING_CONST(b,
36610+
36611+
36612+ BUFFER_APPEND_STRING_CONST(b,
36613 "</table>\n");
36614-
36615-
36616- BUFFER_APPEND_STRING_CONST(b,
36617+
36618+
36619+ BUFFER_APPEND_STRING_CONST(b,
36620 " </body>\n"
36621 "</html>\n"
36622 );
36623-
36624+
36625 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36626-
36627+
36628 return 0;
36629 }
36630
36631@@ -548,7 +547,7 @@
36632 buffer *b;
36633 double avg;
36634 time_t ts;
36635-
36636+
36637 b = chunkqueue_get_append_buffer(con->write_queue);
36638
36639 /* output total number of requests */
36640@@ -556,19 +555,19 @@
36641 avg = p->abs_requests;
36642 buffer_append_long(b, avg);
36643 BUFFER_APPEND_STRING_CONST(b, "\n");
36644-
36645+
36646 /* output total traffic out in kbytes */
36647 BUFFER_APPEND_STRING_CONST(b, "Total kBytes: ");
36648 avg = p->abs_traffic_out / 1024;
36649 buffer_append_long(b, avg);
36650 BUFFER_APPEND_STRING_CONST(b, "\n");
36651-
36652+
36653 /* output uptime */
36654 BUFFER_APPEND_STRING_CONST(b, "Uptime: ");
36655 ts = srv->cur_ts - srv->startup_ts;
36656 buffer_append_long(b, ts);
36657 BUFFER_APPEND_STRING_CONST(b, "\n");
36658-
36659+
36660 /* output busy servers */
36661 BUFFER_APPEND_STRING_CONST(b, "BusyServers: ");
36662 buffer_append_long(b, srv->conns->used);
36663@@ -577,7 +576,7 @@
36664 /* set text/plain output */
36665
36666 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36667-
36668+
36669 return 0;
36670 }
36671
36672@@ -591,10 +590,10 @@
36673 /* we have nothing to send */
36674 con->http_status = 204;
36675 con->file_finished = 1;
36676-
36677+
36678 return HANDLER_FINISHED;
36679 }
36680-
36681+
36682 b = chunkqueue_get_append_buffer(con->write_queue);
36683
36684 for (i = 0; i < st->used; i++) {
36685@@ -605,27 +604,27 @@
36686 buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
36687 buffer_append_string(b, "\n");
36688 }
36689-
36690+
36691 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36692-
36693+
36694 con->http_status = 200;
36695 con->file_finished = 1;
36696-
36697+
36698 return HANDLER_FINISHED;
36699 }
36700
36701
36702 static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
36703-
36704+
36705 if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
36706 mod_status_handle_server_status_text(srv, con, p_d);
36707 } else {
36708 mod_status_handle_server_status_html(srv, con, p_d);
36709 }
36710-
36711+
36712 con->http_status = 200;
36713 con->file_finished = 1;
36714-
36715+
36716 return HANDLER_FINISHED;
36717 }
36718
36719@@ -634,9 +633,9 @@
36720 plugin_data *p = p_d;
36721 buffer *b, *m = p->module_list;
36722 size_t i;
36723-
36724- struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36725- {
36726+
36727+ struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36728+ {
36729 /* - poll is most reliable
36730 * - select works everywhere
36731 * - linux-* are experimental
36732@@ -661,10 +660,10 @@
36733 #endif
36734 { FDEVENT_HANDLER_UNSET, NULL }
36735 };
36736-
36737+
36738 b = chunkqueue_get_append_buffer(con->write_queue);
36739-
36740- BUFFER_COPY_STRING_CONST(b,
36741+
36742+ BUFFER_COPY_STRING_CONST(b,
36743 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36744 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36745 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36746@@ -675,7 +674,7 @@
36747 " <body>\n"
36748 " <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
36749 " <table border=\"1\">\n");
36750-
36751+
36752 mod_status_header_append(b, "Server-Features");
36753 #ifdef HAVE_PCRE_H
36754 mod_status_row_append(b, "RegEx Conditionals", "enabled");
36755@@ -683,21 +682,21 @@
36756 mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
36757 #endif
36758 mod_status_header_append(b, "Network Engine");
36759-
36760+
36761 for (i = 0; event_handlers[i].name; i++) {
36762 if (event_handlers[i].et == srv->event_handler) {
36763 mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
36764 break;
36765 }
36766 }
36767-
36768+
36769 mod_status_header_append(b, "Config-File-Settings");
36770-
36771+
36772 for (i = 0; i < srv->plugins.used; i++) {
36773 plugin **ps = srv->plugins.ptr;
36774-
36775+
36776 plugin *pl = ps[i];
36777-
36778+
36779 if (i == 0) {
36780 buffer_copy_string_buffer(m, pl->name);
36781 } else {
36782@@ -705,137 +704,135 @@
36783 buffer_append_string_buffer(m, pl->name);
36784 }
36785 }
36786-
36787+
36788 mod_status_row_append(b, "Loaded Modules", m->ptr);
36789-
36790+
36791 BUFFER_APPEND_STRING_CONST(b, " </table>\n");
36792-
36793- BUFFER_APPEND_STRING_CONST(b,
36794+
36795+ BUFFER_APPEND_STRING_CONST(b,
36796 " </body>\n"
36797 "</html>\n"
36798 );
36799-
36800+
36801 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36802-
36803+
36804 con->http_status = 200;
36805 con->file_finished = 1;
36806-
36807+
36808 return HANDLER_FINISHED;
36809 }
36810
36811-#define PATCH(x) \
36812- p->conf.x = s->x;
36813 static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
36814 size_t i, j;
36815 plugin_config *s = p->config_storage[0];
36816-
36817- PATCH(status_url);
36818- PATCH(config_url);
36819- PATCH(sort);
36820- PATCH(statistics_url);
36821-
36822+
36823+ PATCH_OPTION(status_url);
36824+ PATCH_OPTION(config_url);
36825+ PATCH_OPTION(sort);
36826+ PATCH_OPTION(statistics_url);
36827+
36828 /* skip the first, the global context */
36829 for (i = 1; i < srv->config_context->used; i++) {
36830 data_config *dc = (data_config *)srv->config_context->data[i];
36831 s = p->config_storage[i];
36832-
36833+
36834 /* condition didn't match */
36835 if (!config_check_cond(srv, con, dc)) continue;
36836-
36837+
36838 /* merge config */
36839 for (j = 0; j < dc->value->used; j++) {
36840 data_unset *du = dc->value->data[j];
36841-
36842+
36843 if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
36844- PATCH(status_url);
36845+ PATCH_OPTION(status_url);
36846 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
36847- PATCH(config_url);
36848+ PATCH_OPTION(config_url);
36849 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
36850- PATCH(sort);
36851+ PATCH_OPTION(sort);
36852 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
36853- PATCH(statistics_url);
36854- }
36855+ PATCH_OPTION(statistics_url);
36856+ }
36857 }
36858 }
36859-
36860+
36861 return 0;
36862 }
36863
36864 static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
36865 plugin_data *p = p_d;
36866-
36867+
36868 mod_status_patch_connection(srv, con, p);
36869-
36870- if (!buffer_is_empty(p->conf.status_url) &&
36871+
36872+ if (!buffer_is_empty(p->conf.status_url) &&
36873 buffer_is_equal(p->conf.status_url, con->uri.path)) {
36874 return mod_status_handle_server_status(srv, con, p_d);
36875- } else if (!buffer_is_empty(p->conf.config_url) &&
36876+ } else if (!buffer_is_empty(p->conf.config_url) &&
36877 buffer_is_equal(p->conf.config_url, con->uri.path)) {
36878 return mod_status_handle_server_config(srv, con, p_d);
36879- } else if (!buffer_is_empty(p->conf.statistics_url) &&
36880+ } else if (!buffer_is_empty(p->conf.statistics_url) &&
36881 buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
36882 return mod_status_handle_server_statistics(srv, con, p_d);
36883 }
36884-
36885+
36886 return HANDLER_GO_ON;
36887 }
36888
36889 TRIGGER_FUNC(mod_status_trigger) {
36890 plugin_data *p = p_d;
36891 size_t i;
36892-
36893+
36894 /* check all connections */
36895 for (i = 0; i < srv->conns->used; i++) {
36896 connection *c = srv->conns->ptr[i];
36897-
36898+
36899 p->bytes_written += c->bytes_written_cur_second;
36900 }
36901-
36902+
36903 /* a sliding average */
36904 p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
36905 p->mod_5s_requests [p->mod_5s_ndx] = p->requests;
36906-
36907+
36908 p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
36909-
36910+
36911 p->abs_traffic_out += p->bytes_written;
36912 p->rel_traffic_out += p->bytes_written;
36913-
36914+
36915 p->bytes_written = 0;
36916-
36917+
36918 /* reset storage - second */
36919 p->traffic_out = 0;
36920 p->requests = 0;
36921-
36922+
36923 return HANDLER_GO_ON;
36924 }
36925
36926 REQUESTDONE_FUNC(mod_status_account) {
36927 plugin_data *p = p_d;
36928-
36929+
36930 UNUSED(srv);
36931
36932 p->requests++;
36933 p->rel_requests++;
36934 p->abs_requests++;
36935-
36936+
36937 p->bytes_written += con->bytes_written_cur_second;
36938-
36939+
36940 return HANDLER_GO_ON;
36941 }
36942
36943 int mod_status_plugin_init(plugin *p) {
36944 p->version = LIGHTTPD_VERSION_ID;
36945 p->name = buffer_init_string("status");
36946-
36947+
36948 p->init = mod_status_init;
36949 p->cleanup = mod_status_free;
36950 p->set_defaults= mod_status_set_defaults;
36951-
36952+
36953 p->handle_uri_clean = mod_status_handler;
36954 p->handle_trigger = mod_status_trigger;
36955 p->handle_request_done = mod_status_account;
36956-
36957+
36958 p->data = NULL;
36959-
36960+
36961 return 0;
36962 }
1175ccec 36963--- ../lighttpd-1.4.11/src/mod_trigger_b4_dl.c 2005-09-23 22:53:55.000000000 +0300
36e2a29e 36964+++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
36965@@ -24,18 +24,18 @@
36966
36967 /**
36968 * this is a trigger_b4_dl for a lighttpd plugin
36969- *
36970+ *
36971 */
36972
36973 /* plugin config for all request/connections */
36974
36975 typedef struct {
36976 buffer *db_filename;
36977-
36978+
36979 buffer *trigger_url;
36980 buffer *download_url;
36981 buffer *deny_url;
36982-
36983+
36984 array *mc_hosts;
36985 buffer *mc_namespace;
36986 #if defined(HAVE_PCRE_H)
36987@@ -46,58 +46,58 @@
36988 GDBM_FILE db;
36989 #endif
36990
36991-#if defined(HAVE_MEMCACHE_H)
36992+#if defined(HAVE_MEMCACHE_H)
36993 struct memcache *mc;
36994 #endif
36995-
36996+
36997 unsigned short trigger_timeout;
36998 unsigned short debug;
36999 } plugin_config;
37000
37001 typedef struct {
37002 PLUGIN_DATA;
37003-
37004+
37005 buffer *tmp_buf;
37006-
37007+
37008 plugin_config **config_storage;
37009-
37010- plugin_config conf;
37011+
37012+ plugin_config conf;
37013 } plugin_data;
37014
37015 /* init the plugin data */
37016 INIT_FUNC(mod_trigger_b4_dl_init) {
37017 plugin_data *p;
37018-
37019+
37020 p = calloc(1, sizeof(*p));
37021-
37022+
37023 p->tmp_buf = buffer_init();
37024-
37025+
37026 return p;
37027 }
37028
37029 /* detroy the plugin data */
37030 FREE_FUNC(mod_trigger_b4_dl_free) {
37031 plugin_data *p = p_d;
37032-
37033+
37034 UNUSED(srv);
37035
37036 if (!p) return HANDLER_GO_ON;
37037-
37038+
37039 if (p->config_storage) {
37040 size_t i;
37041 for (i = 0; i < srv->config_context->used; i++) {
37042 plugin_config *s = p->config_storage[i];
37043
37044 if (!s) continue;
37045-
37046+
37047 buffer_free(s->db_filename);
37048 buffer_free(s->download_url);
37049 buffer_free(s->trigger_url);
37050 buffer_free(s->deny_url);
37051-
37052+
37053 buffer_free(s->mc_namespace);
37054 array_free(s->mc_hosts);
37055-
37056+
37057 #if defined(HAVE_PCRE_H)
37058 if (s->trigger_regex) pcre_free(s->trigger_regex);
37059 if (s->download_regex) pcre_free(s->download_regex);
37060@@ -108,16 +108,16 @@
37061 #if defined(HAVE_MEMCACHE_H)
37062 if (s->mc) mc_free(s->mc);
37063 #endif
37064-
37065+
37066 free(s);
37067 }
37068 free(p->config_storage);
37069 }
37070-
37071+
37072 buffer_free(p->tmp_buf);
37073-
37074+
37075 free(p);
37076-
37077+
37078 return HANDLER_GO_ON;
37079 }
37080
37081@@ -126,9 +126,9 @@
37082 SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
37083 plugin_data *p = p_d;
37084 size_t i = 0;
37085-
37086-
37087- config_values_t cv[] = {
37088+
37089+
37090+ config_values_t cv[] = {
37091 { "trigger-before-download.gdbm-filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
37092 { "trigger-before-download.trigger-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
37093 { "trigger-before-download.download-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
37094@@ -139,18 +139,18 @@
37095 { "trigger-before-download.debug", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
37096 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37097 };
37098-
37099+
37100 if (!p) return HANDLER_ERROR;
37101-
37102+
37103 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37104-
37105+
37106 for (i = 0; i < srv->config_context->used; i++) {
37107 plugin_config *s;
37108 #if defined(HAVE_PCRE_H)
37109 const char *errptr;
37110 int erroff;
37111 #endif
37112-
37113+
37114 s = calloc(1, sizeof(plugin_config));
37115 s->db_filename = buffer_init();
37116 s->download_url = buffer_init();
37117@@ -158,7 +158,7 @@
37118 s->deny_url = buffer_init();
37119 s->mc_hosts = array_init();
37120 s->mc_namespace = buffer_init();
37121-
37122+
37123 cv[0].destination = s->db_filename;
37124 cv[1].destination = s->trigger_url;
37125 cv[2].destination = s->download_url;
37126@@ -167,41 +167,41 @@
37127 cv[5].destination = s->mc_hosts;
37128 cv[6].destination = s->mc_namespace;
37129 cv[7].destination = &(s->debug);
37130-
37131+
37132 p->config_storage[i] = s;
37133-
37134+
37135 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37136 return HANDLER_ERROR;
37137 }
37138 #if defined(HAVE_GDBM_H)
37139 if (!buffer_is_empty(s->db_filename)) {
37140 if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
37141- log_error_write(srv, __FILE__, __LINE__, "s",
37142+ log_error_write(srv, __FILE__, __LINE__, "s",
37143 "gdbm-open failed");
37144 return HANDLER_ERROR;
37145 }
37146 }
37147 #endif
37148-#if defined(HAVE_PCRE_H)
37149+#if defined(HAVE_PCRE_H)
37150 if (!buffer_is_empty(s->download_url)) {
37151 if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
37152 0, &errptr, &erroff, NULL))) {
37153-
37154- log_error_write(srv, __FILE__, __LINE__, "sbss",
37155- "compiling regex for download-url failed:",
37156+
37157+ log_error_write(srv, __FILE__, __LINE__, "sbss",
37158+ "compiling regex for download-url failed:",
37159 s->download_url, "pos:", erroff);
37160 return HANDLER_ERROR;
37161 }
37162 }
37163-
37164+
37165 if (!buffer_is_empty(s->trigger_url)) {
37166 if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
37167 0, &errptr, &erroff, NULL))) {
37168-
37169- log_error_write(srv, __FILE__, __LINE__, "sbss",
37170- "compiling regex for trigger-url failed:",
37171+
37172+ log_error_write(srv, __FILE__, __LINE__, "sbss",
37173+ "compiling regex for trigger-url failed:",
37174 s->trigger_url, "pos:", erroff);
37175-
37176+
37177 return HANDLER_ERROR;
37178 }
37179 }
37180@@ -211,100 +211,97 @@
37181 #if defined(HAVE_MEMCACHE_H)
37182 size_t k;
37183 s->mc = mc_new();
37184-
37185+
37186 for (k = 0; k < s->mc_hosts->used; k++) {
37187 data_string *ds = (data_string *)s->mc_hosts->data[k];
37188-
37189+
37190 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
37191- log_error_write(srv, __FILE__, __LINE__, "sb",
37192- "connection to host failed:",
37193+ log_error_write(srv, __FILE__, __LINE__, "sb",
37194+ "connection to host failed:",
37195 ds->value);
37196-
37197+
37198 return HANDLER_ERROR;
37199 }
37200 }
37201 #else
37202- log_error_write(srv, __FILE__, __LINE__, "s",
37203+ log_error_write(srv, __FILE__, __LINE__, "s",
37204 "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
37205 return HANDLER_ERROR;
37206 #endif
37207 }
37208-
37209+
37210
37211 #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
37212- log_error_write(srv, __FILE__, __LINE__, "s",
37213+ log_error_write(srv, __FILE__, __LINE__, "s",
37214 "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
37215 return HANDLER_ERROR;
37216 #endif
37217 }
37218-
37219+
37220 return HANDLER_GO_ON;
37221 }
37222
37223-#define PATCH(x) \
37224- p->conf.x = s->x;
37225 static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
37226 size_t i, j;
37227 plugin_config *s = p->config_storage[0];
37228-
37229+
37230 #if defined(HAVE_GDBM)
37231- PATCH(db);
37232-#endif
37233+ PATCH_OPTION(db);
37234+#endif
37235 #if defined(HAVE_PCRE_H)
37236- PATCH(download_regex);
37237- PATCH(trigger_regex);
37238-#endif
37239- PATCH(trigger_timeout);
37240- PATCH(deny_url);
37241- PATCH(mc_namespace);
37242- PATCH(debug);
37243+ PATCH_OPTION(download_regex);
37244+ PATCH_OPTION(trigger_regex);
37245+#endif
37246+ PATCH_OPTION(trigger_timeout);
37247+ PATCH_OPTION(deny_url);
37248+ PATCH_OPTION(mc_namespace);
37249+ PATCH_OPTION(debug);
37250 #if defined(HAVE_MEMCACHE_H)
37251- PATCH(mc);
37252+ PATCH_OPTION(mc);
37253 #endif
37254-
37255+
37256 /* skip the first, the global context */
37257 for (i = 1; i < srv->config_context->used; i++) {
37258 data_config *dc = (data_config *)srv->config_context->data[i];
37259 s = p->config_storage[i];
37260-
37261+
37262 /* condition didn't match */
37263 if (!config_check_cond(srv, con, dc)) continue;
37264-
37265+
37266 /* merge config */
37267 for (j = 0; j < dc->value->used; j++) {
37268 data_unset *du = dc->value->data[j];
37269
37270 if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
37271 #if defined(HAVE_PCRE_H)
37272- PATCH(download_regex);
37273+ PATCH_OPTION(download_regex);
37274 #endif
37275 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
37276 # if defined(HAVE_PCRE_H)
37277- PATCH(trigger_regex);
37278+ PATCH_OPTION(trigger_regex);
37279 # endif
37280 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
37281 #if defined(HAVE_GDBM_H)
37282- PATCH(db);
37283+ PATCH_OPTION(db);
37284 #endif
37285 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
37286- PATCH(trigger_timeout);
37287+ PATCH_OPTION(trigger_timeout);
37288 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
37289- PATCH(debug);
37290+ PATCH_OPTION(debug);
37291 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
37292- PATCH(deny_url);
37293+ PATCH_OPTION(deny_url);
37294 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
37295- PATCH(mc_namespace);
37296+ PATCH_OPTION(mc_namespace);
37297 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
37298 #if defined(HAVE_MEMCACHE_H)
37299- PATCH(mc);
37300+ PATCH_OPTION(mc);
37301 #endif
37302 }
37303 }
37304 }
37305-
37306+
37307 return 0;
37308 }
37309-#undef PATCH
37310
37311 URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
37312 plugin_data *p = p_d;
37313@@ -315,20 +312,20 @@
37314 int n;
37315 # define N 10
37316 int ovec[N * 3];
37317-
37318+
37319 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37320-
37321+
37322 mod_trigger_b4_dl_patch_connection(srv, con, p);
37323-
37324+
37325 if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
37326-
37327+
37328 # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
37329 return HANDLER_GO_ON;
37330 # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
37331 if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
37332 if (p->conf.db && p->conf.mc) {
37333 /* can't decide which one */
37334-
37335+
37336 return HANDLER_GO_ON;
37337 }
37338 # elif defined(HAVE_GDBM_H)
37339@@ -336,12 +333,12 @@
37340 # else
37341 if (!p->conf.mc) return HANDLER_GO_ON;
37342 # endif
37343-
37344+
37345 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) {
37346 /* X-Forwarded-For contains the ip behind the proxy */
37347-
37348+
37349 remote_ip = ds->value->ptr;
37350-
37351+
37352 /* memcache can't handle spaces */
37353 } else {
37354 remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
37355@@ -350,13 +347,13 @@
37356 if (p->conf.debug) {
37357 log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
37358 }
37359-
37360+
37361 /* check if URL is a trigger -> insert IP into DB */
37362 if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37363 if (n != PCRE_ERROR_NOMATCH) {
37364 log_error_write(srv, __FILE__, __LINE__, "sd",
37365 "execution error while matching:", n);
37366-
37367+
37368 return HANDLER_ERROR;
37369 }
37370 } else {
37371@@ -364,34 +361,34 @@
37372 if (p->conf.db) {
37373 /* the trigger matched */
37374 datum key, val;
37375-
37376+
37377 key.dptr = (char *)remote_ip;
37378 key.dsize = strlen(remote_ip);
37379-
37380+
37381 val.dptr = (char *)&(srv->cur_ts);
37382 val.dsize = sizeof(srv->cur_ts);
37383-
37384+
37385 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37386 log_error_write(srv, __FILE__, __LINE__, "s",
37387 "insert failed");
37388 }
37389 }
37390 # endif
37391-# if defined(HAVE_MEMCACHE_H)
37392+# if defined(HAVE_MEMCACHE_H)
37393 if (p->conf.mc) {
37394 size_t i;
37395 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37396 buffer_append_string(p->tmp_buf, remote_ip);
37397-
37398+
37399 for (i = 0; i < p->tmp_buf->used - 1; i++) {
37400 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37401 }
37402-
37403+
37404 if (p->conf.debug) {
37405 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
37406 }
37407
37408- if (0 != mc_set(p->conf.mc,
37409+ if (0 != mc_set(p->conf.mc,
37410 CONST_BUF_LEN(p->tmp_buf),
37411 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37412 p->conf.trigger_timeout, 0)) {
37413@@ -401,7 +398,7 @@
37414 }
37415 # endif
37416 }
37417-
37418+
37419 /* check if URL is a download -> check IP in DB, update timestamp */
37420 if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37421 if (n != PCRE_ERROR_NOMATCH) {
37422@@ -411,93 +408,93 @@
37423 }
37424 } else {
37425 /* the download uri matched */
37426-# if defined(HAVE_GDBM_H)
37427+# if defined(HAVE_GDBM_H)
37428 if (p->conf.db) {
37429 datum key, val;
37430 time_t last_hit;
37431-
37432+
37433 key.dptr = (char *)remote_ip;
37434 key.dsize = strlen(remote_ip);
37435-
37436+
37437 val = gdbm_fetch(p->conf.db, key);
37438-
37439+
37440 if (val.dptr == NULL) {
37441 /* not found, redirect */
37442-
37443+
37444 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37445-
37446+
37447 con->http_status = 307;
37448-
37449+
37450 return HANDLER_FINISHED;
37451 }
37452-
37453+
37454 last_hit = *(time_t *)(val.dptr);
37455-
37456+
37457 free(val.dptr);
37458-
37459+
37460 if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
37461 /* found, but timeout, redirect */
37462-
37463+
37464 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37465 con->http_status = 307;
37466-
37467+
37468 if (p->conf.db) {
37469 if (0 != gdbm_delete(p->conf.db, key)) {
37470 log_error_write(srv, __FILE__, __LINE__, "s",
37471 "delete failed");
37472 }
37473 }
37474-
37475+
37476 return HANDLER_FINISHED;
37477 }
37478-
37479+
37480 val.dptr = (char *)&(srv->cur_ts);
37481 val.dsize = sizeof(srv->cur_ts);
37482-
37483+
37484 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37485 log_error_write(srv, __FILE__, __LINE__, "s",
37486 "insert failed");
37487 }
37488 }
37489 # endif
37490-
37491-# if defined(HAVE_MEMCACHE_H)
37492+
37493+# if defined(HAVE_MEMCACHE_H)
37494 if (p->conf.mc) {
37495 void *r;
37496 size_t i;
37497-
37498+
37499 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37500 buffer_append_string(p->tmp_buf, remote_ip);
37501-
37502+
37503 for (i = 0; i < p->tmp_buf->used - 1; i++) {
37504 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37505 }
37506-
37507+
37508 if (p->conf.debug) {
37509 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
37510 }
37511
37512 /**
37513- *
37514+ *
37515 * memcached is do expiration for us, as long as we can fetch it every thing is ok
37516- * and the timestamp is updated
37517- *
37518+ * and the timestamp is updated
37519+ *
37520 */
37521- if (NULL == (r = mc_aget(p->conf.mc,
37522+ if (NULL == (r = mc_aget(p->conf.mc,
37523 CONST_BUF_LEN(p->tmp_buf)
37524 ))) {
37525-
37526+
37527 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37528-
37529+
37530 con->http_status = 307;
37531-
37532+
37533 return HANDLER_FINISHED;
37534 }
37535-
37536+
37537 free(r);
37538-
37539+
37540 /* set a new timeout */
37541- if (0 != mc_set(p->conf.mc,
37542+ if (0 != mc_set(p->conf.mc,
37543 CONST_BUF_LEN(p->tmp_buf),
37544 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37545 p->conf.trigger_timeout, 0)) {
37546@@ -507,13 +504,13 @@
37547 }
37548 # endif
37549 }
37550-
37551+
37552 #else
37553 UNUSED(srv);
37554 UNUSED(con);
37555 UNUSED(p_d);
37556 #endif
37557-
37558+
37559 return HANDLER_GO_ON;
37560 }
37561
37562@@ -521,21 +518,21 @@
37563 TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
37564 plugin_data *p = p_d;
37565 size_t i;
37566-
37567+
37568 /* check DB each minute */
37569 if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
37570-
37571+
37572 /* cleanup */
37573 for (i = 0; i < srv->config_context->used; i++) {
37574 plugin_config *s = p->config_storage[i];
37575 datum key, val, okey;
37576-
37577+
37578 if (!s->db) continue;
37579-
37580+
37581 okey.dptr = NULL;
37582-
37583- /* according to the manual this loop + delete does delete all entries on its way
37584- *
37585+
37586+ /* according to the manual this loop + delete does delete all entries on its way
37587+ *
37588 * we don't care as the next round will remove them. We don't have to perfect here.
37589 */
37590 for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
37591@@ -544,21 +541,21 @@
37592 free(okey.dptr);
37593 okey.dptr = NULL;
37594 }
37595-
37596+
37597 val = gdbm_fetch(s->db, key);
37598-
37599+
37600 last_hit = *(time_t *)(val.dptr);
37601-
37602+
37603 free(val.dptr);
37604-
37605+
37606 if (srv->cur_ts - last_hit > s->trigger_timeout) {
37607 gdbm_delete(s->db, key);
37608 }
37609-
37610+
37611 okey = key;
37612 }
37613 if (okey.dptr) free(okey.dptr);
37614-
37615+
37616 /* reorg once a day */
37617 if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
37618 }
37619@@ -571,7 +568,7 @@
37620 int mod_trigger_b4_dl_plugin_init(plugin *p) {
37621 p->version = LIGHTTPD_VERSION_ID;
37622 p->name = buffer_init_string("trigger_b4_dl");
37623-
37624+
37625 p->init = mod_trigger_b4_dl_init;
37626 p->handle_uri_clean = mod_trigger_b4_dl_uri_handler;
37627 p->set_defaults = mod_trigger_b4_dl_set_defaults;
37628@@ -579,8 +576,8 @@
37629 p->handle_trigger = mod_trigger_b4_dl_handle_trigger;
37630 #endif
37631 p->cleanup = mod_trigger_b4_dl_free;
37632-
37633+
37634 p->data = NULL;
37635-
37636+
37637 return 0;
37638 }
1175ccec 37639--- ../lighttpd-1.4.11/src/mod_userdir.c 2005-10-28 16:48:28.000000000 +0300
36e2a29e 37640+++ lighttpd-1.4.12/src/mod_userdir.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
37641@@ -10,6 +10,7 @@
37642 #include "response.h"
37643
37644 #include "plugin.h"
37645+#include "sys-files.h"
37646
37647 #ifdef HAVE_PWD_H
37648 #include <pwd.h>
37649@@ -25,54 +26,54 @@
37650
37651 typedef struct {
37652 PLUGIN_DATA;
37653-
37654+
37655 buffer *username;
37656 buffer *temp_path;
37657-
37658+
37659 plugin_config **config_storage;
37660-
37661- plugin_config conf;
37662+
37663+ plugin_config conf;
37664 } plugin_data;
37665
37666 /* init the plugin data */
37667 INIT_FUNC(mod_userdir_init) {
37668 plugin_data *p;
37669-
37670+
37671 p = calloc(1, sizeof(*p));
37672-
37673+
37674 p->username = buffer_init();
37675 p->temp_path = buffer_init();
37676-
37677+
37678 return p;
37679 }
37680
37681 /* detroy the plugin data */
37682 FREE_FUNC(mod_userdir_free) {
37683 plugin_data *p = p_d;
37684-
37685+
37686 if (!p) return HANDLER_GO_ON;
37687-
37688+
37689 if (p->config_storage) {
37690 size_t i;
37691-
37692+
37693 for (i = 0; i < srv->config_context->used; i++) {
37694 plugin_config *s = p->config_storage[i];
37695-
37696+
37697 array_free(s->include_user);
37698 array_free(s->exclude_user);
37699 buffer_free(s->path);
37700 buffer_free(s->basepath);
37701-
37702+
37703 free(s);
37704 }
37705 free(p->config_storage);
37706 }
37707-
37708+
37709 buffer_free(p->username);
37710 buffer_free(p->temp_path);
37711-
37712+
37713 free(p);
37714-
37715+
37716 return HANDLER_GO_ON;
37717 }
37718
37719@@ -81,81 +82,78 @@
37720 SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
37721 plugin_data *p = p_d;
37722 size_t i;
37723-
37724- config_values_t cv[] = {
37725+
37726+ config_values_t cv[] = {
37727 { "userdir.path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
37728 { "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
37729 { "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
37730 { "userdir.basepath", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
37731 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37732 };
37733-
37734+
37735 if (!p) return HANDLER_ERROR;
37736-
37737+
37738 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37739-
37740+
37741 for (i = 0; i < srv->config_context->used; i++) {
37742 plugin_config *s;
37743-
37744+
37745 s = calloc(1, sizeof(plugin_config));
37746 s->exclude_user = array_init();
37747 s->include_user = array_init();
37748 s->path = buffer_init();
37749 s->basepath = buffer_init();
37750-
37751+
37752 cv[0].destination = s->path;
37753 cv[1].destination = s->exclude_user;
37754 cv[2].destination = s->include_user;
37755 cv[3].destination = s->basepath;
37756-
37757+
37758 p->config_storage[i] = s;
37759-
37760+
37761 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37762 return HANDLER_ERROR;
37763 }
37764 }
37765-
37766+
37767 return HANDLER_GO_ON;
37768 }
37769
37770-#define PATCH(x) \
37771- p->conf.x = s->x;
37772 static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
37773 size_t i, j;
37774 plugin_config *s = p->config_storage[0];
37775-
37776- PATCH(path);
37777- PATCH(exclude_user);
37778- PATCH(include_user);
37779- PATCH(basepath);
37780-
37781+
37782+ PATCH_OPTION(path);
37783+ PATCH_OPTION(exclude_user);
37784+ PATCH_OPTION(include_user);
37785+ PATCH_OPTION(basepath);
37786+
37787 /* skip the first, the global context */
37788 for (i = 1; i < srv->config_context->used; i++) {
37789 data_config *dc = (data_config *)srv->config_context->data[i];
37790 s = p->config_storage[i];
37791-
37792+
37793 /* condition didn't match */
37794 if (!config_check_cond(srv, con, dc)) continue;
37795-
37796+
37797 /* merge config */
37798 for (j = 0; j < dc->value->used; j++) {
37799 data_unset *du = dc->value->data[j];
37800-
37801+
37802 if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
37803- PATCH(path);
37804+ PATCH_OPTION(path);
37805 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
37806- PATCH(exclude_user);
37807+ PATCH_OPTION(exclude_user);
37808 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
37809- PATCH(include_user);
37810+ PATCH_OPTION(include_user);
37811 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
37812- PATCH(basepath);
37813+ PATCH_OPTION(basepath);
37814 }
37815 }
37816 }
37817-
37818+
37819 return 0;
37820 }
37821-#undef PATCH
37822
37823 URIHANDLER_FUNC(mod_userdir_docroot_handler) {
37824 plugin_data *p = p_d;
37825@@ -169,18 +167,18 @@
37826 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37827
37828 mod_userdir_patch_connection(srv, con, p);
37829-
37830+
37831 uri_len = con->uri.path->used - 1;
37832-
37833+
37834 /* /~user/foo.html -> /home/user/public_html/foo.html */
37835-
37836+
37837 if (con->uri.path->ptr[0] != '/' ||
37838 con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
37839-
37840+
37841 if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
37842 /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
37843 http_response_redirect_to_directory(srv, con);
37844-
37845+
37846 return HANDLER_FINISHED;
37847 }
37848
37849@@ -188,10 +186,10 @@
37850 if (0 == rel_url - (con->uri.path->ptr + 2)) {
37851 return HANDLER_GO_ON;
37852 }
37853-
37854+
37855 buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
37856-
37857- if (buffer_is_empty(p->conf.basepath)
37858+
37859+ if (buffer_is_empty(p->conf.basepath)
37860 #ifdef HAVE_PWD_H
37861 && NULL == (pwd = getpwnam(p->username->ptr))
37862 #endif
37863@@ -200,31 +198,31 @@
37864 return HANDLER_GO_ON;
37865 }
37866
37867-
37868+
37869 for (k = 0; k < p->conf.exclude_user->used; k++) {
37870 data_string *ds = (data_string *)p->conf.exclude_user->data[k];
37871-
37872+
37873 if (buffer_is_equal(ds->value, p->username)) {
37874 /* user in exclude list */
37875 return HANDLER_GO_ON;
37876 }
37877 }
37878-
37879+
37880 if (p->conf.include_user->used) {
37881 int found_user = 0;
37882 for (k = 0; k < p->conf.include_user->used; k++) {
37883 data_string *ds = (data_string *)p->conf.include_user->data[k];
37884-
37885+
37886 if (buffer_is_equal(ds->value, p->username)) {
37887 /* user in include list */
37888 found_user = 1;
37889 break;
37890 }
37891 }
37892-
37893+
37894 if (!found_user) return HANDLER_GO_ON;
37895 }
37896-
37897+
37898 /* we build the physical path */
37899
37900 if (buffer_is_empty(p->conf.basepath)) {
37901@@ -252,23 +250,23 @@
37902 }
37903
37904 buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
37905- BUFFER_APPEND_SLASH(p->temp_path);
37906+ PATHNAME_APPEND_SLASH(p->temp_path);
37907 buffer_append_string_buffer(p->temp_path, p->username);
37908 }
37909- BUFFER_APPEND_SLASH(p->temp_path);
37910- buffer_append_string_buffer(p->temp_path, p->conf.path);
37911+ PATHNAME_APPEND_SLASH(p->temp_path);
37912+ buffer_append_string_buffer(p->temp_path, p->conf.path);
37913
37914 if (buffer_is_empty(p->conf.basepath)) {
37915 struct stat st;
37916 int ret;
37917-
37918+
37919 ret = stat(p->temp_path->ptr, &st);
37920 if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
37921 return HANDLER_GO_ON;
37922- }
37923+ }
37924 }
37925
37926- BUFFER_APPEND_SLASH(p->temp_path);
37927+ PATHNAME_APPEND_SLASH(p->temp_path);
37928 buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
37929 buffer_copy_string_buffer(con->physical.path, p->temp_path);
37930
37931@@ -282,13 +280,13 @@
37932 int mod_userdir_plugin_init(plugin *p) {
37933 p->version = LIGHTTPD_VERSION_ID;
37934 p->name = buffer_init_string("userdir");
37935-
37936+
37937 p->init = mod_userdir_init;
37938 p->handle_physical = mod_userdir_docroot_handler;
37939 p->set_defaults = mod_userdir_set_defaults;
37940 p->cleanup = mod_userdir_free;
37941-
37942+
37943 p->data = NULL;
37944-
37945+
37946 return 0;
37947 }
1175ccec 37948--- ../lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200
36e2a29e 37949+++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
37950@@ -24,44 +24,44 @@
37951
37952 typedef struct {
37953 PLUGIN_DATA;
37954-
37955+
37956 plugin_config **config_storage;
37957-
37958- plugin_config conf;
37959+
37960+ plugin_config conf;
37961 } plugin_data;
37962
37963 /* init the plugin data */
37964 INIT_FUNC(mod_usertrack_init) {
37965 plugin_data *p;
37966-
37967+
37968 p = calloc(1, sizeof(*p));
37969-
37970+
37971 return p;
37972 }
37973
37974 /* detroy the plugin data */
37975 FREE_FUNC(mod_usertrack_free) {
37976 plugin_data *p = p_d;
37977-
37978+
37979 UNUSED(srv);
37980-
37981+
37982 if (!p) return HANDLER_GO_ON;
37983-
37984+
37985 if (p->config_storage) {
37986 size_t i;
37987 for (i = 0; i < srv->config_context->used; i++) {
37988 plugin_config *s = p->config_storage[i];
37989-
37990+
37991 buffer_free(s->cookie_name);
37992 buffer_free(s->cookie_domain);
37993-
37994+
37995 free(s);
37996 }
37997 free(p->config_storage);
37998 }
37999-
38000+
38001 free(p);
38002-
38003+
38004 return HANDLER_GO_ON;
38005 }
38006
38007@@ -70,38 +70,38 @@
38008 SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
38009 plugin_data *p = p_d;
38010 size_t i = 0;
38011-
38012- config_values_t cv[] = {
38013+
38014+ config_values_t cv[] = {
38015 { "usertrack.cookie-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
38016 { "usertrack.cookie-max-age", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
38017 { "usertrack.cookie-domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
38018-
38019- { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38020+
38021+ { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38022 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38023 };
38024-
38025+
38026 if (!p) return HANDLER_ERROR;
38027-
38028+
38029 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38030-
38031+
38032 for (i = 0; i < srv->config_context->used; i++) {
38033 plugin_config *s;
38034-
38035+
38036 s = calloc(1, sizeof(plugin_config));
38037 s->cookie_name = buffer_init();
38038 s->cookie_domain = buffer_init();
38039 s->cookie_max_age = 0;
38040-
38041+
38042 cv[0].destination = s->cookie_name;
38043 cv[1].destination = &(s->cookie_max_age);
38044 cv[2].destination = s->cookie_domain;
38045-
38046+
38047 p->config_storage[i] = s;
38048-
38049+
38050 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38051 return HANDLER_ERROR;
38052 }
38053-
38054+
38055 if (buffer_is_empty(s->cookie_name)) {
38056 buffer_copy_string(s->cookie_name, "TRACKID");
38057 } else {
38058@@ -109,68 +109,65 @@
38059 for (j = 0; j < s->cookie_name->used - 1; j++) {
38060 char c = s->cookie_name->ptr[j] | 32;
38061 if (c < 'a' || c > 'z') {
38062- log_error_write(srv, __FILE__, __LINE__, "sb",
38063- "invalid character in usertrack.cookie-name:",
38064+ log_error_write(srv, __FILE__, __LINE__, "sb",
38065+ "invalid character in usertrack.cookie-name:",
38066 s->cookie_name);
38067-
38068+
38069 return HANDLER_ERROR;
38070 }
38071 }
38072 }
38073-
38074+
38075 if (!buffer_is_empty(s->cookie_domain)) {
38076 size_t j;
38077 for (j = 0; j < s->cookie_domain->used - 1; j++) {
38078 char c = s->cookie_domain->ptr[j];
38079 if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
38080- log_error_write(srv, __FILE__, __LINE__, "sb",
38081- "invalid character in usertrack.cookie-domain:",
38082+ log_error_write(srv, __FILE__, __LINE__, "sb",
38083+ "invalid character in usertrack.cookie-domain:",
38084 s->cookie_domain);
38085-
38086+
38087 return HANDLER_ERROR;
38088 }
38089 }
38090 }
38091 }
38092-
38093+
38094 return HANDLER_GO_ON;
38095 }
38096
38097-#define PATCH(x) \
38098- p->conf.x = s->x;
38099 static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
38100 size_t i, j;
38101 plugin_config *s = p->config_storage[0];
38102-
38103- PATCH(cookie_name);
38104- PATCH(cookie_domain);
38105- PATCH(cookie_max_age);
38106-
38107+
38108+ PATCH_OPTION(cookie_name);
38109+ PATCH_OPTION(cookie_domain);
38110+ PATCH_OPTION(cookie_max_age);
38111+
38112 /* skip the first, the global context */
38113 for (i = 1; i < srv->config_context->used; i++) {
38114 data_config *dc = (data_config *)srv->config_context->data[i];
38115 s = p->config_storage[i];
38116-
38117+
38118 /* condition didn't match */
38119 if (!config_check_cond(srv, con, dc)) continue;
38120-
38121+
38122 /* merge config */
38123 for (j = 0; j < dc->value->used; j++) {
38124 data_unset *du = dc->value->data[j];
38125-
38126+
38127 if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
38128- PATCH(cookie_name);
38129+ PATCH_OPTION(cookie_name);
38130 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
38131- PATCH(cookie_max_age);
38132+ PATCH_OPTION(cookie_max_age);
38133 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
38134- PATCH(cookie_domain);
38135+ PATCH_OPTION(cookie_domain);
38136 }
38137 }
38138 }
38139-
38140+
38141 return 0;
38142 }
38143-#undef PATCH
38144
38145 URIHANDLER_FUNC(mod_usertrack_uri_handler) {
38146 plugin_data *p = p_d;
38147@@ -178,38 +175,38 @@
38148 unsigned char h[16];
38149 MD5_CTX Md5Ctx;
38150 char hh[32];
38151-
38152+
38153 if (con->uri.path->used == 0) return HANDLER_GO_ON;
38154-
38155+
38156 mod_usertrack_patch_connection(srv, con, p);
38157-
38158+
38159 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
38160 char *g;
38161 /* we have a cookie, does it contain a valid name ? */
38162-
38163- /* parse the cookie
38164- *
38165+
38166+ /* parse the cookie
38167+ *
38168 * check for cookiename + (WS | '=')
38169- *
38170+ *
38171 */
38172-
38173+
38174 if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
38175 char *nc;
38176-
38177+
38178 /* skip WS */
38179 for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
38180-
38181+
38182 if (*nc == '=') {
38183 /* ok, found the key of our own cookie */
38184-
38185+
38186 if (strlen(nc) > 32) {
38187 /* i'm lazy */
38188 return HANDLER_GO_ON;
38189 }
38190 }
38191 }
38192- }
38193-
38194+ }
38195+
38196 /* set a cookie */
38197 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
38198 ds = data_response_init();
38199@@ -217,39 +214,39 @@
38200 buffer_copy_string(ds->key, "Set-Cookie");
38201 buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
38202 buffer_append_string(ds->value, "=");
38203-
38204+
38205
38206 /* taken from mod_auth.c */
38207-
38208+
38209 /* generate shared-secret */
38210 MD5_Init(&Md5Ctx);
38211 MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
38212 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
38213-
38214+
38215 /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
38216 ltostr(hh, srv->cur_ts);
38217 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38218 ltostr(hh, rand());
38219 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38220-
38221+
38222 MD5_Final(h, &Md5Ctx);
38223-
38224+
38225 buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
38226 buffer_append_string(ds->value, "; Path=/");
38227 buffer_append_string(ds->value, "; Version=1");
38228-
38229+
38230 if (!buffer_is_empty(p->conf.cookie_domain)) {
38231 buffer_append_string(ds->value, "; Domain=");
38232 buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
38233 }
38234-
38235+
38236 if (p->conf.cookie_max_age) {
38237 buffer_append_string(ds->value, "; max-age=");
38238 buffer_append_long(ds->value, p->conf.cookie_max_age);
38239 }
38240-
38241+
38242 array_insert_unique(con->response.headers, (data_unset *)ds);
38243-
38244+
38245 return HANDLER_GO_ON;
38246 }
38247
38248@@ -258,13 +255,13 @@
38249 int mod_usertrack_plugin_init(plugin *p) {
38250 p->version = LIGHTTPD_VERSION_ID;
38251 p->name = buffer_init_string("usertrack");
38252-
38253+
38254 p->init = mod_usertrack_init;
38255 p->handle_uri_clean = mod_usertrack_uri_handler;
38256 p->set_defaults = mod_usertrack_set_defaults;
38257 p->cleanup = mod_usertrack_free;
38258-
38259+
38260 p->data = NULL;
38261-
38262+
38263 return 0;
38264 }
1175ccec 38265--- ../lighttpd-1.4.11/src/mod_webdav.c 2006-03-03 01:28:58.000000000 +0200
36e2a29e 38266+++ lighttpd-1.4.12/src/mod_webdav.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
38267@@ -3,13 +3,10 @@
38268 #include <ctype.h>
38269 #include <stdlib.h>
38270 #include <string.h>
38271-#include <dirent.h>
38272 #include <errno.h>
38273-#include <unistd.h>
38274 #include <fcntl.h>
38275 #include <stdio.h>
38276 #include <assert.h>
38277-#include <sys/mman.h>
38278
38279 #ifdef HAVE_CONFIG_H
38280 #include "config.h"
38281@@ -23,6 +20,11 @@
38282 #include <sqlite3.h>
38283 #endif
38284
38285+#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
38286+#define USE_LOCKS
38287+#include <uuid/uuid.h>
38288+#endif
38289+
38290 #include "base.h"
38291 #include "log.h"
38292 #include "buffer.h"
38293@@ -33,13 +35,16 @@
38294 #include "stream.h"
38295 #include "stat_cache.h"
38296
38297+#include "sys-files.h"
38298+#include "sys-mmap.h"
38299+#include "sys-strings.h"
38300
38301 /**
38302 * this is a webdav for a lighttpd plugin
38303 *
38304- * at least a very basic one.
38305+ * at least a very basic one.
38306 * - for now it is read-only and we only support PROPFIND
38307- *
38308+ *
38309 */
38310
38311
38312@@ -58,64 +63,70 @@
38313 sqlite3_stmt *stmt_delete_prop;
38314 sqlite3_stmt *stmt_select_prop;
38315 sqlite3_stmt *stmt_select_propnames;
38316-
38317+
38318 sqlite3_stmt *stmt_delete_uri;
38319 sqlite3_stmt *stmt_move_uri;
38320 sqlite3_stmt *stmt_copy_uri;
38321+
38322+ sqlite3_stmt *stmt_remove_lock;
38323+ sqlite3_stmt *stmt_create_lock;
38324+ sqlite3_stmt *stmt_read_lock;
38325+ sqlite3_stmt *stmt_read_lock_by_uri;
38326+ sqlite3_stmt *stmt_refresh_lock;
38327 #endif
38328 } plugin_config;
38329
38330 typedef struct {
38331 PLUGIN_DATA;
38332-
38333+
38334 buffer *tmp_buf;
38335 request_uri uri;
38336 physical physical;
38337
38338 plugin_config **config_storage;
38339-
38340- plugin_config conf;
38341+
38342+ plugin_config conf;
38343 } plugin_data;
38344
38345 /* init the plugin data */
38346 INIT_FUNC(mod_webdav_init) {
38347 plugin_data *p;
38348-
38349+
38350 p = calloc(1, sizeof(*p));
38351-
38352+
38353 p->tmp_buf = buffer_init();
38354
38355 p->uri.scheme = buffer_init();
38356 p->uri.path_raw = buffer_init();
38357 p->uri.path = buffer_init();
38358 p->uri.authority = buffer_init();
38359-
38360+
38361 p->physical.path = buffer_init();
38362 p->physical.rel_path = buffer_init();
38363 p->physical.doc_root = buffer_init();
38364 p->physical.basedir = buffer_init();
38365-
38366+
38367 return p;
38368 }
38369
38370 /* detroy the plugin data */
38371 FREE_FUNC(mod_webdav_free) {
38372 plugin_data *p = p_d;
38373-
38374+
38375 UNUSED(srv);
38376
38377 if (!p) return HANDLER_GO_ON;
38378-
38379+
38380 if (p->config_storage) {
38381 size_t i;
38382 for (i = 0; i < srv->config_context->used; i++) {
38383 plugin_config *s = p->config_storage[i];
38384
38385 if (!s) continue;
38386-
38387+
38388 buffer_free(s->sqlite_db_name);
38389 #ifdef USE_PROPPATCH
38390- if (s->sql) {
38391+ if (s->sql) {
38392 sqlite3_finalize(s->stmt_delete_prop);
38393 sqlite3_finalize(s->stmt_delete_uri);
38394 sqlite3_finalize(s->stmt_copy_uri);
38395@@ -123,9 +134,15 @@
38396 sqlite3_finalize(s->stmt_update_prop);
38397 sqlite3_finalize(s->stmt_select_prop);
38398 sqlite3_finalize(s->stmt_select_propnames);
38399+
38400+ sqlite3_finalize(s->stmt_read_lock);
38401+ sqlite3_finalize(s->stmt_read_lock_by_uri);
38402+ sqlite3_finalize(s->stmt_create_lock);
38403+ sqlite3_finalize(s->stmt_remove_lock);
38404+ sqlite3_finalize(s->stmt_refresh_lock);
38405 sqlite3_close(s->sql);
38406 }
38407-#endif
38408+#endif
38409 free(s);
38410 }
38411 free(p->config_storage);
38412@@ -135,16 +152,16 @@
38413 buffer_free(p->uri.path_raw);
38414 buffer_free(p->uri.path);
38415 buffer_free(p->uri.authority);
38416-
38417+
38418 buffer_free(p->physical.path);
38419 buffer_free(p->physical.rel_path);
38420 buffer_free(p->physical.doc_root);
38421 buffer_free(p->physical.basedir);
38422-
38423+
38424 buffer_free(p->tmp_buf);
38425-
38426+
38427 free(p);
38428-
38429+
38430 return HANDLER_GO_ON;
38431 }
38432
38433@@ -153,32 +170,32 @@
38434 SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
38435 plugin_data *p = p_d;
38436 size_t i = 0;
38437-
38438- config_values_t cv[] = {
38439+
38440+ config_values_t cv[] = {
38441 { "webdav.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
38442 { "webdav.is-readonly", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
38443 { "webdav.sqlite-db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
38444 { "webdav.log-xml", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
38445 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38446 };
38447-
38448+
38449 if (!p) return HANDLER_ERROR;
38450-
38451+
38452 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38453-
38454+
38455 for (i = 0; i < srv->config_context->used; i++) {
38456 plugin_config *s;
38457-
38458+
38459 s = calloc(1, sizeof(plugin_config));
38460 s->sqlite_db_name = buffer_init();
38461-
38462+
38463 cv[0].destination = &(s->enabled);
38464 cv[1].destination = &(s->is_readonly);
38465 cv[2].destination = s->sqlite_db_name;
38466 cv[3].destination = &(s->log_xml);
38467-
38468+
38469 p->config_storage[i] = s;
38470-
38471+
38472 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38473 return HANDLER_ERROR;
38474 }
38475@@ -193,8 +210,26 @@
38476 return HANDLER_ERROR;
38477 }
38478
38479- if (SQLITE_OK != sqlite3_prepare(s->sql,
38480- CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38481+ if (SQLITE_OK != sqlite3_exec(s->sql,
38482+ "CREATE TABLE properties ("
38483+ " resource TEXT NOT NULL,"
38484+ " prop TEXT NOT NULL,"
38485+ " ns TEXT NOT NULL,"
38486+ " value TEXT NOT NULL,"
38487+ " PRIMARY KEY(resource, prop, ns))",
38488+ NULL, NULL, &err)) {
38489+
38490+ if (0 != strcmp(err, "table properties already exists")) {
38491+ log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38492+ sqlite3_free(err);
38493+
38494+ return HANDLER_ERROR;
38495+ }
38496+ sqlite3_free(err);
38497+ }
38498+
38499+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38500+ CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38501 &(s->stmt_select_prop), &next_stmt)) {
38502 /* prepare failed */
38503
38504@@ -202,8 +237,8 @@
38505 return HANDLER_ERROR;
38506 }
38507
38508- if (SQLITE_OK != sqlite3_prepare(s->sql,
38509- CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
38510+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38511+ CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
38512 &(s->stmt_select_propnames), &next_stmt)) {
38513 /* prepare failed */
38514
38515@@ -211,16 +246,67 @@
38516 return HANDLER_ERROR;
38517 }
38518
38519- if (SQLITE_OK != sqlite3_exec(s->sql,
38520- "CREATE TABLE properties ("
38521+
38522+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38523+ CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
38524+ &(s->stmt_update_prop), &next_stmt)) {
38525+ /* prepare failed */
38526+
38527+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38528+ return HANDLER_ERROR;
38529+ }
38530+
38531+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38532+ CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38533+ &(s->stmt_delete_prop), &next_stmt)) {
38534+ /* prepare failed */
38535+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38536+
38537+ return HANDLER_ERROR;
38538+ }
38539+
38540+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38541+ CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
38542+ &(s->stmt_delete_uri), &next_stmt)) {
38543+ /* prepare failed */
38544+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38545+
38546+ return HANDLER_ERROR;
38547+ }
38548+
38549+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38550+ CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
38551+ &(s->stmt_copy_uri), &next_stmt)) {
38552+ /* prepare failed */
38553+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38554+
38555+ return HANDLER_ERROR;
38556+ }
38557+
38558+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38559+ CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
38560+ &(s->stmt_move_uri), &next_stmt)) {
38561+ /* prepare failed */
38562+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38563+
38564+ return HANDLER_ERROR;
38565+ }
38566+
38567+ /* LOCKS */
38568+
38569+ if (SQLITE_OK != sqlite3_exec(s->sql,
38570+ "CREATE TABLE locks ("
38571+ " locktoken TEXT NOT NULL,"
38572 " resource TEXT NOT NULL,"
38573- " prop TEXT NOT NULL,"
38574- " ns TEXT NOT NULL,"
38575- " value TEXT NOT NULL,"
38576- " PRIMARY KEY(resource, prop, ns))",
38577+ " lockscope TEXT NOT NULL,"
38578+ " locktype TEXT NOT NULL,"
38579+ " owner TEXT NOT NULL,"
38580+ " depth INT NOT NULL,"
38581+ " timeout TIMESTAMP NOT NULL,"
38582+ " PRIMARY KEY(locktoken))",
38583 NULL, NULL, &err)) {
38584
38585- if (0 != strcmp(err, "table properties already exists")) {
38586+ if (0 != strcmp(err, "table locks already exists")) {
38587 log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38588 sqlite3_free(err);
38589
38590@@ -228,127 +314,138 @@
38591 }
38592 sqlite3_free(err);
38593 }
38594-
38595- if (SQLITE_OK != sqlite3_prepare(s->sql,
38596- CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
38597- &(s->stmt_update_prop), &next_stmt)) {
38598+
38599+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38600+ CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
38601+ &(s->stmt_create_lock), &next_stmt)) {
38602 /* prepare failed */
38603+ log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38604
38605- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38606 return HANDLER_ERROR;
38607 }
38608
38609- if (SQLITE_OK != sqlite3_prepare(s->sql,
38610- CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38611- &(s->stmt_delete_prop), &next_stmt)) {
38612+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38613+ CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
38614+ &(s->stmt_remove_lock), &next_stmt)) {
38615 /* prepare failed */
38616 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38617
38618 return HANDLER_ERROR;
38619 }
38620
38621- if (SQLITE_OK != sqlite3_prepare(s->sql,
38622- CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
38623- &(s->stmt_delete_uri), &next_stmt)) {
38624+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38625+ CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
38626+ &(s->stmt_read_lock), &next_stmt)) {
38627 /* prepare failed */
38628 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38629
38630 return HANDLER_ERROR;
38631 }
38632
38633- if (SQLITE_OK != sqlite3_prepare(s->sql,
38634- CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
38635- &(s->stmt_copy_uri), &next_stmt)) {
38636+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38637+ CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
38638+ &(s->stmt_read_lock_by_uri), &next_stmt)) {
38639 /* prepare failed */
38640 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38641
38642 return HANDLER_ERROR;
38643 }
38644
38645- if (SQLITE_OK != sqlite3_prepare(s->sql,
38646- CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
38647- &(s->stmt_move_uri), &next_stmt)) {
38648+ if (SQLITE_OK != sqlite3_prepare(s->sql,
38649+ CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
38650+ &(s->stmt_refresh_lock), &next_stmt)) {
38651 /* prepare failed */
38652 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38653
38654 return HANDLER_ERROR;
38655 }
38656+
38657+
38658 #else
38659 log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
38660 return HANDLER_ERROR;
38661 #endif
38662 }
38663 }
38664-
38665+
38666 return HANDLER_GO_ON;
38667 }
38668
38669-#define PATCH(x) \
38670- p->conf.x = s->x;
38671 static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
38672 size_t i, j;
38673 plugin_config *s = p->config_storage[0];
38674-
38675- PATCH(enabled);
38676- PATCH(is_readonly);
38677- PATCH(log_xml);
38678-
38679+
38680+ PATCH_OPTION(enabled);
38681+ PATCH_OPTION(is_readonly);
38682+ PATCH_OPTION(log_xml);
38683+
38684 #ifdef USE_PROPPATCH
38685- PATCH(sql);
38686- PATCH(stmt_update_prop);
38687- PATCH(stmt_delete_prop);
38688- PATCH(stmt_select_prop);
38689- PATCH(stmt_select_propnames);
38690-
38691- PATCH(stmt_delete_uri);
38692- PATCH(stmt_move_uri);
38693- PATCH(stmt_copy_uri);
38694+ PATCH_OPTION(sql);
38695+ PATCH_OPTION(stmt_update_prop);
38696+ PATCH_OPTION(stmt_delete_prop);
38697+ PATCH_OPTION(stmt_select_prop);
38698+ PATCH_OPTION(stmt_select_propnames);
38699+
38700+ PATCH_OPTION(stmt_delete_uri);
38701+ PATCH_OPTION(stmt_move_uri);
38702+ PATCH_OPTION(stmt_copy_uri);
38703+
38704+ PATCH_OPTION(stmt_remove_lock);
38705+ PATCH_OPTION(stmt_refresh_lock);
38706+ PATCH_OPTION(stmt_create_lock);
38707+ PATCH_OPTION(stmt_read_lock);
38708+ PATCH_OPTION(stmt_read_lock_by_uri);
38709 #endif
38710 /* skip the first, the global context */
38711 for (i = 1; i < srv->config_context->used; i++) {
38712 data_config *dc = (data_config *)srv->config_context->data[i];
38713 s = p->config_storage[i];
38714-
38715+
38716 /* condition didn't match */
38717 if (!config_check_cond(srv, con, dc)) continue;
38718-
38719+
38720 /* merge config */
38721 for (j = 0; j < dc->value->used; j++) {
38722 data_unset *du = dc->value->data[j];
38723-
38724+
38725 if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
38726- PATCH(enabled);
38727+ PATCH_OPTION(enabled);
38728 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
38729- PATCH(is_readonly);
38730+ PATCH_OPTION(is_readonly);
38731 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
38732- PATCH(log_xml);
38733+ PATCH_OPTION(log_xml);
38734 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
38735 #ifdef USE_PROPPATCH
38736- PATCH(sql);
38737- PATCH(stmt_update_prop);
38738- PATCH(stmt_delete_prop);
38739- PATCH(stmt_select_prop);
38740- PATCH(stmt_select_propnames);
38741-
38742- PATCH(stmt_delete_uri);
38743- PATCH(stmt_move_uri);
38744- PATCH(stmt_copy_uri);
38745+ PATCH_OPTION(sql);
38746+ PATCH_OPTION(stmt_update_prop);
38747+ PATCH_OPTION(stmt_delete_prop);
38748+ PATCH_OPTION(stmt_select_prop);
38749+ PATCH_OPTION(stmt_select_propnames);
38750+
38751+ PATCH_OPTION(stmt_delete_uri);
38752+ PATCH_OPTION(stmt_move_uri);
38753+ PATCH_OPTION(stmt_copy_uri);
38754+
38755+ PATCH_OPTION(stmt_remove_lock);
38756+ PATCH_OPTION(stmt_refresh_lock);
38757+ PATCH_OPTION(stmt_create_lock);
38758+ PATCH_OPTION(stmt_read_lock);
38759+ PATCH_OPTION(stmt_read_lock_by_uri);
38760 #endif
38761 }
38762 }
38763 }
38764-
38765+
38766 return 0;
38767 }
38768-#undef PATCH
38769
38770 URIHANDLER_FUNC(mod_webdav_uri_handler) {
38771 plugin_data *p = p_d;
38772-
38773+
38774 UNUSED(srv);
38775
38776 if (con->uri.path->used == 0) return HANDLER_GO_ON;
38777-
38778+
38779 mod_webdav_patch_connection(srv, con, p);
38780
38781 if (!p->conf.enabled) return HANDLER_GO_ON;
38782@@ -362,20 +459,20 @@
38783 if (p->conf.is_readonly) {
38784 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
38785 } else {
38786- response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
38787+ response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
38788 }
38789 break;
38790 default:
38791 break;
38792 }
38793-
38794+
38795 /* not found */
38796 return HANDLER_GO_ON;
38797 }
38798-static int webdav_gen_prop_tag(server *srv, connection *con,
38799- char *prop_name,
38800- char *prop_ns,
38801- char *value,
38802+static int webdav_gen_prop_tag(server *srv, connection *con,
38803+ char *prop_name,
38804+ char *prop_ns,
38805+ char *value,
38806 buffer *b) {
38807
38808 UNUSED(srv);
38809@@ -414,7 +511,7 @@
38810 buffer_append_string_buffer(b, dst->rel_path);
38811 buffer_append_string(b,"</D:href>\n");
38812 buffer_append_string(b,"<D:status>\n");
38813-
38814+
38815 if (con->request.http_version == HTTP_VERSION_1_1) {
38816 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
38817 } else {
38818@@ -458,11 +555,11 @@
38819
38820 /* bind the values to the insert */
38821
38822- sqlite3_bind_text(stmt, 1,
38823- dst->rel_path->ptr,
38824+ sqlite3_bind_text(stmt, 1,
38825+ dst->rel_path->ptr,
38826 dst->rel_path->used - 1,
38827 SQLITE_TRANSIENT);
38828-
38829+
38830 if (SQLITE_DONE != sqlite3_step(stmt)) {
38831 /* */
38832 WP();
38833@@ -493,14 +590,14 @@
38834 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38835 continue;
38836 /* ignore the parent dir */
38837- }
38838+ }
38839
38840 buffer_copy_string_buffer(d.path, dst->path);
38841- BUFFER_APPEND_SLASH(d.path);
38842+ PATHNAME_APPEND_SLASH(d.path);
38843 buffer_append_string(d.path, de->d_name);
38844-
38845+
38846 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
38847- BUFFER_APPEND_SLASH(d.rel_path);
38848+ PATHNAME_APPEND_SLASH(d.rel_path);
38849 buffer_append_string(d.rel_path, de->d_name);
38850
38851 /* stat and unlink afterwards */
38852@@ -508,7 +605,7 @@
38853 /* don't about it yet, rmdir will fail too */
38854 } else if (S_ISDIR(st.st_mode)) {
38855 have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
38856-
38857+
38858 /* try to unlink it */
38859 if (-1 == rmdir(d.path->ptr)) {
38860 switch(errno) {
38861@@ -535,11 +632,11 @@
38862
38863 /* bind the values to the insert */
38864
38865- sqlite3_bind_text(stmt, 1,
38866- d.rel_path->ptr,
38867+ sqlite3_bind_text(stmt, 1,
38868+ d.rel_path->ptr,
38869 d.rel_path->used - 1,
38870 SQLITE_TRANSIENT);
38871-
38872+
38873 if (SQLITE_DONE != sqlite3_step(stmt)) {
38874 /* */
38875 WP();
38876@@ -569,7 +666,7 @@
38877 if (stream_open(&s, src->path)) {
38878 return 403;
38879 }
38880-
38881+
38882 if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) {
38883 /* opening the destination failed for some reason */
38884 switch(errno) {
38885@@ -601,7 +698,7 @@
38886 break;
38887 }
38888 }
38889-
38890+
38891 stream_close(&s);
38892 close(ofd);
38893
38894@@ -614,16 +711,16 @@
38895 sqlite3_reset(stmt);
38896
38897 /* bind the values to the insert */
38898- sqlite3_bind_text(stmt, 1,
38899- dst->rel_path->ptr,
38900+ sqlite3_bind_text(stmt, 1,
38901+ dst->rel_path->ptr,
38902 dst->rel_path->used - 1,
38903 SQLITE_TRANSIENT);
38904
38905- sqlite3_bind_text(stmt, 2,
38906- src->rel_path->ptr,
38907+ sqlite3_bind_text(stmt, 2,
38908+ src->rel_path->ptr,
38909 src->rel_path->used - 1,
38910 SQLITE_TRANSIENT);
38911-
38912+
38913 if (SQLITE_DONE != sqlite3_step(stmt)) {
38914 /* */
38915 WP();
38916@@ -655,21 +752,21 @@
38917 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38918 continue;
38919 }
38920-
38921+
38922 buffer_copy_string_buffer(s.path, src->path);
38923- BUFFER_APPEND_SLASH(s.path);
38924+ PATHNAME_APPEND_SLASH(s.path);
38925 buffer_append_string(s.path, de->d_name);
38926
38927 buffer_copy_string_buffer(d.path, dst->path);
38928- BUFFER_APPEND_SLASH(d.path);
38929+ PATHNAME_APPEND_SLASH(d.path);
38930 buffer_append_string(d.path, de->d_name);
38931
38932 buffer_copy_string_buffer(s.rel_path, src->rel_path);
38933- BUFFER_APPEND_SLASH(s.rel_path);
38934+ PATHNAME_APPEND_SLASH(s.rel_path);
38935 buffer_append_string(s.rel_path, de->d_name);
38936
38937 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
38938- BUFFER_APPEND_SLASH(d.rel_path);
38939+ PATHNAME_APPEND_SLASH(d.rel_path);
38940 buffer_append_string(d.rel_path, de->d_name);
38941
38942 if (-1 == stat(s.path->ptr, &st)) {
38943@@ -692,16 +789,16 @@
38944 sqlite3_reset(stmt);
38945
38946 /* bind the values to the insert */
38947- sqlite3_bind_text(stmt, 1,
38948- dst->rel_path->ptr,
38949+ sqlite3_bind_text(stmt, 1,
38950+ dst->rel_path->ptr,
38951 dst->rel_path->used - 1,
38952 SQLITE_TRANSIENT);
38953
38954- sqlite3_bind_text(stmt, 2,
38955- src->rel_path->ptr,
38956+ sqlite3_bind_text(stmt, 2,
38957+ src->rel_path->ptr,
38958 src->rel_path->used - 1,
38959 SQLITE_TRANSIENT);
38960-
38961+
38962 if (SQLITE_DONE != sqlite3_step(stmt)) {
38963 /* */
38964 WP();
38965@@ -721,7 +818,7 @@
38966 buffer_free(s.rel_path);
38967 buffer_free(d.path);
38968 buffer_free(d.rel_path);
38969-
38970+
38971 closedir(srcdir);
38972 }
38973
38974@@ -748,12 +845,12 @@
38975 if (S_ISDIR(sce->st.st_mode)) {
38976 buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
38977 found = 1;
38978- } else if(S_ISREG(sce->st.st_mode)) {
38979+ } else if(S_ISREG(sce->st.st_mode)) {
38980 for (k = 0; k < con->conf.mimetypes->used; k++) {
38981 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
38982-
38983+
38984 if (ds->key->used == 0) continue;
38985-
38986+
38987 if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
38988 buffer_append_string(b,"<D:getcontenttype>");
38989 buffer_append_string_buffer(b, ds->value);
38990@@ -807,23 +904,23 @@
38991
38992 /* bind the values to the insert */
38993
38994- sqlite3_bind_text(stmt, 1,
38995- dst->rel_path->ptr,
38996+ sqlite3_bind_text(stmt, 1,
38997+ dst->rel_path->ptr,
38998 dst->rel_path->used - 1,
38999 SQLITE_TRANSIENT);
39000- sqlite3_bind_text(stmt, 2,
39001+ sqlite3_bind_text(stmt, 2,
39002 prop_name,
39003 strlen(prop_name),
39004 SQLITE_TRANSIENT);
39005- sqlite3_bind_text(stmt, 3,
39006+ sqlite3_bind_text(stmt, 3,
39007 prop_ns,
39008 strlen(prop_ns),
39009 SQLITE_TRANSIENT);
39010
39011 /* it is the PK */
39012- while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
39013+ while (SQLITE_ROW == sqlite3_step(stmt)) {
39014 /* there is a row for us, we only expect a single col 'value' */
39015- webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
39016+ webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
39017 found = 1;
39018 }
39019 }
39020@@ -840,7 +937,7 @@
39021 char *prop;
39022 } webdav_property;
39023
39024-webdav_property live_properties[] = {
39025+webdav_property live_properties[] = {
39026 { "DAV:", "creationdate" },
39027 { "DAV:", "displayname" },
39028 { "DAV:", "getcontentlanguage" },
39029@@ -871,8 +968,8 @@
39030 webdav_property *prop;
39031
39032 prop = props->ptr[i];
39033-
39034- if (0 != webdav_get_property(srv, con, p,
39035+
39036+ if (0 != webdav_get_property(srv, con, p,
39037 dst, prop->prop, prop->ns, b_200)) {
39038 webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
39039 }
39040@@ -916,12 +1013,12 @@
39041 if (-1 == c->file.fd && /* open the file if not already open */
39042 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39043 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39044-
39045+
39046 return -1;
39047 }
39048-
39049+
39050 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39051- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39052+ log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39053 strerror(errno), c->file.name, c->file.fd);
39054
39055 return -1;
39056@@ -938,7 +1035,7 @@
39057 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
39058 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39059 }
39060-
39061+
39062 c->offset += weHave;
39063 cq->bytes_out += weHave;
39064
39065@@ -956,7 +1053,7 @@
39066 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
39067 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39068 }
39069-
39070+
39071 c->offset += weHave;
39072 cq->bytes_out += weHave;
39073
39074@@ -991,6 +1088,113 @@
39075 }
39076 #endif
39077
39078+int webdav_lockdiscovery(server *srv, connection *con,
39079+ buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
39080+
39081+ buffer *b;
39082+
39083+ response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
39084+
39085+ response_header_overwrite(srv, con,
39086+ CONST_STR_LEN("Content-Type"),
39087+ CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39088+
39089+ b = chunkqueue_get_append_buffer(con->write_queue);
39090+
39091+ buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39092+
39093+ buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39094+ buffer_append_string(b,"<D:lockdiscovery>\n");
39095+ buffer_append_string(b,"<D:activelock>\n");
39096+
39097+ buffer_append_string(b,"<D:lockscope>");
39098+ buffer_append_string(b,"<D:");
39099+ buffer_append_string(b, lockscope);
39100+ buffer_append_string(b, "/>");
39101+ buffer_append_string(b,"</D:lockscope>\n");
39102+
39103+ buffer_append_string(b,"<D:locktype>");
39104+ buffer_append_string(b,"<D:");
39105+ buffer_append_string(b, locktype);
39106+ buffer_append_string(b, "/>");
39107+ buffer_append_string(b,"</D:locktype>\n");
39108+
39109+ buffer_append_string(b,"<D:depth>");
39110+ buffer_append_string(b, depth == 0 ? "0" : "infinity");
39111+ buffer_append_string(b,"</D:depth>\n");
39112+
39113+ buffer_append_string(b,"<D:timeout>");
39114+ buffer_append_string(b, "Second-600");
39115+ buffer_append_string(b,"</D:timeout>\n");
39116+
39117+ buffer_append_string(b,"<D:owner>");
39118+ buffer_append_string(b,"</D:owner>\n");
39119+
39120+ buffer_append_string(b,"<D:locktoken>");
39121+ buffer_append_string(b, "<D:href>");
39122+ buffer_append_string_buffer(b, locktoken);
39123+ buffer_append_string(b, "</D:href>");
39124+ buffer_append_string(b,"</D:locktoken>\n");
39125+
39126+ buffer_append_string(b,"</D:activelock>\n");
39127+ buffer_append_string(b,"</D:lockdiscovery>\n");
39128+ buffer_append_string(b,"</D:prop>\n");
39129+
39130+ return 0;
39131+}
39132+/**
39133+ * check if resource is having the right locks to access to resource
39134+ *
39135+ *
39136+ *
39137+ */
39138+int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
39139+ int has_lock = 1;
39140+
39141+#ifdef USE_LOCKS
39142+ data_string *ds;
39143+
39144+ /**
39145+ * If can have
39146+ * - <lock-token>
39147+ * - [etag]
39148+ *
39149+ * there is NOT, AND and OR
39150+ * and a list can be tagged
39151+ *
39152+ * (<lock-token>) is untagged
39153+ * <tag> (<lock-token>) is tagged
39154+ *
39155+ * as long as we don't handle collections it is simple. :)
39156+ *
39157+ * X-Litmus: locks: 11 (owner_modify)
39158+ * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
39159+ *
39160+ * X-Litmus: locks: 16 (fail_cond_put)
39161+ * If: (<DAV:no-lock> ["-1622396671"])
39162+ */
39163+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39164+ } else {
39165+ /* we didn't provided a lock-token -> */
39166+ /* if the resource is locked -> 423 */
39167+
39168+ sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39169+
39170+ sqlite3_reset(stmt);
39171+
39172+ sqlite3_bind_text(stmt, 1,
39173+ CONST_BUF_LEN(uri),
39174+ SQLITE_TRANSIENT);
39175+
39176+ while (SQLITE_ROW == sqlite3_step(stmt)) {
39177+ has_lock = 0;
39178+ }
39179+ }
39180+#endif
39181+
39182+ return has_lock;
39183+}
39184+
39185 URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
39186 plugin_data *p = p_d;
39187 buffer *b;
39188@@ -1001,7 +1205,8 @@
39189 buffer *prop_200;
39190 buffer *prop_404;
39191 webdav_properties *req_props;
39192-
39193+ stat_cache_entry *sce = NULL;
39194+
39195 UNUSED(srv);
39196
39197 if (!p->conf.enabled) return HANDLER_GO_ON;
39198@@ -1019,7 +1224,19 @@
39199 req_props = NULL;
39200
39201 /* is there a content-body ? */
39202-
39203+
39204+ switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
39205+ case HANDLER_ERROR:
39206+ if (errno == ENOENT) {
39207+ con->http_status = 404;
39208+ return HANDLER_FINISHED;
39209+ }
39210+ break;
39211+ default:
39212+ break;
39213+ }
39214+
39215+
39216 #ifdef USE_PROPPATCH
39217 /* any special requests or just allprop ? */
39218 if (con->request.content_length) {
39219@@ -1087,12 +1304,12 @@
39220 /* get all property names (EMPTY) */
39221 sqlite3_reset(stmt);
39222 /* bind the values to the insert */
39223-
39224- sqlite3_bind_text(stmt, 1,
39225- con->uri.path->ptr,
39226+
39227+ sqlite3_bind_text(stmt, 1,
39228+ con->uri.path->ptr,
39229 con->uri.path->used - 1,
39230 SQLITE_TRANSIENT);
39231-
39232+
39233 if (SQLITE_DONE != sqlite3_step(stmt)) {
39234 WP();
39235 }
39236@@ -1115,13 +1332,13 @@
39237 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39238
39239 b = chunkqueue_get_append_buffer(con->write_queue);
39240-
39241+
39242 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39243
39244 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39245
39246 /* allprop */
39247-
39248+
39249 prop_200 = buffer_init();
39250 prop_404 = buffer_init();
39251
39252@@ -1129,7 +1346,7 @@
39253 case 0:
39254 /* Depth: 0 */
39255 webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
39256-
39257+
39258 buffer_append_string(b,"<D:response>\n");
39259 buffer_append_string(b,"<D:href>");
39260 buffer_append_string_buffer(b, con->uri.scheme);
39261@@ -1145,9 +1362,9 @@
39262 buffer_append_string_buffer(b, prop_200);
39263
39264 buffer_append_string(b,"</D:prop>\n");
39265-
39266+
39267 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39268-
39269+
39270 buffer_append_string(b,"</D:propstat>\n");
39271 }
39272 if (!buffer_is_empty(prop_404)) {
39273@@ -1157,16 +1374,16 @@
39274 buffer_append_string_buffer(b, prop_404);
39275
39276 buffer_append_string(b,"</D:prop>\n");
39277-
39278+
39279 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39280-
39281+
39282 buffer_append_string(b,"</D:propstat>\n");
39283 }
39284
39285 buffer_append_string(b,"</D:response>\n");
39286
39287 break;
39288- case 1:
39289+ case 1:
39290 if (NULL != (dir = opendir(con->physical.path->ptr))) {
39291 struct dirent *de;
39292 physical d;
39293@@ -1179,16 +1396,16 @@
39294 if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
39295 continue;
39296 /* ignore the parent dir */
39297- }
39298+ }
39299
39300 buffer_copy_string_buffer(d.path, dst->path);
39301- BUFFER_APPEND_SLASH(d.path);
39302+ PATHNAME_APPEND_SLASH(d.path);
39303
39304 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39305- BUFFER_APPEND_SLASH(d.rel_path);
39306+ PATHNAME_APPEND_SLASH(d.rel_path);
39307
39308 if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
39309- /* don't append the . */
39310+ /* don't append the . */
39311 } else {
39312 buffer_append_string(d.path, de->d_name);
39313 buffer_append_string(d.rel_path, de->d_name);
39314@@ -1198,7 +1415,7 @@
39315 buffer_reset(prop_404);
39316
39317 webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
39318-
39319+
39320 buffer_append_string(b,"<D:response>\n");
39321 buffer_append_string(b,"<D:href>");
39322 buffer_append_string_buffer(b, con->uri.scheme);
39323@@ -1214,9 +1431,9 @@
39324 buffer_append_string_buffer(b, prop_200);
39325
39326 buffer_append_string(b,"</D:prop>\n");
39327-
39328+
39329 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39330-
39331+
39332 buffer_append_string(b,"</D:propstat>\n");
39333 }
39334 if (!buffer_is_empty(prop_404)) {
39335@@ -1226,9 +1443,9 @@
39336 buffer_append_string_buffer(b, prop_404);
39337
39338 buffer_append_string(b,"</D:prop>\n");
39339-
39340+
39341 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39342-
39343+
39344 buffer_append_string(b,"</D:propstat>\n");
39345 }
39346
39347@@ -1275,7 +1492,7 @@
39348
39349 return HANDLER_FINISHED;
39350 }
39351-
39352+
39353 /* let's create the directory */
39354
39355 if (-1 == mkdir(con->physical.path->ptr, 0700)) {
39356@@ -1303,7 +1520,13 @@
39357 con->http_status = 403;
39358 return HANDLER_FINISHED;
39359 }
39360-
39361+
39362+ /* does the client have a lock for this connection ? */
39363+ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39364+ con->http_status = 423;
39365+ return HANDLER_FINISHED;
39366+ }
39367+
39368 /* stat and unlink afterwards */
39369 if (-1 == stat(con->physical.path->ptr, &st)) {
39370 /* don't about it yet, unlink will fail too */
39371@@ -1323,7 +1546,7 @@
39372 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39373
39374 b = chunkqueue_get_append_buffer(con->write_queue);
39375-
39376+
39377 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39378
39379 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
39380@@ -1331,7 +1554,7 @@
39381 buffer_append_string_buffer(b, multi_status_resp);
39382
39383 buffer_append_string(b,"</D:multistatus>\n");
39384-
39385+
39386 if (p->conf.log_xml) {
39387 log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
39388 }
39389@@ -1340,7 +1563,7 @@
39390 con->file_finished = 1;
39391 } else {
39392 /* everything went fine, remove the directory */
39393-
39394+
39395 if (-1 == rmdir(con->physical.path->ptr)) {
39396 switch(errno) {
39397 case ENOENT:
39398@@ -1375,97 +1598,174 @@
39399 case HTTP_METHOD_PUT: {
39400 int fd;
39401 chunkqueue *cq = con->request_content_queue;
39402+ chunk *c;
39403+ data_string *ds_range;
39404
39405 if (p->conf.is_readonly) {
39406 con->http_status = 403;
39407 return HANDLER_FINISHED;
39408 }
39409
39410+ /* is a exclusive lock set on the source */
39411+ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39412+ con->http_status = 423;
39413+ return HANDLER_FINISHED;
39414+ }
39415+
39416+
39417 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
39418
39419- /* taken what we have in the request-body and write it to a file */
39420- if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
39421- /* we can't open the file */
39422- con->http_status = 403;
39423- } else {
39424- chunk *c;
39425+ /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
39426+ * - most important Content-Range
39427+ *
39428+ *
39429+ * Example: Content-Range: bytes 100-1037/1038 */
39430
39431- con->http_status = 201; /* created */
39432- con->file_finished = 1;
39433+ if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
39434+ const char *num = ds_range->value->ptr;
39435+ off_t offset;
39436+ char *err = NULL;
39437
39438- for (c = cq->first; c; c = cq->first) {
39439- int r = 0;
39440+ if (0 != strncmp(num, "bytes ", 6)) {
39441+ con->http_status = 501; /* not implemented */
39442
39443- /* copy all chunks */
39444- switch(c->type) {
39445- case FILE_CHUNK:
39446-
39447- if (c->file.mmap.start == MAP_FAILED) {
39448- if (-1 == c->file.fd && /* open the file if not already open */
39449- -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39450- log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39451-
39452- return -1;
39453- }
39454-
39455- if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39456- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39457- strerror(errno), c->file.name, c->file.fd);
39458+ return HANDLER_FINISHED;
39459+ }
39460
39461- return -1;
39462- }
39463+ /* we only support <num>- ... */
39464
39465- c->file.mmap.length = c->file.length;
39466+ num += 6;
39467
39468- close(c->file.fd);
39469- c->file.fd = -1;
39470-
39471- /* chunk_reset() or chunk_free() will cleanup for us */
39472- }
39473-
39474- if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39475- switch(errno) {
39476- case ENOSPC:
39477- con->http_status = 507;
39478-
39479- break;
39480- default:
39481- con->http_status = 403;
39482- break;
39483- }
39484- }
39485- break;
39486- case MEM_CHUNK:
39487- if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39488- switch(errno) {
39489- case ENOSPC:
39490- con->http_status = 507;
39491-
39492- break;
39493- default:
39494- con->http_status = 403;
39495- break;
39496- }
39497- }
39498+ /* skip WS */
39499+ while (*num == ' ' || *num == '\t') num++;
39500+
39501+ if (*num == '\0') {
39502+ con->http_status = 501; /* not implemented */
39503+
39504+ return HANDLER_FINISHED;
39505+ }
39506+
39507+ offset = strtoll(num, &err, 10);
39508+
39509+ if (*err != '-' || offset < 0) {
39510+ con->http_status = 501; /* not implemented */
39511+
39512+ return HANDLER_FINISHED;
39513+ }
39514+
39515+ if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
39516+ switch (errno) {
39517+ case ENOENT:
39518+ con->http_status = 404; /* not found */
39519 break;
39520- case UNUSED_CHUNK:
39521+ default:
39522+ con->http_status = 403; /* not found */
39523 break;
39524 }
39525+ return HANDLER_FINISHED;
39526+ }
39527+
39528+ if (-1 == lseek(fd, offset, SEEK_SET)) {
39529+ con->http_status = 501; /* not implemented */
39530+
39531+ close(fd);
39532+
39533+ return HANDLER_FINISHED;
39534+ }
39535+ con->http_status = 200; /* modified */
39536+ } else {
39537+ /* take what we have in the request-body and write it to a file */
39538+
39539+ /* if the file doesn't exist, create it */
39540+ if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
39541+ if (errno == ENOENT &&
39542+ -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
39543+ /* we can't open the file */
39544+ con->http_status = 403;
39545
39546- if (r > 0) {
39547- c->offset += r;
39548- cq->bytes_out += r;
39549+ return HANDLER_FINISHED;
39550 } else {
39551- break;
39552+ con->http_status = 201; /* created */
39553+ }
39554+ } else {
39555+ con->http_status = 200; /* modified */
39556+ }
39557+ }
39558+
39559+ con->file_finished = 1;
39560+
39561+ for (c = cq->first; c; c = cq->first) {
39562+ int r = 0;
39563+
39564+ /* copy all chunks */
39565+ switch(c->type) {
39566+ case FILE_CHUNK:
39567+
39568+ if (c->file.mmap.start == MAP_FAILED) {
39569+ if (-1 == c->file.fd && /* open the file if not already open */
39570+ -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39571+ log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39572+
39573+ return -1;
39574+ }
39575+
39576+ if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39577+ log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39578+ strerror(errno), c->file.name, c->file.fd);
39579+
39580+ return -1;
39581+ }
39582+
39583+ c->file.mmap.length = c->file.length;
39584+
39585+ close(c->file.fd);
39586+ c->file.fd = -1;
39587+
39588+ /* chunk_reset() or chunk_free() will cleanup for us */
39589+ }
39590+
39591+ if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39592+ switch(errno) {
39593+ case ENOSPC:
39594+ con->http_status = 507;
39595+
39596+ break;
39597+ default:
39598+ con->http_status = 403;
39599+ break;
39600+ }
39601 }
39602- chunkqueue_remove_finished_chunks(cq);
39603+ break;
39604+ case MEM_CHUNK:
39605+ if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39606+ switch(errno) {
39607+ case ENOSPC:
39608+ con->http_status = 507;
39609+
39610+ break;
39611+ default:
39612+ con->http_status = 403;
39613+ break;
39614+ }
39615+ }
39616+ break;
39617+ case UNUSED_CHUNK:
39618+ break;
39619 }
39620- close(fd);
39621
39622+ if (r > 0) {
39623+ c->offset += r;
39624+ cq->bytes_out += r;
39625+ } else {
39626+ break;
39627+ }
39628+ chunkqueue_remove_finished_chunks(cq);
39629 }
39630+ close(fd);
39631+
39632 return HANDLER_FINISHED;
39633 }
39634- case HTTP_METHOD_MOVE:
39635+ case HTTP_METHOD_MOVE:
39636 case HTTP_METHOD_COPY: {
39637 buffer *destination = NULL;
39638 char *sep, *start;
39639@@ -1475,7 +1775,15 @@
39640 con->http_status = 403;
39641 return HANDLER_FINISHED;
39642 }
39643-
39644+
39645+ /* is a exclusive lock set on the source */
39646+ if (con->request.http_method == HTTP_METHOD_MOVE) {
39647+ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39648+ con->http_status = 423;
39649+ return HANDLER_FINISHED;
39650+ }
39651+ }
39652+
39653 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
39654 destination = ds->value;
39655 } else {
39656@@ -1549,10 +1857,10 @@
39657 }
39658
39659 buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
39660- BUFFER_APPEND_SLASH(p->physical.path);
39661+ PATHNAME_APPEND_SLASH(p->physical.path);
39662 buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
39663
39664- /* don't add a second / */
39665+ /* don't add a second / */
39666 if (p->physical.rel_path->ptr[0] == '/') {
39667 buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
39668 } else {
39669@@ -1613,6 +1921,12 @@
39670 /* it is just a file, good */
39671 int r;
39672
39673+ /* does the client have a lock for this connection ? */
39674+ if (!webdav_has_lock(srv, con, p, p->uri.path)) {
39675+ con->http_status = 423;
39676+ return HANDLER_FINISHED;
39677+ }
39678+
39679 /* destination exists */
39680 if (0 == (r = stat(p->physical.path->ptr, &st))) {
39681 if (S_ISDIR(st.st_mode)) {
39682@@ -1636,7 +1950,7 @@
39683 return HANDLER_FINISHED;
39684 }
39685 } else if (overwrite == 0) {
39686- /* destination exists, but overwrite is not set */
39687+ /* destination exists, but overwrite is not set */
39688 con->http_status = 412;
39689 return HANDLER_FINISHED;
39690 } else {
39691@@ -1655,16 +1969,16 @@
39692 sqlite3_reset(stmt);
39693
39694 /* bind the values to the insert */
39695- sqlite3_bind_text(stmt, 1,
39696- p->uri.path->ptr,
39697+ sqlite3_bind_text(stmt, 1,
39698+ p->uri.path->ptr,
39699 p->uri.path->used - 1,
39700 SQLITE_TRANSIENT);
39701
39702- sqlite3_bind_text(stmt, 2,
39703- con->uri.path->ptr,
39704+ sqlite3_bind_text(stmt, 2,
39705+ con->uri.path->ptr,
39706 con->uri.path->used - 1,
39707 SQLITE_TRANSIENT);
39708-
39709+
39710 if (SQLITE_DONE != sqlite3_step(stmt)) {
39711 log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
39712 }
39713@@ -1691,12 +2005,17 @@
39714
39715 return HANDLER_FINISHED;
39716 }
39717- case HTTP_METHOD_PROPPATCH: {
39718+ case HTTP_METHOD_PROPPATCH:
39719 if (p->conf.is_readonly) {
39720 con->http_status = 403;
39721 return HANDLER_FINISHED;
39722 }
39723
39724+ if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39725+ con->http_status = 423;
39726+ return HANDLER_FINISHED;
39727+ }
39728+
39729 /* check if destination exists */
39730 if (-1 == stat(con->physical.path->ptr, &st)) {
39731 switch(errno) {
39732@@ -1737,7 +2056,7 @@
39733
39734 sqlite3_stmt *stmt;
39735
39736- stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
39737+ stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
39738 p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
39739
39740 for (props = cmd->children; props; props = props->next) {
39741@@ -1762,34 +2081,35 @@
39742
39743 /* bind the values to the insert */
39744
39745- sqlite3_bind_text(stmt, 1,
39746- con->uri.path->ptr,
39747+ sqlite3_bind_text(stmt, 1,
39748+ con->uri.path->ptr,
39749 con->uri.path->used - 1,
39750 SQLITE_TRANSIENT);
39751- sqlite3_bind_text(stmt, 2,
39752+ sqlite3_bind_text(stmt, 2,
39753 (char *)prop->name,
39754 strlen((char *)prop->name),
39755 SQLITE_TRANSIENT);
39756 if (prop->ns) {
39757- sqlite3_bind_text(stmt, 3,
39758+ sqlite3_bind_text(stmt, 3,
39759 (char *)prop->ns->href,
39760 strlen((char *)prop->ns->href),
39761 SQLITE_TRANSIENT);
39762 } else {
39763- sqlite3_bind_text(stmt, 3,
39764+ sqlite3_bind_text(stmt, 3,
39765 "",
39766 0,
39767 SQLITE_TRANSIENT);
39768 }
39769 if (stmt == p->conf.stmt_update_prop) {
39770- sqlite3_bind_text(stmt, 4,
39771+ sqlite3_bind_text(stmt, 4,
39772 (char *)xmlNodeGetContent(prop),
39773 strlen((char *)xmlNodeGetContent(prop)),
39774 SQLITE_TRANSIENT);
39775 }
39776-
39777+
39778 if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
39779- log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39780+ log_error_write(srv, __FILE__, __LINE__, "ss",
39781+ "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39782 }
39783 }
39784 }
39785@@ -1804,7 +2124,7 @@
39786
39787 goto propmatch_cleanup;
39788 }
39789-
39790+
39791 con->http_status = 400;
39792 } else {
39793 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
39794@@ -1821,6 +2141,7 @@
39795 }
39796
39797 propmatch_cleanup:
39798+
39799 xmlFreeDoc(xml);
39800 } else {
39801 con->http_status = 400;
39802@@ -1830,11 +2151,307 @@
39803 #endif
39804 con->http_status = 501;
39805 return HANDLER_FINISHED;
39806- }
39807+ case HTTP_METHOD_LOCK:
39808+ /**
39809+ * a mac wants to write
39810+ *
39811+ * LOCK /dav/expire.txt HTTP/1.1\r\n
39812+ * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
39813+ * Accept: * / *\r\n
39814+ * Depth: 0\r\n
39815+ * Timeout: Second-600\r\n
39816+ * Content-Type: text/xml; charset=\"utf-8\"\r\n
39817+ * Content-Length: 229\r\n
39818+ * Connection: keep-alive\r\n
39819+ * Host: 192.168.178.23:1025\r\n
39820+ * \r\n
39821+ * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
39822+ * <D:lockinfo xmlns:D=\"DAV:\">\n
39823+ * <D:lockscope><D:exclusive/></D:lockscope>\n
39824+ * <D:locktype><D:write/></D:locktype>\n
39825+ * <D:owner>\n
39826+ * <D:href>http://www.apple.com/webdav_fs/</D:href>\n
39827+ * </D:owner>\n
39828+ * </D:lockinfo>\n
39829+ */
39830+
39831+ if (depth != 0 && depth != -1) {
39832+ con->http_status = 400;
39833+
39834+ return HANDLER_FINISHED;
39835+ }
39836+
39837+#ifdef USE_LOCKS
39838+ if (con->request.content_length) {
39839+ xmlDocPtr xml;
39840+ buffer *hdr_if = NULL;
39841+
39842+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39843+ hdr_if = ds->value;
39844+ }
39845+
39846+ /* we don't support Depth: Infinity on locks */
39847+ if (hdr_if == NULL && depth == -1) {
39848+ con->http_status = 409; /* Conflict */
39849+
39850+ return HANDLER_FINISHED;
39851+ }
39852+
39853+ if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
39854+ xmlNode *rootnode = xmlDocGetRootElement(xml);
39855+
39856+ assert(rootnode);
39857+
39858+ if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
39859+ xmlNode *lockinfo;
39860+ const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
39861+
39862+ for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
39863+ if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
39864+ xmlNode *value;
39865+ for (value = lockinfo->children; value; value = value->next) {
39866+ if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
39867+ (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
39868+ lockscope = value->name;
39869+ } else {
39870+ con->http_status = 400;
39871+
39872+ xmlFreeDoc(xml);
39873+ return HANDLER_FINISHED;
39874+ }
39875+ }
39876+ } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
39877+ xmlNode *value;
39878+ for (value = lockinfo->children; value; value = value->next) {
39879+ if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
39880+ locktype = value->name;
39881+ } else {
39882+ con->http_status = 400;
39883+
39884+ xmlFreeDoc(xml);
39885+ return HANDLER_FINISHED;
39886+ }
39887+ }
39888+
39889+ } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
39890+ }
39891+ }
39892+
39893+ if (lockscope && locktype) {
39894+ sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39895+
39896+ /* is this resourse already locked ? */
39897+
39898+ /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
39899+ * FROM locks
39900+ * WHERE resource = ? */
39901+
39902+ if (stmt) {
39903+
39904+ sqlite3_reset(stmt);
39905+
39906+ sqlite3_bind_text(stmt, 1,
39907+ p->uri.path->ptr,
39908+ p->uri.path->used - 1,
39909+ SQLITE_TRANSIENT);
39910+
39911+ /* it is the PK */
39912+ while (SQLITE_ROW == sqlite3_step(stmt)) {
39913+ /* we found a lock
39914+ * 1. is it compatible ?
39915+ * 2. is it ours */
39916+ char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
39917+
39918+ if (strcmp(sql_lockscope, "exclusive")) {
39919+ con->http_status = 423;
39920+ } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
39921+ /* resourse is locked with a shared lock
39922+ * client wants exclusive */
39923+ con->http_status = 423;
39924+ }
39925+ }
39926+ if (con->http_status == 423) {
39927+ xmlFreeDoc(xml);
39928+ return HANDLER_FINISHED;
39929+ }
39930+ }
39931+
39932+ stmt = p->conf.stmt_create_lock;
39933+ if (stmt) {
39934+ /* create a lock-token */
39935+ uuid_t id;
39936+ char uuid[37] /* 36 + \0 */;
39937+
39938+ uuid_generate(id);
39939+ uuid_unparse(id, uuid);
39940+
39941+ buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
39942+ buffer_append_string(p->tmp_buf, uuid);
39943+
39944+ /* "CREATE TABLE locks ("
39945+ * " locktoken TEXT NOT NULL,"
39946+ * " resource TEXT NOT NULL,"
39947+ * " lockscope TEXT NOT NULL,"
39948+ * " locktype TEXT NOT NULL,"
39949+ * " owner TEXT NOT NULL,"
39950+ * " depth INT NOT NULL,"
39951+ */
39952+
39953+ sqlite3_reset(stmt);
39954+
39955+ sqlite3_bind_text(stmt, 1,
39956+ CONST_BUF_LEN(p->tmp_buf),
39957+ SQLITE_TRANSIENT);
39958+
39959+ sqlite3_bind_text(stmt, 2,
39960+ CONST_BUF_LEN(con->uri.path),
39961+ SQLITE_TRANSIENT);
39962+
39963+ sqlite3_bind_text(stmt, 3,
39964+ lockscope,
39965+ xmlStrlen(lockscope),
39966+ SQLITE_TRANSIENT);
39967+
39968+ sqlite3_bind_text(stmt, 4,
39969+ locktype,
39970+ xmlStrlen(locktype),
39971+ SQLITE_TRANSIENT);
39972+
39973+ /* owner */
39974+ sqlite3_bind_text(stmt, 5,
39975+ "",
39976+ 0,
39977+ SQLITE_TRANSIENT);
39978+
39979+ /* depth */
39980+ sqlite3_bind_int(stmt, 6,
39981+ depth);
39982+
39983+
39984+ if (SQLITE_DONE != sqlite3_step(stmt)) {
39985+ log_error_write(srv, __FILE__, __LINE__, "ss",
39986+ "create lock:", sqlite3_errmsg(p->conf.sql));
39987+ }
39988+
39989+ /* looks like we survived */
39990+ webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
39991+
39992+ con->http_status = 201;
39993+ con->file_finished = 1;
39994+ }
39995+ }
39996+ }
39997+
39998+ xmlFreeDoc(xml);
39999+ return HANDLER_FINISHED;
40000+ } else {
40001+ con->http_status = 400;
40002+ return HANDLER_FINISHED;
40003+ }
40004+ } else {
40005+
40006+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
40007+ buffer *locktoken = ds->value;
40008+ sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
40009+
40010+ /* remove the < > around the token */
40011+ if (locktoken->used < 6) {
40012+ con->http_status = 400;
40013+
40014+ return HANDLER_FINISHED;
40015+ }
40016+
40017+ buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
40018+
40019+ sqlite3_reset(stmt);
40020+
40021+ sqlite3_bind_text(stmt, 1,
40022+ CONST_BUF_LEN(p->tmp_buf),
40023+ SQLITE_TRANSIENT);
40024+
40025+ if (SQLITE_DONE != sqlite3_step(stmt)) {
40026+ log_error_write(srv, __FILE__, __LINE__, "ss",
40027+ "refresh lock:", sqlite3_errmsg(p->conf.sql));
40028+ }
40029+
40030+ webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
40031+
40032+ con->http_status = 200;
40033+ con->file_finished = 1;
40034+ return HANDLER_FINISHED;
40035+ } else {
40036+ /* we need a lock-token to refresh */
40037+ con->http_status = 400;
40038+
40039+ return HANDLER_FINISHED;
40040+ }
40041+ }
40042+ break;
40043+#else
40044+ con->http_status = 501;
40045+ return HANDLER_FINISHED;
40046+#endif
40047+ case HTTP_METHOD_UNLOCK:
40048+#ifdef USE_LOCKS
40049+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
40050+ buffer *locktoken = ds->value;
40051+ sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
40052+
40053+ /* remove the < > around the token */
40054+ if (locktoken->used < 4) {
40055+ con->http_status = 400;
40056+
40057+ return HANDLER_FINISHED;
40058+ }
40059+
40060+ /**
40061+ * FIXME:
40062+ *
40063+ * if the resourse is locked:
40064+ * - by us: unlock
40065+ * - by someone else: 401
40066+ * if the resource is not locked:
40067+ * - 412
40068+ * */
40069+
40070+ buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
40071+
40072+ sqlite3_reset(stmt);
40073+
40074+ sqlite3_bind_text(stmt, 1,
40075+ CONST_BUF_LEN(p->tmp_buf),
40076+ SQLITE_TRANSIENT);
40077+
40078+ sqlite3_bind_text(stmt, 2,
40079+ CONST_BUF_LEN(con->uri.path),
40080+ SQLITE_TRANSIENT);
40081+
40082+ if (SQLITE_DONE != sqlite3_step(stmt)) {
40083+ log_error_write(srv, __FILE__, __LINE__, "ss",
40084+ "remove lock:", sqlite3_errmsg(p->conf.sql));
40085+ }
40086+
40087+ if (0 == sqlite3_changes(p->conf.sql)) {
40088+ con->http_status = 401;
40089+ } else {
40090+ con->http_status = 204;
40091+ }
40092+ return HANDLER_FINISHED;
40093+ } else {
40094+ /* we need a lock-token to unlock */
40095+ con->http_status = 400;
40096+
40097+ return HANDLER_FINISHED;
40098+ }
40099+ break;
40100+#else
40101+ con->http_status = 501;
40102+ return HANDLER_FINISHED;
40103+#endif
40104 default:
40105 break;
40106 }
40107-
40108+
40109 /* not found */
40110 return HANDLER_GO_ON;
40111 }
40112@@ -1845,14 +2462,14 @@
40113 int mod_webdav_plugin_init(plugin *p) {
40114 p->version = LIGHTTPD_VERSION_ID;
40115 p->name = buffer_init_string("webdav");
40116-
40117+
40118 p->init = mod_webdav_init;
40119 p->handle_uri_clean = mod_webdav_uri_handler;
40120 p->handle_physical = mod_webdav_subrequest_handler;
40121 p->set_defaults = mod_webdav_set_defaults;
40122 p->cleanup = mod_webdav_free;
40123-
40124+
40125 p->data = NULL;
40126-
40127+
40128 return 0;
40129 }
1175ccec 40130--- ../lighttpd-1.4.11/src/network.c 2006-03-04 16:45:46.000000000 +0200
36e2a29e 40131+++ lighttpd-1.4.12/src/network.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
40132@@ -1,14 +1,14 @@
40133 #include <sys/types.h>
40134 #include <sys/stat.h>
40135-#include <sys/time.h>
40136
40137 #include <errno.h>
40138 #include <fcntl.h>
40139-#include <unistd.h>
40140 #include <string.h>
40141 #include <stdlib.h>
40142 #include <assert.h>
40143
40144+#include <stdio.h>
40145+
40146 #include "network.h"
40147 #include "fdevent.h"
40148 #include "log.h"
40149@@ -19,11 +19,12 @@
40150 #include "network_backends.h"
40151 #include "sys-mmap.h"
40152 #include "sys-socket.h"
40153+#include "sys-files.h"
40154
40155 #ifdef USE_OPENSSL
40156-# include <openssl/ssl.h>
40157-# include <openssl/err.h>
40158-# include <openssl/rand.h>
40159+# include <openssl/ssl.h>
40160+# include <openssl/err.h>
40161+# include <openssl/rand.h>
40162 #endif
40163
40164 handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
40165@@ -31,11 +32,11 @@
40166 server_socket *srv_socket = (server_socket *)context;
40167 connection *con;
40168 int loops = 0;
40169-
40170+
40171 UNUSED(context);
40172-
40173+
40174 if (revents != FDEVENT_IN) {
40175- log_error_write(srv, __FILE__, __LINE__, "sdd",
40176+ log_error_write(srv, __FILE__, __LINE__, "sdd",
40177 "strange event for server socket",
40178 srv_socket->fd,
40179 revents);
40180@@ -44,12 +45,12 @@
40181
40182 /* accept()s at most 100 connections directly
40183 *
40184- * we jump out after 100 to give the waiting connections a chance */
40185+ * we jump out after 100 to give the waiting connections a chance */
40186 for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
40187 handler_t r;
40188-
40189+
40190 connection_state_machine(srv, con);
40191-
40192+
40193 switch(r = plugins_call_handle_joblist(srv, con)) {
40194 case HANDLER_FINISHED:
40195 case HANDLER_GO_ON:
40196@@ -72,18 +73,18 @@
40197 buffer *b;
40198 int is_unix_domain_socket = 0;
40199 int fd;
40200-
40201+
40202 #ifdef SO_ACCEPTFILTER
40203 struct accept_filter_arg afa;
40204 #endif
40205
40206-#ifdef __WIN32
40207+#ifdef _WIN32
40208 WORD wVersionRequested;
40209 WSADATA wsaData;
40210 int err;
40211-
40212+
40213 wVersionRequested = MAKEWORD( 2, 2 );
40214-
40215+
40216 err = WSAStartup( wVersionRequested, &wsaData );
40217 if ( err != 0 ) {
40218 /* Tell the user that we could not find a usable */
40219@@ -91,37 +92,37 @@
40220 return -1;
40221 }
40222 #endif
40223-
40224+
40225 srv_socket = calloc(1, sizeof(*srv_socket));
40226 srv_socket->fd = -1;
40227-
40228+
40229 srv_socket->srv_token = buffer_init();
40230 buffer_copy_string_buffer(srv_socket->srv_token, host_token);
40231-
40232+
40233 b = buffer_init();
40234 buffer_copy_string_buffer(b, host_token);
40235-
40236- /* ipv4:port
40237+
40238+ /* ipv4:port
40239 * [ipv6]:port
40240 */
40241 if (NULL == (sp = strrchr(b->ptr, ':'))) {
40242 log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
40243-
40244+
40245 return -1;
40246 }
40247-
40248+
40249 host = b->ptr;
40250-
40251+
40252 /* check for [ and ] */
40253 if (b->ptr[0] == '[' && *(sp-1) == ']') {
40254 *(sp-1) = '\0';
40255 host++;
40256-
40257+
40258 s->use_ipv6 = 1;
40259 }
40260-
40261+
40262 *(sp++) = '\0';
40263-
40264+
40265 port = strtol(sp, NULL, 10);
40266
40267 if (host[0] == '/') {
40268@@ -129,17 +130,17 @@
40269 is_unix_domain_socket = 1;
40270 } else if (port == 0 || port > 65535) {
40271 log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
40272-
40273+
40274 return -1;
40275 }
40276-
40277+
40278 if (*host == '\0') host = NULL;
40279
40280 if (is_unix_domain_socket) {
40281 #ifdef HAVE_SYS_UN_H
40282
40283 srv_socket->addr.plain.sa_family = AF_UNIX;
40284-
40285+
40286 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
40287 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40288 return -1;
40289@@ -154,7 +155,7 @@
40290 #ifdef HAVE_IPV6
40291 if (s->use_ipv6) {
40292 srv_socket->addr.plain.sa_family = AF_INET6;
40293-
40294+
40295 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40296 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40297 return -1;
40298@@ -162,7 +163,7 @@
40299 srv_socket->use_ipv6 = 1;
40300 }
40301 #endif
40302-
40303+
40304 if (srv_socket->fd == -1) {
40305 srv_socket->addr.plain.sa_family = AF_INET;
40306 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40307@@ -170,16 +171,16 @@
40308 return -1;
40309 }
40310 }
40311-
40312+
40313 /* */
40314 srv->cur_fds = srv_socket->fd;
40315-
40316+
40317 val = 1;
40318 if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
40319 log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
40320 return -1;
40321 }
40322-
40323+
40324 switch(srv_socket->addr.plain.sa_family) {
40325 #ifdef HAVE_IPV6
40326 case AF_INET6:
40327@@ -190,23 +191,23 @@
40328 } else {
40329 struct addrinfo hints, *res;
40330 int r;
40331-
40332+
40333 memset(&hints, 0, sizeof(hints));
40334-
40335+
40336 hints.ai_family = AF_INET6;
40337 hints.ai_socktype = SOCK_STREAM;
40338 hints.ai_protocol = IPPROTO_TCP;
40339-
40340+
40341 if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
40342- log_error_write(srv, __FILE__, __LINE__,
40343- "sssss", "getaddrinfo failed: ",
40344+ log_error_write(srv, __FILE__, __LINE__,
40345+ "sssss", "getaddrinfo failed: ",
40346 gai_strerror(r), "'", host, "'");
40347-
40348+
40349 return -1;
40350 }
40351-
40352+
40353 memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
40354-
40355+
40356 freeaddrinfo(res);
40357 }
40358 srv_socket->addr.ipv6.sin6_port = htons(port);
40359@@ -221,33 +222,34 @@
40360 } else {
40361 struct hostent *he;
40362 if (NULL == (he = gethostbyname(host))) {
40363- log_error_write(srv, __FILE__, __LINE__,
40364- "sds", "gethostbyname failed: ",
40365+ log_error_write(srv, __FILE__, __LINE__,
40366+ "sds", "gethostbyname failed: ",
40367 h_errno, host);
40368 return -1;
40369 }
40370-
40371+
40372 if (he->h_addrtype != AF_INET) {
40373 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
40374 return -1;
40375 }
40376-
40377+
40378 if (he->h_length != sizeof(struct in_addr)) {
40379 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
40380 return -1;
40381 }
40382-
40383+
40384 memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
40385 }
40386 srv_socket->addr.ipv4.sin_port = htons(port);
40387-
40388+
40389 addr_len = sizeof(struct sockaddr_in);
40390-
40391+
40392 break;
40393+#ifndef _WIN32
40394 case AF_UNIX:
40395 srv_socket->addr.un.sun_family = AF_UNIX;
40396 strcpy(srv_socket->addr.un.sun_path, host);
40397-
40398+
40399 #ifdef SUN_LEN
40400 addr_len = SUN_LEN(&srv_socket->addr.un);
40401 #else
40402@@ -259,8 +261,8 @@
40403 if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
40404 close(fd);
40405
40406- log_error_write(srv, __FILE__, __LINE__, "ss",
40407- "server socket is still in use:",
40408+ log_error_write(srv, __FILE__, __LINE__, "ss",
40409+ "server socket is still in use:",
40410 host);
40411
40412
40413@@ -275,88 +277,89 @@
40414 case ENOENT:
40415 break;
40416 default:
40417- log_error_write(srv, __FILE__, __LINE__, "sds",
40418- "testing socket failed:",
40419+ log_error_write(srv, __FILE__, __LINE__, "sds",
40420+ "testing socket failed:",
40421 host, strerror(errno));
40422
40423 return -1;
40424 }
40425
40426 break;
40427+#endif
40428 default:
40429 addr_len = 0;
40430-
40431+
40432 return -1;
40433 }
40434-
40435+
40436 if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
40437 switch(srv_socket->addr.plain.sa_family) {
40438 case AF_UNIX:
40439- log_error_write(srv, __FILE__, __LINE__, "sds",
40440- "can't bind to socket:",
40441+ log_error_write(srv, __FILE__, __LINE__, "sds",
40442+ "can't bind to socket:",
40443 host, strerror(errno));
40444 break;
40445 default:
40446- log_error_write(srv, __FILE__, __LINE__, "ssds",
40447- "can't bind to port:",
40448+ log_error_write(srv, __FILE__, __LINE__, "ssds",
40449+ "can't bind to port:",
40450 host, port, strerror(errno));
40451 break;
40452 }
40453 return -1;
40454 }
40455-
40456+
40457 if (-1 == listen(srv_socket->fd, 128 * 8)) {
40458 log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
40459 return -1;
40460 }
40461-
40462+
40463 if (s->is_ssl) {
40464 #ifdef USE_OPENSSL
40465 if (srv->ssl_is_init == 0) {
40466 SSL_load_error_strings();
40467 SSL_library_init();
40468 srv->ssl_is_init = 1;
40469-
40470+
40471 if (0 == RAND_status()) {
40472- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40473+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40474 "not enough entropy in the pool");
40475 return -1;
40476 }
40477 }
40478-
40479+
40480 if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
40481- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40482+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40483 ERR_error_string(ERR_get_error(), NULL));
40484 return -1;
40485 }
40486-
40487+
40488 if (buffer_is_empty(s->ssl_pemfile)) {
40489 log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
40490 return -1;
40491 }
40492-
40493+
40494 if (!buffer_is_empty(s->ssl_ca_file)) {
40495 if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
40496- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40497+ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40498 ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
40499 return -1;
40500 }
40501 }
40502-
40503+
40504 if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40505- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40506+ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40507 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40508 return -1;
40509 }
40510-
40511+
40512 if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40513- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40514+ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40515 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40516 return -1;
40517 }
40518-
40519+
40520 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
40521- log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
40522+ log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
40523 "Private key does not match the certificate public key, reason:",
40524 ERR_error_string(ERR_get_error(), NULL),
40525 s->ssl_pemfile);
40526@@ -364,15 +367,15 @@
40527 }
40528 srv_socket->ssl_ctx = s->ssl_ctx;
40529 #else
40530-
40531+
40532 buffer_free(srv_socket->srv_token);
40533 free(srv_socket);
40534-
40535+
40536 buffer_free(b);
40537-
40538- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40539+
40540+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40541 "ssl requested but openssl support is not compiled in");
40542-
40543+
40544 return -1;
40545 #endif
40546 } else {
40547@@ -390,10 +393,10 @@
40548 }
40549 #endif
40550 }
40551-
40552+
40553 srv_socket->is_ssl = s->is_ssl;
40554 srv_socket->fde_ndx = -1;
40555-
40556+
40557 if (srv->srv_sockets.size == 0) {
40558 srv->srv_sockets.size = 4;
40559 srv->srv_sockets.used = 0;
40560@@ -402,11 +405,10 @@
40561 srv->srv_sockets.size += 4;
40562 srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
40563 }
40564-
40565+
40566 srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
40567-
40568 buffer_free(b);
40569-
40570+
40571 return 0;
40572 }
40573
40574@@ -414,45 +416,58 @@
40575 size_t i;
40576 for (i = 0; i < srv->srv_sockets.used; i++) {
40577 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40578-
40579+
40580 if (srv_socket->fd != -1) {
40581 /* check if server fd are already registered */
40582 if (srv_socket->fde_ndx != -1) {
40583 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
40584 fdevent_unregister(srv->ev, srv_socket->fd);
40585 }
40586-
40587+
40588 close(srv_socket->fd);
40589 }
40590-
40591+
40592+ if (srv_socket->is_ssl) {
40593+#ifdef USE_OPENSSL
40594+ SSL_CTX_free(srv_socket->ssl_ctx);
40595+#endif
40596+ }
40597+
40598 buffer_free(srv_socket->srv_token);
40599-
40600+
40601 free(srv_socket);
40602 }
40603-
40604+
40605+#ifdef USE_OPENSSL
40606+ ERR_free_strings();
40607+#endif
40608 free(srv->srv_sockets.ptr);
40609-
40610+
f26f9fd5
ER
40611 return 0;
40612 }
f26f9fd5 40613
2519e6e5
ER
40614 typedef enum {
40615 NETWORK_BACKEND_UNSET,
40616+
40617 NETWORK_BACKEND_WRITE,
40618 NETWORK_BACKEND_WRITEV,
40619 NETWORK_BACKEND_LINUX_SENDFILE,
40620 NETWORK_BACKEND_FREEBSD_SENDFILE,
40621- NETWORK_BACKEND_SOLARIS_SENDFILEV
40622+ NETWORK_BACKEND_SOLARIS_SENDFILEV,
40623+
40624+ NETWORK_BACKEND_WIN32_SEND,
40625+ NETWORK_BACKEND_WIN32_TRANSMITFILE,
40626 } network_backend_t;
40627
40628 int network_init(server *srv) {
40629 buffer *b;
40630 size_t i;
40631 network_backend_t backend;
40632-
40633- struct nb_map {
40634- network_backend_t nb;
40635- const char *name;
40636- } network_backends[] = {
40637+
40638+ struct nb_map {
40639+ network_backend_t nb;
40640+ const char *name;
40641+ } network_backends[] = {
40642 /* lowest id wins */
40643 #if defined USE_LINUX_SENDFILE
40644 { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" },
40645@@ -466,21 +481,30 @@
40646 #if defined USE_WRITEV
40647 { NETWORK_BACKEND_WRITEV, "writev" },
40648 #endif
40649+#if defined USE_WRITE
40650 { NETWORK_BACKEND_WRITE, "write" },
40651+#endif
40652+#if defined USE_WIN32_TRANSMITFILE
40653+ { NETWORK_BACKEND_WIN32_TRANSMITFILE, "win32-transmitfile" },
40654+#endif
40655+#if defined USE_WIN32_SEND
40656+ { NETWORK_BACKEND_WIN32_SEND, "win32-send" },
40657+#endif
40658+
40659 { NETWORK_BACKEND_UNSET, NULL }
40660 };
40661-
40662+
40663 b = buffer_init();
40664-
40665+
40666 buffer_copy_string_buffer(b, srv->srvconf.bindhost);
40667 buffer_append_string(b, ":");
40668 buffer_append_long(b, srv->srvconf.port);
40669-
40670+
40671 if (0 != network_server_init(srv, b, srv->config_storage[0])) {
40672 return -1;
40673 }
40674 buffer_free(b);
40675-
40676+
40677 #ifdef USE_OPENSSL
40678 srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
40679 #endif
40680@@ -500,54 +524,80 @@
40681 if (NULL == network_backends[i].name) {
40682 /* we don't know it */
40683
40684- log_error_write(srv, __FILE__, __LINE__, "sb",
40685- "server.network-backend has a unknown value:",
40686+ log_error_write(srv, __FILE__, __LINE__, "sb",
40687+ "server.network-backend has a unknown value:",
40688 srv->srvconf.network_backend);
40689
40690 return -1;
40691 }
40692 }
40693
40694+#define SET_NETWORK_BACKEND(read, write) \
40695+ srv->network_backend_write = network_write_chunkqueue_##write;\
40696+ srv->network_backend_read = network_read_chunkqueue_##read
40697+
40698+#define SET_NETWORK_BACKEND_SSL(read, write) \
40699+ srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
40700+ srv->network_ssl_backend_read = network_read_chunkqueue_##read
40701+
40702 switch(backend) {
40703+
40704+#ifdef USE_WIN32_SEND
40705+ case NETWORK_BACKEND_WIN32_SEND:
40706+ SET_NETWORK_BACKEND(win32recv, win32send);
40707+ break;
40708+#ifdef USE_WIN32_TRANSMITFILE
40709+ case NETWORK_BACKEND_WIN32_TRANSMITFILE:
40710+ SET_NETWORK_BACKEND(win32recv, win32transmitfile);
40711+ break;
40712+#endif
40713+#endif
40714+
40715+#ifdef USE_WRITE
40716 case NETWORK_BACKEND_WRITE:
40717- srv->network_backend_write = network_write_chunkqueue_write;
40718+ SET_NETWORK_BACKEND(read, write);
40719 break;
40720+
40721 #ifdef USE_WRITEV
40722 case NETWORK_BACKEND_WRITEV:
40723- srv->network_backend_write = network_write_chunkqueue_writev;
40724+ SET_NETWORK_BACKEND(read, writev);
40725 break;
40726 #endif
40727 #ifdef USE_LINUX_SENDFILE
40728 case NETWORK_BACKEND_LINUX_SENDFILE:
40729- srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
40730+ SET_NETWORK_BACKEND(read, linuxsendfile);
40731 break;
40732 #endif
40733 #ifdef USE_FREEBSD_SENDFILE
40734 case NETWORK_BACKEND_FREEBSD_SENDFILE:
40735- srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
40736+ SET_NETWORK_BACKEND(read, freebsdsendfile);
40737 break;
40738 #endif
40739 #ifdef USE_SOLARIS_SENDFILEV
40740 case NETWORK_BACKEND_SOLARIS_SENDFILEV:
40741- srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
40742+ SET_NETWORK_BACKEND(read, solarissendfilev);
40743 break;
40744 #endif
40745+#endif
40746 default:
40747 return -1;
40748 }
40749+#ifdef USE_OPENSSL
40750+ SET_NETWORK_BACKEND_SSL(openssl, openssl);
40751+#endif
40752
40753 /* check for $SERVER["socket"] */
40754 for (i = 1; i < srv->config_context->used; i++) {
40755 data_config *dc = (data_config *)srv->config_context->data[i];
40756 specific_config *s = srv->config_storage[i];
40757 size_t j;
40758-
40759+
40760 /* not our stage */
40761 if (COMP_SERVER_SOCKET != dc->comp) continue;
40762-
40763+
40764 if (dc->cond != CONFIG_COND_EQ) {
40765 log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
40766-
40767+
40768 return -1;
40769 }
40770
40771@@ -558,36 +608,47 @@
40772 break;
40773 }
40774 }
40775-
40776+
40777 if (j == srv->srv_sockets.used) {
40778 if (0 != network_server_init(srv, dc->string, s)) return -1;
40779 }
40780 }
40781-
40782+
40783 return 0;
40784 }
40785
40786 int network_register_fdevents(server *srv) {
40787 size_t i;
40788-
40789 if (-1 == fdevent_reset(srv->ev)) {
40790 return -1;
40791 }
40792-
40793 /* register fdevents after reset */
40794 for (i = 0; i < srv->srv_sockets.used; i++) {
40795 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40796-
40797 fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
40798 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
40799 }
40800 return 0;
40801 }
40802
40803-int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40804- int ret = -1;
40805+network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40806+ server_socket *srv_socket = con->srv_socket;
40807+
40808+ if (srv_socket->is_ssl) {
40809+#ifdef USE_OPENSSL
40810+ return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
40811+#else
40812+ return NETWORK_STATUS_FATAL_ERROR;
40813+#endif
40814+ } else {
40815+ return srv->network_backend_read(srv, con, con->fd, cq);
40816+ }
40817+}
40818+
40819+network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40820+ network_status_t ret = NETWORK_STATUS_UNSET;
40821 off_t written = 0;
40822-#ifdef TCP_CORK
40823+#ifdef TCP_CORK
40824 int corked = 0;
40825 #endif
40826 server_socket *srv_socket = con->srv_socket;
40827@@ -600,11 +661,11 @@
40828 joblist_append(srv, con);
40829
40830 return 1;
40831- }
40832+ }
40833
40834 written = cq->bytes_out;
40835
40836-#ifdef TCP_CORK
40837+#ifdef TCP_CORK
40838 /* Linux: put a cork into the socket as we want to combine the write() calls
40839 * but only if we really have multiple chunks
40840 */
40841@@ -613,7 +674,7 @@
40842 setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
40843 }
40844 #endif
40845-
40846+
40847 if (srv_socket->is_ssl) {
40848 #ifdef USE_OPENSSL
40849 ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
40850@@ -621,12 +682,17 @@
40851 } else {
40852 ret = srv->network_backend_write(srv, con, con->fd, cq);
40853 }
40854-
40855- if (ret >= 0) {
40856+
40857+ switch (ret) {
40858+ case NETWORK_STATUS_WAIT_FOR_EVENT:
40859+ case NETWORK_STATUS_SUCCESS:
40860 chunkqueue_remove_finished_chunks(cq);
40861- ret = chunkqueue_is_empty(cq) ? 0 : 1;
40862+
40863+ break;
40864+ default:
40865+ break;
40866 }
40867-
40868+
40869 #ifdef TCP_CORK
40870 if (corked) {
40871 corked = 0;
40872@@ -639,13 +705,13 @@
40873 con->bytes_written_cur_second += written;
40874
40875 *(con->conf.global_bytes_per_second_cnt_ptr) += written;
40876-
40877+
40878 if (con->conf.kbytes_per_second &&
40879 (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
40880 /* we reached the traffic limit */
40881
40882 con->traffic_limit_reached = 1;
40883 joblist_append(srv, con);
40884- }
40885+ }
40886 return ret;
40887 }
1175ccec 40888--- ../lighttpd-1.4.11/src/network.h 2005-08-11 01:26:42.000000000 +0300
36e2a29e 40889+++ lighttpd-1.4.12/src/network.h 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
40890@@ -3,7 +3,8 @@
40891
40892 #include "server.h"
40893
40894-int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
40895+network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
40896+network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
40897
40898 int network_init(server *srv);
40899 int network_close(server *srv);
1175ccec 40900--- ../lighttpd-1.4.11/src/network_backends.h 2005-10-24 15:13:51.000000000 +0300
36e2a29e 40901+++ lighttpd-1.4.12/src/network_backends.h 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
40902@@ -43,16 +43,52 @@
40903 # define USE_AIX_SENDFILE
40904 #endif
40905
40906+/**
40907+* unix can use read/write or recv/send on sockets
40908+* win32 only recv/send
40909+*/
40910+#ifdef _WIN32
40911+# define USE_WIN32_SEND
40912+/* wait for async-io support
40913+# define USE_WIN32_TRANSMITFILE
40914+*/
40915+#else
40916+# define USE_WRITE
40917+#endif
40918+
40919 #include "base.h"
40920+#include "network.h"
40921+
40922+#define NETWORK_BACKEND_WRITE_CHUNK(x) \
40923+ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c)
40924+
40925+#define NETWORK_BACKEND_WRITE(x) \
40926+ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
40927+#define NETWORK_BACKEND_READ(x) \
40928+ network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
f26f9fd5 40929
2519e6e5
ER
40930+NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
40931+
40932+NETWORK_BACKEND_WRITE(write);
40933+NETWORK_BACKEND_WRITE(writev);
40934+NETWORK_BACKEND_WRITE(linuxsendfile);
40935+NETWORK_BACKEND_WRITE(freebsdsendfile);
40936+NETWORK_BACKEND_WRITE(solarissendfilev);
40937+
40938+NETWORK_BACKEND_WRITE(win32transmitfile);
40939+NETWORK_BACKEND_WRITE(win32send);
40940+
40941+NETWORK_BACKEND_READ(read);
40942+NETWORK_BACKEND_READ(win32recv);
f26f9fd5 40943
2519e6e5
ER
40944-int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
40945-int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
40946-int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
40947-int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
40948-int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
40949 #ifdef USE_OPENSSL
40950-int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
40951+#define NETWORK_BACKEND_WRITE_SSL(x) \
40952+ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
40953+#define NETWORK_BACKEND_READ_SSL(x) \
40954+ network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
f673a614 40955+
2519e6e5
ER
40956+NETWORK_BACKEND_WRITE_SSL(openssl);
40957+NETWORK_BACKEND_READ_SSL(openssl);
f26f9fd5 40958 #endif
f26f9fd5 40959
2519e6e5 40960 #endif
1175ccec 40961--- ../lighttpd-1.4.11/src/network_freebsd_sendfile.c 2005-10-22 12:28:18.000000000 +0300
36e2a29e 40962+++ lighttpd-1.4.12/src/network_freebsd_sendfile.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
40963@@ -26,142 +26,61 @@
40964
40965 #ifndef UIO_MAXIOV
40966 # ifdef __FreeBSD__
40967-/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
40968+/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
40969 # define UIO_MAXIOV 1024
40970 # endif
40971 #endif
40972
40973-int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
40974+NETWORK_BACKEND_WRITE(freebsdsendfile) {
40975 chunk *c;
40976 size_t chunks_written = 0;
f26f9fd5 40977-
f673a614 40978+
2519e6e5
ER
40979 for(c = cq->first; c; c = c->next, chunks_written++) {
40980 int chunk_finished = 0;
40981-
40982+ network_status_t ret;
40983+
40984 switch(c->type) {
40985- case MEM_CHUNK: {
40986- char * offset;
40987- size_t toSend;
40988- ssize_t r;
40989-
40990- size_t num_chunks, i;
40991- struct iovec chunks[UIO_MAXIOV];
40992- chunk *tc;
40993- size_t num_bytes = 0;
40994-
40995- /* we can't send more then SSIZE_MAX bytes in one chunk */
40996-
40997- /* build writev list
40998- *
40999- * 1. limit: num_chunks < UIO_MAXIOV
41000- * 2. limit: num_bytes < SSIZE_MAX
41001- */
41002- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41003-
41004- for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41005- if (tc->mem->used == 0) {
41006- chunks[i].iov_base = tc->mem->ptr;
41007- chunks[i].iov_len = 0;
41008- } else {
41009- offset = tc->mem->ptr + tc->offset;
41010- toSend = tc->mem->used - 1 - tc->offset;
41011-
41012- chunks[i].iov_base = offset;
41013-
41014- /* protect the return value of writev() */
41015- if (toSend > SSIZE_MAX ||
41016- num_bytes + toSend > SSIZE_MAX) {
41017- chunks[i].iov_len = SSIZE_MAX - num_bytes;
41018-
41019- num_chunks = i + 1;
41020- break;
41021- } else {
41022- chunks[i].iov_len = toSend;
41023- }
41024-
41025- num_bytes += toSend;
41026- }
41027- }
41028-
41029- if ((r = writev(fd, chunks, num_chunks)) < 0) {
41030- switch (errno) {
41031- case EAGAIN:
41032- case EINTR:
41033- r = 0;
41034- break;
41035- case EPIPE:
41036- case ECONNRESET:
41037- return -2;
41038- default:
41039- log_error_write(srv, __FILE__, __LINE__, "ssd",
41040- "writev failed:", strerror(errno), fd);
41041-
41042- return -1;
41043- }
41044+ case MEM_CHUNK:
41045+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41046
41047- r = 0;
41048- }
41049-
41050- /* check which chunks have been written */
41051- cq->bytes_out += r;
41052-
41053- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41054- if (r >= (ssize_t)chunks[i].iov_len) {
41055- /* written */
41056- r -= chunks[i].iov_len;
41057- tc->offset += chunks[i].iov_len;
41058-
41059- if (chunk_finished) {
41060- /* skip the chunks from further touches */
41061- chunks_written++;
41062- c = c->next;
41063- } else {
41064- /* chunks_written + c = c->next is done in the for()*/
41065- chunk_finished++;
41066- }
41067- } else {
41068- /* partially written */
41069-
41070- tc->offset += r;
41071- chunk_finished = 0;
41072-
41073- break;
41074- }
41075+ if (ret != NETWORK_STATUS_SUCCESS) {
41076+ return ret;
41077 }
41078-
41079+
41080+ chunk_finished = 1;
41081+
41082 break;
41083- }
41084 case FILE_CHUNK: {
41085 off_t offset, r;
41086 size_t toSend;
41087 stat_cache_entry *sce = NULL;
41088 int ifd;
41089-
41090+
41091 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41092 log_error_write(srv, __FILE__, __LINE__, "sb",
41093 strerror(errno), c->file.name);
41094- return -1;
41095+ return NETWORK_STATUS_FATAL_ERROR;
41096 }
41097-
41098+
41099 offset = c->file.start + c->offset;
41100 /* limit the toSend to 2^31-1 bytes in a chunk */
41101- toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41102+ toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41103 ((1 << 30) - 1) : c->file.length - c->offset;
41104-
41105+
41106 if (offset > sce->st.st_size) {
41107 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41108-
41109- return -1;
41110+
41111+ return NETWORK_STATUS_FATAL_ERROR;
41112 }
41113-
41114+
41115 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41116 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41117-
41118- return -1;
41119+
41120+ return NETWORK_STATUS_FATAL_ERROR;
41121 }
41122-
41123+
41124 r = 0;
41125-
41126+
41127 /* FreeBSD sendfile() */
41128 if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
41129 switch(errno) {
41130@@ -169,39 +88,39 @@
41131 break;
41132 case ENOTCONN:
41133 close(ifd);
41134- return -2;
41135+ return NETWORK_STATUS_CONNECTION_CLOSE;
41136 default:
41137 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41138 close(ifd);
41139- return -1;
41140+ return NETWORK_STATUS_FATAL_ERROR;
41141 }
f26f9fd5 41142 }
2519e6e5
ER
41143 close(ifd);
41144-
41145+
41146 c->offset += r;
41147 cq->bytes_out += r;
41148-
41149+
41150 if (c->offset == c->file.length) {
41151 chunk_finished = 1;
f26f9fd5 41152 }
2519e6e5
ER
41153-
41154+
41155 break;
41156 }
41157 default:
41158-
41159+
41160 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41161-
41162+
41163 return -1;
41164 }
41165-
41166+
41167 if (!chunk_finished) {
41168 /* not finished yet */
41169-
41170+
41171 break;
f26f9fd5
ER
41172 }
41173 }
f673a614 41174
2519e6e5
ER
41175- return chunks_written;
41176+ return NETWORK_STATUS_SUCCESS;
41177 }
f673a614 41178
2519e6e5 41179 #endif
1175ccec
ER
41180--- ../lighttpd-1.4.11/src/network_linux_sendfile.c 2006-02-15 20:02:36.000000000 +0200
41181+++ lighttpd-1.4.12/src/network_linux_sendfile.c 2006-07-15 22:43:21.000000000 +0300
2519e6e5
ER
41182@@ -26,122 +26,54 @@
41183 /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
41184 #undef HAVE_POSIX_FADVISE
f673a614 41185
2519e6e5
ER
41186-int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41187- chunk *c;
41188+NETWORK_BACKEND_WRITE(linuxsendfile) {
41189+ chunk *c, *tc;
41190 size_t chunks_written = 0;
41191-
41192+
41193 for(c = cq->first; c; c = c->next, chunks_written++) {
41194 int chunk_finished = 0;
41195-
41196+ network_status_t ret;
41197+
41198 switch(c->type) {
41199- case MEM_CHUNK: {
41200- char * offset;
41201- size_t toSend;
41202- ssize_t r;
41203-
41204- size_t num_chunks, i;
41205- struct iovec chunks[UIO_MAXIOV];
41206- chunk *tc;
41207- size_t num_bytes = 0;
41208-
41209- /* we can't send more then SSIZE_MAX bytes in one chunk */
41210-
41211- /* build writev list
41212- *
41213- * 1. limit: num_chunks < UIO_MAXIOV
41214- * 2. limit: num_bytes < SSIZE_MAX
41215- */
41216- for (num_chunks = 0, tc = c;
41217- tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
41218- tc = tc->next, num_chunks++);
41219-
41220- for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41221- if (tc->mem->used == 0) {
41222- chunks[i].iov_base = tc->mem->ptr;
41223- chunks[i].iov_len = 0;
41224- } else {
41225- offset = tc->mem->ptr + tc->offset;
41226- toSend = tc->mem->used - 1 - tc->offset;
41227-
41228- chunks[i].iov_base = offset;
41229-
41230- /* protect the return value of writev() */
41231- if (toSend > SSIZE_MAX ||
41232- num_bytes + toSend > SSIZE_MAX) {
41233- chunks[i].iov_len = SSIZE_MAX - num_bytes;
41234-
41235- num_chunks = i + 1;
41236- break;
41237- } else {
41238- chunks[i].iov_len = toSend;
41239- }
41240-
41241- num_bytes += toSend;
41242- }
41243- }
41244-
41245- if ((r = writev(fd, chunks, num_chunks)) < 0) {
41246- switch (errno) {
41247- case EAGAIN:
41248- case EINTR:
41249- r = 0;
41250- break;
41251- case EPIPE:
41252- case ECONNRESET:
41253- return -2;
41254- default:
41255- log_error_write(srv, __FILE__, __LINE__, "ssd",
41256- "writev failed:", strerror(errno), fd);
41257-
41258- return -1;
41259- }
41260- }
41261-
41262- /* check which chunks have been written */
41263- cq->bytes_out += r;
41264+ case MEM_CHUNK:
41265+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
f673a614 41266
2519e6e5
ER
41267- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41268- if (r >= (ssize_t)chunks[i].iov_len) {
41269- /* written */
41270- r -= chunks[i].iov_len;
41271- tc->offset += chunks[i].iov_len;
41272-
41273+ /* check which chunks are finished now */
41274+ for (tc = c; tc; tc = tc->next) {
41275+ /* finished the chunk */
41276+ if (tc->offset == tc->mem->used - 1) {
41277+ /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
41278 if (chunk_finished) {
41279- /* skip the chunks from further touches */
41280- chunks_written++;
41281 c = c->next;
41282 } else {
41283- /* chunks_written + c = c->next is done in the for()*/
41284- chunk_finished++;
41285+ chunk_finished = 1;
41286 }
41287 } else {
41288- /* partially written */
41289-
41290- tc->offset += r;
41291- chunk_finished = 0;
41292-
41293 break;
41294 }
41295 }
41296-
f673a614 41297+
2519e6e5
ER
41298+ if (ret != NETWORK_STATUS_SUCCESS) {
41299+ return ret;
41300+ }
41301+
41302 break;
41303- }
41304 case FILE_CHUNK: {
41305 ssize_t r;
41306 off_t offset;
41307 size_t toSend;
41308 stat_cache_entry *sce = NULL;
41309-
41310+
41311 offset = c->file.start + c->offset;
41312 /* limit the toSend to 2^31-1 bytes in a chunk */
41313- toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41314+ toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41315 ((1 << 30) - 1) : c->file.length - c->offset;
41316-
41317- /* open file if not already opened */
f673a614 41318+
2519e6e5
ER
41319+ /* open file if not already opened */
41320 if (-1 == c->file.fd) {
41321 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
41322 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41323-
41324+
41325 return -1;
41326 }
41327 #ifdef FD_CLOEXEC
41328@@ -151,7 +83,7 @@
41329 /* tell the kernel that we want to stream the file */
41330 if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
41331 if (ENOSYS != errno) {
41332- log_error_write(srv, __FILE__, __LINE__, "ssd",
41333+ log_error_write(srv, __FILE__, __LINE__, "ssd",
41334 "posix_fadvise failed:", strerror(errno), c->file.fd);
41335 }
41336 }
41337@@ -168,7 +100,7 @@
41338 case ECONNRESET:
41339 return -2;
41340 default:
41341- log_error_write(srv, __FILE__, __LINE__, "ssd",
41342+ log_error_write(srv, __FILE__, __LINE__, "ssd",
41343 "sendfile failed:", strerror(errno), fd);
41344 return -1;
41345 }
41346@@ -179,7 +111,7 @@
41347 *
41348 * - the file shrinked -> error
41349 * - the remote side closed inbetween -> remote-close */
41350-
41351+
41352 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41353 /* file is gone ? */
41354 return -1;
41355@@ -196,22 +128,22 @@
41356 #ifdef HAVE_POSIX_FADVISE
41357 #if 0
41358 #define K * 1024
41359-#define M * 1024 K
41360+#define M * 1024 K
41361 #define READ_AHEAD 4 M
41362 /* check if we need a new chunk */
41363 if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
41364 /* tell the kernel that we want to stream the file */
41365 if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
41366- log_error_write(srv, __FILE__, __LINE__, "ssd",
41367+ log_error_write(srv, __FILE__, __LINE__, "ssd",
41368 "posix_fadvise failed:", strerror(errno), c->file.fd);
41369 }
41370 }
f26f9fd5 41371 #endif
2519e6e5
ER
41372 #endif
41373-
41374+
41375 c->offset += r;
41376 cq->bytes_out += r;
41377-
41378+
41379 if (c->offset == c->file.length) {
41380 chunk_finished = 1;
f673a614 41381
1175ccec 41382@@ -222,24 +154,24 @@
2519e6e5
ER
41383 c->file.fd = -1;
41384 }
f26f9fd5 41385 }
2519e6e5
ER
41386-
41387+
41388 break;
41389 }
41390 default:
41391-
41392+
41393 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41394-
41395+
41396 return -1;
41397 }
41398-
41399+
41400 if (!chunk_finished) {
41401 /* not finished yet */
41402-
41403+
41404 break;
f26f9fd5 41405 }
f673a614 41406 }
1175ccec
ER
41407
41408- return chunks_written;
41409+ return NETWORK_STATUS_SUCCESS;
41410 }
41411
41412 #endif
41413--- ../lighttpd-1.4.11/src/network_openssl.c 2005-11-17 14:53:29.000000000 +0200
36e2a29e 41414+++ lighttpd-1.4.12/src/network_openssl.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
41415@@ -23,17 +23,87 @@
41416 #include "log.h"
41417 #include "stat_cache.h"
f673a614 41418
2519e6e5
ER
41419-# include <openssl/ssl.h>
41420-# include <openssl/err.h>
41421+# include <openssl/ssl.h>
41422+# include <openssl/err.h>
f673a614 41423
2519e6e5
ER
41424-int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
41425+NETWORK_BACKEND_READ_SSL(openssl) {
41426+ buffer *b;
41427+ off_t len;
41428+
41429+ b = chunkqueue_get_append_buffer(cq);
41430+ buffer_prepare_copy(b, 8192);
41431+ len = SSL_read(ssl, b->ptr, b->size - 1);
41432+
41433+ log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
41434+
41435+ if (len < 0) {
41436+ int r, ssl_err;
41437+
41438+ switch ((r = SSL_get_error(con->ssl, len))) {
41439+ case SSL_ERROR_WANT_READ:
41440+ return NETWORK_STATUS_WAIT_FOR_EVENT;
41441+ case SSL_ERROR_SYSCALL:
41442+ /**
41443+ * man SSL_get_error()
41444+ *
41445+ * SSL_ERROR_SYSCALL
41446+ * Some I/O error occurred. The OpenSSL error queue may contain more
41447+ * information on the error. If the error queue is empty (i.e.
41448+ * ERR_get_error() returns 0), ret can be used to find out more about
41449+ * the error: If ret == 0, an EOF was observed that violates the
41450+ * protocol. If ret == -1, the underlying BIO reported an I/O error
41451+ * (for socket I/O on Unix systems, consult errno for details).
41452+ *
41453+ */
41454+ while((ssl_err = ERR_get_error())) {
41455+ /* get all errors from the error-queue */
41456+ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41457+ r, ERR_error_string(ssl_err, NULL));
41458+ }
41459+
41460+ switch(errno) {
41461+ default:
41462+ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41463+ len, r, errno,
41464+ strerror(errno));
41465+ break;
41466+ }
41467+
41468+ break;
41469+ case SSL_ERROR_ZERO_RETURN:
41470+ /* clean shutdown on the remote side */
41471+
41472+ if (r == 0) {
41473+ /* FIXME: later */
41474+ }
41475+
41476+ /* fall thourgh */
41477+ default:
41478+ while((ssl_err = ERR_get_error())) {
41479+ /* get all errors from the error-queue */
41480+ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41481+ r, ERR_error_string(ssl_err, NULL));
41482+ }
41483+ break;
41484+ }
41485+ }
41486+
41487+ assert(len > 0);
41488+ b->used += len;
41489+ b->ptr[b->used - 1] = '\0';
41490+
41491+ return NETWORK_STATUS_SUCCESS;
41492+}
41493+
41494+
41495+NETWORK_BACKEND_WRITE_SSL(openssl) {
41496 int ssl_r;
41497 chunk *c;
41498 size_t chunks_written = 0;
f673a614 41499
2519e6e5
ER
41500 /* this is a 64k sendbuffer
41501 *
41502- * it has to stay at the same location all the time to satisfy the needs
41503+ * it has to stay at the same location all the time to satisfy the needs
41504 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
41505 *
41506 * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
41507@@ -43,14 +113,14 @@
41508 * In reality we would like to use mmap() but we don't have a guarantee that
41509 * we get the same mmap() address for each call. On openbsd the mmap() address
41510 * even randomized.
41511- * That means either we keep the mmap() open or we do a read() into a
41512- * constant buffer
41513+ * That means either we keep the mmap() open or we do a read() into a
41514+ * constant buffer
41515 * */
41516 #define LOCAL_SEND_BUFSIZE (64 * 1024)
41517 static char *local_send_buffer = NULL;
41518
41519 /* the remote side closed the connection before without shutdown request
41520- * - IE
41521+ * - IE
41522 * - wget
41523 * if keep-alive is disabled */
41524
41525@@ -60,32 +130,34 @@
41526
41527 for(c = cq->first; c; c = c->next) {
41528 int chunk_finished = 0;
41529-
41530+
41531 switch(c->type) {
41532 case MEM_CHUNK: {
41533 char * offset;
41534 size_t toSend;
41535- ssize_t r;
41536-
41537+ ssize_t r = 0;
41538+
41539 if (c->mem->used == 0) {
41540 chunk_finished = 1;
41541 break;
41542 }
41543-
41544+
41545 offset = c->mem->ptr + c->offset;
41546 toSend = c->mem->used - 1 - c->offset;
41547-
41548+
41549 /**
41550 * SSL_write man-page
41551- *
41552+ *
41553 * WARNING
41554 * When an SSL_write() operation has to be repeated because of
41555 * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
41556 * repeated with the same arguments.
41557- *
41558+ *
41559+ * SSL_write(..., 0) return 0 which is handle as an error (Success)
41560+ * checking toSend and not calling SSL_write() is simpler
41561 */
41562-
41563- if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
41564+
41565+ if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
41566 unsigned long err;
f26f9fd5 41567
2519e6e5
ER
41568 switch ((ssl_r = SSL_get_error(ssl, r))) {
41569@@ -95,7 +167,7 @@
41570 /* perhaps we have error waiting in our error-queue */
41571 if (0 != (err = ERR_get_error())) {
41572 do {
41573- log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41574+ log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41575 ssl_r, r,
41576 ERR_error_string(err, NULL));
41577 } while((err = ERR_get_error()));
41578@@ -105,43 +177,43 @@
41579 case EPIPE:
41580 return -2;
41581 default:
41582- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41583+ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41584 ssl_r, r, errno,
41585 strerror(errno));
41586 break;
41587 }
41588 } else {
41589 /* neither error-queue nor errno ? */
41590- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41591+ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41592 ssl_r, r, errno,
41593 strerror(errno));
41594 }
41595-
41596+
41597 return -1;
41598 case SSL_ERROR_ZERO_RETURN:
41599 /* clean shutdown on the remote side */
41600-
41601+
41602 if (r == 0) return -2;
41603-
41604+
41605 /* fall through */
41606 default:
41607 while((err = ERR_get_error())) {
41608- log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41609+ log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41610 ssl_r, r,
41611 ERR_error_string(err, NULL));
41612 }
41613-
41614+
41615 return -1;
41616 }
41617 } else {
41618 c->offset += r;
41619 cq->bytes_out += r;
41620 }
41621-
41622+
41623 if (c->offset == (off_t)c->mem->used - 1) {
41624 chunk_finished = 1;
f26f9fd5 41625 }
2519e6e5
ER
41626-
41627+
41628 break;
f26f9fd5 41629 }
2519e6e5
ER
41630 case FILE_CHUNK: {
41631@@ -150,7 +222,7 @@
41632 stat_cache_entry *sce = NULL;
41633 int ifd;
41634 int write_wait = 0;
41635-
41636+
41637 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41638 log_error_write(srv, __FILE__, __LINE__, "sb",
41639 strerror(errno), c->file.name);
41640@@ -164,13 +236,13 @@
41641
41642 do {
41643 off_t offset = c->file.start + c->offset;
41644- off_t toSend = c->file.length - c->offset;
41645+ off_t toSend = c->file.length - c->offset;
f673a614 41646
2519e6e5
ER
41647 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
41648-
41649+
41650 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41651 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
41652-
41653+
41654 return -1;
41655 }
f673a614 41656
2519e6e5
ER
41657@@ -183,9 +255,9 @@
41658 }
f26f9fd5 41659
2519e6e5
ER
41660 s = local_send_buffer;
41661-
41662+
41663 close(ifd);
41664-
41665+
41666 if ((r = SSL_write(ssl, s, toSend)) <= 0) {
41667 unsigned long err;
41668
41669@@ -197,7 +269,7 @@
41670 /* perhaps we have error waiting in our error-queue */
41671 if (0 != (err = ERR_get_error())) {
41672 do {
41673- log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41674+ log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41675 ssl_r, r,
41676 ERR_error_string(err, NULL));
41677 } while((err = ERR_get_error()));
41678@@ -207,58 +279,58 @@
41679 case EPIPE:
41680 return -2;
41681 default:
41682- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41683+ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41684 ssl_r, r, errno,
41685 strerror(errno));
41686 break;
41687 }
41688 } else {
41689 /* neither error-queue nor errno ? */
41690- log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41691+ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41692 ssl_r, r, errno,
41693 strerror(errno));
41694 }
41695-
41696+
41697 return -1;
41698 case SSL_ERROR_ZERO_RETURN:
41699 /* clean shutdown on the remote side */
41700-
41701+
41702 if (r == 0) return -2;
41703-
41704+
41705 /* fall thourgh */
41706 default:
41707 while((err = ERR_get_error())) {
41708- log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41709+ log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41710 ssl_r, r,
41711 ERR_error_string(err, NULL));
41712 }
41713-
41714+
41715 return -1;
41716 }
41717 } else {
41718 c->offset += r;
41719 cq->bytes_out += r;
41720 }
41721-
41722+
41723 if (c->offset == c->file.length) {
41724 chunk_finished = 1;
41725 }
41726 } while(!chunk_finished && !write_wait);
41727-
41728+
41729 break;
41730 }
41731 default:
41732 log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
41733-
41734+
41735 return -1;
41736 }
41737-
41738+
41739 if (!chunk_finished) {
41740 /* not finished yet */
41741-
41742+
41743 break;
41744 }
41745-
41746+
41747 chunks_written++;
41748 }
f673a614 41749
1175ccec 41750--- ../lighttpd-1.4.11/src/network_solaris_sendfilev.c 2005-10-22 12:28:27.000000000 +0300
36e2a29e 41751+++ lighttpd-1.4.12/src/network_solaris_sendfilev.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
41752@@ -29,114 +29,34 @@
41753 #endif
f673a614 41754
2519e6e5
ER
41755 /**
41756- * a very simple sendfilev() interface for solaris which can be optimised a lot more
41757+ * a very simple sendfilev() interface for solaris which can be optimised a lot more
41758 * as solaris sendfilev() supports 'sending everythin in one syscall()'
41759- *
41760- * If you want such an interface and need the performance, just give me an account on
41761- * a solaris box.
41762+ *
41763+ * If you want such an interface and need the performance, just give me an account on
41764+ * a solaris box.
41765 * - jan@kneschke.de
41766 */
f673a614 41767
f673a614 41768
2519e6e5
ER
41769-int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
41770+NETWORK_BACKEND_WRITE(solarissendfilev) {
41771 chunk *c;
41772 size_t chunks_written = 0;
41773-
41774+
41775 for(c = cq->first; c; c = c->next, chunks_written++) {
41776 int chunk_finished = 0;
41777-
41778+ network_status_t ret;
41779+
41780 switch(c->type) {
41781- case MEM_CHUNK: {
41782- char * offset;
41783- size_t toSend;
41784- ssize_t r;
41785-
41786- size_t num_chunks, i;
41787- struct iovec chunks[UIO_MAXIOV];
41788- chunk *tc;
41789-
41790- size_t num_bytes = 0;
41791-
41792- /* we can't send more then SSIZE_MAX bytes in one chunk */
41793-
41794- /* build writev list
41795- *
41796- * 1. limit: num_chunks < UIO_MAXIOV
41797- * 2. limit: num_bytes < SSIZE_MAX
41798- */
41799- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41800-
41801- for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41802- if (tc->mem->used == 0) {
41803- chunks[i].iov_base = tc->mem->ptr;
41804- chunks[i].iov_len = 0;
41805- } else {
41806- offset = tc->mem->ptr + tc->offset;
41807- toSend = tc->mem->used - 1 - tc->offset;
41808-
41809- chunks[i].iov_base = offset;
41810-
41811- /* protect the return value of writev() */
41812- if (toSend > SSIZE_MAX ||
41813- num_bytes + toSend > SSIZE_MAX) {
41814- chunks[i].iov_len = SSIZE_MAX - num_bytes;
41815-
41816- num_chunks = i + 1;
41817- break;
41818- } else {
41819- chunks[i].iov_len = toSend;
41820- }
41821-
41822- num_bytes += toSend;
41823- }
41824- }
41825-
41826- if ((r = writev(fd, chunks, num_chunks)) < 0) {
41827- switch (errno) {
41828- case EAGAIN:
41829- case EINTR:
41830- r = 0;
41831- break;
41832- case EPIPE:
41833- case ECONNRESET:
41834- return -2;
41835- default:
41836- log_error_write(srv, __FILE__, __LINE__, "ssd",
41837- "writev failed:", strerror(errno), fd);
41838-
41839- return -1;
41840- }
41841- }
41842-
41843- /* check which chunks have been written */
41844- cq->bytes_out += r;
41845-
41846- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41847- if (r >= (ssize_t)chunks[i].iov_len) {
41848- /* written */
41849- r -= chunks[i].iov_len;
41850- tc->offset += chunks[i].iov_len;
41851-
41852- if (chunk_finished) {
41853- /* skip the chunks from further touches */
41854- chunks_written++;
41855- c = c->next;
41856- } else {
41857- /* chunks_written + c = c->next is done in the for()*/
41858- chunk_finished++;
41859- }
41860- } else {
41861- /* partially written */
41862-
41863- tc->offset += r;
41864- chunk_finished = 0;
41865-
41866- break;
41867- }
41868+ case MEM_CHUNK:
41869+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41870+
41871+ if (ret != NETWORK_STATUS_SUCCESS) {
41872+ return ret;
41873 }
41874-
41875+
41876+ chunk_finished = 1;
41877+
41878 break;
41879- }
41880 case FILE_CHUNK: {
41881 ssize_t r;
41882 off_t offset;
41883@@ -144,25 +64,25 @@
41884 sendfilevec_t fvec;
41885 stat_cache_entry *sce = NULL;
41886 int ifd;
41887-
41888+
41889 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41890 log_error_write(srv, __FILE__, __LINE__, "sb",
41891 strerror(errno), c->file.name);
41892 return -1;
41893 }
41894-
41895+
41896 offset = c->file.start + c->offset;
41897 toSend = c->file.length - c->offset;
41898-
41899+
41900 if (offset > sce->st.st_size) {
41901 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41902-
41903+
41904 return -1;
41905 }
f673a614 41906
2519e6e5
ER
41907 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41908 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41909-
41910+
41911 return -1;
41912 }
f673a614 41913
2519e6e5
ER
41914@@ -170,44 +90,43 @@
41915 fvec.sfv_flag = 0;
41916 fvec.sfv_off = offset;
41917 fvec.sfv_len = toSend;
41918-
41919+
41920 /* Solaris sendfilev() */
41921 if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
41922 if (errno != EAGAIN) {
41923 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41924-
41925+
41926 close(ifd);
41927- return -1;
41928+ return NETWORK_STATUS_FATAL_ERROR;
41929 }
41930-
41931+
41932 r = 0;
41933 }
41934-
41935+
41936 close(ifd);
41937 c->offset += written;
41938 cq->bytes_out += written;
41939-
41940+
41941 if (c->offset == c->file.length) {
41942 chunk_finished = 1;
41943 }
41944-
41945+
41946 break;
41947 }
41948 default:
41949-
41950 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41951-
41952- return -1;
41953+
41954+ return NETWORK_STATUS_FATAL_ERROR;
41955 }
41956-
41957+
41958 if (!chunk_finished) {
41959 /* not finished yet */
41960-
41961+
41962 break;
41963 }
41964 }
f673a614 41965
2519e6e5
ER
41966- return chunks_written;
41967+ return NETWORK_STATUS_SUCCESS;
41968 }
f673a614 41969
2519e6e5 41970 #endif
1175ccec
ER
41971--- ../lighttpd-1.4.11/src/network_write.c 2005-10-22 12:27:56.000000000 +0300
41972+++ lighttpd-1.4.12/src/network_write.c 2006-07-15 22:43:21.000000000 +0300
2519e6e5
ER
41973@@ -1,11 +1,11 @@
41974 #include <sys/types.h>
41975 #include <sys/stat.h>
41976-#include <sys/time.h>
41977+
41978 #include <errno.h>
41979 #include <fcntl.h>
41980-#include <unistd.h>
41981 #include <string.h>
41982 #include <stdlib.h>
41983+#include <assert.h>
f673a614 41984
2519e6e5
ER
41985 #include "network.h"
41986 #include "fdevent.h"
41987@@ -13,9 +13,12 @@
41988 #include "stat_cache.h"
f673a614 41989
2519e6e5
ER
41990 #include "sys-socket.h"
41991+#include "sys-files.h"
f673a614 41992
2519e6e5 41993 #include "network_backends.h"
f673a614 41994
2519e6e5
ER
41995+#ifdef USE_WRITE
41996+
41997 #ifdef HAVE_SYS_FILIO_H
41998 # include <sys/filio.h>
41999 #endif
1175ccec 42000@@ -24,47 +27,84 @@
2519e6e5
ER
42001 #include <sys/resource.h>
42002 #endif
f673a614 42003
2519e6e5
ER
42004-int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
42005+/**
42006+* fill the chunkqueue will all the data that we can get
42007+*
42008+* this might be optimized into a readv() which uses the chunks
42009+* as vectors
42010+*/
42011+NETWORK_BACKEND_READ(read) {
1175ccec
ER
42012+ int toread;
42013+ buffer *b;
42014+ off_t r;
2519e6e5 42015+
1175ccec
ER
42016+ /* use a chunk-size of 8k */
42017+ do {
42018+ toread = 8192;
2519e6e5 42019+
1175ccec 42020+ b = chunkqueue_get_append_buffer(cq);
2519e6e5 42021+
1175ccec 42022+ buffer_prepare_copy(b, toread);
2519e6e5 42023+
1175ccec
ER
42024+ if (-1 == (r = read(fd, b->ptr, toread))) {
42025+ switch (errno) {
42026+ case EAGAIN:
42027+ return NETWORK_STATUS_WAIT_FOR_EVENT;
42028+ default:
42029+ log_error_write(srv, __FILE__, __LINE__, "sds",
42030+ "unexpected end-of-file (perhaps the proxy process died):",
42031+ fd, strerror(errno));
42032+ return NETWORK_STATUS_FATAL_ERROR;
42033+ }
42034+ }
2519e6e5 42035+
1175ccec
ER
42036+ if (r == 0) {
42037+ return NETWORK_STATUS_CONNECTION_CLOSE;
42038+ }
2519e6e5 42039+
1175ccec
ER
42040+ /* this should be catched by the b > 0 above */
42041+ assert(r);
42042+ b->used += r + 1;
42043+ b->ptr[b->used - 1] = '\0';
42044+ } while (r == toread);
2519e6e5 42045+
1175ccec 42046+ return NETWORK_STATUS_SUCCESS;
2519e6e5
ER
42047+}
42048+
42049+NETWORK_BACKEND_WRITE(write) {
42050 chunk *c;
42051 size_t chunks_written = 0;
42052-
42053+
42054 for(c = cq->first; c; c = c->next) {
42055 int chunk_finished = 0;
42056-
42057+
42058 switch(c->type) {
42059 case MEM_CHUNK: {
42060 char * offset;
42061 size_t toSend;
42062 ssize_t r;
42063-
42064+
42065 if (c->mem->used == 0) {
42066 chunk_finished = 1;
42067 break;
42068 }
42069-
42070+
42071 offset = c->mem->ptr + c->offset;
42072 toSend = c->mem->used - 1 - c->offset;
42073-#ifdef __WIN32
42074- if ((r = send(fd, offset, toSend, 0)) < 0) {
42075- log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42076-
42077- return -1;
42078- }
42079-#else
42080+
42081 if ((r = write(fd, offset, toSend)) < 0) {
42082 log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42083-
42084- return -1;
42085+
42086+ return NETWORK_STATUS_FATAL_ERROR;
42087 }
42088-#endif
42089-
42090+
42091 c->offset += r;
42092 cq->bytes_out += r;
42093-
42094+
42095 if (c->offset == (off_t)c->mem->used - 1) {
42096 chunk_finished = 1;
42097 }
42098-
42099+
42100 break;
42101 }
42102 case FILE_CHUNK: {
1175ccec 42103@@ -76,93 +116,89 @@
2519e6e5
ER
42104 size_t toSend;
42105 stat_cache_entry *sce = NULL;
42106 int ifd;
42107-
42108+
42109 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42110 log_error_write(srv, __FILE__, __LINE__, "sb",
42111 strerror(errno), c->file.name);
42112- return -1;
42113+ return NETWORK_STATUS_FATAL_ERROR;
42114 }
42115-
42116+
42117 offset = c->file.start + c->offset;
42118 toSend = c->file.length - c->offset;
42119-
42120+
42121 if (offset > sce->st.st_size) {
42122 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42123-
42124- return -1;
42125+
42126+ return NETWORK_STATUS_FATAL_ERROR;
42127 }
f673a614 42128
2519e6e5
ER
42129 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42130 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42131-
42132- return -1;
42133+
42134+ return NETWORK_STATUS_FATAL_ERROR;
42135 }
42136-
42137+
42138 #if defined USE_MMAP
42139 if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
42140 log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
f673a614 42141
2519e6e5
ER
42142 close(ifd);
42143-
42144- return -1;
42145+
42146+ return NETWORK_STATUS_FATAL_ERROR;
42147 }
42148 close(ifd);
42149
42150 if ((r = write(fd, p + offset, toSend)) <= 0) {
42151 log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
42152 munmap(p, sce->st.st_size);
42153- return -1;
42154+ return NETWORK_STATUS_FATAL_ERROR;
42155 }
42156-
42157+
42158 munmap(p, sce->st.st_size);
42159 #else
42160 buffer_prepare_copy(srv->tmp_buf, toSend);
42161-
42162+
42163 lseek(ifd, offset, SEEK_SET);
42164 if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
42165 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
42166 close(ifd);
42167-
42168- return -1;
42169+
42170+ return NETWORK_STATUS_FATAL_ERROR;
42171 }
42172 close(ifd);
42173
42174 if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
42175 log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
42176-
42177- return -1;
42178+
42179+ return NETWORK_STATUS_FATAL_ERROR;
42180 }
42181 #endif
42182 c->offset += r;
42183 cq->bytes_out += r;
42184-
42185+
42186 if (c->offset == c->file.length) {
42187 chunk_finished = 1;
42188 }
42189-
42190+
42191 break;
f673a614 42192 }
2519e6e5
ER
42193 default:
42194-
42195+
42196 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42197-
42198- return -1;
42199+
42200+ return NETWORK_STATUS_FATAL_ERROR;
f673a614 42201 }
2519e6e5
ER
42202-
42203+
42204 if (!chunk_finished) {
42205 /* not finished yet */
42206-
42207+
42208 break;
f26f9fd5 42209 }
2519e6e5
ER
42210-
42211+
42212 chunks_written++;
42213 }
42214
42215- return chunks_written;
42216+ return NETWORK_STATUS_SUCCESS;
f673a614
ER
42217 }
42218
2519e6e5
ER
42219-#if 0
42220-network_write_init(void) {
42221- p->write = network_write_write_chunkset;
42222-}
42223 #endif
1175ccec
ER
42224--- ../lighttpd-1.4.11/src/network_writev.c 2006-02-15 01:02:36.000000000 +0200
42225+++ lighttpd-1.4.12/src/network_writev.c 2006-07-15 22:43:21.000000000 +0300
2519e6e5
ER
42226@@ -28,10 +28,10 @@
42227
42228 #ifndef UIO_MAXIOV
42229 # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
42230-/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42231+/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42232 # define UIO_MAXIOV 1024
42233 # elif defined(__sgi)
42234-/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42235+/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42236 # define UIO_MAXIOV 512
42237 # elif defined(__sun)
42238 /* Solaris (and SunOS?) defines IOV_MAX instead */
1175ccec 42239@@ -51,105 +51,121 @@
2519e6e5
ER
42240 #define LOCAL_BUFFERING 1
42241 #endif
42242
42243-int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
42244- chunk *c;
42245+NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
42246+ char * offset;
42247+ size_t toSend;
42248+ ssize_t r;
42249+
42250+ size_t num_chunks, i;
42251+ struct iovec chunks[UIO_MAXIOV];
42252+ chunk *tc; /* transfer chunks */
42253+ size_t num_bytes = 0;
42254+
42255+ /* we can't send more then SSIZE_MAX bytes in one chunk */
42256+
42257+ /* build writev list
42258+ *
42259+ * 1. limit: num_chunks < UIO_MAXIOV
42260+ * 2. limit: num_bytes < SSIZE_MAX
42261+ */
42262+ for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42263+
42264+ for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42265+ if (tc->mem->used == 0) {
42266+ chunks[i].iov_base = tc->mem->ptr;
42267+ chunks[i].iov_len = 0;
42268+ } else {
42269+ offset = tc->mem->ptr + tc->offset;
42270+ toSend = tc->mem->used - 1 - tc->offset;
42271+
42272+ chunks[i].iov_base = offset;
42273+
42274+ /* protect the return value of writev() */
42275+ if (toSend > SSIZE_MAX ||
42276+ num_bytes + toSend > SSIZE_MAX) {
42277+ chunks[i].iov_len = SSIZE_MAX - num_bytes;
42278+
42279+ num_chunks = i + 1;
42280+ break;
42281+ } else {
42282+ chunks[i].iov_len = toSend;
42283+ }
42284+
42285+ num_bytes += toSend;
42286+ }
42287+ }
42288+
42289+ if ((r = writev(fd, chunks, num_chunks)) < 0) {
42290+ switch (errno) {
42291+ case EAGAIN:
1175ccec 42292+ return NETWORK_STATUS_WAIT_FOR_EVENT;
2519e6e5 42293+ case EINTR:
1175ccec 42294+ return NETWORK_STATUS_INTERRUPTED;
2519e6e5
ER
42295+ case EPIPE:
42296+ case ECONNRESET:
42297+ return NETWORK_STATUS_CONNECTION_CLOSE;
42298+ default:
42299+ log_error_write(srv, __FILE__, __LINE__, "ssd",
42300+ "writev failed:", strerror(errno), fd);
42301+
42302+ return NETWORK_STATUS_FATAL_ERROR;
42303+ }
42304+ }
42305+
42306+ cq->bytes_out += r;
42307+
42308+ /* check which chunks have been written */
42309+
42310+ for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42311+ if (r >= (ssize_t)chunks[i].iov_len) {
42312+ /* written */
42313+ r -= chunks[i].iov_len;
42314+ tc->offset += chunks[i].iov_len;
42315+ } else {
42316+ /* partially written */
42317+
42318+ tc->offset += r;
1175ccec
ER
42319+
42320+ return NETWORK_STATUS_WAIT_FOR_EVENT;
2519e6e5
ER
42321+ }
42322+ }
42323+
1175ccec 42324+ /* all chunks have been pushed out */
2519e6e5
ER
42325+ return NETWORK_STATUS_SUCCESS;
42326+}
42327+
42328+NETWORK_BACKEND_WRITE(writev) {
42329+ chunk *c, *tc;
42330 size_t chunks_written = 0;
42331-
42332+
42333 for(c = cq->first; c; c = c->next) {
42334 int chunk_finished = 0;
42335-
42336+ network_status_t ret;
42337+
42338 switch(c->type) {
42339- case MEM_CHUNK: {
42340- char * offset;
42341- size_t toSend;
42342- ssize_t r;
42343-
42344- size_t num_chunks, i;
42345- struct iovec chunks[UIO_MAXIOV];
42346- chunk *tc;
42347- size_t num_bytes = 0;
42348-
42349- /* we can't send more then SSIZE_MAX bytes in one chunk */
42350-
42351- /* build writev list
42352- *
42353- * 1. limit: num_chunks < UIO_MAXIOV
42354- * 2. limit: num_bytes < SSIZE_MAX
42355- */
42356- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42357-
42358- for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42359- if (tc->mem->used == 0) {
42360- chunks[i].iov_base = tc->mem->ptr;
42361- chunks[i].iov_len = 0;
42362- } else {
42363- offset = tc->mem->ptr + tc->offset;
42364- toSend = tc->mem->used - 1 - tc->offset;
42365-
42366- chunks[i].iov_base = offset;
42367-
42368- /* protect the return value of writev() */
42369- if (toSend > SSIZE_MAX ||
42370- num_bytes + toSend > SSIZE_MAX) {
42371- chunks[i].iov_len = SSIZE_MAX - num_bytes;
42372-
42373- num_chunks = i + 1;
42374- break;
42375- } else {
42376- chunks[i].iov_len = toSend;
42377- }
42378-
42379- num_bytes += toSend;
42380- }
42381- }
42382-
42383- if ((r = writev(fd, chunks, num_chunks)) < 0) {
42384- switch (errno) {
42385- case EAGAIN:
42386- case EINTR:
42387- r = 0;
42388- break;
42389- case EPIPE:
42390- case ECONNRESET:
42391- return -2;
42392- default:
42393- log_error_write(srv, __FILE__, __LINE__, "ssd",
42394- "writev failed:", strerror(errno), fd);
42395-
42396- return -1;
42397- }
42398- }
42399-
42400- cq->bytes_out += r;
42401+ case MEM_CHUNK:
42402+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
42403
42404- /* check which chunks have been written */
42405-
42406- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42407- if (r >= (ssize_t)chunks[i].iov_len) {
42408- /* written */
42409- r -= chunks[i].iov_len;
42410- tc->offset += chunks[i].iov_len;
42411-
42412+ /* check which chunks are finished now */
42413+ for (tc = c; tc; tc = tc->next) {
42414+ /* finished the chunk */
42415+ if (tc->offset == tc->mem->used - 1) {
42416+ /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
42417 if (chunk_finished) {
42418- /* skip the chunks from further touches */
42419- chunks_written++;
42420 c = c->next;
42421 } else {
42422- /* chunks_written + c = c->next is done in the for()*/
42423- chunk_finished++;
42424+ chunk_finished = 1;
42425 }
42426 } else {
42427- /* partially written */
42428-
42429- tc->offset += r;
42430- chunk_finished = 0;
42431-
42432 break;
42433 }
42434 }
42435-
42436+
42437+ if (ret != NETWORK_STATUS_SUCCESS) {
42438+ return ret;
42439+ }
42440+
42441 break;
42442- }
42443 case FILE_CHUNK: {
42444 ssize_t r;
42445 off_t abs_offset;
1175ccec 42446@@ -159,26 +175,26 @@
2519e6e5
ER
42447 #define KByte * 1024
42448 #define MByte * 1024 KByte
42449 #define GByte * 1024 MByte
42450- const off_t we_want_to_mmap = 512 KByte;
42451+ const off_t we_want_to_mmap = 512 KByte;
42452 char *start = NULL;
f673a614 42453
2519e6e5
ER
42454 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42455 log_error_write(srv, __FILE__, __LINE__, "sb",
42456 strerror(errno), c->file.name);
42457- return -1;
42458+ return NETWORK_STATUS_FATAL_ERROR;
42459 }
f673a614 42460
2519e6e5
ER
42461 abs_offset = c->file.start + c->offset;
42462-
42463+
42464 if (abs_offset > sce->st.st_size) {
42465- log_error_write(srv, __FILE__, __LINE__, "sb",
42466+ log_error_write(srv, __FILE__, __LINE__, "sb",
42467 "file was shrinked:", c->file.name);
42468-
42469- return -1;
42470+
42471+ return NETWORK_STATUS_FATAL_ERROR;
f26f9fd5 42472 }
f673a614 42473
2519e6e5
ER
42474- /* mmap the buffer
42475- * - first mmap
42476+ /* mmap the buffer
42477+ * - first mmap
42478 * - new mmap as the we are at the end of the last one */
42479 if (c->file.mmap.start == MAP_FAILED ||
42480 abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
1175ccec 42481@@ -188,7 +204,7 @@
2519e6e5
ER
42482 * adaptive mem-mapping
42483 * the problem:
42484 * we mmap() the whole file. If someone has alot large files and 32bit
42485- * machine the virtual address area will be unrun and we will have a failing
42486+ * machine the virtual address area will be unrun and we will have a failing
42487 * mmap() call.
42488 * solution:
42489 * only mmap 16M in one chunk and move the window as soon as we have finished
1175ccec 42490@@ -234,8 +250,8 @@
2519e6e5
ER
42491 if (-1 == c->file.fd) { /* open the file if not already open */
42492 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
42493 log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
42494-
42495- return -1;
42496+
42497+ return NETWORK_STATUS_FATAL_ERROR;
42498 }
42499 #ifdef FD_CLOEXEC
42500 fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
1175ccec 42501@@ -245,10 +261,10 @@
2519e6e5
ER
42502 if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
42503 /* close it here, otherwise we'd have to set FD_CLOEXEC */
f673a614 42504
2519e6e5
ER
42505- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
42506+ log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
42507 strerror(errno), c->file.name, c->file.fd);
f673a614 42508
2519e6e5
ER
42509- return -1;
42510+ return NETWORK_STATUS_FATAL_ERROR;
42511 }
f673a614 42512
2519e6e5 42513 c->file.mmap.length = to_mmap;
1175ccec 42514@@ -258,7 +274,7 @@
2519e6e5
ER
42515 #ifdef HAVE_MADVISE
42516 /* don't advise files < 64Kb */
42517 if (c->file.mmap.length > (64 KByte)) {
42518- /* darwin 7 is returning EINVAL all the time and I don't know how to
42519+ /* darwin 7 is returning EINVAL all the time and I don't know how to
42520 * detect this at runtime.i
42521 *
42522 * ignore the return value for now */
1175ccec 42523@@ -274,12 +290,12 @@
2519e6e5
ER
42524 toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
42525
42526 if (toSend < 0) {
42527- log_error_write(srv, __FILE__, __LINE__, "soooo",
42528+ log_error_write(srv, __FILE__, __LINE__, "soooo",
42529 "toSend is negative:",
42530 toSend,
42531 c->file.mmap.length,
42532 abs_offset,
42533- c->file.mmap.offset);
42534+ c->file.mmap.offset);
42535 assert(toSend < 0);
42536 }
42537
1175ccec 42538@@ -297,18 +313,18 @@
2519e6e5
ER
42539 break;
42540 case EPIPE:
42541 case ECONNRESET:
42542- return -2;
42543+ return NETWORK_STATUS_CONNECTION_CLOSE;
42544 default:
42545- log_error_write(srv, __FILE__, __LINE__, "ssd",
42546+ log_error_write(srv, __FILE__, __LINE__, "ssd",
42547 "write failed:", strerror(errno), fd);
42548-
42549- return -1;
42550+
42551+ return NETWORK_STATUS_FATAL_ERROR;
42552 }
f673a614 42553 }
2519e6e5
ER
42554-
42555+
42556 c->offset += r;
42557 cq->bytes_out += r;
42558-
42559+
42560 if (c->offset == c->file.length) {
42561 chunk_finished = 1;
42562
1175ccec 42563@@ -318,26 +334,26 @@
2519e6e5
ER
42564 c->file.mmap.start = MAP_FAILED;
42565 }
42566 }
42567-
42568+
42569 break;
42570 }
42571 default:
42572-
42573+
42574 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42575-
42576- return -1;
42577+
42578+ return NETWORK_STATUS_FATAL_ERROR;
42579 }
42580-
42581+
42582 if (!chunk_finished) {
42583 /* not finished yet */
42584-
42585+
42586 break;
f673a614 42587 }
2519e6e5
ER
42588-
42589+
42590 chunks_written++;
f673a614 42591 }
2519e6e5
ER
42592
42593- return chunks_written;
42594+ return NETWORK_STATUS_SUCCESS;
f673a614
ER
42595 }
42596
2519e6e5 42597 #endif
1175ccec 42598--- ../lighttpd-1.4.11/src/plugin.c 2006-02-08 14:00:54.000000000 +0200
36e2a29e 42599+++ lighttpd-1.4.12/src/plugin.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
42600@@ -13,27 +13,27 @@
42601 #include <valgrind/valgrind.h>
42602 #endif
f673a614 42603
2519e6e5
ER
42604-#ifndef __WIN32
42605+#ifndef _WIN32
42606 #include <dlfcn.h>
42607 #endif
42608 /*
42609- *
42610+ *
42611 * if you change this enum to add a new callback, be sure
42612 * - that PLUGIN_FUNC_SIZEOF is the last entry
42613 * - that you add PLUGIN_TO_SLOT twice:
42614- * 1. as callback-dispatcher
42615+ * 1. as callback-dispatcher
42616 * 2. in plugins_call_init()
42617- *
42618+ *
42619 */
f26f9fd5 42620
2519e6e5
ER
42621 typedef struct {
42622 PLUGIN_DATA;
42623 } plugin_data;
f26f9fd5 42624
2519e6e5
ER
42625-typedef enum {
42626+typedef enum {
42627 PLUGIN_FUNC_UNSET,
42628- PLUGIN_FUNC_HANDLE_URI_CLEAN,
42629- PLUGIN_FUNC_HANDLE_URI_RAW,
42630+ PLUGIN_FUNC_HANDLE_URI_CLEAN,
42631+ PLUGIN_FUNC_HANDLE_URI_RAW,
42632 PLUGIN_FUNC_HANDLE_REQUEST_DONE,
42633 PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
42634 PLUGIN_FUNC_HANDLE_TRIGGER,
42635@@ -44,38 +44,42 @@
42636 PLUGIN_FUNC_HANDLE_DOCROOT,
42637 PLUGIN_FUNC_HANDLE_PHYSICAL,
42638 PLUGIN_FUNC_CONNECTION_RESET,
42639- PLUGIN_FUNC_INIT,
42640+ PLUGIN_FUNC_INIT,
42641 PLUGIN_FUNC_CLEANUP,
42642 PLUGIN_FUNC_SET_DEFAULTS,
42643-
42644+
42645 PLUGIN_FUNC_SIZEOF
42646 } plugin_t;
f26f9fd5 42647
2519e6e5
ER
42648 static plugin *plugin_init(void) {
42649 plugin *p;
42650-
42651+
42652 p = calloc(1, sizeof(*p));
42653-
42654+
42655+ p->required_plugins = array_init();
42656+
42657 return p;
f26f9fd5
ER
42658 }
42659
2519e6e5
ER
42660 static void plugin_free(plugin *p) {
42661 int use_dlclose = 1;
42662 if (p->name) buffer_free(p->name);
42663+
42664+ array_free(p->required_plugins);
42665 #ifdef HAVE_VALGRIND_VALGRIND_H
42666 /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
42667 #endif
42668
42669 #ifndef LIGHTTPD_STATIC
42670- if (use_dlclose && p->lib) {
42671-#ifdef __WIN32
42672+ if (use_dlclose && p->lib) {
42673+#ifdef _WIN32
42674 FreeLibrary(p->lib);
42675 #else
42676 dlclose(p->lib);
42677 #endif
f673a614 42678 }
2519e6e5
ER
42679 #endif
42680-
42681+
42682 free(p);
42683 }
42684
42685@@ -89,17 +93,17 @@
42686 srv->plugins.size += 4;
42687 srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
42688 }
42689-
42690+
42691 ps = srv->plugins.ptr;
42692 ps[srv->plugins.used++] = p;
42693-
42694+
f26f9fd5 42695 return 0;
f673a614
ER
42696 }
42697
2519e6e5
ER
42698 /**
42699- *
42700- *
42701- *
42702+ *
42703+ *
42704+ *
42705 */
f673a614 42706
2519e6e5
ER
42707 #ifdef LIGHTTPD_STATIC
42708@@ -121,30 +125,35 @@
42709 #else
42710 int plugins_load(server *srv) {
42711 plugin *p;
42712+#ifdef _WIN32
42713+ FARPROC init;
42714+#else
42715 int (*init)(plugin *pl);
42716+#endif
42717+
42718 const char *error;
42719- size_t i;
42720-
42721+ size_t i, j, k;
42722+
42723 for (i = 0; i < srv->srvconf.modules->used; i++) {
42724 data_string *d = (data_string *)srv->srvconf.modules->data[i];
42725 char *modules = d->value->ptr;
42726-
42727+
42728 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
42729
42730 buffer_append_string(srv->tmp_buf, "/");
42731 buffer_append_string(srv->tmp_buf, modules);
42732-#if defined(__WIN32) || defined(__CYGWIN__)
42733+#if defined(_WIN32) || defined(__CYGWIN__)
42734 buffer_append_string(srv->tmp_buf, ".dll");
42735 #else
42736 buffer_append_string(srv->tmp_buf, ".so");
42737 #endif
42738-
42739+
42740 p = plugin_init();
42741-#ifdef __WIN32
42742+#ifdef _WIN32
42743 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
42744 LPVOID lpMsgBuf;
42745 FormatMessage(
42746- FORMAT_MESSAGE_ALLOCATE_BUFFER |
42747+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
42748 FORMAT_MESSAGE_FROM_SYSTEM,
42749 NULL,
42750 GetLastError(),
42751@@ -152,36 +161,36 @@
42752 (LPTSTR) &lpMsgBuf,
42753 0, NULL );
42754
42755- log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
42756+ log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
42757 lpMsgBuf, srv->tmp_buf);
42758-
42759+
42760 plugin_free(p);
42761-
42762+
42763 return -1;
42764
42765 }
42766-#else
42767+#else
42768 if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
42769- log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
42770+ log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
42771 srv->tmp_buf, dlerror());
42772-
42773+
42774 plugin_free(p);
42775-
42776+
42777 return -1;
42778 }
42779-
42780+
42781 #endif
42782 buffer_reset(srv->tmp_buf);
42783 buffer_copy_string(srv->tmp_buf, modules);
42784 buffer_append_string(srv->tmp_buf, "_plugin_init");
42785
42786-#ifdef __WIN32
42787+#ifdef _WIN32
42788 init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
42789
42790 if (init == NULL) {
42791 LPVOID lpMsgBuf;
42792 FormatMessage(
42793- FORMAT_MESSAGE_ALLOCATE_BUFFER |
42794+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
42795 FORMAT_MESSAGE_FROM_SYSTEM,
42796 NULL,
42797 GetLastError(),
42798@@ -190,7 +199,7 @@
42799 0, NULL );
42800
42801 log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
42802-
42803+
42804 plugin_free(p);
42805 return -1;
42806 }
42807@@ -203,24 +212,43 @@
42808 #endif
42809 if ((error = dlerror()) != NULL) {
42810 log_error_write(srv, __FILE__, __LINE__, "s", error);
42811-
42812+
42813 plugin_free(p);
42814 return -1;
42815 }
42816-
42817+
42818 #endif
42819 if ((*init)(p)) {
42820 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
42821-
42822+
42823 plugin_free(p);
42824 return -1;
42825 }
42826 #if 0
42827 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
42828 #endif
42829+ /* check if the required plugin is loaded */
42830+ for (k = 0; k < p->required_plugins->used; k++) {
42831+ data_string *req = (data_string *)p->required_plugins->data[k];
42832+
42833+ for (j = 0; j < i; j++) {
42834+ data_string *mod = (data_string *)srv->srvconf.modules->data[j];
42835+
42836+ if (buffer_is_equal(req->value, mod->value)) break;
42837+ }
42838+
42839+ if (j == i) {
42840+ /* not found */
42841+ log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
42842+
42843+ plugin_free(p);
42844+
42845+ return -1;
42846+ }
42847+ }
42848 plugins_register(srv, p);
42849 }
42850-
42851+
42852 return 0;
42853 }
f673a614 42854 #endif
2519e6e5
ER
42855@@ -253,8 +281,8 @@
42856 }
f26f9fd5 42857
2519e6e5
ER
42858 /**
42859- * plugins that use
42860- *
42861+ * plugins that use
42862+ *
42863 * - server *srv
42864 * - connection *con
42865 * - void *p_d (plugin_data *)
42866@@ -301,12 +329,12 @@
42867 }
42868
42869 /**
42870- * plugins that use
42871- *
42872+ * plugins that use
42873+ *
42874 * - server *srv
42875 * - void *p_d (plugin_data *)
42876 */
42877-
f673a614 42878+
2519e6e5
ER
42879 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
42880 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
42881 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
42882@@ -314,18 +342,18 @@
f26f9fd5 42883
2519e6e5 42884 #undef PLUGIN_TO_SLOT
f26f9fd5 42885
2519e6e5
ER
42886-#if 0
42887+#if 0
f26f9fd5 42888 /**
2519e6e5
ER
42889- *
42890+ *
42891 * special handler
42892- *
42893+ *
42894 */
42895 handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
42896 size_t i;
42897 plugin **ps;
42898-
f673a614 42899+
2519e6e5
ER
42900 ps = srv->plugins.ptr;
42901-
f673a614 42902+
2519e6e5
ER
42903 for (i = 0; i < srv->plugins.used; i++) {
42904 plugin *p = ps[i];
42905 if (p->handle_fdevent) {
42906@@ -344,34 +372,34 @@
f673a614 42907 }
2519e6e5
ER
42908 }
42909 }
42910-
42911+
42912 return HANDLER_GO_ON;
42913 }
42914 #endif
42915 /**
42916- *
42917+ *
42918 * - call init function of all plugins to init the plugin-internals
42919 * - added each plugin that supports has callback to the corresponding slot
42920- *
42921+ *
42922 * - is only called once.
42923 */
f26f9fd5 42924
2519e6e5
ER
42925 handler_t plugins_call_init(server *srv) {
42926 size_t i;
42927 plugin **ps;
42928-
f673a614 42929+
2519e6e5
ER
42930 ps = srv->plugins.ptr;
42931-
f673a614 42932+
2519e6e5
ER
42933 /* fill slots */
42934-
f673a614 42935+
2519e6e5
ER
42936 srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
42937-
f673a614 42938+
2519e6e5
ER
42939 for (i = 0; i < srv->plugins.used; i++) {
42940 size_t j;
42941 /* check which calls are supported */
42942-
f673a614 42943+
2519e6e5
ER
42944 plugin *p = ps[i];
42945-
f673a614 42946+
2519e6e5
ER
42947 #define PLUGIN_TO_SLOT(x, y) \
42948 if (p->y) { \
42949 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
42950@@ -384,11 +412,11 @@
42951 slot[j] = p;\
42952 break;\
42953 }\
42954- }
42955-
42956-
42957- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
42958- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
42959+ }
f673a614 42960+
f673a614 42961+
2519e6e5
ER
42962+ PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
42963+ PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
42964 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
42965 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
42966 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
42967@@ -402,19 +430,19 @@
42968 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
42969 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
42970 #undef PLUGIN_TO_SLOT
42971-
f673a614 42972+
2519e6e5
ER
42973 if (p->init) {
42974 if (NULL == (p->data = p->init())) {
42975- log_error_write(srv, __FILE__, __LINE__, "sb",
42976+ log_error_write(srv, __FILE__, __LINE__, "sb",
42977 "plugin-init failed for module", p->name);
42978 return HANDLER_ERROR;
42979 }
42980-
f673a614 42981+
2519e6e5
ER
42982 /* used for con->mode, DIRECT == 0, plugins above that */
42983 ((plugin_data *)(p->data))->id = i + 1;
42984-
f673a614 42985+
2519e6e5
ER
42986 if (p->version != LIGHTTPD_VERSION_ID) {
42987- log_error_write(srv, __FILE__, __LINE__, "sb",
42988+ log_error_write(srv, __FILE__, __LINE__, "sb",
42989 "plugin-version doesn't match lighttpd-version for", p->name);
42990 return HANDLER_ERROR;
42991 }
42992@@ -422,29 +450,46 @@
42993 p->data = NULL;
42994 }
42995 }
42996-
f673a614 42997+
2519e6e5
ER
42998 return HANDLER_GO_ON;
42999 }
43000
43001+/**
43002+ * get the config-storage of the named plugin
43003+ */
43004+void *plugin_get_config(server *srv, const char *name) {
43005+ size_t i;
f673a614 43006+
2519e6e5
ER
43007+ for (i = 0; i < srv->plugins.used; i++) {
43008+ plugin *p = ((plugin **)srv->plugins.ptr)[i];
f673a614 43009+
2519e6e5
ER
43010+ if (buffer_is_equal_string(p->name, name, strlen(name))) {
43011+ return p->data;
43012+ }
43013+ }
f673a614 43014+
2519e6e5
ER
43015+ return NULL;
43016+}
f673a614 43017+
2519e6e5
ER
43018 void plugins_free(server *srv) {
43019 size_t i;
43020 plugins_call_cleanup(srv);
43021-
f673a614 43022+
2519e6e5
ER
43023 for (i = 0; i < srv->plugins.used; i++) {
43024 plugin *p = ((plugin **)srv->plugins.ptr)[i];
43025-
f673a614 43026+
2519e6e5
ER
43027 plugin_free(p);
43028 }
43029-
f673a614 43030+
2519e6e5
ER
43031 for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
43032 plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
43033-
43034+
43035 if (slot) free(slot);
43036 }
43037-
43038+
43039 free(srv->plugin_slots);
43040 srv->plugin_slots = NULL;
43041-
43042+
43043 free(srv->plugins.ptr);
43044 srv->plugins.ptr = NULL;
43045 srv->plugins.used = 0;
1175ccec 43046--- ../lighttpd-1.4.11/src/plugin.h 2005-08-15 12:28:56.000000000 +0300
36e2a29e 43047+++ lighttpd-1.4.12/src/plugin.h 2006-07-11 22:07:52.000000000 +0300
2519e6e5 43048@@ -12,6 +12,12 @@
f673a614 43049
2519e6e5
ER
43050 #define INIT_FUNC(x) \
43051 static void *x()
43052+/*
43053+ * The PATCH_OPTION() macro is used in the patch_connection() functions
43054+ * of the modules to update the config object for the current request.
43055+ */
43056+#define PATCH_OPTION(x) \
43057+ p->conf.x = s->x
43058
43059 #define FREE_FUNC SERVER_FUNC
43060 #define TRIGGER_FUNC SERVER_FUNC
43061@@ -25,19 +31,19 @@
43062 #define URIHANDLER_FUNC CONNECTION_FUNC
43063
43064 #define PLUGIN_DATA size_t id
43065-
f673a614 43066+
2519e6e5
ER
43067 typedef struct {
43068 size_t version;
43069-
f673a614 43070+
2519e6e5
ER
43071 buffer *name; /* name of the plugin */
43072-
f673a614 43073+
2519e6e5
ER
43074 void *(* init) ();
43075 handler_t (* set_defaults) (server *srv, void *p_d);
43076 handler_t (* cleanup) (server *srv, void *p_d);
43077 /* is called ... */
43078 handler_t (* handle_trigger) (server *srv, void *p_d); /* once a second */
43079 handler_t (* handle_sighup) (server *srv, void *p_d); /* at a signup */
43080-
f26f9fd5 43081+
2519e6e5
ER
43082 handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d); /* after uri_raw is set */
43083 handler_t (* handle_uri_clean) (server *srv, connection *con, void *p_d); /* after uri is set */
43084 handler_t (* handle_docroot) (server *srv, connection *con, void *p_d); /* getting the document-root */
43085@@ -45,20 +51,22 @@
43086 handler_t (* handle_request_done) (server *srv, connection *con, void *p_d); /* at the end of a request */
43087 handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d); /* at the end of a connection */
43088 handler_t (* handle_joblist) (server *srv, connection *con, void *p_d); /* after all events are handled */
43089-
43090-
43091-
43092- handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43093-
43094- /* when a handler for the request
43095+
43096+
43097+
43098+ handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43099+
43100+ /* when a handler for the request
43101 * has to be found
43102 */
43103 handler_t (* handle_subrequest) (server *srv, connection *con, void *p_d); /* */
43104 handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* */
43105 void *data;
43106-
43107+
43108 /* dlopen handle */
43109 void *lib;
43110+
43111+ array *required_plugins;
43112 } plugin;
43113
43114 int plugins_load(server *srv);
43115@@ -88,5 +96,8 @@
43116 int config_patch_connection(server *srv, connection *con, comp_key_t comp);
43117 int config_check_cond(server *srv, connection *con, data_config *dc);
43118 int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
43119+int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
43120+
43121+void *plugin_get_config(server *srv, const char *name);
43122
43123 #endif
1175ccec 43124--- ../lighttpd-1.4.11/src/proc_open.c 2005-08-11 01:26:39.000000000 +0300
36e2a29e 43125+++ lighttpd-1.4.12/src/proc_open.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5 43126@@ -13,13 +13,13 @@
f26f9fd5 43127 #endif
f673a614 43128
f26f9fd5 43129
2519e6e5
ER
43130-#ifdef WIN32
43131+#ifdef _WIN32
43132 /* {{{ win32 stuff */
43133 # define SHELLENV "ComSpec"
43134 # define SECURITY_DC , SECURITY_ATTRIBUTES *security
43135 # define SECURITY_CC , security
43136 # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
43137-static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43138+static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43139 {
43140 HANDLE copy, self = GetCurrentProcess();
f26f9fd5 43141
2519e6e5
ER
43142@@ -148,11 +148,14 @@
43143 STARTUPINFO si;
43144 BOOL procok;
43145 SECURITY_ATTRIBUTES security;
43146- const char *shell;
43147+ const char *shell = NULL;
43148+ const char *windir = NULL;
43149 buffer *cmdline;
f26f9fd5 43150
2519e6e5
ER
43151- if (NULL == (shell = getenv(SHELLENV))) {
43152- fprintf(stderr, "env %s is required", SHELLENV);
43153+ if (NULL == (shell = getenv(SHELLENV)) &&
43154+ NULL == (windir = getenv("SystemRoot")) &&
43155+ NULL == (windir = getenv("windir"))) {
43156+ fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
43157 return -1;
43158 }
f26f9fd5 43159
2519e6e5
ER
43160@@ -177,17 +180,23 @@
43161 memset(&pi, 0, sizeof(pi));
f26f9fd5 43162
2519e6e5
ER
43163 cmdline = buffer_init();
43164- buffer_append_string(cmdline, shell);
43165+ if (shell) {
43166+ buffer_append_string(cmdline, shell);
43167+ } else {
43168+ buffer_append_string(cmdline, windir);
43169+ buffer_append_string(cmdline, "\\system32\\cmd.exe");
43170+ }
43171 buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
43172 buffer_append_string(cmdline, command);
43173 procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
43174 NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
43175- buffer_free(cmdline);
f26f9fd5 43176
2519e6e5
ER
43177 if (FALSE == procok) {
43178- fprintf(stderr, "failed to CreateProcess");
43179+ fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
43180+ buffer_free(cmdline);
43181 return -1;
43182 }
43183+ buffer_free(cmdline);
f26f9fd5 43184
2519e6e5
ER
43185 proc->child = pi.hProcess;
43186 CloseHandle(pi.hThread);
43187@@ -226,8 +235,7 @@
43188 const char *shell;
43189
43190 if (NULL == (shell = getenv(SHELLENV))) {
43191- fprintf(stderr, "env %s is required", SHELLENV);
43192- return -1;
43193+ shell = "/bin/sh";
43194 }
43195
43196 if (proc_open_pipes(proc) != 0) {
43197@@ -262,11 +270,11 @@
43198 }
f26f9fd5 43199 }
2519e6e5
ER
43200 /* }}} */
43201-#endif /* WIN32 */
43202+#endif /* _WIN32 */
f26f9fd5 43203
2519e6e5
ER
43204 /* {{{ proc_read_fd_to_buffer */
43205 static void proc_read_fd_to_buffer(int fd, buffer *b) {
43206- ssize_t s;
43207+ int s; /* win32 has not ssize_t */
43208
43209 for (;;) {
43210 buffer_prepare_append(b, 512);
1175ccec 43211--- ../lighttpd-1.4.11/src/proc_open.h 2005-08-11 01:26:39.000000000 +0300
36e2a29e 43212+++ lighttpd-1.4.12/src/proc_open.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
43213@@ -1,7 +1,7 @@
43214
43215 #include "buffer.h"
43216
43217-#ifdef WIN32
43218+#ifdef _WIN32
43219 #include <windows.h>
43220 typedef HANDLE descriptor_t;
43221 typedef HANDLE proc_pid_t;
1175ccec 43222--- ../lighttpd-1.4.11/src/request.c 2006-03-05 11:58:09.000000000 +0200
36e2a29e 43223+++ lighttpd-1.4.12/src/request.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5
ER
43224@@ -10,15 +10,17 @@
43225 #include "keyvalue.h"
43226 #include "log.h"
43227
43228+#include "sys-strings.h"
f673a614 43229+
2519e6e5
ER
43230 static int request_check_hostname(server *srv, connection *con, buffer *host) {
43231 enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
43232 size_t i;
43233 int label_len = 0;
43234 size_t host_len;
43235 char *colon;
43236- int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
43237+ int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
43238 int level = 0;
43239-
f673a614 43240+
2519e6e5
ER
43241 UNUSED(srv);
43242 UNUSED(con);
43243
43244@@ -32,17 +34,17 @@
43245 * IPv6address = "[" ... "]"
43246 * port = *digit
43247 */
43248-
43249+
43250 /* no Host: */
43251 if (!host || host->used == 0) return 0;
43252-
43253+
43254 host_len = host->used - 1;
43255-
43256+
43257 /* IPv6 adress */
43258 if (host->ptr[0] == '[') {
43259 char *c = host->ptr + 1;
43260 int colon_cnt = 0;
43261-
43262+
43263 /* check portnumber */
43264 for (; *c && *c != ']'; c++) {
43265 if (*c == ':') {
43266@@ -53,12 +55,12 @@
43267 return -1;
43268 }
43269 }
43270-
43271+
43272 /* missing ] */
43273 if (!*c) {
43274 return -1;
43275 }
43276-
43277+
43278 /* check port */
43279 if (*(c+1) == ':') {
43280 for (c += 2; *c; c++) {
43281@@ -69,39 +71,39 @@
43282 }
43283 return 0;
43284 }
43285-
43286+
43287 if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
43288 char *c = colon + 1;
43289-
43290+
43291 /* check portnumber */
43292 for (; *c; c++) {
43293 if (!light_isdigit(*c)) return -1;
43294 }
43295-
f673a614 43296+
2519e6e5
ER
43297 /* remove the port from the host-len */
43298 host_len = colon - host->ptr;
43299 }
43300-
f673a614 43301+
2519e6e5
ER
43302 /* Host is empty */
43303 if (host_len == 0) return -1;
43304-
f673a614 43305+
2519e6e5
ER
43306 /* scan from the right and skip the \0 */
43307 for (i = host_len - 1; i + 1 > 0; i--) {
43308 const char c = host->ptr[i];
43309
43310 switch (stage) {
43311- case TOPLABEL:
43312+ case TOPLABEL:
43313 if (c == '.') {
43314 /* only switch stage, if this is not the last character */
43315 if (i != host_len - 1) {
43316 if (label_len == 0) {
43317 return -1;
43318 }
43319-
f673a614 43320+
2519e6e5
ER
43321 /* check the first character at right of the dot */
43322 if (is_ip == 0) {
43323 if (!light_isalpha(host->ptr[i+1])) {
43324- return -1;
43325+ return -1;
43326 }
43327 } else if (!light_isdigit(host->ptr[i+1])) {
43328 is_ip = 0;
43329@@ -111,9 +113,9 @@
43330 /* just digits */
43331 is_ip = 1;
43332 }
43333-
f26f9fd5 43334+
2519e6e5
ER
43335 stage = DOMAINLABEL;
43336-
f26f9fd5 43337+
2519e6e5
ER
43338 label_len = 0;
43339 level++;
43340 } else if (i == 0) {
43341@@ -135,7 +137,7 @@
43342 }
43343 label_len++;
43344 }
43345-
f26f9fd5 43346+
2519e6e5
ER
43347 break;
43348 case DOMAINLABEL:
43349 if (is_ip == 1) {
43350@@ -143,7 +145,7 @@
43351 if (label_len == 0) {
43352 return -1;
43353 }
43354-
f26f9fd5 43355+
2519e6e5
ER
43356 label_len = 0;
43357 level++;
43358 } else if (!light_isdigit(c)) {
43359@@ -156,12 +158,12 @@
43360 if (label_len == 0) {
43361 return -1;
43362 }
43363-
f26f9fd5 43364+
2519e6e5
ER
43365 /* c is either - or alphanum here */
43366 if ('-' == host->ptr[i+1]) {
43367 return -1;
43368 }
43369-
f26f9fd5 43370+
2519e6e5
ER
43371 label_len = 0;
43372 level++;
43373 } else if (i == 0) {
43374@@ -176,20 +178,20 @@
43375 label_len++;
43376 }
43377 }
43378-
f673a614 43379+
2519e6e5
ER
43380 break;
43381 }
43382 }
43383-
f673a614 43384+
2519e6e5
ER
43385 /* a IP has to consist of 4 parts */
43386 if (is_ip == 1 && level != 3) {
43387 return -1;
43388 }
43389-
f673a614 43390+
2519e6e5
ER
43391 if (label_len == 0) {
43392 return -1;
43393 }
43394-
f673a614 43395+
2519e6e5
ER
43396 return 0;
43397 }
43398
43399@@ -201,53 +203,53 @@
43400 char *s;
43401 size_t i;
43402 int state = 0;
43403- /*
43404- * parse
43405- *
43406+ /*
43407+ * parse
f26f9fd5 43408+ *
2519e6e5
ER
43409 * val1, val2, val3, val4
43410- *
f26f9fd5 43411+ *
2519e6e5
ER
43412 * into a array (more or less a explode() incl. striping of whitespaces
43413 */
43414-
f673a614 43415+
2519e6e5
ER
43416 if (b->used == 0) return 0;
43417-
f673a614 43418+
2519e6e5
ER
43419 s = b->ptr;
43420-
f673a614 43421+
2519e6e5
ER
43422 for (i =0; i < b->used - 1; ) {
43423 char *start = NULL, *end = NULL;
43424 data_string *ds;
43425-
f673a614 43426+
2519e6e5
ER
43427 switch (state) {
43428 case 0: /* ws */
43429-
f673a614 43430+
2519e6e5
ER
43431 /* skip ws */
43432 for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
43433-
43434-
f673a614 43435+
f673a614 43436+
2519e6e5
ER
43437 state = 1;
43438 break;
43439 case 1: /* value */
43440 start = s;
43441-
f673a614 43442+
2519e6e5
ER
43443 for (; *s != ',' && i < b->used - 1; i++, s++);
43444 end = s - 1;
43445-
43446+
43447 for (; (*end == ' ' || *end == '\t') && end > start; end--);
43448-
43449+
43450 if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
43451 ds = data_string_init();
43452 }
f26f9fd5 43453
2519e6e5
ER
43454 buffer_copy_string_len(ds->value, start, end-start+1);
43455 array_insert_unique(vals, (data_unset *)ds);
43456-
43457+
43458 if (*s == ',') {
43459 state = 0;
43460 i++;
43461 s++;
43462 } else {
43463 /* end of string */
43464-
43465+
43466 state = 2;
43467 }
43468 break;
43469@@ -263,7 +265,7 @@
43470 if (c <= 32) return 0;
43471 if (c == 127) return 0;
43472 if (c == 255) return 0;
43473-
43474+
43475 return 1;
43476 }
f26f9fd5 43477
2519e6e5
ER
43478@@ -271,28 +273,28 @@
43479 char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
43480 int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
43481 char *value = NULL, *key = NULL;
43482-
f673a614 43483+
2519e6e5
ER
43484 enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
43485-
43486+
43487 int line = 0;
43488-
43489+
43490 int request_line_stage = 0;
43491 size_t i, first;
43492-
43493+
43494 int done = 0;
43495-
43496+
43497 data_string *ds = NULL;
43498-
43499- /*
43500- * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43501- * Option : "^([-a-zA-Z]+): (.+)$"
43502+
43503+ /*
43504+ * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43505+ * Option : "^([-a-zA-Z]+): (.+)$"
43506 * End : "^$"
43507 */
f673a614 43508
2519e6e5
ER
43509 if (con->conf.log_request_header) {
43510- log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43511- "fd:", con->fd,
43512- "request-len:", con->request.request->used,
43513+ log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43514+ "fd:", con->fd,
43515+ "request-len:", con->request.request->used,
43516 "\n", con->request.request);
43517 }
f673a614 43518
2519e6e5
ER
43519@@ -300,13 +302,13 @@
43520 con->request.request->ptr[0] == '\r' &&
43521 con->request.request->ptr[1] == '\n') {
43522 /* we are in keep-alive and might get \r\n after a previous POST request.*/
43523-
f673a614 43524+
2519e6e5
ER
43525 buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
43526 } else {
43527 /* fill the local request buffer */
43528 buffer_copy_string_buffer(con->parse_request, con->request.request);
43529 }
43530-
f673a614 43531+
2519e6e5
ER
43532 keep_alive_set = 0;
43533 con_length_set = 0;
f673a614 43534
2519e6e5
ER
43535@@ -318,25 +320,25 @@
43536 * */
43537 for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
43538 char *cur = con->parse_request->ptr + i;
43539-
f673a614 43540+
2519e6e5
ER
43541 switch(*cur) {
43542- case '\r':
43543+ case '\r':
43544 if (con->parse_request->ptr[i+1] == '\n') {
43545 http_method_t r;
43546 char *nuri = NULL;
43547 size_t j;
43548-
f673a614 43549+
2519e6e5
ER
43550 /* \r\n -> \0\0 */
43551 con->parse_request->ptr[i] = '\0';
43552 con->parse_request->ptr[i+1] = '\0';
43553-
f673a614 43554+
2519e6e5
ER
43555 buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
43556-
f673a614 43557+
2519e6e5
ER
43558 if (request_line_stage != 2) {
43559 con->http_status = 400;
43560 con->response.keep_alive = 0;
43561 con->keep_alive = 0;
43562-
f673a614 43563+
2519e6e5
ER
43564 if (srv->srvconf.log_request_header_on_error) {
43565 log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
43566 log_error_write(srv, __FILE__, __LINE__, "Sb",
43567@@ -345,36 +347,36 @@
43568 }
43569 return 0;
43570 }
43571-
43572+
43573 proto = con->parse_request->ptr + first;
43574-
43575+
43576 *(uri - 1) = '\0';
43577 *(proto - 1) = '\0';
43578-
43579+
43580 /* we got the first one :) */
43581 if (-1 == (r = get_http_method_key(method))) {
43582 con->http_status = 501;
43583 con->response.keep_alive = 0;
43584 con->keep_alive = 0;
43585-
43586+
43587 if (srv->srvconf.log_request_header_on_error) {
43588 log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
43589 log_error_write(srv, __FILE__, __LINE__, "Sb",
43590 "request-header:\n",
43591 con->request.request);
43592 }
43593-
43594+
43595 return 0;
43596 }
43597-
f673a614 43598+
2519e6e5
ER
43599 con->request.http_method = r;
43600-
43601- /*
43602+
43603+ /*
43604 * RFC2616 says:
43605 *
43606 * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
43607 *
43608- * */
43609+ * */
43610 if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
43611 char * major = proto + sizeof("HTTP/") - 1;
43612 char * minor = strchr(major, '.');
43613@@ -413,10 +415,10 @@
43614 }
43615
43616 if (major_num == 1 && minor_num == 1) {
43617- con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
43618+ con->request.http_version = HTTP_VERSION_1_1;
43619 } else if (major_num == 1 && minor_num == 0) {
43620 con->request.http_version = HTTP_VERSION_1_0;
43621- } else {
43622+ } else {
43623 con->http_status = 505;
43624
43625 if (srv->srvconf.log_request_header_on_error) {
43626@@ -439,30 +441,30 @@
43627 }
43628 return 0;
43629 }
43630-
f673a614 43631+
2519e6e5
ER
43632 if (0 == strncmp(uri, "http://", 7) &&
43633 NULL != (nuri = strchr(uri + 7, '/'))) {
43634 /* ignore the host-part */
43635-
f673a614 43636+
2519e6e5
ER
43637 buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
43638 } else {
43639 /* everything looks good so far */
43640 buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
43641 }
43642-
f673a614 43643+
2519e6e5
ER
43644 /* check uri for invalid characters */
43645 for (j = 0; j < con->request.uri->used - 1; j++) {
43646 if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
43647 unsigned char buf[2];
43648 con->http_status = 400;
43649 con->keep_alive = 0;
43650-
f673a614 43651+
2519e6e5
ER
43652 if (srv->srvconf.log_request_header_on_error) {
43653 buf[0] = con->request.uri->ptr[j];
43654 buf[1] = '\0';
43655-
f673a614 43656+
2519e6e5
ER
43657 if (con->request.uri->ptr[j] > 32 &&
43658- con->request.uri->ptr[j] != 127) {
43659+ con->request.uri->ptr[j] != 127) {
43660 /* the character is printable -> print it */
43661 log_error_write(srv, __FILE__, __LINE__, "ss",
43662 "invalid character in URI -> 400",
43663@@ -473,20 +475,20 @@
43664 "invalid character in URI -> 400",
43665 con->request.uri->ptr[j]);
43666 }
43667-
f673a614 43668+
2519e6e5
ER
43669 log_error_write(srv, __FILE__, __LINE__, "Sb",
43670 "request-header:\n",
43671 con->request.request);
43672 }
43673-
f673a614 43674+
2519e6e5
ER
43675 return 0;
43676 }
43677 }
43678-
f673a614 43679+
2519e6e5
ER
43680 buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
43681-
f673a614 43682+
2519e6e5
ER
43683 con->http_status = 0;
43684-
f673a614 43685+
2519e6e5
ER
43686 i++;
43687 line++;
43688 first = i+1;
43689@@ -494,14 +496,14 @@
43690 break;
43691 case ' ':
43692 switch(request_line_stage) {
43693- case 0:
43694+ case 0:
43695 /* GET|POST|... */
43696- method = con->parse_request->ptr + first;
43697+ method = con->parse_request->ptr + first;
43698 first = i + 1;
43699 break;
43700 case 1:
43701 /* /foobar/... */
43702- uri = con->parse_request->ptr + first;
43703+ uri = con->parse_request->ptr + first;
43704 first = i + 1;
43705 break;
43706 default:
43707@@ -509,7 +511,7 @@
43708 con->http_status = 400;
43709 con->response.keep_alive = 0;
43710 con->keep_alive = 0;
43711-
f673a614 43712+
2519e6e5
ER
43713 if (srv->srvconf.log_request_header_on_error) {
43714 log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
43715 log_error_write(srv, __FILE__, __LINE__, "Sb",
43716@@ -518,12 +520,12 @@
43717 }
43718 return 0;
f26f9fd5 43719 }
2519e6e5 43720-
f673a614 43721+
2519e6e5
ER
43722 request_line_stage++;
43723 break;
f26f9fd5 43724 }
2519e6e5
ER
43725 }
43726-
f673a614 43727+
2519e6e5 43728 in_folding = 0;
f673a614 43729
2519e6e5
ER
43730 if (con->request.uri->used == 1) {
43731@@ -540,30 +542,30 @@
43732 return 0;
f26f9fd5 43733 }
f673a614 43734
2519e6e5 43735-
f673a614 43736+
2519e6e5
ER
43737 for (; i < con->parse_request->used && !done; i++) {
43738 char *cur = con->parse_request->ptr + i;
43739-
43740+
43741 if (is_key) {
43742 size_t j;
43743 int got_colon = 0;
43744-
43745+
43746 /**
43747 * 1*<any CHAR except CTLs or separators>
43748 * CTLs == 0-31 + 127
43749- *
43750+ *
43751 */
43752 switch(*cur) {
43753 case ':':
43754 is_key = 0;
43755-
43756+
43757 value = cur + 1;
43758-
43759+
43760 if (is_ws_after_key == 0) {
43761 key_len = i - first;
f26f9fd5 43762 }
2519e6e5
ER
43763 is_ws_after_key = 0;
43764-
f673a614 43765+
2519e6e5
ER
43766 break;
43767 case '(':
43768 case ')':
43769@@ -584,8 +586,8 @@
f26f9fd5 43770 con->http_status = 400;
2519e6e5
ER
43771 con->keep_alive = 0;
43772 con->response.keep_alive = 0;
43773-
43774- log_error_write(srv, __FILE__, __LINE__, "sbsds",
43775+
43776+ log_error_write(srv, __FILE__, __LINE__, "sbsds",
43777 "invalid character in key", con->request.request, cur, *cur, "-> 400");
43778 return 0;
43779 case ' ':
43780@@ -594,13 +596,13 @@
43781 is_key = 0;
43782 in_folding = 1;
43783 value = cur;
43784-
f673a614 43785+
2519e6e5
ER
43786 break;
43787 }
43788-
43789-
f673a614 43790+
f673a614 43791+
2519e6e5
ER
43792 key_len = i - first;
43793-
f673a614 43794+
2519e6e5
ER
43795 /* skip every thing up to the : */
43796 for (j = 1; !got_colon; j++) {
43797 switch(con->parse_request->ptr[j + i]) {
43798@@ -610,40 +612,40 @@
43799 continue;
43800 case ':':
43801 /* ok, done */
43802-
f673a614 43803+
2519e6e5
ER
43804 i += j - 1;
43805 got_colon = 1;
43806-
f673a614 43807+
2519e6e5
ER
43808 break;
43809 default:
43810 /* error */
43811-
f673a614 43812+
2519e6e5
ER
43813 if (srv->srvconf.log_request_header_on_error) {
43814 log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
43815 log_error_write(srv, __FILE__, __LINE__, "Sb",
43816 "request-header:\n",
43817 con->request.request);
43818 }
43819-
f673a614 43820+
2519e6e5
ER
43821 con->http_status = 400;
43822 con->response.keep_alive = 0;
43823 con->keep_alive = 0;
43824-
f673a614 43825+
2519e6e5
ER
43826 return 0;
43827 }
43828 }
43829-
f673a614 43830+
2519e6e5
ER
43831 break;
43832 case '\r':
43833 if (con->parse_request->ptr[i+1] == '\n' && i == first) {
43834 /* End of Header */
43835 con->parse_request->ptr[i] = '\0';
43836 con->parse_request->ptr[i+1] = '\0';
43837-
f673a614 43838+
2519e6e5
ER
43839 i++;
43840-
43841+
43842 done = 1;
43843-
43844+
43845 break;
43846 } else {
43847 if (srv->srvconf.log_request_header_on_error) {
43848@@ -652,7 +654,7 @@
43849 "request-header:\n",
43850 con->request.request);
43851 }
43852-
f673a614 43853+
2519e6e5
ER
43854 con->http_status = 400;
43855 con->keep_alive = 0;
43856 con->response.keep_alive = 0;
43857@@ -693,16 +695,16 @@
43858 con->http_status = 400;
43859 con->keep_alive = 0;
43860 con->response.keep_alive = 0;
43861-
f673a614 43862+
2519e6e5
ER
43863 if (srv->srvconf.log_request_header_on_error) {
43864- log_error_write(srv, __FILE__, __LINE__, "sbsds",
43865+ log_error_write(srv, __FILE__, __LINE__, "sbsds",
43866 "CTL character in key", con->request.request, cur, *cur, "-> 400");
43867
43868 log_error_write(srv, __FILE__, __LINE__, "Sb",
43869 "request-header:\n",
43870 con->request.request);
43871 }
43872-
f673a614 43873+
2519e6e5
ER
43874 return 0;
43875 default:
43876 /* ok */
43877@@ -710,25 +712,25 @@
43878 }
43879 } else {
43880 switch(*cur) {
43881- case '\r':
43882+ case '\r':
43883 if (con->parse_request->ptr[i+1] == '\n') {
43884 /* End of Headerline */
43885 con->parse_request->ptr[i] = '\0';
43886 con->parse_request->ptr[i+1] = '\0';
43887-
f673a614 43888+
2519e6e5
ER
43889 if (in_folding) {
43890 if (!ds) {
43891 /* 400 */
43892-
f673a614 43893+
2519e6e5
ER
43894 if (srv->srvconf.log_request_header_on_error) {
43895 log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
43896-
f673a614 43897+
2519e6e5
ER
43898 log_error_write(srv, __FILE__, __LINE__, "Sb",
43899 "request-header:\n",
43900 con->request.request);
43901 }
43902
43903-
f673a614 43904+
2519e6e5
ER
43905 con->http_status = 400;
43906 con->keep_alive = 0;
43907 con->response.keep_alive = 0;
43908@@ -738,9 +740,9 @@
43909 } else {
43910 int s_len;
43911 key = con->parse_request->ptr + first;
43912-
f673a614 43913+
2519e6e5
ER
43914 s_len = cur - value;
43915-
f673a614 43916+
2519e6e5
ER
43917 if (s_len > 0) {
43918 int cmp = 0;
43919 if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
43920@@ -748,86 +750,87 @@
43921 }
43922 buffer_copy_string_len(ds->key, key, key_len);
43923 buffer_copy_string_len(ds->value, value, s_len);
43924-
43925- /* retreive values
43926- *
43927- *
43928+
43929+ /* retreive values
43930+ *
43931+ *
43932 * the list of options is sorted to simplify the search
43933 */
43934-
f673a614 43935+
2519e6e5
ER
43936 if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
43937 array *vals;
43938 size_t vi;
43939-
f673a614 43940+
2519e6e5
ER
43941 /* split on , */
43942-
f673a614 43943+
2519e6e5
ER
43944 vals = srv->split_vals;
43945
43946 array_reset(vals);
43947-
f673a614 43948+
2519e6e5
ER
43949 http_request_split_value(vals, ds->value);
43950-
f673a614 43951+
2519e6e5
ER
43952 for (vi = 0; vi < vals->used; vi++) {
43953 data_string *dsv = (data_string *)vals->data[vi];
43954-
f673a614 43955+
2519e6e5
ER
43956 if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
43957 keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
43958-
f673a614 43959+
2519e6e5
ER
43960 break;
43961 } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
43962 keep_alive_set = HTTP_CONNECTION_CLOSE;
43963-
f673a614 43964+
2519e6e5
ER
43965 break;
43966 }
43967 }
43968-
43969+
43970 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
43971 char *err;
43972 unsigned long int r;
43973 size_t j;
43974-
43975+
43976 if (con_length_set) {
43977 con->http_status = 400;
43978 con->keep_alive = 0;
43979-
43980+
43981 if (srv->srvconf.log_request_header_on_error) {
43982- log_error_write(srv, __FILE__, __LINE__, "s",
43983+ log_error_write(srv, __FILE__, __LINE__, "s",
43984 "duplicate Content-Length-header -> 400");
43985 log_error_write(srv, __FILE__, __LINE__, "Sb",
43986 "request-header:\n",
43987 con->request.request);
43988 }
43989+ ds->free((data_unset *) ds);
43990 return 0;
43991 }
43992-
f673a614 43993+
2519e6e5
ER
43994 if (ds->value->used == 0) SEGFAULT();
43995-
f673a614 43996+
2519e6e5
ER
43997 for (j = 0; j < ds->value->used - 1; j++) {
43998 char c = ds->value->ptr[j];
43999 if (!isdigit((unsigned char)c)) {
44000- log_error_write(srv, __FILE__, __LINE__, "sbs",
44001+ log_error_write(srv, __FILE__, __LINE__, "sbs",
44002 "content-length broken:", ds->value, "-> 400");
44003-
f673a614 44004+
2519e6e5
ER
44005 con->http_status = 400;
44006 con->keep_alive = 0;
44007-
f673a614 44008+
2519e6e5
ER
44009 array_insert_unique(con->request.headers, (data_unset *)ds);
44010 return 0;
44011 }
44012 }
44013-
f673a614 44014+
2519e6e5
ER
44015 r = strtoul(ds->value->ptr, &err, 10);
44016-
f673a614 44017+
2519e6e5
ER
44018 if (*err == '\0') {
44019 con_length_set = 1;
44020 con->request.content_length = r;
44021 } else {
44022- log_error_write(srv, __FILE__, __LINE__, "sbs",
44023+ log_error_write(srv, __FILE__, __LINE__, "sbs",
44024 "content-length broken:", ds->value, "-> 400");
44025-
f673a614 44026+
2519e6e5
ER
44027 con->http_status = 400;
44028 con->keep_alive = 0;
44029-
f673a614 44030+
2519e6e5
ER
44031 array_insert_unique(con->request.headers, (data_unset *)ds);
44032 return 0;
44033 }
44034@@ -838,23 +841,24 @@
44035 } else {
44036 con->http_status = 400;
44037 con->keep_alive = 0;
44038-
44039+
44040 if (srv->srvconf.log_request_header_on_error) {
44041- log_error_write(srv, __FILE__, __LINE__, "s",
44042+ log_error_write(srv, __FILE__, __LINE__, "s",
44043 "duplicate Content-Type-header -> 400");
44044 log_error_write(srv, __FILE__, __LINE__, "Sb",
44045 "request-header:\n",
44046 con->request.request);
44047 }
44048+ ds->free((data_unset *) ds);
44049 return 0;
44050 }
44051 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
44052- /* HTTP 2616 8.2.3
44053+ /* HTTP 2616 8.2.3
44054 * Expect: 100-continue
44055- *
44056+ *
44057 * -> (10.1.1) 100 (read content, process request, send final status-code)
44058 * -> (10.4.18) 417 (close)
44059- *
44060+ *
44061 * (not handled at all yet, we always send 417 here)
44062 *
44063 * What has to be added ?
44064@@ -863,10 +867,10 @@
44065 * header
44066 *
44067 */
44068-
44069+
44070 con->http_status = 417;
44071 con->keep_alive = 0;
44072-
44073+
44074 array_insert_unique(con->request.headers, (data_unset *)ds);
44075 return 0;
44076 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
44077@@ -875,14 +879,15 @@
44078 } else {
44079 con->http_status = 400;
44080 con->keep_alive = 0;
44081-
44082+
44083 if (srv->srvconf.log_request_header_on_error) {
44084- log_error_write(srv, __FILE__, __LINE__, "s",
44085+ log_error_write(srv, __FILE__, __LINE__, "s",
44086 "duplicate Host-header -> 400");
44087 log_error_write(srv, __FILE__, __LINE__, "Sb",
44088 "request-header:\n",
44089 con->request.request);
44090 }
44091+ ds->free((data_unset *) ds);
44092 return 0;
44093 }
44094 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
44095@@ -897,14 +902,15 @@
44096 } else {
44097 con->http_status = 400;
44098 con->keep_alive = 0;
44099-
44100+
44101 if (srv->srvconf.log_request_header_on_error) {
44102- log_error_write(srv, __FILE__, __LINE__, "s",
44103+ log_error_write(srv, __FILE__, __LINE__, "s",
44104 "duplicate If-Modified-Since header -> 400");
44105 log_error_write(srv, __FILE__, __LINE__, "Sb",
44106 "request-header:\n",
44107 con->request.request);
44108 }
44109+ ds->free((data_unset *) ds);
44110 return 0;
44111 }
44112 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
44113@@ -914,47 +920,49 @@
44114 } else {
44115 con->http_status = 400;
44116 con->keep_alive = 0;
44117-
44118+
44119 if (srv->srvconf.log_request_header_on_error) {
44120- log_error_write(srv, __FILE__, __LINE__, "s",
44121+ log_error_write(srv, __FILE__, __LINE__, "s",
44122 "duplicate If-None-Match-header -> 400");
44123 log_error_write(srv, __FILE__, __LINE__, "Sb",
44124 "request-header:\n",
44125 con->request.request);
44126 }
44127+ ds->free((data_unset *) ds);
44128 return 0;
44129 }
44130 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
44131 if (!con->request.http_range) {
44132 /* bytes=.*-.* */
44133-
f673a614 44134+
2519e6e5
ER
44135 if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
44136 NULL != strchr(ds->value->ptr+6, '-')) {
44137-
f673a614 44138+
2519e6e5
ER
44139 /* if dup, only the first one will survive */
44140 con->request.http_range = ds->value->ptr + 6;
44141 }
44142 } else {
44143 con->http_status = 400;
44144 con->keep_alive = 0;
44145-
44146+
44147 if (srv->srvconf.log_request_header_on_error) {
44148- log_error_write(srv, __FILE__, __LINE__, "s",
44149+ log_error_write(srv, __FILE__, __LINE__, "s",
44150 "duplicate Range-header -> 400");
44151 log_error_write(srv, __FILE__, __LINE__, "Sb",
44152 "request-header:\n",
44153 con->request.request);
44154 }
44155+ ds->free((data_unset *) ds);
44156 return 0;
44157 }
44158 }
44159-
f673a614 44160+
2519e6e5
ER
44161 array_insert_unique(con->request.headers, (data_unset *)ds);
44162 } else {
44163 /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
44164 }
44165 }
44166-
f673a614 44167+
2519e6e5
ER
44168 i++;
44169 first = i+1;
44170 is_key = 1;
44171@@ -963,10 +971,10 @@
44172 in_folding = 0;
44173 } else {
44174 if (srv->srvconf.log_request_header_on_error) {
44175- log_error_write(srv, __FILE__, __LINE__, "sbs",
44176+ log_error_write(srv, __FILE__, __LINE__, "sbs",
44177 "CR without LF", con->request.request, "-> 400");
44178 }
44179-
f673a614 44180+
2519e6e5
ER
44181 con->http_status = 400;
44182 con->keep_alive = 0;
44183 con->response.keep_alive = 0;
44184@@ -982,28 +990,28 @@
44185 }
44186 }
44187 }
44188-
f673a614 44189+
2519e6e5
ER
44190 con->header_len = i;
44191-
f673a614 44192+
2519e6e5
ER
44193 /* do some post-processing */
44194
44195 if (con->request.http_version == HTTP_VERSION_1_1) {
44196 if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
44197 /* no Connection-Header sent */
44198-
f673a614 44199+
2519e6e5
ER
44200 /* HTTP/1.1 -> keep-alive default TRUE */
44201 con->keep_alive = 1;
44202 } else {
44203 con->keep_alive = 0;
44204 }
44205-
f673a614 44206+
2519e6e5
ER
44207 /* RFC 2616, 14.23 */
44208 if (con->request.http_host == NULL ||
44209 buffer_is_empty(con->request.http_host)) {
44210 con->http_status = 400;
44211 con->response.keep_alive = 0;
44212 con->keep_alive = 0;
44213-
f673a614 44214+
2519e6e5
ER
44215 if (srv->srvconf.log_request_header_on_error) {
44216 log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
44217 log_error_write(srv, __FILE__, __LINE__, "Sb",
44218@@ -1015,18 +1023,18 @@
44219 } else {
44220 if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
44221 /* no Connection-Header sent */
44222-
f673a614 44223+
2519e6e5
ER
44224 /* HTTP/1.0 -> keep-alive default FALSE */
44225 con->keep_alive = 1;
44226 } else {
44227 con->keep_alive = 0;
44228 }
44229 }
44230-
f673a614 44231+
2519e6e5
ER
44232 /* check hostname field if it is set */
44233 if (NULL != con->request.http_host &&
44234 0 != request_check_hostname(srv, con, con->request.http_host)) {
44235-
f673a614 44236+
2519e6e5
ER
44237 if (srv->srvconf.log_request_header_on_error) {
44238 log_error_write(srv, __FILE__, __LINE__, "s",
44239 "Invalid Hostname -> 400");
44240@@ -1038,7 +1046,7 @@
44241 con->http_status = 400;
44242 con->response.keep_alive = 0;
44243 con->keep_alive = 0;
44244-
f673a614 44245+
2519e6e5
ER
44246 return 0;
44247 }
44248
44249@@ -1048,7 +1056,7 @@
44250 /* content-length is forbidden for those */
44251 if (con_length_set && con->request.content_length != 0) {
44252 /* content-length is missing */
44253- log_error_write(srv, __FILE__, __LINE__, "s",
44254+ log_error_write(srv, __FILE__, __LINE__, "s",
44255 "GET/HEAD with content-length -> 400");
44256
44257 con->keep_alive = 0;
44258@@ -1060,7 +1068,7 @@
44259 /* content-length is required for them */
44260 if (!con_length_set) {
44261 /* content-length is missing */
44262- log_error_write(srv, __FILE__, __LINE__, "s",
44263+ log_error_write(srv, __FILE__, __LINE__, "s",
44264 "POST-request, but content-length missing -> 411");
44265
44266 con->keep_alive = 0;
44267@@ -1073,16 +1081,16 @@
44268 /* the may have a content-length */
44269 break;
44270 }
44271-
44272-
44273+
44274+
44275 /* check if we have read post data */
44276 if (con_length_set) {
44277 /* don't handle more the SSIZE_MAX bytes in content-length */
44278 if (con->request.content_length > SSIZE_MAX) {
44279- con->http_status = 413;
44280+ con->http_status = 413;
44281 con->keep_alive = 0;
44282
44283- log_error_write(srv, __FILE__, __LINE__, "sds",
44284+ log_error_write(srv, __FILE__, __LINE__, "sds",
44285 "request-size too long:", con->request.content_length, "-> 413");
44286 return 0;
44287 }
44288@@ -1090,25 +1098,25 @@
44289 /* divide by 1024 as srvconf.max_request_size is in kBytes */
44290 if (srv->srvconf.max_request_size != 0 &&
44291 (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
44292- /* the request body itself is larger then
44293+ /* the request body itself is larger then
44294 * our our max_request_size
44295 */
44296-
f673a614 44297+
2519e6e5
ER
44298 con->http_status = 413;
44299 con->keep_alive = 0;
44300-
44301- log_error_write(srv, __FILE__, __LINE__, "sds",
f673a614 44302+
2519e6e5
ER
44303+ log_error_write(srv, __FILE__, __LINE__, "sds",
44304 "request-size too long:", con->request.content_length, "-> 413");
44305 return 0;
44306 }
44307-
44308-
f673a614 44309+
f673a614 44310+
2519e6e5
ER
44311 /* we have content */
44312 if (con->request.content_length != 0) {
44313 return 1;
44314 }
44315 }
44316-
f673a614 44317+
2519e6e5
ER
44318 return 0;
44319 }
44320
44321@@ -1116,9 +1124,9 @@
44322 UNUSED(srv);
44323
44324 if (con->request.request->used < 5) return 0;
44325-
f673a614 44326+
2519e6e5
ER
44327 if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
44328 if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
44329-
f673a614 44330+
2519e6e5
ER
44331 return 0;
44332 }
1175ccec 44333--- ../lighttpd-1.4.11/src/response.c 2006-03-04 16:41:39.000000000 +0200
36e2a29e 44334+++ lighttpd-1.4.12/src/response.c 2006-07-11 22:07:52.000000000 +0300
2519e6e5 44335@@ -7,7 +7,6 @@
f26f9fd5 44336 #include <stdlib.h>
2519e6e5
ER
44337 #include <string.h>
44338 #include <time.h>
44339-#include <unistd.h>
44340 #include <ctype.h>
f26f9fd5
ER
44341 #include <assert.h>
44342
2519e6e5
ER
44343@@ -24,15 +23,17 @@
44344 #include "plugin.h"
44345
f26f9fd5
ER
44346 #include "sys-socket.h"
44347+#include "sys-files.h"
2519e6e5 44348+#include "sys-strings.h"
f26f9fd5 44349
2519e6e5
ER
44350 int http_response_write_header(server *srv, connection *con) {
44351 buffer *b;
44352 size_t i;
44353 int have_date = 0;
44354 int have_server = 0;
f26f9fd5 44355-
f673a614 44356+
2519e6e5
ER
44357 b = chunkqueue_get_prepend_buffer(con->write_queue);
44358-
f673a614 44359+
2519e6e5
ER
44360 if (con->request.http_version == HTTP_VERSION_1_1) {
44361 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
44362 } else {
44363@@ -41,25 +42,26 @@
44364 buffer_append_long(b, con->http_status);
44365 BUFFER_APPEND_STRING_CONST(b, " ");
44366 buffer_append_string(b, get_http_status_name(con->http_status));
44367-
f26f9fd5 44368+
2519e6e5
ER
44369 if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
44370 BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
44371 buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
f26f9fd5 44372 }
2519e6e5 44373-
f673a614 44374+
2519e6e5
ER
44375 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
44376 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
44377 }
44378-
44379-
f673a614 44380+
f673a614 44381+
2519e6e5
ER
44382 /* add all headers */
44383 for (i = 0; i < con->response.headers->used; i++) {
44384 data_string *ds;
44385-
f26f9fd5 44386+
2519e6e5
ER
44387 ds = (data_string *)con->response.headers->data[i];
44388-
f26f9fd5 44389+
2519e6e5
ER
44390 if (ds->value->used && ds->key->used &&
44391- 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
44392+ 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
44393+ 0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
44394 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
44395 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
44396
44397@@ -68,28 +70,28 @@
44398 BUFFER_APPEND_STRING_CONST(b, ": ");
44399 buffer_append_string_buffer(b, ds->value);
44400 #if 0
44401- log_error_write(srv, __FILE__, __LINE__, "bb",
44402+ log_error_write(srv, __FILE__, __LINE__, "bb",
44403 ds->key, ds->value);
f26f9fd5 44404 #endif
2519e6e5 44405 }
f26f9fd5 44406 }
f26f9fd5 44407-
2519e6e5
ER
44408+
44409 if (!have_date) {
44410 /* HTTP/1.1 requires a Date: header */
44411 BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
f673a614 44412-
2519e6e5
ER
44413+
44414 /* cache the generated timestamp */
44415 if (srv->cur_ts != srv->last_generated_date_ts) {
44416 buffer_prepare_copy(srv->ts_date_str, 255);
44417-
44418- strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
44419+
44420+ strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
44421 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
44422-
44423+
44424 srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
f673a614
ER
44425-
44426+
2519e6e5
ER
44427 srv->last_generated_date_ts = srv->cur_ts;
44428 }
44429-
f673a614 44430+
2519e6e5 44431 buffer_append_string_buffer(b, srv->ts_date_str);
f26f9fd5 44432 }
2519e6e5
ER
44433
44434@@ -101,16 +103,16 @@
44435 buffer_append_string_buffer(b, con->conf.server_tag);
44436 }
44437 }
44438-
f26f9fd5 44439+
2519e6e5
ER
44440 BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
44441-
44442-
44443+
44444+
44445 con->bytes_header = b->used - 1;
44446-
44447+
44448 if (con->conf.log_response_header) {
44449 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
f673a614 44450 }
2519e6e5
ER
44451-
44452+
44453 return 0;
44454 }
f26f9fd5 44455
2519e6e5 44456@@ -118,71 +120,71 @@
f673a614 44457
2519e6e5
ER
44458 handler_t http_response_prepare(server *srv, connection *con) {
44459 handler_t r;
44460-
44461- /* looks like someone has already done a decision */
44462- if (con->mode == DIRECT &&
f673a614 44463+
2519e6e5
ER
44464+ /* looks like someone has already made a decision */
44465+ if (con->mode == DIRECT &&
44466 (con->http_status != 0 && con->http_status != 200)) {
44467 /* remove a packets in the queue */
44468 if (con->file_finished == 0) {
44469 chunkqueue_reset(con->write_queue);
44470 }
44471-
f673a614 44472+
2519e6e5
ER
44473 return HANDLER_FINISHED;
44474 }
44475-
f673a614 44476+
2519e6e5
ER
44477 /* no decision yet, build conf->filename */
44478 if (con->mode == DIRECT && con->physical.path->used == 0) {
44479 char *qstr;
f26f9fd5 44480
2519e6e5
ER
44481- /* we only come here when we have the parse the full request again
44482- *
44483- * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44484+ /* we only come here when we have to parse the full request again
44485+ *
44486+ * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44487 * problem here as mod_setenv might get called multiple times
44488 *
44489 * fastcgi-auth might lead to a COMEBACK too
44490 * fastcgi again dead server too
44491 *
44492 * mod_compress might add headers twice too
44493- *
44494+ *
44495 * */
44496-
f673a614 44497+
2519e6e5
ER
44498 if (con->conf.log_condition_handling) {
44499 log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
44500 }
44501 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
44502-
f673a614 44503+
2519e6e5
ER
44504 /**
44505 * prepare strings
44506- *
44507- * - uri.path_raw
44508+ *
44509+ * - uri.path_raw
44510 * - uri.path (secure)
44511 * - uri.query
44512- *
44513+ *
44514 */
44515-
44516- /**
f26f9fd5 44517+
2519e6e5
ER
44518+ /**
44519 * Name according to RFC 2396
44520- *
44521+ *
44522 * - scheme
44523 * - authority
44524 * - path
44525 * - query
44526- *
44527+ *
44528 * (scheme)://(authority)(path)?(query)
44529- *
44530- *
44531+ *
44532+ *
44533 */
44534-
f673a614 44535+
2519e6e5
ER
44536 buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
44537 buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
44538 buffer_to_lower(con->uri.authority);
44539-
44540+
44541 config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */
44542 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */
44543 config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
44544 config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */
44545 config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */
44546-
44547+
44548 /** extract query string from request.uri */
44549 if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
44550 buffer_copy_string (con->uri.query, qstr + 1);
44551@@ -200,22 +202,22 @@
44552 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path_raw);
44553 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-query : ", con->uri.query);
44554 }
44555-
44556+
44557 /* disable keep-alive if requested */
44558-
44559+
44560 if (con->request_count > con->conf.max_keep_alive_requests) {
44561 con->keep_alive = 0;
44562 }
44563-
44564-
44565+
44566+
44567 /**
44568- *
44569- * call plugins
44570- *
44571+ *
44572+ * call plugins
44573+ *
44574 * - based on the raw URL
44575- *
44576+ *
44577 */
44578-
44579+
44580 switch(r = plugins_call_handle_uri_raw(srv, con)) {
44581 case HANDLER_GO_ON:
44582 break;
44583@@ -229,14 +231,14 @@
f26f9fd5 44584 break;
f673a614 44585 }
f673a614 44586
2519e6e5
ER
44587- /* build filename
44588+ /* build filename
44589 *
44590 * - decode url-encodings (e.g. %20 -> ' ')
44591 * - remove path-modifiers (e.g. /../)
44592 */
44593-
44594-
44595-
f673a614 44596+
2519e6e5
ER
44597+
44598+
44599 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44600 con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44601 /* OPTIONS * ... */
44602@@ -253,15 +255,20 @@
44603 }
f26f9fd5 44604
2519e6e5
ER
44605 /**
44606- *
44607- * call plugins
44608- *
44609+ *
44610+ * call plugins
44611+ *
44612 * - based on the clean URL
44613- *
44614+ *
44615 */
44616-
f673a614 44617+
2519e6e5
ER
44618 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
44619-
f673a614 44620+
2519e6e5
ER
44621+ /* do we have to downgrade to 1.0 ? */
44622+ if (!con->conf.allow_http11) {
44623+ con->request.http_version = HTTP_VERSION_1_0;
44624+ }
f673a614 44625+
2519e6e5
ER
44626 switch(r = plugins_call_handle_uri_clean(srv, con)) {
44627 case HANDLER_GO_ON:
44628 break;
44629@@ -274,11 +281,11 @@
44630 log_error_write(srv, __FILE__, __LINE__, "");
44631 break;
44632 }
44633-
f673a614 44634+
2519e6e5
ER
44635 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44636 con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44637- /* option requests are handled directly without checking of the path */
44638-
44639+ /* option requests are handled directly without checking the path */
44640+
44641 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
44642
44643 con->http_status = 200;
44644@@ -288,46 +295,47 @@
44645 }
44646
44647 /***
44648- *
44649- * border
44650- *
44651+ *
44652+ * border
44653+ *
44654 * logical filename (URI) becomes a physical filename here
44655- *
44656- *
44657- *
44658+ *
44659+ *
44660+ *
44661 */
44662-
44663-
44664-
44665-
f673a614 44666+
f673a614 44667+
f673a614 44668+
f673a614 44669+
2519e6e5
ER
44670 /* 1. stat()
44671 * ... ISREG() -> ok, go on
44672 * ... ISDIR() -> index-file -> redirect
44673- *
44674- * 2. pathinfo()
44675+ *
44676+ * 2. pathinfo()
44677 * ... ISREG()
44678- *
44679+ *
44680 * 3. -> 404
44681- *
44682+ *
44683 */
44684-
f673a614 44685+
2519e6e5
ER
44686 /*
44687 * SEARCH DOCUMENT ROOT
44688 */
44689-
f673a614 44690+
2519e6e5
ER
44691 /* set a default */
44692-
f673a614 44693+
2519e6e5
ER
44694 buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
44695 buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
44696-
44697-#if defined(__WIN32) || defined(__CYGWIN__)
44698- /* strip dots from the end and spaces
f26f9fd5 44699+
2519e6e5
ER
44700+ filename_unix2local(con->physical.rel_path);
44701+#if defined(_WIN32) || defined(__CYGWIN__)
44702+ /* strip dots and spaces from the end
44703 *
44704 * windows/dos handle those filenames as the same file
44705 *
44706 * foo == foo. == foo..... == "foo... " == "foo.. ./"
44707 *
44708- * This will affect in some cases PATHINFO
44709+ * This will affect PATHINFO in some cases
44710 *
44711 * on native windows we could prepend the filename with \\?\ to circumvent
44712 * this behaviour. I have no idea how to push this through cygwin
44713@@ -377,36 +385,41 @@
44714 log_error_write(srv, __FILE__, __LINE__, "");
f26f9fd5 44715 break;
f673a614 44716 }
2519e6e5
ER
44717-
44718- /* MacOS X and Windows can't distiguish between upper and lower-case
44719- *
44720- * convert to lower-case
44721+
44722+ /* The default Mac OS X and Windows filesystems can't distiguish between
44723+ * upper- and lowercase, so convert to lowercase
44724 */
44725 if (con->conf.force_lowercase_filenames) {
44726 buffer_to_lower(con->physical.rel_path);
44727 }
44728
44729- /* the docroot plugins might set the servername, if they don't we take http-host */
44730+ /* the docroot plugins might set the servername; if they don't we take http-host */
44731 if (buffer_is_empty(con->server_name)) {
44732 buffer_copy_string_buffer(con->server_name, con->uri.authority);
44733 }
44734-
44735- /**
44736- * create physical filename
44737+
44738+ /**
44739+ * create physical filename
44740 * -> physical.path = docroot + rel_path
44741- *
44742+ *
44743 */
44744-
44745+
44746 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
44747- BUFFER_APPEND_SLASH(con->physical.path);
44748+ PATHNAME_APPEND_SLASH(con->physical.path);
44749 buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
44750 if (con->physical.rel_path->used &&
44751- con->physical.rel_path->ptr[0] == '/') {
44752+ con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
44753 buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
44754 } else {
44755 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
44756 }
44757
44758+ /* win32: directories can't have a trailing slash */
44759+ if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
44760+ con->physical.path->ptr[con->physical.path->used - 2] = '\0';
44761+ con->physical.path->used--;
44762+ }
44763+
44764 if (con->conf.log_request_handling) {
44765 log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root");
44766 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
44767@@ -426,7 +439,7 @@
44768 log_error_write(srv, __FILE__, __LINE__, "");
44769 break;
f673a614 44770 }
2519e6e5
ER
44771-
44772+
44773 if (con->conf.log_request_handling) {
44774 log_error_write(srv, __FILE__, __LINE__, "s", "-- logical -> physical");
44775 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
44776@@ -434,38 +447,38 @@
44777 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
f673a614
ER
44778 }
44779 }
2519e6e5
ER
44780-
44781- /*
44782- * Noone catched away the file from normal path of execution yet (like mod_access)
44783- *
f673a614 44784+
2519e6e5
ER
44785+ /*
44786+ * No one took the file away from the normal path of execution yet (like mod_access)
44787+ *
44788 * Go on and check of the file exists at all
44789 */
44790-
f673a614 44791+
2519e6e5
ER
44792 if (con->mode == DIRECT) {
44793 char *slash = NULL;
44794 char *pathinfo = NULL;
44795 int found = 0;
44796 stat_cache_entry *sce = NULL;
44797-
f673a614 44798+
2519e6e5
ER
44799 if (con->conf.log_request_handling) {
44800 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path");
44801 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44802 }
44803-
f673a614 44804+
2519e6e5
ER
44805 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
44806 /* file exists */
44807-
f673a614 44808+
2519e6e5
ER
44809 if (con->conf.log_request_handling) {
44810 log_error_write(srv, __FILE__, __LINE__, "s", "-- file found");
44811 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44812 }
44813-
f673a614 44814+
2519e6e5
ER
44815 if (S_ISDIR(sce->st.st_mode)) {
44816- if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
44817+ if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
44818 /* redirect to .../ */
44819-
f673a614 44820+
2519e6e5
ER
44821 http_response_redirect_to_directory(srv, con);
44822-
f673a614 44823+
2519e6e5
ER
44824 return HANDLER_FINISHED;
44825 }
44826 } else if (!S_ISREG(sce->st.st_mode)) {
44827@@ -477,12 +490,12 @@
44828 switch (errno) {
44829 case EACCES:
44830 con->http_status = 403;
44831-
f673a614 44832+
2519e6e5
ER
44833 if (con->conf.log_request_handling) {
44834 log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied");
44835 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44836 }
44837-
f673a614 44838+
2519e6e5
ER
44839 buffer_reset(con->physical.path);
44840 return HANDLER_FINISHED;
44841 case ENOENT:
44842@@ -499,77 +512,77 @@
44843 /* PATH_INFO ! :) */
44844 break;
44845 default:
44846- /* we have no idea what happend. let's tell the user so. */
44847+ /* we have no idea what happened, so tell the user. */
44848 con->http_status = 500;
44849 buffer_reset(con->physical.path);
44850-
f673a614 44851+
2519e6e5
ER
44852 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
44853 "file not found ... or so: ", strerror(errno),
44854 con->uri.path,
44855 "->", con->physical.path);
44856-
44857+
44858 return HANDLER_FINISHED;
f26f9fd5 44859 }
2519e6e5
ER
44860-
44861+
44862 /* not found, perhaps PATHINFO */
44863-
44864+
44865 buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
44866-
44867+
44868 do {
44869 struct stat st;
44870-
44871+
44872 if (slash) {
44873 buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
44874 } else {
44875 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
44876 }
44877-
44878+
44879 if (0 == stat(con->physical.path->ptr, &(st)) &&
44880 S_ISREG(st.st_mode)) {
44881 found = 1;
44882 break;
44883 }
44884-
44885+
44886 if (pathinfo != NULL) {
44887 *pathinfo = '\0';
44888 }
44889 slash = strrchr(srv->tmp_buf->ptr, '/');
44890-
44891+
44892 if (pathinfo != NULL) {
44893 /* restore '/' */
44894 *pathinfo = '/';
44895 }
44896-
44897+
44898 if (slash) pathinfo = slash;
44899 } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
44900-
44901+
44902 if (found == 0) {
44903- /* no it really doesn't exists */
44904+ /* no, it really doesn't exists */
44905 con->http_status = 404;
44906-
44907+
44908 if (con->conf.log_file_not_found) {
44909 log_error_write(srv, __FILE__, __LINE__, "sbsb",
44910 "file not found:", con->uri.path,
44911 "->", con->physical.path);
44912 }
44913-
44914+
44915 buffer_reset(con->physical.path);
44916-
44917+
44918 return HANDLER_FINISHED;
f26f9fd5 44919 }
2519e6e5
ER
44920-
44921+
44922 /* we have a PATHINFO */
44923 if (pathinfo) {
44924 buffer_copy_string(con->request.pathinfo, pathinfo);
44925-
44926+
44927 /*
44928 * shorten uri.path
44929 */
44930-
44931+
44932 con->uri.path->used -= strlen(pathinfo);
44933 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
f26f9fd5 44934 }
2519e6e5
ER
44935-
44936+
44937 if (con->conf.log_request_handling) {
44938 log_error_write(srv, __FILE__, __LINE__, "s", "-- after pathinfo check");
44939 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44940@@ -577,12 +590,12 @@
44941 log_error_write(srv, __FILE__, __LINE__, "sb", "Pathinfo :", con->request.pathinfo);
f673a614 44942 }
2519e6e5
ER
44943 }
44944-
44945+
44946 if (con->conf.log_request_handling) {
44947 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling subrequest");
44948 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44949 }
44950-
44951+
44952 /* call the handlers */
44953 switch(r = plugins_call_handle_subrequest_start(srv, con)) {
44954 case HANDLER_GO_ON:
44955@@ -593,32 +606,32 @@
44956 if (con->conf.log_request_handling) {
44957 log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished");
f26f9fd5 44958 }
2519e6e5
ER
44959-
44960- /* something strange happend */
44961+
44962+ /* something strange happened */
44963 return r;
44964 }
44965-
44966- /* if we are still here, no one wanted the file, status 403 is ok I think */
44967-
44968+
44969+ /* if we are still here, no one wanted the file; status 403 is ok I think */
44970+
44971 if (con->mode == DIRECT) {
44972 con->http_status = 403;
44973-
44974+
44975 return HANDLER_FINISHED;
44976 }
44977-
44978+
44979 }
44980-
44981+
44982 switch(r = plugins_call_handle_subrequest(srv, con)) {
44983 case HANDLER_GO_ON:
44984- /* request was not handled, looks like we are done */
44985+ /* request was not handled; looks like we are done */
44986 return HANDLER_FINISHED;
44987 case HANDLER_FINISHED:
44988 /* request is finished */
44989 default:
44990- /* something strange happend */
44991+ /* something strange happened */
44992 return r;
44993 }
44994-
44995+
44996 /* can't happen */
44997 return HANDLER_COMEBACK;
44998 }
1175ccec 44999--- ../lighttpd-1.4.11/src/server.c 2006-03-04 19:12:17.000000000 +0200
36e2a29e 45000+++ lighttpd-1.4.12/src/server.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
45001@@ -1,11 +1,9 @@
45002 #include <sys/types.h>
45003-#include <sys/time.h>
45004 #include <sys/stat.h>
f26f9fd5 45005
2519e6e5
ER
45006 #include <string.h>
45007 #include <errno.h>
45008 #include <fcntl.h>
45009-#include <unistd.h>
45010 #include <stdlib.h>
45011 #include <time.h>
45012 #include <signal.h>
45013@@ -29,9 +27,14 @@
45014 #include "plugin.h"
45015 #include "joblist.h"
45016 #include "network_backends.h"
45017-
45018+#ifdef _WIN32
45019+/* use local getopt implementation */
45020+# undef HAVE_GETOPT_H
45021+#endif
45022 #ifdef HAVE_GETOPT_H
45023 #include <getopt.h>
45024+#else
45025+#include "getopt.h"
45026 #endif
f673a614 45027
2519e6e5
ER
45028 #ifdef HAVE_VALGRIND_VALGRIND_H
45029@@ -60,8 +63,16 @@
45030 /* #define USE_ALARM */
f26f9fd5 45031 #endif
f26f9fd5 45032
2519e6e5
ER
45033+#ifdef _WIN32
45034+#undef HAVE_SIGNAL
45035+#endif
45036+
45037+#include "sys-files.h"
45038+#include "sys-process.h"
45039+
45040 static volatile sig_atomic_t srv_shutdown = 0;
45041 static volatile sig_atomic_t graceful_shutdown = 0;
45042+static volatile sig_atomic_t graceful_restart = 0;
45043 static volatile sig_atomic_t handle_sig_alarm = 1;
45044 static volatile sig_atomic_t handle_sig_hup = 0;
f673a614 45045
2519e6e5
ER
45046@@ -72,9 +83,9 @@
45047
45048 switch (sig) {
45049 case SIGTERM: srv_shutdown = 1; break;
45050- case SIGINT:
45051+ case SIGINT:
45052 if (graceful_shutdown) srv_shutdown = 1;
45053- else graceful_shutdown = 1;
45054+ else graceful_shutdown = 1;
45055
45056 break;
45057 case SIGALRM: handle_sig_alarm = 1; break;
45058@@ -86,9 +97,9 @@
45059 static void signal_handler(int sig) {
45060 switch (sig) {
45061 case SIGTERM: srv_shutdown = 1; break;
45062- case SIGINT:
45063+ case SIGINT:
45064 if (graceful_shutdown) srv_shutdown = 1;
45065- else graceful_shutdown = 1;
45066+ else graceful_shutdown = 1;
45067
45068 break;
45069 case SIGALRM: handle_sig_alarm = 1; break;
45070@@ -110,25 +121,26 @@
45071 signal(SIGTSTP, SIG_IGN);
f26f9fd5 45072 #endif
2519e6e5
ER
45073 if (0 != fork()) exit(0);
45074-
45075+
45076 if (-1 == setsid()) exit(0);
45077
45078 signal(SIGHUP, SIG_IGN);
45079
45080 if (0 != fork()) exit(0);
45081-
45082+
45083 if (0 != chdir("/")) exit(0);
45084 }
f26f9fd5 45085 #endif
f673a614 45086
2519e6e5
ER
45087 static server *server_init(void) {
45088 int i;
f673a614 45089-
f673a614 45090+
2519e6e5
ER
45091 server *srv = calloc(1, sizeof(*srv));
45092 assert(srv);
45093+ srv->max_fds = 1024;
45094 #define CLEAN(x) \
45095 srv->x = buffer_init();
45096-
f673a614 45097+
2519e6e5
ER
45098 CLEAN(response_header);
45099 CLEAN(parse_full_path);
45100 CLEAN(ts_debug_str);
45101@@ -138,7 +150,7 @@
45102 CLEAN(tmp_buf);
45103 srv->empty_string = buffer_init_string("");
45104 CLEAN(cond_check_buf);
45105-
f673a614 45106+
2519e6e5
ER
45107 CLEAN(srvconf.errorlog_file);
45108 CLEAN(srvconf.groupname);
45109 CLEAN(srvconf.username);
45110@@ -146,58 +158,58 @@
45111 CLEAN(srvconf.bindhost);
45112 CLEAN(srvconf.event_handler);
45113 CLEAN(srvconf.pid_file);
45114-
f673a614 45115+
2519e6e5
ER
45116 CLEAN(tmp_chunk_len);
45117 #undef CLEAN
45118-
f673a614 45119+
2519e6e5
ER
45120 #define CLEAN(x) \
45121 srv->x = array_init();
45122-
f673a614 45123+
2519e6e5
ER
45124 CLEAN(config_context);
45125 CLEAN(config_touched);
45126 CLEAN(status);
45127 #undef CLEAN
45128-
45129+
45130 for (i = 0; i < FILE_CACHE_MAX; i++) {
45131 srv->mtime_cache[i].str = buffer_init();
45132 }
45133-
45134+
45135 srv->cur_ts = time(NULL);
45136 srv->startup_ts = srv->cur_ts;
45137-
45138+
45139 srv->conns = calloc(1, sizeof(*srv->conns));
45140 assert(srv->conns);
45141-
45142+
45143 srv->joblist = calloc(1, sizeof(*srv->joblist));
45144 assert(srv->joblist);
45145-
45146+
45147 srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
45148 assert(srv->fdwaitqueue);
45149-
45150+
45151 srv->srvconf.modules = array_init();
45152 srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
45153 srv->srvconf.network_backend = buffer_init();
45154 srv->srvconf.upload_tempdirs = array_init();
45155-
45156+
45157 /* use syslog */
45158 srv->errorlog_fd = -1;
45159 srv->errorlog_mode = ERRORLOG_STDERR;
f26f9fd5 45160
2519e6e5
ER
45161 srv->split_vals = array_init();
45162-
45163+
45164 return srv;
45165 }
f26f9fd5 45166
2519e6e5
ER
45167 static void server_free(server *srv) {
45168 size_t i;
45169-
45170+
45171 for (i = 0; i < FILE_CACHE_MAX; i++) {
45172 buffer_free(srv->mtime_cache[i].str);
45173 }
45174-
45175+
45176 #define CLEAN(x) \
45177 buffer_free(srv->x);
45178-
45179+
45180 CLEAN(response_header);
45181 CLEAN(parse_full_path);
45182 CLEAN(ts_debug_str);
45183@@ -207,7 +219,7 @@
45184 CLEAN(tmp_buf);
45185 CLEAN(empty_string);
45186 CLEAN(cond_check_buf);
45187-
45188+
45189 CLEAN(srvconf.errorlog_file);
45190 CLEAN(srvconf.groupname);
45191 CLEAN(srvconf.username);
45192@@ -217,7 +229,7 @@
45193 CLEAN(srvconf.pid_file);
45194 CLEAN(srvconf.modules_dir);
45195 CLEAN(srvconf.network_backend);
45196-
45197+
45198 CLEAN(tmp_chunk_len);
45199 #undef CLEAN
f26f9fd5 45200
2519e6e5
ER
45201@@ -225,15 +237,15 @@
45202 fdevent_unregister(srv->ev, srv->fd);
45203 #endif
45204 fdevent_free(srv->ev);
45205-
45206+
45207 free(srv->conns);
45208-
45209+
45210 if (srv->config_storage) {
45211 for (i = 0; i < srv->config_context->used; i++) {
45212 specific_config *s = srv->config_storage[i];
f26f9fd5 45213
2519e6e5
ER
45214 if (!s) continue;
45215-
45216+
45217 buffer_free(s->document_root);
45218 buffer_free(s->server_name);
45219 buffer_free(s->server_tag);
45220@@ -242,32 +254,32 @@
45221 buffer_free(s->error_handler);
45222 buffer_free(s->errorfile_prefix);
45223 array_free(s->mimetypes);
45224-
45225+
45226 free(s);
f673a614 45227 }
2519e6e5
ER
45228 free(srv->config_storage);
45229 srv->config_storage = NULL;
45230 }
45231-
45232+
45233 #define CLEAN(x) \
45234 array_free(srv->x);
45235-
45236+
45237 CLEAN(config_context);
45238 CLEAN(config_touched);
45239 CLEAN(status);
45240 CLEAN(srvconf.upload_tempdirs);
45241 #undef CLEAN
45242-
45243+
45244 joblist_free(srv, srv->joblist);
45245 fdwaitqueue_free(srv, srv->fdwaitqueue);
45246-
45247+
45248 if (srv->stat_cache) {
45249 stat_cache_free(srv->stat_cache);
f673a614 45250 }
f673a614 45251
2519e6e5
ER
45252 array_free(srv->srvconf.modules);
45253 array_free(srv->split_vals);
45254-
45255+
45256 free(srv);
45257 }
45258
45259@@ -281,14 +293,12 @@
45260 " - a light and fast webserver\n" \
45261 "Build-Date: " __DATE__ " " __TIME__ "\n";
45262 ;
45263-#undef TEXT_SSL
45264+#undef TEXT_SSL
45265 write(STDOUT_FILENO, b, strlen(b));
f26f9fd5 45266 }
f673a614 45267
2519e6e5
ER
45268 static void show_features (void) {
45269- show_version();
45270- printf("\nEvent Handlers:\n\n%s",
45271-
45272+ const char *s = ""
45273 #ifdef USE_SELECT
45274 "\t+ select (generic)\n"
45275 #else
45276@@ -355,11 +365,6 @@
45277 #else
45278 "\t- crypt support\n"
f673a614 45279 #endif
2519e6e5
ER
45280-#ifdef USE_PAM
45281- "\t+ PAM support\n"
45282-#else
45283- "\t- PAM support\n"
45284-#endif
45285 #ifdef USE_OPENSSL
45286 "\t+ SSL Support\n"
45287 #else
45288@@ -371,9 +376,9 @@
45289 "\t- PCRE support\n"
f26f9fd5 45290 #endif
2519e6e5
ER
45291 #ifdef HAVE_MYSQL
45292- "\t+ mySQL support\n"
45293+ "\t+ MySQL support\n"
45294 #else
45295- "\t- mySQL support\n"
45296+ "\t- MySQL support\n"
f673a614 45297 #endif
2519e6e5
ER
45298 #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
45299 "\t+ LDAP support\n"
45300@@ -410,8 +415,11 @@
45301 #else
45302 "\t- GDBM support\n"
45303 #endif
45304- "\n"
45305- );
45306+ "\n";
f673a614 45307+
2519e6e5
ER
45308+ show_version();
45309+
45310+ printf("\nEvent Handlers:\n\n%s", s);
f26f9fd5 45311 }
f673a614 45312
2519e6e5
ER
45313 static void show_help (void) {
45314@@ -433,12 +441,12 @@
45315 " -h show this help\n" \
45316 "\n"
45317 ;
45318-#undef TEXT_SSL
45319+#undef TEXT_SSL
45320 #undef TEXT_IPV6
45321 write(STDOUT_FILENO, b, strlen(b));
45322 }
f673a614 45323
2519e6e5
ER
45324-int main (int argc, char **argv) {
45325+int main (int argc, char **argv, char **envp) {
45326 server *srv = NULL;
45327 int print_config = 0;
45328 int test_config = 0;
45329@@ -447,33 +455,37 @@
45330 int num_childs = 0;
45331 int pid_fd = -1, fd;
45332 size_t i;
f26f9fd5 45333+#ifdef _WIN32
2519e6e5 45334+ char *optarg = NULL;
f26f9fd5 45335+#endif
f673a614 45336+
2519e6e5
ER
45337 #ifdef HAVE_SIGACTION
45338 struct sigaction act;
f673a614 45339 #endif
2519e6e5
ER
45340 #ifdef HAVE_GETRLIMIT
45341 struct rlimit rlim;
f673a614 45342 #endif
2519e6e5 45343-
f673a614 45344+
2519e6e5
ER
45345 #ifdef USE_ALARM
45346 struct itimerval interval;
45347-
f673a614 45348+
2519e6e5
ER
45349 interval.it_interval.tv_sec = 1;
45350 interval.it_interval.tv_usec = 0;
45351 interval.it_value.tv_sec = 1;
45352 interval.it_value.tv_usec = 0;
45353 #endif
45354-
45355-
f673a614 45356+
f673a614 45357+
2519e6e5
ER
45358 /* for nice %b handling in strfime() */
45359 setlocale(LC_TIME, "C");
45360-
45361+
45362 if (NULL == (srv = server_init())) {
45363 fprintf(stderr, "did this really happen?\n");
45364 return -1;
f673a614 45365 }
2519e6e5 45366-
f673a614 45367+
2519e6e5
ER
45368 /* init structs done */
45369-
f673a614 45370+
2519e6e5
ER
45371 srv->srvconf.port = 0;
45372 #ifdef HAVE_GETUID
45373 i_am_root = (getuid() == 0);
45374@@ -481,14 +493,19 @@
45375 i_am_root = 0;
45376 #endif
45377 srv->srvconf.dont_daemonize = 0;
45378-
f673a614 45379+
2519e6e5
ER
45380 while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
45381 switch(o) {
45382- case 'f':
45383- if (config_read(srv, optarg)) {
45384+ case 'f':
45385+#ifdef _WIN32
45386+ /* evil HACK for windows, optarg is not set */
45387+ optarg = argv[optind-1];
45388+#endif
45389+ if (config_read(srv, optarg)) {
45390 server_free(srv);
45391 return -1;
45392 }
f673a614 45393+
2519e6e5
ER
45394 break;
45395 case 'm':
45396 buffer_copy_string(srv->srvconf.modules_dir, optarg);
45397@@ -497,23 +514,23 @@
45398 case 't': test_config = 1; break;
45399 case 'D': srv->srvconf.dont_daemonize = 1; break;
45400 case 'v': show_version(); return 0;
45401- case 'V': show_features(); return 0;
45402+ case 'V': show_features(); return 0;
45403 case 'h': show_help(); return 0;
45404- default:
45405+ default:
45406 show_help();
45407 server_free(srv);
45408 return -1;
45409 }
45410 }
45411-
f673a614 45412+
2519e6e5
ER
45413 if (!srv->config_storage) {
45414 log_error_write(srv, __FILE__, __LINE__, "s",
45415 "No configuration available. Try using -f option.");
45416-
f673a614 45417+
2519e6e5
ER
45418 server_free(srv);
45419 return -1;
45420 }
45421-
45422+
45423 if (print_config) {
45424 data_unset *dc = srv->config_context->data[0];
45425 if (dc) {
45426@@ -533,7 +550,7 @@
45427 server_free(srv);
45428 return 0;
45429 }
45430-
45431+
45432 /* close stdin and stdout, as they are not needed */
45433 /* move stdin to /dev/null */
45434 if (-1 != (fd = open("/dev/null", O_RDONLY))) {
45435@@ -541,54 +558,55 @@
45436 dup2(fd, STDIN_FILENO);
45437 close(fd);
45438 }
45439-
45440+
45441 /* move stdout to /dev/null */
45442 if (-1 != (fd = open("/dev/null", O_WRONLY))) {
45443 close(STDOUT_FILENO);
45444 dup2(fd, STDOUT_FILENO);
45445 close(fd);
45446 }
45447-
45448+
45449 if (0 != config_set_defaults(srv)) {
45450- log_error_write(srv, __FILE__, __LINE__, "s",
45451+ log_error_write(srv, __FILE__, __LINE__, "s",
45452 "setting default values failed");
45453 server_free(srv);
f26f9fd5
ER
45454 return -1;
45455 }
2519e6e5
ER
45456-
45457+
45458 /* UID handling */
45459 #ifdef HAVE_GETUID
45460 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
45461 /* we are setuid-root */
45462-
45463- log_error_write(srv, __FILE__, __LINE__, "s",
45464+
45465+ log_error_write(srv, __FILE__, __LINE__, "s",
45466 "Are you nuts ? Don't apply a SUID bit to this binary");
45467-
45468+
45469 server_free(srv);
f26f9fd5 45470 return -1;
f673a614 45471 }
2519e6e5
ER
45472 #endif
45473-
45474+
45475 /* check document-root */
45476 if (srv->config_storage[0]->document_root->used <= 1) {
45477- log_error_write(srv, __FILE__, __LINE__, "s",
45478+ log_error_write(srv, __FILE__, __LINE__, "s",
45479 "document-root is not set\n");
45480-
45481+
45482 server_free(srv);
45483-
45484+
45485 return -1;
f673a614 45486 }
2519e6e5
ER
45487-
45488+
45489 if (plugins_load(srv)) {
45490 log_error_write(srv, __FILE__, __LINE__, "s",
45491 "loading plugins finally failed");
45492-
45493+
45494 plugins_free(srv);
45495 server_free(srv);
45496-
45497+
45498 return -1;
f673a614 45499 }
2519e6e5
ER
45500-
45501+
45502+#ifndef _WIN32
45503 /* open pid file BEFORE chroot */
45504 if (srv->srvconf.pid_file->used) {
45505 if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
45506@@ -598,18 +616,18 @@
45507 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45508 return -1;
45509 }
45510-
45511+
45512 if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
45513 log_error_write(srv, __FILE__, __LINE__, "sbs",
45514 "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45515 }
45516-
45517+
45518 if (!S_ISREG(st.st_mode)) {
45519 log_error_write(srv, __FILE__, __LINE__, "sb",
45520 "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
45521 return -1;
45522 }
45523-
45524+
45525 if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
45526 log_error_write(srv, __FILE__, __LINE__, "sbs",
45527 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45528@@ -617,13 +635,14 @@
45529 }
45530 }
45531 }
45532-
45533+#endif
45534 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45535 /* select limits itself
45536 *
45537 * as it is a hard limit and will lead to a segfault we add some safety
45538 * */
45539- srv->max_fds = FD_SETSIZE - 200;
45540+ fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
45541+ srv->max_fds = FD_SETSIZE - 4;
45542 } else {
45543 srv->max_fds = 4096;
45544 }
45545@@ -636,7 +655,7 @@
45546 #ifdef HAVE_VALGRIND_VALGRIND_H
45547 if (RUNNING_ON_VALGRIND) use_rlimit = 0;
45548 #endif
45549-
45550+
45551 #ifdef HAVE_GETRLIMIT
45552 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
45553 log_error_write(srv, __FILE__, __LINE__,
45554@@ -644,13 +663,13 @@
45555 strerror(errno));
45556 return -1;
45557 }
45558-
45559+
45560 if (use_rlimit && srv->srvconf.max_fds) {
45561 /* set rlimits */
45562-
45563+
45564 rlim.rlim_cur = srv->srvconf.max_fds;
45565 rlim.rlim_max = srv->srvconf.max_fds;
45566-
45567+
45568 if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
45569 log_error_write(srv, __FILE__, __LINE__,
45570 "ss", "couldn't set 'max filedescriptors'",
45571@@ -659,7 +678,7 @@
45572 }
45573 }
f673a614 45574
2519e6e5
ER
45575- /* #372: solaris need some fds extra for devpoll */
45576+ /* #372: solaris need some fds extra for devpoll */
45577 if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
f673a614 45578
2519e6e5
ER
45579 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45580@@ -677,33 +696,33 @@
45581 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45582 /* don't raise the limit above FD_SET_SIZE */
45583 if (srv->max_fds > FD_SETSIZE - 200) {
45584- log_error_write(srv, __FILE__, __LINE__, "sd",
45585+ log_error_write(srv, __FILE__, __LINE__, "sd",
45586 "can't raise max filedescriptors above", FD_SETSIZE - 200,
45587 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45588 return -1;
45589 }
45590 }
f673a614 45591
2519e6e5
ER
45592-
45593+
45594 #ifdef HAVE_PWD_H
45595 /* set user and group */
45596 if (srv->srvconf.username->used) {
45597 if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
45598- log_error_write(srv, __FILE__, __LINE__, "sb",
45599+ log_error_write(srv, __FILE__, __LINE__, "sb",
45600 "can't find username", srv->srvconf.username);
45601 return -1;
45602 }
45603-
45604+
45605 if (pwd->pw_uid == 0) {
45606 log_error_write(srv, __FILE__, __LINE__, "s",
45607 "I will not set uid to 0\n");
45608 return -1;
45609 }
45610 }
45611-
45612+
45613 if (srv->srvconf.groupname->used) {
45614 if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
45615- log_error_write(srv, __FILE__, __LINE__, "sb",
45616+ log_error_write(srv, __FILE__, __LINE__, "sb",
45617 "can't find groupname", srv->srvconf.groupname);
45618 return -1;
45619 }
45620@@ -713,15 +732,15 @@
45621 return -1;
45622 }
45623 }
45624-#endif
45625+#endif
45626 /* we need root-perms for port < 1024 */
45627 if (0 != network_init(srv)) {
45628 plugins_free(srv);
45629 server_free(srv);
45630-
45631+
45632 return -1;
45633 }
45634-#ifdef HAVE_CHROOT
45635+#ifdef HAVE_CHROOT
45636 if (srv->srvconf.changeroot->used) {
45637 tzset();
f673a614 45638
2519e6e5
ER
45639@@ -761,7 +780,7 @@
45640 }
f26f9fd5 45641
2519e6e5
ER
45642 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45643- srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
45644+ srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
45645 } else {
45646 srv->max_fds = rlim.rlim_cur;
45647 }
45648@@ -775,18 +794,18 @@
45649 #endif
45650 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45651 /* don't raise the limit above FD_SET_SIZE */
45652- if (srv->max_fds > FD_SETSIZE - 200) {
45653- log_error_write(srv, __FILE__, __LINE__, "sd",
45654- "can't raise max filedescriptors above", FD_SETSIZE - 200,
45655+ if (srv->max_fds > FD_SETSIZE - 4) {
45656+ log_error_write(srv, __FILE__, __LINE__, "sd",
45657+ "can't raise max filedescriptors above", FD_SETSIZE - 4,
45658 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45659 return -1;
45660 }
45661 }
45662-
f673a614 45663+
2519e6e5
ER
45664 if (0 != network_init(srv)) {
45665 plugins_free(srv);
45666 server_free(srv);
45667-
45668+
45669 return -1;
45670 }
45671 }
45672@@ -802,25 +821,27 @@
45673 /* or use the default */
45674 srv->max_conns = srv->max_fds;
45675 }
45676-
45677+
45678 if (HANDLER_GO_ON != plugins_call_init(srv)) {
45679 log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
45680-
45681+
45682 plugins_free(srv);
45683 network_close(srv);
45684 server_free(srv);
45685-
45686+
45687 return -1;
45688 }
f673a614 45689
2519e6e5
ER
45690-#ifdef HAVE_FORK
45691+#ifdef HAVE_FORK
45692 /* network is up, let's deamonize ourself */
45693 if (srv->srvconf.dont_daemonize == 0) daemonize();
45694 #endif
f673a614 45695
2519e6e5
ER
45696+#ifdef HAVE_PWD_H
45697 srv->gid = getgid();
45698 srv->uid = getuid();
45699-
45700+#endif
45701+
45702 /* write pid file */
45703 if (pid_fd != -1) {
45704 buffer_copy_long(srv->tmp_buf, getpid());
45705@@ -829,17 +850,17 @@
45706 close(pid_fd);
45707 pid_fd = -1;
45708 }
45709-
45710+
45711 if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
45712 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
45713-
45714+
45715 plugins_free(srv);
45716 network_close(srv);
45717 server_free(srv);
45718-
45719+
45720 return -1;
45721 }
45722-
45723+
45724 /* dump unused config-keys */
45725 for (i = 0; i < srv->config_context->used; i++) {
45726 array *config = ((data_config *)srv->config_context->data[i])->value;
45727@@ -847,43 +868,42 @@
f673a614 45728
2519e6e5
ER
45729 for (j = 0; config && j < config->used; j++) {
45730 data_unset *du = config->data[j];
45731-
45732+
45733 /* all var.* is known as user defined variable */
45734 if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
45735 continue;
45736 }
f673a614 45737
2519e6e5
ER
45738 if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
45739- log_error_write(srv, __FILE__, __LINE__, "sbs",
45740+ log_error_write(srv, __FILE__, __LINE__, "sbs",
45741 "WARNING: unknown config-key:",
45742 du->key,
45743 "(ignored)");
45744 }
45745 }
45746 }
45747-
45748+
45749 if (srv->config_deprecated) {
45750- log_error_write(srv, __FILE__, __LINE__, "s",
45751+ log_error_write(srv, __FILE__, __LINE__, "s",
45752 "Configuration contains deprecated keys. Going down.");
45753-
45754+
45755 plugins_free(srv);
45756 network_close(srv);
45757 server_free(srv);
45758-
45759+
45760 return -1;
45761 }
45762-
45763+
45764 if (-1 == log_error_open(srv)) {
45765- log_error_write(srv, __FILE__, __LINE__, "s",
45766+ log_error_write(srv, __FILE__, __LINE__, "s",
45767 "opening errorlog failed, dying");
45768-
45769+
45770 plugins_free(srv);
45771 network_close(srv);
45772 server_free(srv);
45773 return -1;
45774 }
45775-
45776-
45777+
45778 #ifdef HAVE_SIGACTION
45779 memset(&act, 0, sizeof(act));
45780 act.sa_handler = SIG_IGN;
45781@@ -903,7 +923,7 @@
45782 sigaction(SIGHUP, &act, NULL);
45783 sigaction(SIGALRM, &act, NULL);
45784 sigaction(SIGCHLD, &act, NULL);
45785-
45786+
45787 #elif defined(HAVE_SIGNAL)
45788 /* ignore the SIGPIPE from sendfile() */
45789 signal(SIGPIPE, SIG_IGN);
45790@@ -914,20 +934,20 @@
45791 signal(SIGCHLD, signal_handler);
45792 signal(SIGINT, signal_handler);
45793 #endif
45794-
45795+
45796 #ifdef USE_ALARM
45797 signal(SIGALRM, signal_handler);
45798-
45799+
45800 /* setup periodic timer (1 second) */
45801 if (setitimer(ITIMER_REAL, &interval, NULL)) {
45802 log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
45803 return -1;
45804 }
45805-
45806+
45807 getitimer(ITIMER_REAL, &interval);
45808 #endif
f673a614 45809
2519e6e5
ER
45810-#ifdef HAVE_FORK
45811+#ifdef HAVE_FORK
45812 /* start watcher and workers */
45813 num_childs = srv->srvconf.max_worker;
45814 if (num_childs > 0) {
45815@@ -957,13 +977,13 @@
45816 }
45817 #endif
f26f9fd5 45818
2519e6e5
ER
45819- if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
45820+ if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
45821 log_error_write(srv, __FILE__, __LINE__,
45822 "s", "fdevent_init failed");
45823 return -1;
45824 }
45825- /*
45826- * kqueue() is called here, select resets its internals,
45827+ /*
45828+ * kqueue() is called here, select resets its internals,
45829 * all server sockets get their handlers
45830 *
45831 * */
45832@@ -971,7 +991,7 @@
45833 plugins_free(srv);
45834 network_close(srv);
45835 server_free(srv);
45836-
f673a614 45837+
2519e6e5
ER
45838 return -1;
45839 }
f673a614 45840
2519e6e5
ER
45841@@ -986,7 +1006,7 @@
45842 /* setup FAM */
45843 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
45844 if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
45845- log_error_write(srv, __FILE__, __LINE__, "s",
45846+ log_error_write(srv, __FILE__, __LINE__, "s",
45847 "could not open a fam connection, dieing.");
45848 return -1;
f26f9fd5 45849 }
2519e6e5
ER
45850@@ -1018,16 +1038,40 @@
45851 int n;
45852 size_t ndx;
45853 time_t min_ts;
45854-
45855+
45856 if (handle_sig_hup) {
45857 handler_t r;
45858-
45859+
45860 /* reset notification */
45861 handle_sig_hup = 0;
45862-
45863-
45864+
45865+#if 0
45866+ pid_t pid;
45867+
45868+ /* send the old process into a graceful-shutdown and start a
45869+ * new process right away
45870+ *
45871+ * BUGS:
45872+ * - if webserver is running on port < 1024 (e.g. 80, 433)
45873+ * we don't have the permissions to bind to that port anymore
45874+ *
45875+ *
45876+ * */
45877+ if (0 == (pid = fork())) {
45878+ execve(argv[0], argv, envp);
45879+
45880+ exit(-1);
45881+ } else if (pid == -1) {
45882+
45883+ } else {
45884+ /* parent */
45885+
45886+ graceful_shutdown = 1; /* shutdown without killing running connections */
45887+ graceful_restart = 1; /* don't delete pid file */
45888+ }
45889+#else
45890 /* cycle logfiles */
45891-
45892+
45893 switch(r = plugins_call_handle_sighup(srv)) {
45894 case HANDLER_GO_ON:
45895 break;
45896@@ -1035,30 +1079,31 @@
45897 log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
45898 break;
45899 }
45900-
45901+
45902 if (-1 == log_error_cycle(srv)) {
45903 log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
45904-
45905+
45906 return -1;
45907 }
45908+#endif
45909 }
45910-
45911+
45912 if (handle_sig_alarm) {
45913 /* a new second */
45914-
45915+
45916 #ifdef USE_ALARM
45917 /* reset notification */
45918 handle_sig_alarm = 0;
45919 #endif
45920-
45921+
45922 /* get current time */
45923 min_ts = time(NULL);
45924-
45925+
45926 if (min_ts != srv->cur_ts) {
45927 int cs = 0;
45928 connections *conns = srv->conns;
45929 handler_t r;
45930-
45931+
45932 switch(r = plugins_call_handle_trigger(srv)) {
45933 case HANDLER_GO_ON:
45934 break;
45935@@ -1069,21 +1114,21 @@
45936 log_error_write(srv, __FILE__, __LINE__, "d", r);
45937 break;
45938 }
45939-
45940+
45941 /* trigger waitpid */
45942 srv->cur_ts = min_ts;
45943-
45944- /* cleanup stat-cache */
45945+
45946+ /* cleanup stat-cache */
45947 stat_cache_trigger_cleanup(srv);
45948 /**
45949- * check all connections for timeouts
45950- *
45951+ * check all connections for timeouts
45952+ *
45953 */
45954 for (ndx = 0; ndx < conns->used; ndx++) {
45955 int changed = 0;
45956 connection *con;
45957 int t_diff;
45958-
45959+
45960 con = conns->ptr[ndx];
45961
45962 if (con->state == CON_STATE_READ ||
45963@@ -1092,7 +1137,7 @@
45964 if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
45965 /* time - out */
45966 #if 0
45967- log_error_write(srv, __FILE__, __LINE__, "sd",
45968+ log_error_write(srv, __FILE__, __LINE__, "sd",
45969 "connection closed - read-timeout:", con->fd);
45970 #endif
45971 connection_set_state(srv, con, CON_STATE_ERROR);
45972@@ -1102,7 +1147,7 @@
45973 if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
45974 /* time - out */
45975 #if 0
45976- log_error_write(srv, __FILE__, __LINE__, "sd",
45977+ log_error_write(srv, __FILE__, __LINE__, "sd",
45978 "connection closed - read-timeout:", con->fd);
45979 #endif
45980 connection_set_state(srv, con, CON_STATE_ERROR);
45981@@ -1110,20 +1155,20 @@
45982 }
45983 }
45984 }
45985-
45986+
45987 if ((con->state == CON_STATE_WRITE) &&
45988- (con->write_request_ts != 0)) {
45989+ (con->write_request_ts != 0)) {
45990 #if 0
45991 if (srv->cur_ts - con->write_request_ts > 60) {
45992- log_error_write(srv, __FILE__, __LINE__, "sdd",
45993+ log_error_write(srv, __FILE__, __LINE__, "sdd",
45994 "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
45995 }
45996 #endif
45997-
45998+
45999 if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
46000 /* time - out */
46001 #if 1
46002- log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46003+ log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46004 "NOTE: a request for",
46005 con->request.uri,
46006 "timed out after writing",
46007@@ -1138,35 +1183,35 @@
46008 }
46009 /* we don't like div by zero */
46010 if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
46011-
46012- if (con->traffic_limit_reached &&
46013- (con->conf.kbytes_per_second == 0 ||
46014+
46015+ if (con->traffic_limit_reached &&
46016+ (con->conf.kbytes_per_second == 0 ||
46017 ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
46018 /* enable connection again */
46019 con->traffic_limit_reached = 0;
46020-
46021+
46022 changed = 1;
46023 }
46024-
46025+
46026 if (changed) {
46027 connection_state_machine(srv, con);
46028 }
46029 con->bytes_written_cur_second = 0;
46030 *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
46031-
46032+
46033 #if 0
46034 if (cs == 0) {
46035 fprintf(stderr, "connection-state: ");
46036 cs = 1;
46037 }
46038-
46039+
46040 fprintf(stderr, "c[%d,%d]: %s ",
46041 con->fd,
46042 con->fcgi.fd,
46043 connection_get_state(con->state));
46044 #endif
46045 }
46046-
46047+
46048 if (cs == 1) fprintf(stderr, "\n");
46049 }
f26f9fd5 46050 }
2519e6e5
ER
46051@@ -1181,18 +1226,18 @@
46052 server_socket *srv_socket = srv->srv_sockets.ptr[i];
46053 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
46054 }
46055-
46056+
46057 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
46058-
46059+
46060 srv->sockets_disabled = 0;
46061 }
46062 } else {
46063 if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
46064 (srv->conns->used > srv->max_conns) || /* out of connections */
46065- (graceful_shutdown)) { /* graceful_shutdown */
46066+ (graceful_shutdown)) { /* graceful_shutdown */
f673a614 46067
2519e6e5
ER
46068 /* disable server-fds */
46069-
46070+
46071 for (i = 0; i < srv->srv_sockets.used; i++) {
46072 server_socket *srv_socket = srv->srv_sockets.ptr[i];
46073 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
46074@@ -1211,7 +1256,7 @@
46075 /* network_close() will cleanup after us */
46076 }
46077 }
46078-
46079+
46080 if (graceful_shutdown) {
46081 log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
46082 } else if (srv->conns->used > srv->max_conns) {
46083@@ -1219,7 +1264,7 @@
46084 } else {
46085 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
46086 }
46087-
46088+
46089 srv->sockets_disabled = 1;
46090 }
f26f9fd5 46091 }
2519e6e5
ER
46092@@ -1229,16 +1274,16 @@
46093 * we are ready to terminate without harming anyone */
46094 srv_shutdown = 1;
f673a614 46095 }
2519e6e5 46096-
f673a614 46097+
2519e6e5
ER
46098 /* we still have some fds to share */
46099- if (srv->want_fds) {
46100+ if (srv->want_fds) {
46101 /* check the fdwaitqueue for waiting fds */
46102 int free_fds = srv->max_fds - srv->cur_fds - 16;
46103 connection *con;
46104-
46105+
46106 for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
46107 connection_state_machine(srv, con);
46108-
46109+
46110 srv->want_fds--;
f26f9fd5 46111 }
2519e6e5
ER
46112 }
46113@@ -1249,27 +1294,27 @@
46114 int fd_ndx;
46115 #if 0
46116 if (n > 0) {
46117- log_error_write(srv, __FILE__, __LINE__, "sd",
46118+ log_error_write(srv, __FILE__, __LINE__, "sd",
46119 "polls:", n);
46120 }
46121-#endif
46122+#endif
46123 fd_ndx = -1;
46124 do {
46125 fdevent_handler handler;
46126 void *context;
46127 handler_t r;
46128-
46129+
46130 fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx);
46131 revents = fdevent_event_get_revent (srv->ev, fd_ndx);
46132 fd = fdevent_event_get_fd (srv->ev, fd_ndx);
46133 handler = fdevent_get_handler(srv->ev, fd);
46134 context = fdevent_get_context(srv->ev, fd);
46135-
46136+
46137 /* connection_handle_fdevent needs a joblist_append */
46138 #if 0
46139- log_error_write(srv, __FILE__, __LINE__, "sdd",
46140+ log_error_write(srv, __FILE__, __LINE__, "sdd",
46141 "event for", fd, revents);
46142-#endif
46143+#endif
46144 switch (r = (*handler)(srv, context, revents)) {
46145 case HANDLER_FINISHED:
46146 case HANDLER_GO_ON:
46147@@ -1286,17 +1331,17 @@
46148 }
46149 } while (--n > 0);
46150 } else if (n < 0 && errno != EINTR) {
46151- log_error_write(srv, __FILE__, __LINE__, "ss",
46152- "fdevent_poll failed:",
46153+ log_error_write(srv, __FILE__, __LINE__, "ss",
46154+ "fdevent_poll failed:",
46155 strerror(errno));
46156 }
46157-
46158+
46159 for (ndx = 0; ndx < srv->joblist->used; ndx++) {
46160 connection *con = srv->joblist->ptr[ndx];
46161 handler_t r;
46162-
46163+
46164 connection_state_machine(srv, con);
46165-
46166+
46167 switch(r = plugins_call_handle_joblist(srv, con)) {
46168 case HANDLER_FINISHED:
46169 case HANDLER_GO_ON:
46170@@ -1305,32 +1350,33 @@
46171 log_error_write(srv, __FILE__, __LINE__, "d", r);
f26f9fd5 46172 break;
f26f9fd5 46173 }
2519e6e5
ER
46174-
46175+
46176 con->in_joblist = 0;
f673a614 46177 }
2519e6e5
ER
46178-
46179+
46180 srv->joblist->used = 0;
f673a614 46181 }
2519e6e5
ER
46182-
46183- if (srv->srvconf.pid_file->used &&
46184+
46185+ if (0 == graceful_restart &&
46186+ srv->srvconf.pid_file->used &&
46187 srv->srvconf.changeroot->used == 0) {
46188 if (0 != unlink(srv->srvconf.pid_file->ptr)) {
46189 if (errno != EACCES && errno != EPERM) {
46190- log_error_write(srv, __FILE__, __LINE__, "sbds",
46191- "unlink failed for:",
46192+ log_error_write(srv, __FILE__, __LINE__, "sbds",
46193+ "unlink failed for:",
46194 srv->srvconf.pid_file,
46195 errno,
46196 strerror(errno));
46197 }
46198 }
46199 }
46200-
46201+
46202 /* clean-up */
46203 log_error_close(srv);
46204 network_close(srv);
46205 connections_free(srv);
46206 plugins_free(srv);
46207 server_free(srv);
46208-
46209+
46210 return 0;
46211 }
1175ccec 46212--- ../lighttpd-1.4.11/src/settings.h 2005-08-11 01:26:41.000000000 +0300
36e2a29e 46213+++ lighttpd-1.4.12/src/settings.h 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
46214@@ -9,24 +9,24 @@
46215 /**
46216 * max size of a buffer which will just be reset
46217 * to ->used = 0 instead of really freeing the buffer
46218- *
46219+ *
46220 * 64kB (no real reason, just a guess)
46221 */
46222 #define BUFFER_MAX_REUSE_SIZE (4 * 1024)
46223
46224 /**
46225 * max size of the HTTP request header
46226- *
46227+ *
46228 * 32k should be enough for everything (just a guess)
46229- *
46230+ *
46231 */
46232 #define MAX_HTTP_REQUEST_HEADER (32 * 1024)
46233
46234-typedef enum { HANDLER_UNSET,
46235- HANDLER_GO_ON,
46236+typedef enum { HANDLER_UNSET,
46237+ HANDLER_GO_ON,
46238 HANDLER_FINISHED,
46239- HANDLER_COMEBACK,
46240- HANDLER_WAIT_FOR_EVENT,
46241+ HANDLER_COMEBACK,
46242+ HANDLER_WAIT_FOR_EVENT,
46243 HANDLER_ERROR,
46244 HANDLER_WAIT_FOR_FD
46245 } handler_t;
1175ccec 46246--- ../lighttpd-1.4.11/src/spawn-fcgi.c 2006-03-07 14:18:10.000000000 +0200
36e2a29e 46247+++ lighttpd-1.4.12/src/spawn-fcgi.c 2006-07-11 22:07:53.000000000 +0300
2519e6e5 46248@@ -1,19 +1,16 @@
f26f9fd5
ER
46249 #include <sys/types.h>
46250-#include <sys/time.h>
46251 #include <sys/stat.h>
f673a614 46252
2519e6e5 46253 #include <stdlib.h>
f26f9fd5
ER
46254 #include <string.h>
46255 #include <errno.h>
2519e6e5 46256 #include <stdio.h>
f26f9fd5 46257-#include <unistd.h>
2519e6e5 46258 #include <fcntl.h>
f26f9fd5 46259-
2519e6e5
ER
46260+#include <time.h>
46261 #ifdef HAVE_CONFIG_H
46262 #include "config.h"
f673a614
ER
46263 #endif
46264
2519e6e5
ER
46265-
46266 #ifdef HAVE_PWD_H
46267 #include <grp.h>
46268 #include <pwd.h>
46269@@ -30,6 +27,7 @@
f673a614 46270 #endif
f673a614 46271
2519e6e5 46272 #include "sys-socket.h"
f26f9fd5 46273+#include "sys-files.h"
f673a614 46274
2519e6e5
ER
46275 #ifdef HAVE_SYS_WAIT_H
46276 #include <sys/wait.h>
46277@@ -45,28 +43,28 @@
46278 int fcgi_fd;
46279 int socket_type, status;
46280 struct timeval tv = { 0, 100 * 1000 };
46281-
46282+
46283 struct sockaddr_un fcgi_addr_un;
46284 struct sockaddr_in fcgi_addr_in;
46285 struct sockaddr *fcgi_addr;
46286-
46287+
46288 socklen_t servlen;
46289-
46290+
46291 if (child_count < 2) {
46292 child_count = 5;
46293 }
46294-
46295+
46296 if (child_count > 256) {
46297 child_count = 256;
46298 }
46299-
46300-
46301+
46302+
46303 if (unixsocket) {
46304 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
46305-
46306+
46307 fcgi_addr_un.sun_family = AF_UNIX;
46308 strcpy(fcgi_addr_un.sun_path, unixsocket);
46309-
46310+
46311 #ifdef SUN_LEN
46312 servlen = SUN_LEN(&fcgi_addr_un);
f26f9fd5 46313 #else
2519e6e5
ER
46314@@ -84,50 +82,50 @@
46315 }
46316 fcgi_addr_in.sin_port = htons(port);
46317 servlen = sizeof(fcgi_addr_in);
46318-
46319+
46320 socket_type = AF_INET;
46321 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
46322 }
46323-
f673a614 46324+
2519e6e5
ER
46325 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46326- fprintf(stderr, "%s.%d\n",
46327+ fprintf(stderr, "%s.%d\n",
46328 __FILE__, __LINE__);
46329 return -1;
46330 }
46331-
f26f9fd5 46332+
2519e6e5
ER
46333 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
46334 /* server is not up, spawn in */
46335 pid_t child;
46336 int val;
46337-
46338+
46339 if (unixsocket) unlink(unixsocket);
46340-
46341+
46342 close(fcgi_fd);
46343-
46344+
46345 /* reopen socket */
46346 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46347- fprintf(stderr, "%s.%d\n",
46348+ fprintf(stderr, "%s.%d\n",
46349 __FILE__, __LINE__);
46350 return -1;
46351 }
f673a614 46352
2519e6e5
ER
46353 val = 1;
46354 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
46355- fprintf(stderr, "%s.%d\n",
46356+ fprintf(stderr, "%s.%d\n",
46357 __FILE__, __LINE__);
46358 return -1;
46359 }
f673a614 46360
2519e6e5
ER
46361 /* create socket */
46362 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
46363- fprintf(stderr, "%s.%d: bind failed: %s\n",
46364+ fprintf(stderr, "%s.%d: bind failed: %s\n",
46365 __FILE__, __LINE__,
46366 strerror(errno));
46367 return -1;
46368 }
46369-
f673a614 46370+
2519e6e5
ER
46371 if (-1 == listen(fcgi_fd, 1024)) {
46372- fprintf(stderr, "%s.%d: fd = -1\n",
46373+ fprintf(stderr, "%s.%d: fd = -1\n",
46374 __FILE__, __LINE__);
46375 return -1;
46376 }
46377@@ -137,42 +135,45 @@
46378 } else {
46379 child = 0;
46380 }
46381-
46382+
46383 switch (child) {
46384 case 0: {
46385 char cgi_childs[64];
46386 char *b;
46387-
46388+
46389 int i = 0;
46390-
46391+
46392+ /* loose control terminal */
46393+ setsid();
46394+
46395 /* is save as we limit to 256 childs */
46396 sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
46397-
46398+
46399 if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
46400 close(FCGI_LISTENSOCK_FILENO);
46401 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
46402 close(fcgi_fd);
46403 }
46404-
46405+
46406 /* we don't need the client socket */
46407 for (i = 3; i < 256; i++) {
46408 close(i);
f26f9fd5 46409 }
2519e6e5
ER
46410-
46411+
46412 /* create environment */
46413-
46414+
46415 putenv(cgi_childs);
46416-
46417+
46418 /* fork and replace shell */
46419 b = malloc(strlen("exec ") + strlen(appPath) + 1);
46420 strcpy(b, "exec ");
46421 strcat(b, appPath);
46422-
46423+
46424 /* exec the cgi */
46425 execl("/bin/sh", "sh", "-c", b, NULL);
46426-
46427+
46428 exit(errno);
46429-
f673a614 46430+
f26f9fd5 46431 break;
2519e6e5
ER
46432 }
46433 case -1:
46434@@ -180,47 +181,47 @@
46435 break;
46436 default:
46437 /* father */
46438-
46439+
46440 /* wait */
46441 select(0, NULL, NULL, NULL, &tv);
46442-
46443+
46444 switch (waitpid(child, &status, WNOHANG)) {
46445 case 0:
46446- fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
46447+ fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
46448 __FILE__, __LINE__,
46449 child);
46450-
46451+
46452 /* write pid file */
46453 if (pid_fd != -1) {
46454 /* assume a 32bit pid_t */
46455 char pidbuf[12];
46456-
46457+
46458 snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
46459-
46460+
46461 write(pid_fd, pidbuf, strlen(pidbuf));
46462 close(pid_fd);
46463 pid_fd = -1;
46464 }
46465-
46466+
46467 break;
46468 case -1:
46469 break;
46470 default:
46471 if (WIFEXITED(status)) {
46472- fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
46473+ fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
46474 __FILE__, __LINE__,
46475 WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
46476 } else if (WIFSIGNALED(status)) {
46477- fprintf(stderr, "%s.%d: child signaled: %d\n",
46478+ fprintf(stderr, "%s.%d: child signaled: %d\n",
46479 __FILE__, __LINE__,
46480 WTERMSIG(status));
46481 } else {
46482- fprintf(stderr, "%s.%d: child died somehow: %d\n",
46483+ fprintf(stderr, "%s.%d: child died somehow: %d\n",
46484 __FILE__, __LINE__,
46485 status);
46486 }
f26f9fd5 46487 }
2519e6e5
ER
46488-
46489+
46490 break;
f26f9fd5 46491 }
f26f9fd5 46492 } else {
2519e6e5
ER
46493@@ -228,16 +229,16 @@
46494 __FILE__, __LINE__);
46495 return -1;
f26f9fd5 46496 }
2519e6e5
ER
46497-
46498+
46499 close(fcgi_fd);
46500-
46501+
46502 return 0;
46503 }
f673a614 46504
f673a614 46505
2519e6e5
ER
46506 void show_version () {
46507 char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
46508-" - spawns fastcgi processes\n"
46509+" - spawns fastcgi processes\n"
46510 ;
46511 write(1, b, strlen(b));
46512 }
46513@@ -265,7 +266,7 @@
46514
46515
46516 int main(int argc, char **argv) {
46517- char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
46518+ char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
46519 *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
46520 *addr = NULL;
46521 unsigned short port = 0;
46522@@ -273,9 +274,9 @@
46523 int i_am_root, o;
46524 int pid_fd = -1;
46525 int nofork = 0;
46526-
46527+
46528 i_am_root = (getuid() == 0);
46529-
46530+
46531 while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
46532 switch(o) {
46533 case 'f': fcgi_app = optarg; break;
46534@@ -290,137 +291,137 @@
46535 case 'P': pid_file = optarg; /* PID file */ break;
46536 case 'v': show_version(); return 0;
46537 case 'h': show_help(); return 0;
46538- default:
46539+ default:
46540 show_help();
46541 return -1;
46542 }
46543 }
46544-
46545+
46546 if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
46547 show_help();
46548 return -1;
46549 }
46550-
46551+
46552 if (unixsocket && port) {
46553- fprintf(stderr, "%s.%d: %s\n",
46554+ fprintf(stderr, "%s.%d: %s\n",
46555 __FILE__, __LINE__,
46556 "either a unix domain socket or a tcp-port, but not both\n");
46557-
46558+
f26f9fd5
ER
46559 return -1;
46560 }
f673a614 46561-
2519e6e5
ER
46562+
46563 if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) {
46564- fprintf(stderr, "%s.%d: %s\n",
46565+ fprintf(stderr, "%s.%d: %s\n",
46566 __FILE__, __LINE__,
46567 "path of the unix socket is too long\n");
46568-
46569+
46570 return -1;
f26f9fd5 46571 }
f26f9fd5 46572
2519e6e5
ER
46573 /* UID handling */
46574 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
46575 /* we are setuid-root */
46576-
46577- fprintf(stderr, "%s.%d: %s\n",
46578+
46579+ fprintf(stderr, "%s.%d: %s\n",
46580 __FILE__, __LINE__,
46581 "Are you nuts ? Don't apply a SUID bit to this binary\n");
46582-
46583+
f26f9fd5 46584 return -1;
2519e6e5
ER
46585 }
46586-
46587- if (pid_file &&
46588+
46589+ if (pid_file &&
46590 (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
46591 struct stat st;
46592 if (errno != EEXIST) {
46593- fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46594+ fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46595 __FILE__, __LINE__,
46596 pid_file, strerror(errno));
46597-
f673a614 46598+
2519e6e5
ER
46599 return -1;
46600 }
46601-
f673a614 46602+
2519e6e5
ER
46603 /* ok, file exists */
46604-
46605+
46606 if (0 != stat(pid_file, &st)) {
46607- fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
46608+ fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
46609 __FILE__, __LINE__,
46610 pid_file, strerror(errno));
46611-
46612+
46613 return -1;
46614 }
46615-
46616+
46617 /* is it a regular file ? */
46618-
46619+
46620 if (!S_ISREG(st.st_mode)) {
46621- fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
46622+ fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
46623 __FILE__, __LINE__,
46624 pid_file);
46625-
46626+
46627 return -1;
46628 }
46629-
46630+
46631 if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
46632- fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46633+ fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46634 __FILE__, __LINE__,
46635 pid_file, strerror(errno));
46636-
46637+
46638 return -1;
46639 }
46640 }
46641-
46642+
46643 if (i_am_root) {
46644 struct group *grp = NULL;
46645 struct passwd *pwd = NULL;
46646-
46647+
46648 /* set user and group */
46649-
46650+
46651 if (username) {
46652 if (NULL == (pwd = getpwnam(username))) {
46653- fprintf(stderr, "%s.%d: %s, %s\n",
46654+ fprintf(stderr, "%s.%d: %s, %s\n",
46655 __FILE__, __LINE__,
46656 "can't find username", username);
46657 return -1;
46658 }
46659-
46660+
46661 if (pwd->pw_uid == 0) {
46662- fprintf(stderr, "%s.%d: %s\n",
46663+ fprintf(stderr, "%s.%d: %s\n",
46664 __FILE__, __LINE__,
46665 "I will not set uid to 0\n");
46666 return -1;
46667 }
46668 }
46669-
46670+
46671 if (groupname) {
46672 if (NULL == (grp = getgrnam(groupname))) {
46673- fprintf(stderr, "%s.%d: %s %s\n",
46674+ fprintf(stderr, "%s.%d: %s %s\n",
46675 __FILE__, __LINE__,
46676- "can't find groupname",
46677+ "can't find groupname",
46678 groupname);
46679 return -1;
46680 }
46681 if (grp->gr_gid == 0) {
46682- fprintf(stderr, "%s.%d: %s\n",
46683+ fprintf(stderr, "%s.%d: %s\n",
46684 __FILE__, __LINE__,
46685 "I will not set gid to 0\n");
46686 return -1;
46687 }
46688 }
46689-
f673a614 46690+
2519e6e5
ER
46691 if (changeroot) {
46692 if (-1 == chroot(changeroot)) {
46693- fprintf(stderr, "%s.%d: %s %s\n",
46694+ fprintf(stderr, "%s.%d: %s %s\n",
46695 __FILE__, __LINE__,
46696 "chroot failed: ", strerror(errno));
46697 return -1;
46698 }
46699 if (-1 == chdir("/")) {
46700- fprintf(stderr, "%s.%d: %s %s\n",
46701+ fprintf(stderr, "%s.%d: %s %s\n",
46702 __FILE__, __LINE__,
46703 "chdir failed: ", strerror(errno));
f26f9fd5
ER
46704 return -1;
46705 }
f26f9fd5 46706 }
2519e6e5
ER
46707-
46708+
46709 /* drop root privs */
46710 if (groupname) {
46711 setgid(grp->gr_gid);
46712@@ -428,7 +429,7 @@
46713 }
46714 if (username) setuid(pwd->pw_uid);
f26f9fd5 46715 }
2519e6e5
ER
46716-
46717+
46718 return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
46719 }
46720 #else
1175ccec 46721--- ../lighttpd-1.4.11/src/splaytree.c 2005-09-12 21:51:28.000000000 +0300
36e2a29e 46722+++ lighttpd-1.4.12/src/splaytree.c 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
46723@@ -56,19 +56,19 @@
46724
46725 #define node_size splaytree_size
46726
46727-/* Splay using the key i (which may or may not be in the tree.)
46728- * The starting root is t, and the tree used is defined by rat
46729+/* Splay using the key i (which may or may not be in the tree.)
46730+ * The starting root is t, and the tree used is defined by rat
46731 * size fields are maintained */
46732 splay_tree * splaytree_splay (splay_tree *t, int i) {
46733 splay_tree N, *l, *r, *y;
46734 int comp, root_size, l_size, r_size;
46735-
46736+
46737 if (t == NULL) return t;
46738 N.left = N.right = NULL;
46739 l = r = &N;
46740 root_size = node_size(t);
46741 l_size = r_size = 0;
46742-
46743+
46744 for (;;) {
46745 comp = compare(i, t->key);
46746 if (comp < 0) {
46747@@ -120,7 +120,7 @@
46748 y->size = r_size;
46749 r_size -= 1+node_size(y->right);
46750 }
46751-
46752+
46753 l->right = t->left; /* assemble */
46754 r->left = t->right;
46755 t->left = N.right;
1175ccec 46756--- ../lighttpd-1.4.11/src/splaytree.h 2005-09-12 21:51:13.000000000 +0300
36e2a29e 46757+++ lighttpd-1.4.12/src/splaytree.h 2006-07-11 22:07:51.000000000 +0300
2519e6e5
ER
46758@@ -19,6 +19,6 @@
46759 /* This macro returns the size of a node. Unlike "x->size", */
46760 /* it works even if x=NULL. The test could be avoided by using */
46761 /* a special version of NULL which was a real node with size 0. */
46762-
46763+
f673a614 46764
f26f9fd5 46765 #endif
1175ccec
ER
46766--- ../lighttpd-1.4.11/src/stat_cache.c 2005-11-22 15:23:51.000000000 +0200
46767+++ lighttpd-1.4.12/src/stat_cache.c 2006-07-15 22:43:21.000000000 +0300
f26f9fd5
ER
46768@@ -6,7 +6,6 @@
46769 #include <stdlib.h>
46770 #include <string.h>
46771 #include <errno.h>
46772-#include <unistd.h>
46773 #include <stdio.h>
46774 #include <fcntl.h>
46775 #include <assert.h>
46776@@ -25,19 +24,8 @@
46777 #endif
f673a614 46778
f26f9fd5
ER
46779 #include "sys-mmap.h"
46780-
46781-/* NetBSD 1.3.x needs it */
46782-#ifndef MAP_FAILED
46783-# define MAP_FAILED -1
46784-#endif
46785-
46786-#ifndef O_LARGEFILE
46787-# define O_LARGEFILE 0
46788-#endif
46789-
46790-#ifndef HAVE_LSTAT
46791-#define lstat stat
46792-#endif
46793+#include "sys-files.h"
46794+#include "sys-strings.h"
f673a614 46795
2519e6e5
ER
46796 #if 0
46797 /* enables debug code for testing if all nodes in the stat-cache as accessable */
46798@@ -52,8 +40,8 @@
46799 *
46800 * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
46801 *
46802- * if the stat()-cache is queried we check if the version id for the directory is the
46803- * same and return immediatly.
46804+ * if the stat()-cache is queried we check if the version id for the directory is the
46805+ * same and return immediatly.
46806 *
46807 *
46808 * What we need:
46809@@ -62,17 +50,17 @@
46810 * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
46811 *
46812 * stat <<-> directory <-> FAMRequest
46813- *
46814- * if file is deleted, directory is dirty, file is rechecked ...
46815+ *
46816+ * if file is deleted, directory is dirty, file is rechecked ...
46817 * if directory is deleted, directory mapping is removed
46818- *
46819+ *
46820 * */
46821
46822 #ifdef HAVE_FAM_H
46823 typedef struct {
46824 FAMRequest *req;
46825 FAMConnection *fc;
46826-
46827+
46828 buffer *name;
46829
46830 int version;
46831@@ -83,16 +71,16 @@
46832 * - we need a hash
46833 * - the hash-key is used as sorting criteria for a tree
46834 * - a splay-tree is used as we can use the caching effect of it
46835- */
46836+ */
46837
46838 /* we want to cleanup the stat-cache every few seconds, let's say 10
46839 *
46840 * - remove entries which are outdated since 30s
46841 * - remove entries which are fresh but havn't been used since 60s
46842 * - if we don't have a stat-cache entry for a directory, release it from the monitor
46843- */
46844+ */
46845
46846-#ifdef DEBUG_STAT_CACHE
46847+#ifdef DEBUG_STAT_CACHE
46848 typedef struct {
46849 int *ptr;
46850
46851@@ -105,15 +93,15 @@
46852
46853 stat_cache *stat_cache_init(void) {
46854 stat_cache *fc = NULL;
46855-
46856+
46857 fc = calloc(1, sizeof(*fc));
46858-
46859+
46860 fc->dir_name = buffer_init();
46861 #ifdef HAVE_FAM_H
46862 fc->fam = calloc(1, sizeof(*fc->fam));
46863 #endif
46864
46865-#ifdef DEBUG_STAT_CACHE
46866+#ifdef DEBUG_STAT_CACHE
46867 ctrl.size = 0;
46868 #endif
46869
46870@@ -122,24 +110,24 @@
46871
46872 static stat_cache_entry * stat_cache_entry_init(void) {
46873 stat_cache_entry *sce = NULL;
46874-
46875+
46876 sce = calloc(1, sizeof(*sce));
46877-
46878+
46879 sce->name = buffer_init();
46880 sce->etag = buffer_init();
46881 sce->content_type = buffer_init();
46882-
46883+
46884 return sce;
46885 }
46886
46887 static void stat_cache_entry_free(void *data) {
46888 stat_cache_entry *sce = data;
46889 if (!sce) return;
46890-
46891+
46892 buffer_free(sce->etag);
46893 buffer_free(sce->name);
46894 buffer_free(sce->content_type);
46895-
46896+
46897 free(sce);
46898 }
46899
46900@@ -148,22 +136,22 @@
46901 fam_dir_entry *fam_dir = NULL;
46902
46903 fam_dir = calloc(1, sizeof(*fam_dir));
46904-
46905+
46906 fam_dir->name = buffer_init();
46907-
46908+
46909 return fam_dir;
46910 }
46911
46912 static void fam_dir_entry_free(void *data) {
46913 fam_dir_entry *fam_dir = data;
46914-
46915+
46916 if (!fam_dir) return;
46917-
46918+
46919 FAMCancelMonitor(fam_dir->fc, fam_dir->req);
46920-
46921+
46922 buffer_free(fam_dir->name);
46923 free(fam_dir->req);
46924-
46925+
46926 free(fam_dir);
46927 }
46928 #endif
46929@@ -174,7 +162,7 @@
46930 splay_tree *node = sc->files;
46931
46932 osize = sc->files->size;
46933-
46934+
46935 stat_cache_entry_free(node->data);
46936 sc->files = splaytree_delete(sc->files, node->key);
46937
46938@@ -187,12 +175,12 @@
46939 while (sc->dirs) {
46940 int osize;
46941 splay_tree *node = sc->dirs;
46942-
46943+
46944 osize = sc->dirs->size;
46945
46946 fam_dir_entry_free(node->data);
46947 sc->dirs = splaytree_delete(sc->dirs, node->key);
46948-
46949+
46950 if (osize == 1) {
46951 assert(NULL == sc->dirs);
46952 } else {
46953@@ -212,7 +200,7 @@
46954 static int stat_cache_attr_get(buffer *buf, char *name) {
46955 int attrlen;
46956 int ret;
46957-
46958+
46959 attrlen = 1024;
46960 buffer_prepare_copy(buf, attrlen);
46961 attrlen--;
46962@@ -251,15 +239,15 @@
46963 sc->fam) {
46964
46965 events = FAMPending(sc->fam);
46966-
46967+
46968 for (i = 0; i < events; i++) {
46969 FAMEvent fe;
46970 fam_dir_entry *fam_dir;
46971 splay_tree *node;
46972 int ndx;
46973-
46974+
46975 FAMNextEvent(sc->fam, &fe);
46976-
46977+
46978 /* handle event */
46979
46980 switch(fe.code) {
46981@@ -280,7 +268,7 @@
46982
46983 sc->dirs = splaytree_splay(sc->dirs, ndx);
46984 node = sc->dirs;
46985-
46986+
46987 if (node && (node->key == ndx)) {
46988 int osize = splaytree_size(sc->dirs);
46989
46990@@ -308,7 +296,7 @@
46991
46992 sc->fam = NULL;
46993 }
46994-
46995+
46996 return HANDLER_GO_ON;
46997 }
46998
46999@@ -332,7 +320,7 @@
47000 *
47001 *
47002 *
47003- * returns:
47004+ * returns:
47005 * - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
47006 * - HANDLER_ERROR on stat() failed -> see errno for problem
47007 */
47008@@ -348,16 +336,16 @@
47009 struct stat st;
47010 size_t k;
47011 int fd;
47012-#ifdef DEBUG_STAT_CACHE
47013+#ifdef DEBUG_STAT_CACHE
47014 size_t i;
47015 #endif
47016
47017 int file_ndx;
47018 splay_tree *file_node = NULL;
47019
47020- *ret_sce = NULL;
47021+ *ret_sce = NULL;
47022
47023- /*
47024+ /*
47025 * check if the directory for this file has changed
47026 */
47027
47028@@ -366,23 +354,23 @@
47029 file_ndx = hashme(name);
47030 sc->files = splaytree_splay(sc->files, file_ndx);
47031
47032-#ifdef DEBUG_STAT_CACHE
47033+#ifdef DEBUG_STAT_CACHE
47034 for (i = 0; i < ctrl.used; i++) {
47035 if (ctrl.ptr[i] == file_ndx) break;
47036 }
47037 #endif
47038
47039 if (sc->files && (sc->files->key == file_ndx)) {
47040-#ifdef DEBUG_STAT_CACHE
47041+#ifdef DEBUG_STAT_CACHE
47042 /* it was in the cache */
47043 assert(i < ctrl.used);
47044 #endif
47045-
47046- /* we have seen this file already and
47047+
47048+ /* we have seen this file already and
47049 * don't stat() it again in the same second */
47050
47051 file_node = sc->files;
47052-
47053+
47054 sce = file_node->data;
47055
47056 /* check if the name is the same, we might have a collision */
47057@@ -390,7 +378,7 @@
47058 if (buffer_is_equal(name, sce->name)) {
47059 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
47060 if (sce->stat_ts == srv->cur_ts) {
47061- *ret_sce = sce;
47062+ *ret_sce = sce;
47063 return HANDLER_GO_ON;
47064 }
47065 }
47066@@ -400,15 +388,15 @@
47067 * file_node is used by the FAM check below to see if we know this file
47068 * and if we can save a stat().
47069 *
47070- * BUT, the sce is not reset here as the entry into the cache is ok, we
47071+ * BUT, the sce is not reset here as the entry into the cache is ok, we
47072 * it is just not pointing to our requested file.
47073- *
47074+ *
47075 * */
47076
47077 file_node = NULL;
47078 }
47079 } else {
47080-#ifdef DEBUG_STAT_CACHE
47081+#ifdef DEBUG_STAT_CACHE
47082 if (i != ctrl.used) {
47083 fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr);
47084 }
47085@@ -424,23 +412,23 @@
47086 }
47087
47088 dir_ndx = hashme(sc->dir_name);
47089-
47090+
47091 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
47092-
47093+
47094 if (sc->dirs && (sc->dirs->key == dir_ndx)) {
47095 dir_node = sc->dirs;
47096 }
47097-
47098+
47099 if (dir_node && file_node) {
47100 /* we found a file */
47101-
47102+
47103 sce = file_node->data;
47104 fam_dir = dir_node->data;
47105-
47106+
47107 if (fam_dir->version == sce->dir_version) {
47108 /* the stat()-cache entry is still ok */
47109-
47110- *ret_sce = sce;
47111+
47112+ *ret_sce = sce;
47113 return HANDLER_GO_ON;
47114 }
47115 }
47116@@ -448,7 +436,7 @@
47117 #endif
47118
47119 /*
47120- * *lol*
47121+ * *lol*
47122 * - open() + fstat() on a named-pipe results in a (intended) hang.
47123 * - stat() if regualar file + open() to see if we can read from it is better
47124 *
47125@@ -469,16 +457,16 @@
47126
47127 if (NULL == sce) {
47128 int osize = 0;
47129-
47130+
47131 if (sc->files) {
47132 osize = sc->files->size;
47133 }
47134
47135 sce = stat_cache_entry_init();
47136 buffer_copy_string_buffer(sce->name, name);
47137-
47138- sc->files = splaytree_insert(sc->files, file_ndx, sce);
47139-#ifdef DEBUG_STAT_CACHE
47140+
47141+ sc->files = splaytree_insert(sc->files, file_ndx, sce);
47142+#ifdef DEBUG_STAT_CACHE
47143 if (ctrl.size == 0) {
47144 ctrl.size = 16;
47145 ctrl.used = 0;
47146@@ -499,29 +487,29 @@
47147 sce->st = st;
47148 sce->stat_ts = srv->cur_ts;
47149
47150- /* catch the obvious symlinks
47151+ /* catch the obvious symlinks
47152 *
47153 * this is not a secure check as we still have a race-condition between
47154- * the stat() and the open. We can only solve this by
47155+ * the stat() and the open. We can only solve this by
47156 * 1. open() the file
47157 * 2. fstat() the fd
47158 *
47159 * and keeping the file open for the rest of the time. But this can
47160 * only be done at network level.
47161- *
47162+ *
47163 * */
47164 if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
47165 return HANDLER_ERROR;
47166 }
47167
47168- if (S_ISREG(st.st_mode)) {
47169+ if (S_ISREG(st.st_mode)) {
47170 /* determine mimetype */
47171 buffer_reset(sce->content_type);
47172-
47173+
47174 for (k = 0; k < con->conf.mimetypes->used; k++) {
47175 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
47176 buffer *type = ds->key;
47177-
47178+
47179 if (type->used == 0) continue;
47180
47181 /* check if the right side is the same */
1175ccec
ER
47182@@ -538,8 +526,10 @@
47183 stat_cache_attr_get(sce->content_type, name->ptr);
2519e6e5
ER
47184 }
47185 #endif
1175ccec
ER
47186+ } else if (S_ISDIR(st.st_mode)) {
47187+ etag_create(sce->etag, &(sce->st));
2519e6e5
ER
47188 }
47189-
47190+
47191 #ifdef HAVE_FAM_H
47192 if (sc->fam &&
47193 (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
1175ccec 47194@@ -549,19 +539,19 @@
2519e6e5
ER
47195 fam_dir->fc = sc->fam;
47196
47197 buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
47198-
47199+
47200 fam_dir->version = 1;
47201-
47202+
47203 fam_dir->req = calloc(1, sizeof(FAMRequest));
47204-
47205- if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47206+
47207+ if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47208 fam_dir->req, fam_dir)) {
47209-
47210- log_error_write(srv, __FILE__, __LINE__, "sbs",
47211- "monitoring dir failed:",
47212- fam_dir->name,
47213+
47214+ log_error_write(srv, __FILE__, __LINE__, "sbs",
47215+ "monitoring dir failed:",
47216+ fam_dir->name,
47217 FamErrlist[FAMErrno]);
47218-
47219+
47220 fam_dir_entry_free(fam_dir);
47221 } else {
47222 int osize = 0;
1175ccec 47223@@ -570,7 +560,7 @@
2519e6e5
ER
47224 osize = sc->dirs->size;
47225 }
47226
47227- sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47228+ sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47229 assert(sc->dirs);
47230 assert(sc->dirs->data == fam_dir);
47231 assert(osize == (sc->dirs->size - 1));
1175ccec 47232@@ -578,9 +568,9 @@
2519e6e5
ER
47233 } else {
47234 fam_dir = dir_node->data;
47235 }
47236-
47237+
47238 /* bind the fam_fc to the stat() cache entry */
47239-
47240+
47241 if (fam_dir) {
47242 sce->dir_version = fam_dir->version;
47243 sce->dir_ndx = dir_ndx;
1175ccec 47244@@ -594,11 +584,11 @@
2519e6e5
ER
47245 }
47246
47247 /**
47248- * remove stat() from cache which havn't been stat()ed for
47249+ * remove stat() from cache which havn't been stat()ed for
47250 * more than 10 seconds
47251- *
47252 *
47253- * walk though the stat-cache, collect the ids which are too old
47254+ *
47255+ * walk though the stat-cache, collect the ids which are too old
47256 * and remove them in a second loop
47257 */
47258
1175ccec 47259@@ -639,9 +629,9 @@
2519e6e5
ER
47260 sc->files = splaytree_splay(sc->files, ndx);
47261
47262 node = sc->files;
47263-
47264+
47265 if (node && (node->key == ndx)) {
47266-#ifdef DEBUG_STAT_CACHE
47267+#ifdef DEBUG_STAT_CACHE
47268 size_t j;
47269 int osize = splaytree_size(sc->files);
47270 stat_cache_entry *sce = node->data;
1175ccec 47271@@ -649,7 +639,7 @@
2519e6e5
ER
47272 stat_cache_entry_free(node->data);
47273 sc->files = splaytree_delete(sc->files, ndx);
47274
47275-#ifdef DEBUG_STAT_CACHE
47276+#ifdef DEBUG_STAT_CACHE
47277 for (j = 0; j < ctrl.used; j++) {
47278 if (ctrl.ptr[j] == ndx) {
47279 ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
1175ccec 47280--- ../lighttpd-1.4.11/src/stream.c 2005-09-23 21:50:15.000000000 +0300
36e2a29e 47281+++ lighttpd-1.4.12/src/stream.c 2006-07-11 22:07:53.000000000 +0300
f26f9fd5
ER
47282@@ -1,7 +1,6 @@
47283 #include <sys/types.h>
47284 #include <sys/stat.h>
f673a614 47285
f26f9fd5
ER
47286-#include <unistd.h>
47287 #include <fcntl.h>
47288
47289 #include "stream.h"
47290@@ -10,6 +9,7 @@
f673a614 47291 #endif
f26f9fd5
ER
47292
47293 #include "sys-mmap.h"
47294+#include "sys-files.h"
47295
47296 #ifndef O_BINARY
47297 # define O_BINARY 0
2519e6e5 47298@@ -19,39 +19,39 @@
f26f9fd5
ER
47299 struct stat st;
47300 #ifdef HAVE_MMAP
47301 int fd;
47302-#elif defined __WIN32
f673a614 47303+#elif defined _WIN32
f26f9fd5
ER
47304 HANDLE *fh, *mh;
47305 void *p;
f673a614 47306 #endif
2519e6e5
ER
47307
47308 f->start = NULL;
47309-
47310+
47311 if (-1 == stat(fn->ptr, &st)) {
47312 return -1;
47313 }
47314-
47315+
47316 f->size = st.st_size;
47317
47318 #ifdef HAVE_MMAP
47319 if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
47320 return -1;
47321 }
47322-
47323+
47324 f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
47325-
47326+
47327 close(fd);
47328-
47329+
47330 if (MAP_FAILED == f->start) {
f26f9fd5
ER
47331 return -1;
47332 }
f673a614 47333
f26f9fd5 47334-#elif defined __WIN32
2519e6e5
ER
47335- fh = CreateFile(fn->ptr,
47336- GENERIC_READ,
47337- FILE_SHARE_READ,
47338- NULL,
47339- OPEN_EXISTING,
47340- FILE_ATTRIBUTE_READONLY,
f26f9fd5 47341+#elif defined _WIN32
2519e6e5
ER
47342+ fh = CreateFile(fn->ptr,
47343+ GENERIC_READ,
47344+ FILE_SHARE_READ,
47345+ NULL,
47346+ OPEN_EXISTING,
47347+ FILE_ATTRIBUTE_READONLY,
47348 NULL);
47349
47350 if (!fh) return -1;
47351@@ -66,7 +66,7 @@
47352 if (!mh) {
47353 LPVOID lpMsgBuf;
47354 FormatMessage(
47355- FORMAT_MESSAGE_ALLOCATE_BUFFER |
47356+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
47357 FORMAT_MESSAGE_FROM_SYSTEM,
47358 NULL,
47359 GetLastError(),
47360@@ -76,7 +76,7 @@
47361
47362 return -1;
47363 }
47364-
47365+
47366 p = MapViewOfFile(mh,
47367 FILE_MAP_READ,
47368 0,
47369@@ -87,9 +87,9 @@
47370
47371 f->start = p;
47372 #else
47373-# error no mmap found
47374+# error no mmap found
47375 #endif
47376-
47377+
47378 return 0;
47379 }
47380
1175ccec 47381--- ../lighttpd-1.4.11/src/sys-files.h 1970-01-01 03:00:00.000000000 +0300
36e2a29e
ER
47382+++ lighttpd-1.4.12/src/sys-files.h 2006-07-11 22:07:53.000000000 +0300
47383@@ -0,0 +1,67 @@
47384+#ifndef _SYS_FILES_H_
47385+#define _SYS_FILES_H_
47386+
47387+#define DIR_SEPERATOR_UNIX '/'
47388+#define DIR_SEPERATOR_WIN '\\'
47389+
47390+#ifdef _WIN32
47391+#include <windows.h>
47392+#include <io.h> /* open */
47393+#include <direct.h> /* chdir */
47394+
47395+#include "buffer.h"
47396+
47397+#define DIR_SEPERATOR DIR_SEPERATOR_WIN
47398+
47399+#define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
47400+
47401+#define S_ISDIR(mode) __S_ISTYPE((mode), _S_IFDIR)
47402+#define S_ISCHR(mode) __S_ISTYPE((mode), _S_IFCHR)
47403+#define S_ISBLK(mode) __S_ISTYPE((mode), _S_IFBLK)
47404+#define S_ISREG(mode) __S_ISTYPE((mode), _S_IFREG)
47405+/* we don't support symlinks */
47406+#define S_ISLNK(mode) 0
47407+
47408+#define lstat stat
47409+#define mkstemp mktemp
47410+#define mkdir(x, y) mkdir(x)
47411+
47412+struct dirent {
47413+ const char *d_name;
47414+};
47415+
47416+typedef struct {
47417+ HANDLE h;
47418+ WIN32_FIND_DATA finddata;
47419+ struct dirent dent;
47420+} DIR;
47421+
47422+DIR *opendir(const char *dn);
47423+struct dirent *readdir(DIR *d);
47424+void closedir(DIR *d);
47425+
47426+buffer *filename_unix2local(buffer *b);
47427+buffer *pathname_unix2local(buffer *b);
47428+
47429+#else
47430+#include <unistd.h>
47431+#include <dirent.h>
47432+
47433+#define DIR_SEPERATOR DIR_SEPERATOR_UNIX
47434+
47435+#define filename_unix2local(x) (x)
47436+#define pathname_unix2local(x) (x)
47437+#endif
47438+
47439+#define PATHNAME_APPEND_SLASH(x) \
47440+ if (x->used > 1 && x->ptr[x->used - 2] != DIR_SEPERATOR) { \
47441+ char sl[2] = { DIR_SEPERATOR, 0 }; \
47442+ BUFFER_APPEND_STRING_CONST(x, sl); \
47443+ }
47444+
47445+#ifndef O_LARGEFILE
47446+# define O_LARGEFILE 0
47447+#endif
47448+
47449+#endif
47450+
1175ccec 47451--- ../lighttpd-1.4.11/src/sys-mmap.h 2005-08-11 01:26:34.000000000 +0300
36e2a29e 47452+++ lighttpd-1.4.12/src/sys-mmap.h 2006-07-11 22:07:52.000000000 +0300
f26f9fd5
ER
47453@@ -1,7 +1,7 @@
47454 #ifndef WIN32_MMAP_H
47455 #define WIN32_MMAP_H
f673a614 47456
f26f9fd5
ER
47457-#ifdef __WIN32
47458+#ifdef _WIN32
f673a614 47459
f26f9fd5
ER
47460 #define MAP_FAILED -1
47461 #define PROT_SHARED 0
1175ccec
ER
47462--- ../lighttpd-1.4.11/src/sys-process.h 1970-01-01 03:00:00.000000000 +0300
47463+++ lighttpd-1.4.12/src/sys-process.h 2006-07-15 22:43:21.000000000 +0300
47464@@ -0,0 +1,17 @@
36e2a29e
ER
47465+#ifndef _SYS_PROCESS_H_
47466+#define _SYS_PROCESS_H_
47467+
47468+#ifdef _WIN32
47469+#include <process.h>
47470+#define pid_t int
47471+/* win32 has no fork() */
47472+#define kill(x, y)
1175ccec 47473+#define getpid() 0
36e2a29e
ER
47474+
47475+#else
47476+#include <sys/wait.h>
47477+#include <unistd.h>
47478+#endif
47479+
47480+#endif
47481+
1175ccec
ER
47482--- ../lighttpd-1.4.11/src/sys-socket.h 2005-08-11 01:26:39.000000000 +0300
47483+++ lighttpd-1.4.12/src/sys-socket.h 2006-07-15 22:43:21.000000000 +0300
f26f9fd5
ER
47484@@ -1,15 +1,26 @@
47485 #ifndef WIN32_SOCKET_H
47486 #define WIN32_SOCKET_H
f673a614 47487
f26f9fd5
ER
47488-#ifdef __WIN32
47489+#ifdef _WIN32
f673a614 47490
f26f9fd5 47491 #include <winsock2.h>
f673a614 47492
f26f9fd5
ER
47493 #define ECONNRESET WSAECONNRESET
47494 #define EINPROGRESS WSAEINPROGRESS
47495 #define EALREADY WSAEALREADY
47496+#define ENOTCONN WSAENOTCONN
47497+#define EWOULDBLOCK WSAEWOULDBLOCK
47498 #define ioctl ioctlsocket
47499 #define hstrerror(x) ""
47500+#define STDIN_FILENO 0
47501+#define STDOUT_FILENO 1
47502+#define STDERR_FILENO 2
47503+#define ssize_t int
47504+
47505+int inet_aton(const char *cp, struct in_addr *inp);
47506+#define HAVE_INET_ADDR
47507+#undef HAVE_INET_ATON
47508+
47509 #else
47510 #include <sys/socket.h>
47511 #include <sys/ioctl.h>
1175ccec 47512@@ -18,7 +29,23 @@
f26f9fd5
ER
47513 #include <sys/un.h>
47514 #include <arpa/inet.h>
f673a614 47515
f26f9fd5
ER
47516+#ifndef SUN_LEN
47517+#define SUN_LEN(su) \
47518+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
47519+#endif
47520+
47521 #include <netdb.h>
47522 #endif
f673a614 47523
1175ccec
ER
47524+typedef union {
47525+#ifdef HAVE_IPV6
47526+ struct sockaddr_in6 ipv6;
47527+#endif
47528+ struct sockaddr_in ipv4;
47529+#ifdef HAVE_SYS_UN_H
47530+ struct sockaddr_un un;
47531+#endif
47532+ struct sockaddr plain;
47533+} sock_addr;
47534+
47535 #endif
47536--- ../lighttpd-1.4.11/src/sys-strings.h 1970-01-01 03:00:00.000000000 +0300
36e2a29e
ER
47537+++ lighttpd-1.4.12/src/sys-strings.h 2006-07-11 22:07:51.000000000 +0300
47538@@ -0,0 +1,11 @@
47539+#ifndef _SYS_STRINGS_H_
47540+#define _SYS_STRINGS_H_
47541+
47542+#ifdef _WIN32
47543+#define strcasecmp stricmp
47544+#define strncasecmp strnicmp
47545+#define strtoll(p, e, b) _strtoi64(p, e, b)
47546+#endif
47547+
47548+#endif
47549+
1175ccec 47550--- ../lighttpd-1.4.11/tests/LightyTest.pm 2006-01-14 20:32:31.000000000 +0200
36e2a29e 47551+++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-11 22:07:53.000000000 +0300
f26f9fd5
ER
47552@@ -87,14 +87,14 @@
47553 # pre-process configfile if necessary
47554 #
f673a614 47555
f26f9fd5
ER
47556- unlink($self->{TESTDIR}."/tmp/cfg.file");
47557- system("cat ".$self->{SRCDIR}."/".$self->{CONFIGFILE}.' | perl -pe "s#\@SRCDIR\@#'.$self->{BASEDIR}.'/tests/#" > '.$self->{TESTDIR}.'/tmp/cfg.file');
47558+ $ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
47559+ $ENV{'PORT'} = $self->{PORT};
f673a614 47560
f26f9fd5
ER
47561 unlink($self->{LIGHTTPD_PIDFILE});
47562 if (1) {
47563- system($self->{LIGHTTPD_PATH}." -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH});
47564+ system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH});
47565 } else {
47566- system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=foo ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH}." &");
47567+ system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=foo ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
47568 }
f673a614 47569
f26f9fd5
ER
47570 select(undef, undef, undef, 0.1);
47571@@ -184,7 +184,7 @@
47572 (my $h = $1) =~ tr/[A-Z]/[a-z]/;
f673a614 47573
f26f9fd5
ER
47574 if (defined $resp_hdr{$h}) {
47575- diag(sprintf("header %s is duplicated: %s and %s\n",
47576+ diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
47577 $h, $resp_hdr{$h}, $2));
47578 } else {
47579 $resp_hdr{$h} = $2;
47580@@ -196,6 +196,9 @@
47581 }
47582 }
f673a614 47583
f26f9fd5
ER
47584+ $t->{etag} = $resp_hdr{'etag'};
47585+ $t->{date} = $resp_hdr{'date'};
47586+
47587 # check length
47588 if (defined $resp_hdr{"content-length"}) {
47589 $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
1175ccec
ER
47590--- ../lighttpd-1.4.11/tests/Makefile.am 2005-09-16 15:48:40.000000000 +0300
47591+++ lighttpd-1.4.12/tests/Makefile.am 2006-07-15 22:43:22.000000000 +0300
47592@@ -39,10 +39,18 @@
f26f9fd5
ER
47593 mod-redirect.t \
47594 mod-userdir.t \
47595 mod-rewrite.t \
47596+ mod-proxy.t \
47597 request.t \
47598 mod-ssi.t \
47599 LightyTest.pm \
47600- mod-setenv.t
47601+ mod-setenv.t \
47602+ lowercase.t \
47603+ lowercase.conf \
47604+ proxy.conf \
1175ccec
ER
47605+ cachable.t \
47606+ default.conf \
47607+ proxy-backend-1.conf \
47608+ proxy-backend-2.conf
f673a614 47609
f673a614 47610
f26f9fd5 47611 TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
1175ccec 47612--- ../lighttpd-1.4.11/tests/bug-06.conf 2005-08-27 17:44:19.000000000 +0300
36e2a29e 47613+++ lighttpd-1.4.12/tests/bug-06.conf 2006-07-11 22:07:53.000000000 +0300
f26f9fd5 47614@@ -1,5 +1,5 @@
f673a614
ER
47615-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47616-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47617+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47618+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47619
47620 ## bind to port (default: 80)
47621 server.port = 2048
f26f9fd5 47622@@ -8,7 +8,7 @@
f673a614
ER
47623
47624 ## bind to localhost (default: all interfaces)
47625 server.bind = "localhost"
47626-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47627+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47628 server.name = "www.example.org"
47629 server.tag = "Apache 1.3.29"
47630
f26f9fd5 47631@@ -59,7 +59,7 @@
f673a614
ER
47632 ######################## MODULE CONFIG ############################
47633
47634
47635-accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47636+accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47637
47638 mimetype.assign = ( ".png" => "image/png",
47639 ".jpg" => "image/jpeg",
f26f9fd5 47640@@ -77,7 +77,7 @@
f673a614
ER
47641 ".c" => "text/plain",
47642 ".conf" => "text/plain" )
47643
47644-compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47645+compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47646 compress.filetype = ("text/plain", "text/html")
47647
f26f9fd5
ER
47648 setenv.add-environment = ( "TRAC_ENV" => "foo")
47649@@ -90,7 +90,7 @@
47650 "host" => "127.0.0.1",
47651 "port" => 1026,
47652 # "mode" => "authorizer",
47653-# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47654+# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47655 )
47656 )
47657 )
47658@@ -106,7 +106,7 @@
f673a614
ER
47659 ssl.pemfile = "server.pem"
47660
47661 auth.backend = "plain"
47662-auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47663+auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47664 auth.backend.plain.groupfile = "lighttpd.group"
47665
47666 auth.backend.ldap.hostname = "localhost"
f26f9fd5 47667@@ -149,15 +149,15 @@
f673a614
ER
47668 status.config-url = "/server-config"
47669
f26f9fd5
ER
47670 simple-vhost.document-root = "pages"
47671-simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
47672+simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
47673 simple-vhost.default-host = "www.example.org"
47674
f673a614
ER
47675 $HTTP["host"] == "vvv.example.org" {
47676- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47677+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47678 }
47679
47680 $HTTP["host"] == "zzz.example.org" {
47681- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47682+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47683 server.name = "zzz.example.org"
47684 }
47685
1175ccec 47686--- ../lighttpd-1.4.11/tests/bug-12.conf 2005-08-27 17:44:19.000000000 +0300
36e2a29e 47687+++ lighttpd-1.4.12/tests/bug-12.conf 2006-07-11 22:07:53.000000000 +0300
f673a614
ER
47688@@ -1,5 +1,5 @@
47689-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47690-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47691+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47692+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47693
47694 ## bind to port (default: 80)
47695 server.port = 2048
47696@@ -8,7 +8,7 @@
47697
47698 ## bind to localhost (default: all interfaces)
47699 server.bind = "localhost"
47700-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47701+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47702 server.name = "www.example.org"
47703 server.tag = "Apache 1.3.29"
47704
f26f9fd5 47705@@ -61,7 +61,7 @@
f673a614
ER
47706 ######################## MODULE CONFIG ############################
47707
47708
47709-accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47710+accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47711
47712 mimetype.assign = ( ".png" => "image/png",
47713 ".jpg" => "image/jpeg",
f26f9fd5 47714@@ -79,7 +79,7 @@
f673a614
ER
47715 ".c" => "text/plain",
47716 ".conf" => "text/plain" )
47717
47718-compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47719+compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47720 compress.filetype = ("text/plain", "text/html")
47721
47722 setenv.add-environment = ( "TRAC_ENV" => "foo")
f26f9fd5 47723@@ -92,7 +92,7 @@
f673a614
ER
47724 "host" => "127.0.0.1",
47725 "port" => 1026,
47726 # "mode" => "authorizer",
47727-# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47728+# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47729 )
47730 )
47731 )
f26f9fd5 47732@@ -108,7 +108,7 @@
f673a614
ER
47733 ssl.pemfile = "server.pem"
47734
47735 auth.backend = "plain"
47736-auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47737+auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47738 auth.backend.plain.groupfile = "lighttpd.group"
47739
47740 auth.backend.ldap.hostname = "localhost"
f26f9fd5 47741@@ -151,15 +151,15 @@
f673a614
ER
47742 status.config-url = "/server-config"
47743
47744 simple-vhost.document-root = "pages"
47745-simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
47746+simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
47747 simple-vhost.default-host = "www.example.org"
47748
47749 $HTTP["host"] == "vvv.example.org" {
47750- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47751+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47752 }
47753
47754 $HTTP["host"] == "zzz.example.org" {
47755- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47756+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47757 server.name = "zzz.example.org"
47758 }
47759
1175ccec 47760--- ../lighttpd-1.4.11/tests/cachable.t 1970-01-01 03:00:00.000000000 +0300
36e2a29e 47761+++ lighttpd-1.4.12/tests/cachable.t 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
47762@@ -0,0 +1,112 @@
47763+#!/usr/bin/env perl
47764+BEGIN {
47765+ # add current source dir to the include-path
47766+ # we need this for make distcheck
47767+ (my $srcdir = $0) =~ s#/[^/]+$#/#;
47768+ unshift @INC, $srcdir;
47769+}
47770+
47771+use strict;
47772+use IO::Socket;
47773+use Test::More tests => 12;
47774+use LightyTest;
47775+
47776+my $tf = LightyTest->new();
47777+my $t;
47778+
47779+$tf->{CONFIGFILE} = 'lighttpd.conf';
47780+
47781+ok($tf->start_proc == 0, "Starting lighttpd") or die();
47782+
47783+## check if If-Modified-Since, If-None-Match works
47784+
47785+$t->{REQUEST} = ( <<EOF
47786+GET / HTTP/1.0
47787+If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
47788+EOF
47789+ );
47790+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47791+ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
47792+
47793+$t->{REQUEST} = ( <<EOF
47794+GET / HTTP/1.0
47795+If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47796+EOF
47797+ );
47798+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47799+ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
47800+
47801+my $now = $t->{date};
47802+
47803+$t->{REQUEST} = ( <<EOF
47804+GET / HTTP/1.0
47805+If-Modified-Since: $now
47806+EOF
47807+ );
47808+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47809+ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
47810+
47811+$t->{REQUEST} = ( <<EOF
47812+GET / HTTP/1.0
47813+If-Modified-Since: $now; foo
47814+EOF
47815+ );
47816+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47817+ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
47818+
47819+$t->{REQUEST} = ( <<EOF
47820+GET / HTTP/1.0
47821+If-None-Match: foo
47822+EOF
47823+ );
47824+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47825+ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47826+
47827+my $etag = $t->{etag};
47828+
47829+$t->{REQUEST} = ( <<EOF
47830+GET / HTTP/1.0
47831+If-None-Match: $etag
47832+EOF
47833+ );
47834+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47835+ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47836+
47837+$t->{REQUEST} = ( <<EOF
47838+GET / HTTP/1.0
47839+If-None-Match: $etag
47840+If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47841+EOF
47842+ );
47843+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47844+ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
47845+
47846+$t->{REQUEST} = ( <<EOF
47847+GET / HTTP/1.0
47848+If-None-Match: $etag
47849+If-Modified-Since: $now; foo
47850+EOF
47851+ );
47852+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47853+ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
47854+
47855+$t->{REQUEST} = ( <<EOF
47856+GET / HTTP/1.0
47857+If-None-Match: Foo
47858+If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47859+EOF
47860+ );
47861+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47862+ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
47863+
47864+$t->{REQUEST} = ( <<EOF
47865+GET / HTTP/1.0
47866+If-None-Match: $etag
47867+If-Modified-Since: $now foo
47868+EOF
47869+ );
47870+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
47871+ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
47872+
47873+ok($tf->stop_proc == 0, "Stopping lighttpd");
47874+
1175ccec 47875--- ../lighttpd-1.4.11/tests/condition.conf 2005-08-27 17:44:19.000000000 +0300
36e2a29e 47876+++ lighttpd-1.4.12/tests/condition.conf 2006-07-11 22:07:53.000000000 +0300
f673a614
ER
47877@@ -2,15 +2,15 @@
47878 debug.log-request-handling = "enable"
47879 debug.log-condition-handling = "enable"
47880
47881-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47882-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47883+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47884+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47885
47886 ## bind to port (default: 80)
47887 server.port = 2048
47888
47889 ## bind to localhost (default: all interfaces)
47890 server.bind = "localhost"
47891-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47892+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47893 server.name = "www.example.org"
47894 server.tag = "Apache 1.3.29"
47895
47896@@ -22,25 +22,25 @@
47897 ######################## MODULE CONFIG ############################
47898
47899
47900-accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47901+accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47902
47903 mimetype.assign = ( ".html" => "text/html" )
47904
47905 url.redirect = ("^" => "/default")
47906
47907 $HTTP["host"] == "www.example.org" {
47908- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47909+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47910 server.name = "www.example.org"
47911 url.redirect = ("^" => "/match_1")
47912 }
47913 else $HTTP["host"] == "test1.example.org" {
47914- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47915+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47916 server.name = "test1.example.org"
47917 url.redirect = ("^" => "/match_2")
47918 }
47919 # comments
47920 else $HTTP["host"] == "test2.example.org" {
47921- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47922+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47923 server.name = "test2.example.org"
47924 url.redirect = ("^" => "/match_3")
47925 }
47926@@ -48,7 +48,7 @@
47927 # comments
47928
47929 else $HTTP["host"] == "test3.example.org" {
47930- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47931+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47932 server.name = "test3.example.org"
47933 url.redirect = ("^" => "/match_4")
47934
1175ccec 47935--- ../lighttpd-1.4.11/tests/core-keepalive.t 2005-11-17 15:54:19.000000000 +0200
36e2a29e 47936+++ lighttpd-1.4.12/tests/core-keepalive.t 2006-07-11 22:07:53.000000000 +0300
f26f9fd5
ER
47937@@ -40,7 +40,7 @@
47938
47939 GET /12345.txt HTTP/1.0
47940 Host: 123.example.org
47941-Connection: keep-alive
47942+Connection: close
47943 EOF
47944 );
47945 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
1175ccec
ER
47946--- ../lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries 2006-03-09 19:21:49.000000000 +0200
47947+++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries 2006-07-15 22:43:22.000000000 +0300
f26f9fd5
ER
47948@@ -9,5 +9,6 @@
47949 last-author="jan"
47950 kind="dir"
47951 uuid="152afb58-edef-0310-8abb-c4023f1b3aa9"
47952- revision="1040"/>
47953+ repos="svn://svn.lighttpd.net/lighttpd"
1175ccec 47954+ revision="1173"/>
f26f9fd5 47955 </wc-entries>
1175ccec 47956--- ../lighttpd-1.4.11/tests/fastcgi-10.conf 2005-08-31 23:36:34.000000000 +0300
36e2a29e 47957+++ lighttpd-1.4.12/tests/fastcgi-10.conf 2006-07-11 22:07:53.000000000 +0300
f26f9fd5 47958@@ -1,12 +1,12 @@
f673a614
ER
47959-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47960-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47961+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47962+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47963
f26f9fd5
ER
47964 ## bind to port (default: 80)
47965 server.port = 2048
f673a614
ER
47966
47967 ## bind to localhost (default: all interfaces)
47968 server.bind = "localhost"
47969-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47970+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47971 server.name = "www.example.org"
47972 server.tag = "Apache 1.3.29"
47973
f26f9fd5 47974@@ -44,7 +44,7 @@
f673a614
ER
47975 ######################## MODULE CONFIG ############################
47976
47977
47978-accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47979+accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47980
47981 mimetype.assign = ( ".png" => "image/png",
47982 ".jpg" => "image/jpeg",
f26f9fd5 47983@@ -62,7 +62,7 @@
f673a614
ER
47984 ".c" => "text/plain",
47985 ".conf" => "text/plain" )
47986
47987-compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47988+compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47989 compress.filetype = ("text/plain", "text/html")
47990
47991 fastcgi.debug = 0
f26f9fd5 47992@@ -85,7 +85,7 @@
f673a614
ER
47993 ssl.pemfile = "server.pem"
47994
47995 auth.backend = "plain"
47996-auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47997+auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47998 auth.backend.plain.groupfile = "lighttpd.group"
47999
48000 auth.backend.ldap.hostname = "localhost"
f26f9fd5 48001@@ -128,11 +128,11 @@
f673a614
ER
48002 status.config-url = "/server-config"
48003
48004 $HTTP["host"] == "vvv.example.org" {
48005- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48006+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48007 }
48008
48009 $HTTP["host"] == "zzz.example.org" {
48010- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48011+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48012 server.name = "zzz.example.org"
48013 }
48014
1175ccec 48015--- ../lighttpd-1.4.11/tests/fastcgi-13.conf 2006-01-03 12:38:17.000000000 +0200
36e2a29e 48016+++ lighttpd-1.4.12/tests/fastcgi-13.conf 2006-07-11 22:07:53.000000000 +0300
f26f9fd5 48017@@ -1,5 +1,5 @@
f673a614
ER
48018-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48019-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48020+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48021+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
f673a614 48022
f26f9fd5
ER
48023 debug.log-request-header = "enable"
48024 debug.log-response-header = "enable"
48025@@ -10,7 +10,7 @@
f673a614 48026
f26f9fd5
ER
48027 ## bind to localhost (default: all interfaces)
48028 server.bind = "localhost"
f673a614 48029-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
f26f9fd5
ER
48030+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48031 server.name = "www.example.org"
48032 server.tag = "Apache 1.3.29"
48033
48034@@ -59,7 +59,7 @@
48035 ######################## MODULE CONFIG ############################
48036
f673a614 48037
f673a614 48038-accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
f26f9fd5 48039+accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
f673a614 48040
f26f9fd5
ER
48041 mimetype.assign = ( ".png" => "image/png",
48042 ".jpg" => "image/jpeg",
48043@@ -77,7 +77,7 @@
48044 ".c" => "text/plain",
48045 ".conf" => "text/plain" )
48046
48047-compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48048+compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48049 compress.filetype = ("text/plain", "text/html")
48050
48051 fastcgi.debug = 0
48052@@ -102,7 +102,7 @@
48053 ssl.pemfile = "server.pem"
48054
48055 auth.backend = "plain"
48056-auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48057+auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48058 auth.backend.plain.groupfile = "lighttpd.group"
48059
48060 auth.backend.ldap.hostname = "localhost"
48061@@ -145,11 +145,11 @@
48062 status.config-url = "/server-config"
f673a614 48063
f673a614
ER
48064 $HTTP["host"] == "vvv.example.org" {
48065- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48066+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
f673a614
ER
48067 }
48068
48069 $HTTP["host"] == "zzz.example.org" {
48070- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48071+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48072 server.name = "zzz.example.org"
48073 }
48074
1175ccec 48075--- ../lighttpd-1.4.11/tests/fastcgi-auth.conf 2005-08-27 17:44:19.000000000 +0300
36e2a29e 48076+++ lighttpd-1.4.12/tests/fastcgi-auth.conf 2006-07-11 22:07:53.000000000 +0300
f673a614
ER
48077@@ -1,5 +1,5 @@
48078-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48079-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48080+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48081+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48082
f26f9fd5
ER
48083 debug.log-request-header = "enable"
48084 debug.log-response-header = "enable"
48085@@ -12,7 +12,7 @@
f673a614
ER
48086
48087 ## bind to localhost (default: all interfaces)
48088 server.bind = "localhost"
48089-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48090+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48091 server.name = "www.example.org"
48092 server.tag = "Apache 1.3.29"
48093
f26f9fd5 48094@@ -61,7 +61,7 @@
f673a614
ER
48095 ######################## MODULE CONFIG ############################
48096
48097
48098-accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48099+accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48100
48101 mimetype.assign = ( ".png" => "image/png",
48102 ".jpg" => "image/jpeg",
f26f9fd5 48103@@ -79,7 +79,7 @@
f673a614
ER
48104 ".c" => "text/plain",
48105 ".conf" => "text/plain" )
48106
48107-compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48108+compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48109 compress.filetype = ("text/plain", "text/html")
48110
48111 fastcgi.debug = 0
f26f9fd5 48112@@ -87,9 +87,9 @@
f673a614
ER
48113 "grisu" => (
48114 "host" => "127.0.0.1",
f26f9fd5
ER
48115 "port" => 20000,
48116- "bin-path" => "@SRCDIR@/fcgi-auth",
48117+ "bin-path" => env.SRCDIR + "/fcgi-auth",
48118 "mode" => "authorizer",
48119- "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
48120+ "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
48121
f673a614
ER
48122 )
48123 )
f26f9fd5 48124@@ -106,7 +106,7 @@
f673a614
ER
48125 ssl.pemfile = "server.pem"
48126
48127 auth.backend = "plain"
48128-auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48129+auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48130 auth.backend.plain.groupfile = "lighttpd.group"
48131
48132 auth.backend.ldap.hostname = "localhost"
f26f9fd5 48133@@ -149,11 +149,11 @@
f673a614
ER
48134 status.config-url = "/server-config"
48135
48136 $HTTP["host"] == "vvv.example.org" {
48137- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48138+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48139 }
48140
48141 $HTTP["host"] == "zzz.example.org" {
48142- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48143+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48144 server.name = "zzz.example.org"
48145 }
48146
1175ccec 48147--- ../lighttpd-1.4.11/tests/fastcgi-responder.conf 2005-08-27 17:44:19.000000000 +0300
36e2a29e 48148+++ lighttpd-1.4.12/tests/fastcgi-responder.conf 2006-07-11 22:07:53.000000000 +0300
f673a614
ER
48149@@ -1,5 +1,5 @@
48150-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48151-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48152+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48153+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48154
f26f9fd5
ER
48155 #debug.log-request-header = "enable"
48156 #debug.log-response-header = "enable"
48157@@ -15,7 +15,7 @@
f673a614
ER
48158
48159 ## bind to localhost (default: all interfaces)
48160 server.bind = "localhost"
48161-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48162+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48163 server.name = "www.example.org"
48164 server.tag = "Apache 1.3.29"
48165
f26f9fd5 48166@@ -64,7 +64,7 @@
f673a614
ER
48167 ######################## MODULE CONFIG ############################
48168
48169
48170-accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48171+accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48172
48173 mimetype.assign = ( ".png" => "image/png",
48174 ".jpg" => "image/jpeg",
f26f9fd5 48175@@ -82,7 +82,7 @@
f673a614
ER
48176 ".c" => "text/plain",
48177 ".conf" => "text/plain" )
48178
48179-compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48180+compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48181 compress.filetype = ("text/plain", "text/html")
48182
48183 fastcgi.debug = 0
f26f9fd5 48184@@ -90,10 +90,11 @@
f673a614
ER
48185 "grisu" => (
48186 "host" => "127.0.0.1",
f26f9fd5
ER
48187 "port" => 10000,
48188- "bin-path" => "@SRCDIR@/fcgi-responder",
48189+ "bin-path" => env.SRCDIR + "/fcgi-responder",
48190 "check-local" => "disable",
48191 "max-procs" => 1,
48192- "min-procs" => 1
48193+ "min-procs" => 1,
48194+ "allow-x-send-file" => "enable",
f673a614
ER
48195 )
48196 )
f26f9fd5
ER
48197 )
48198@@ -109,7 +110,7 @@
f673a614
ER
48199 ssl.pemfile = "server.pem"
48200
48201 auth.backend = "plain"
48202-auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48203+auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48204 auth.backend.plain.groupfile = "lighttpd.group"
48205
48206 auth.backend.ldap.hostname = "localhost"
f26f9fd5 48207@@ -152,11 +153,11 @@
f673a614
ER
48208 status.config-url = "/server-config"
48209
48210 $HTTP["host"] == "vvv.example.org" {
48211- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48212+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48213 }
48214
48215 $HTTP["host"] == "zzz.example.org" {
48216- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48217+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48218 server.name = "zzz.example.org"
48219 }
48220
1175ccec 48221--- ../lighttpd-1.4.11/tests/fcgi-responder.c 2005-08-11 01:26:55.000000000 +0300
36e2a29e 48222+++ lighttpd-1.4.12/tests/fcgi-responder.c 2006-07-11 22:07:53.000000000 +0300
f26f9fd5
ER
48223@@ -6,11 +6,17 @@
48224 int main () {
48225 int num_requests = 2;
48226
48227- while (num_requests > 0 &&
48228- FCGI_Accept() >= 0) {
48229- char* p;
2519e6e5
ER
48230-
48231- if (NULL != (p = getenv("QUERY_STRING"))) {
f26f9fd5
ER
48232+ while (num_requests > 0 && FCGI_Accept() >= 0) {
48233+ char* p = NULL;
48234+ char* doc_root = NULL;
48235+ char fname[4096];
48236+ char* pfname = (char *)fname;
2519e6e5 48237+
f26f9fd5
ER
48238+ doc_root = getenv("DOCUMENT_ROOT");
48239+ p = getenv("QUERY_STRING");
48240+
48241+ if (NULL != p && NULL != doc_root) {
48242+ snprintf(pfname, sizeof(fname), "%s/phpinfo.php", doc_root);
48243 if (0 == strcmp(p, "lf")) {
48244 printf("Status: 200 OK\n\n");
48245 } else if (0 == strcmp(p, "crlf")) {
48246@@ -23,6 +29,18 @@
48247 printf("Status: 200 OK\r\n");
48248 fflush(stdout);
48249 printf("\r\n");
48250+ } else if (0 == strcmp(p,"x-lighttpd-send-file")) {
48251+ printf("Status: 200 OK\r\n");
48252+ printf("X-LIGHTTPD-send-file: %s\r\n", pfname);
48253+ printf("\r\n");
48254+ } else if (0 == strcmp(p,"xsendfile")) {
48255+ printf("Status: 200 OK\r\n");
48256+ printf("X-Sendfile: %s\r\n", pfname);
48257+ printf("\r\n");
48258+ } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
48259+ printf("Status: 200 OK\r\n");
48260+ printf("X-SeNdFiLe: %s\r\n", pfname);
48261+ printf("\r\n");
48262 } else if (0 == strcmp(p, "die-at-end")) {
48263 printf("Status: 200 OK\r\n\r\n");
48264 num_requests--;
1175ccec 48265--- ../lighttpd-1.4.11/tests/lighttpd.conf 2006-03-09 15:26:58.000000000 +0200
36e2a29e 48266+++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-11 22:07:53.000000000 +0300
f26f9fd5
ER
48267@@ -1,80 +1,18 @@
48268-debug.log-request-handling = "enable"
48269-debug.log-condition-handling = "enable"
f673a614 48270-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
f26f9fd5 48271-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
f673a614 48272+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
f26f9fd5
ER
48273+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48274+server.tag = "Apache 1.3.29"
f673a614 48275
f26f9fd5
ER
48276 ## 64 Mbyte ... nice limit
48277 server.max-request-size = 65000
f673a614 48278
f26f9fd5
ER
48279-## bind to port (default: 80)
48280-server.port = 2048
2519e6e5
ER
48281+include "default.conf"
48282
f673a614
ER
48283-## bind to localhost (default: all interfaces)
48284-server.bind = "localhost"
48285-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48286-server.name = "www.example.org"
f26f9fd5 48287-server.tag = "Apache 1.3.29"
f673a614
ER
48288-
48289-server.dir-listing = "enable"
2519e6e5 48290-
f673a614
ER
48291-#server.event-handler = "linux-sysepoll"
48292-#server.event-handler = "linux-rtsig"
48293-
48294-#server.modules.path = ""
48295-server.modules = (
48296- "mod_rewrite",
48297- "mod_setenv",
f26f9fd5 48298- "mod_secdownload",
f673a614
ER
48299- "mod_access",
48300- "mod_auth",
48301-# "mod_httptls",
48302- "mod_status",
48303- "mod_expire",
48304- "mod_simple_vhost",
48305- "mod_redirect",
48306-# "mod_evhost",
48307-# "mod_localizer",
48308- "mod_fastcgi",
f673a614
ER
48309- "mod_cgi",
48310- "mod_compress",
48311- "mod_userdir",
f26f9fd5 48312- "mod_ssi",
f673a614
ER
48313- "mod_accesslog" )
48314-
48315-server.indexfiles = ( "index.php", "index.html",
48316- "index.htm", "default.htm" )
48317-
48318-
48319-######################## MODULE CONFIG ############################
48320-
f26f9fd5 48321-ssi.extension = ( ".shtml" )
f673a614
ER
48322-
48323-accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48324-
48325-mimetype.assign = ( ".png" => "image/png",
48326- ".jpg" => "image/jpeg",
48327- ".jpeg" => "image/jpeg",
48328- ".gif" => "image/gif",
48329- ".html" => "text/html",
48330- ".htm" => "text/html",
48331- ".pdf" => "application/pdf",
48332- ".swf" => "application/x-shockwave-flash",
48333- ".spl" => "application/futuresplash",
48334- ".txt" => "text/plain",
48335- ".tar.gz" => "application/x-tgz",
48336- ".tgz" => "application/x-tgz",
48337- ".gz" => "application/x-gzip",
48338- ".c" => "text/plain",
48339- ".conf" => "text/plain" )
f26f9fd5
ER
48340+setenv.add-request-header = ( "FOO" => "foo")
48341+setenv.add-response-header = ( "BAR" => "foo")
48342
48343 $HTTP["host"] == "cache.example.org" {
48344- compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48345+ compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48346 }
f673a614
ER
48347-compress.filetype = ("text/plain", "text/html")
48348-
f26f9fd5 48349-setenv.add-environment = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
f673a614
ER
48350-setenv.add-request-header = ( "FOO" => "foo")
48351-setenv.add-response-header = ( "BAR" => "foo")
f26f9fd5
ER
48352
48353 $HTTP["url"] =~ "\.pdf$" {
48354 server.range-requests = "disable"
48355@@ -85,76 +23,31 @@
48356 "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48357 )
f673a614
ER
48358
48359-
48360-cgi.assign = ( ".pl" => "/usr/bin/perl",
48361- ".cgi" => "/usr/bin/perl",
48362- ".py" => "/usr/bin/python" )
48363-
48364-userdir.include-user = ( "jan" )
48365-userdir.path = "/"
48366-
48367-ssl.engine = "disable"
48368-ssl.pemfile = "server.pem"
48369-
f26f9fd5
ER
48370 $HTTP["host"] == "auth-htpasswd.example.org" {
48371 auth.backend = "htpasswd"
48372 }
48373
f673a614
ER
48374-auth.backend = "plain"
48375-auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
f673a614 48376-
f26f9fd5
ER
48377-auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
48378-
f673a614
ER
48379-
48380-auth.require = ( "/server-status" =>
48381- (
48382- "method" => "digest",
48383- "realm" => "download archiv",
f673a614
ER
48384- "require" => "group=www|user=jan|host=192.168.2.10"
48385- ),
f673a614
ER
48386- "/server-config" =>
48387- (
48388- "method" => "basic",
48389- "realm" => "download archiv",
f26f9fd5 48390- "require" => "valid-user"
f673a614
ER
48391- )
48392- )
48393-
48394-url.access-deny = ( "~", ".inc")
48395-
f673a614 48396-url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
f26f9fd5
ER
48397- "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48398-
48399-expire.url = ( "/expire/access" => "access 2 hours",
48400- "/expire/modification" => "access plus 1 seconds 2 minutes")
48401-
48402-#cache.cache-dir = "/home/weigon/wwwroot/cache/"
48403-
48404-#### status module
48405-status.status-url = "/server-status"
48406-status.config-url = "/server-config"
48407-
48408 $HTTP["host"] == "vvv.example.org" {
48409- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48410+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48411 secdownload.secret = "verysecret"
48412- secdownload.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48413+ secdownload.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48414 secdownload.uri-prefix = "/sec/"
48415 secdownload.timeout = 120
48416 }
f673a614 48417
f26f9fd5
ER
48418 $HTTP["host"] == "zzz.example.org" {
48419- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48420+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48421 server.name = "zzz.example.org"
48422 }
f673a614 48423
f26f9fd5
ER
48424 $HTTP["host"] == "no-simple.example.org" {
48425- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
48426+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/123.example.org/pages/"
48427 server.name = "zzz.example.org"
48428 }
f673a614 48429
f26f9fd5
ER
48430 $HTTP["host"] !~ "(no-simple\.example\.org)" {
48431 simple-vhost.document-root = "pages"
48432- simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
48433+ simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
48434 simple-vhost.default-host = "www.example.org"
48435 }
f673a614 48436
1175ccec 48437--- ../lighttpd-1.4.11/tests/lowercase.conf 1970-01-01 03:00:00.000000000 +0300
36e2a29e 48438+++ lighttpd-1.4.12/tests/lowercase.conf 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
48439@@ -0,0 +1,80 @@
48440+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48441+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48442+
48443+## bind to port (default: 80)
48444+server.port = 2048
48445+
48446+## bind to localhost (default: all interfaces)
48447+server.bind = "localhost"
48448+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48449+
48450+server.force-lowercase-filenames = "enable"
48451+
48452+server.dir-listing = "enable"
48453+
48454+server.modules = (
48455+ "mod_rewrite",
48456+ "mod_setenv",
48457+ "mod_secdownload",
48458+ "mod_access",
48459+ "mod_auth",
48460+ "mod_status",
48461+ "mod_expire",
48462+ "mod_redirect",
48463+ "mod_fastcgi",
48464+ "mod_cgi" )
48465+
48466+server.indexfiles = ( "index.php", "index.html",
48467+ "index.htm", "default.htm" )
48468+
48469+
48470+######################## MODULE CONFIG ############################
48471+
48472+mimetype.assign = ( ".png" => "image/png",
48473+ ".jpg" => "image/jpeg",
48474+ ".jpeg" => "image/jpeg",
48475+ ".gif" => "image/gif",
48476+ ".html" => "text/html",
48477+ ".htm" => "text/html",
48478+ ".pdf" => "application/pdf",
48479+ ".swf" => "application/x-shockwave-flash",
48480+ ".spl" => "application/futuresplash",
48481+ ".txt" => "text/plain",
48482+ ".tar.gz" => "application/x-tgz",
48483+ ".tgz" => "application/x-tgz",
48484+ ".gz" => "application/x-gzip",
48485+ ".c" => "text/plain",
48486+ ".conf" => "text/plain" )
48487+
48488+fastcgi.debug = 0
48489+fastcgi.server = ( ".php" => ( ( "host" => "127.0.0.1", "port" => 1026, "broken-scriptfilename" => "enable" ) ),
48490+ "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48491+ )
48492+
48493+
48494+cgi.assign = ( ".pl" => "/usr/bin/perl",
48495+ ".cgi" => "/usr/bin/perl",
48496+ ".py" => "/usr/bin/python" )
48497+
48498+auth.backend = "plain"
48499+auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48500+
48501+auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
48502+
48503+$HTTP["host"] == "lowercase-auth" {
48504+ auth.require = ( "/image.jpg" =>
48505+ (
48506+ "method" => "digest",
48507+ "realm" => "download archiv",
48508+ "require" => "valid-user"
48509+ )
48510+ )
48511+}
48512+
48513+$HTTP["host"] == "lowercase-deny" {
48514+ url.access-deny = ( ".jpg")
48515+}
48516+
48517+$HTTP["host"] == "lowercase-exclude" {
48518+ static-file.exclude-extensions = ( ".jpg" )
48519+}
1175ccec 48520--- ../lighttpd-1.4.11/tests/lowercase.t 1970-01-01 03:00:00.000000000 +0300
36e2a29e 48521+++ lighttpd-1.4.12/tests/lowercase.t 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
48522@@ -0,0 +1,94 @@
48523+#!/usr/bin/env perl
48524+BEGIN {
48525+ # add current source dir to the include-path
48526+ # we need this for make distcheck
48527+ (my $srcdir = $0) =~ s#/[^/]+$#/#;
48528+ unshift @INC, $srcdir;
48529+}
48530+
48531+use strict;
48532+use IO::Socket;
48533+use Test::More tests => 10;
48534+use LightyTest;
48535+
48536+my $tf = LightyTest->new();
48537+my $t;
48538+
48539+$tf->{CONFIGFILE} = 'lowercase.conf';
48540+
48541+ok($tf->start_proc == 0, "Starting lighttpd") or die();
48542+
48543+## check if lower-casing works
48544+
48545+$t->{REQUEST} = ( <<EOF
48546+GET /image.JPG HTTP/1.0
48547+EOF
48548+ );
48549+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48550+ok($tf->handle_http($t) == 0, 'uppercase access');
48551+
48552+$t->{REQUEST} = ( <<EOF
48553+GET /image.jpg HTTP/1.0
48554+EOF
48555+ );
48556+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48557+ok($tf->handle_http($t) == 0, 'lowercase access');
48558+
48559+## check that mod-auth works
48560+
48561+$t->{REQUEST} = ( <<EOF
48562+GET /image.JPG HTTP/1.0
48563+Host: lowercase-auth
48564+EOF
48565+ );
48566+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48567+ok($tf->handle_http($t) == 0, 'uppercase access');
48568+
48569+$t->{REQUEST} = ( <<EOF
48570+GET /image.jpg HTTP/1.0
48571+Host: lowercase-auth
48572+EOF
48573+ );
48574+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48575+ok($tf->handle_http($t) == 0, 'lowercase access');
48576+
48577+
48578+## check that mod-staticfile exclude works
48579+$t->{REQUEST} = ( <<EOF
48580+GET /image.JPG HTTP/1.0
48581+Host: lowercase-exclude
48582+EOF
48583+ );
48584+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48585+ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
48586+
48587+$t->{REQUEST} = ( <<EOF
48588+GET /image.jpg HTTP/1.0
48589+Host: lowercase-exclude
48590+EOF
48591+ );
48592+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48593+ok($tf->handle_http($t) == 0, 'lowercase access');
48594+
48595+
48596+## check that mod-access exclude works
48597+$t->{REQUEST} = ( <<EOF
48598+GET /image.JPG HTTP/1.0
48599+Host: lowercase-deny
48600+EOF
48601+ );
48602+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48603+ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
48604+
48605+$t->{REQUEST} = ( <<EOF
48606+GET /image.jpg HTTP/1.0
48607+Host: lowercase-deny
48608+EOF
48609+ );
48610+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48611+ok($tf->handle_http($t) == 0, 'lowercase access');
48612+
48613+
48614+
48615+ok($tf->stop_proc == 0, "Stopping lighttpd");
48616+
1175ccec 48617--- ../lighttpd-1.4.11/tests/mod-fastcgi.t 2006-03-09 15:30:45.000000000 +0200
36e2a29e 48618+++ lighttpd-1.4.12/tests/mod-fastcgi.t 2006-07-11 22:07:53.000000000 +0300
f26f9fd5
ER
48619@@ -7,7 +7,7 @@
48620 }
f673a614 48621
f26f9fd5
ER
48622 use strict;
48623-use Test::More tests => 47;
48624+use Test::More tests => 49;
48625 use LightyTest;
f673a614 48626
f26f9fd5
ER
48627 my $tf = LightyTest->new();
48628@@ -15,7 +15,7 @@
48629 my $t;
f673a614 48630
f26f9fd5
ER
48631 SKIP: {
48632- skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
48633+ skip "no PHP running on port 1026", 29 unless $tf->listening_on(1026);
f673a614 48634
f26f9fd5 48635 ok($tf->start_proc == 0, "Starting lighttpd") or die();
f673a614 48636
2519e6e5
ER
48637@@ -223,7 +223,7 @@
48638 }
48639
48640 SKIP: {
48641- skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48642+ skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48643 $tf->{CONFIGFILE} = 'fastcgi-13.conf';
48644 ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
48645 $t->{REQUEST} = ( <<EOF
f26f9fd5
ER
48646@@ -285,6 +285,34 @@
48647 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
48648 ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
f673a614 48649
f26f9fd5
ER
48650+ # X-LIGHTTPD-send-file
48651+ $t->{REQUEST} = ( <<EOF
48652+GET /index.fcgi?x-lighttpd-send-file HTTP/1.0
48653+Host: www.example.org
48654+EOF
48655+ );
48656+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48657+' } ];
48658+ ok($tf->handle_http($t) == 0, 'X-LIGHTTPD-send-file');
48659+ # X-Sendfile
48660+ $t->{REQUEST} = ( <<EOF
48661+GET /index.fcgi?xsendfile HTTP/1.0
48662+Host: www.example.org
48663+EOF
48664+ );
48665+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48666+' } ];
48667+ ok($tf->handle_http($t) == 0, 'X-Sendfile');
f673a614 48668+
f26f9fd5
ER
48669+ $t->{REQUEST} = ( <<EOF
48670+GET /index.fcgi?xsendfile-mixed-case HTTP/1.0
48671+Host: www.example.org
48672+EOF
48673+ );
48674+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48675+' } ];
48676+ ok($tf->handle_http($t) == 0, 'X-SeNdFiLe in mixed case');
f673a614 48677+
f26f9fd5
ER
48678 $t->{REQUEST} = ( <<EOF
48679 GET /index.fcgi?die-at-end HTTP/1.0
48680 Host: www.example.org
1175ccec 48681--- ../lighttpd-1.4.11/tests/mod-proxy.t 1970-01-01 03:00:00.000000000 +0300
36e2a29e 48682+++ lighttpd-1.4.12/tests/mod-proxy.t 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
48683@@ -0,0 +1,173 @@
48684+#!/usr/bin/env perl
48685+BEGIN {
48686+ # add current source dir to the include-path
48687+ # we need this for make distcheck
48688+ (my $srcdir = $0) =~ s#/[^/]+$#/#;
48689+ unshift @INC, $srcdir;
48690+}
48691+
48692+use strict;
48693+use IO::Socket;
48694+use Test::More tests => 21;
48695+use LightyTest;
48696+
48697+my $tf_proxy = LightyTest->new();
48698+my $tf_backend1 = LightyTest->new();
48699+my $tf_backend2 = LightyTest->new();
48700+
48701+my $t;
48702+
48703+## we need two procs
48704+## 1. the real webserver
48705+## 2. the proxy server
48706+
48707+$tf_proxy->{PORT} = 2048;
48708+$tf_proxy->{CONFIGFILE} = 'proxy.conf';
48709+$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
48710+
48711+$tf_backend1->{PORT} = 2050;
48712+$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
48713+$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
48714+
48715+$tf_backend2->{PORT} = 2051;
48716+$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
48717+$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
48718+
48719+
48720+ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
48721+
48722+ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
48723+
48724+sleep(1);
48725+
48726+$t->{REQUEST} = ( <<EOF
48727+GET /index.html HTTP/1.0
48728+Host: www.example.org
48729+EOF
48730+ );
48731+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48732+ok($tf_proxy->handle_http($t) == 0, 'valid request');
48733+
48734+$t->{REQUEST} = ( <<EOF
48735+GET /index.html HTTP/1.0
48736+Host: www.example.org
48737+EOF
48738+ );
48739+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'proxy-backend-1' } ];
48740+ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
48741+
48742+$t->{REQUEST} = ( <<EOF
48743+GET /balance-rr/foo HTTP/1.0
48744+Host: www.example.org
48745+EOF
48746+ );
48747+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48748+ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
48749+
48750+$t->{REQUEST} = ( <<EOF
48751+GET /balance-rr/foo HTTP/1.0
48752+Host: www.example.org
48753+EOF
48754+ );
48755+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48756+ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
48757+
48758+$t->{REQUEST} = ( <<EOF
48759+GET /balance-fair/foo HTTP/1.0
48760+Host: www.example.org
48761+EOF
48762+ );
48763+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48764+ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
48765+
48766+## backend 2 starting
48767+ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
48768+
48769+$t->{REQUEST} = ( <<EOF
48770+GET /balance-rr/foo HTTP/1.0
48771+Host: www.example.org
48772+EOF
48773+ );
48774+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48775+ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
48776+
48777+$t->{REQUEST} = ( <<EOF
48778+GET /balance-rr/foo HTTP/1.0
48779+Host: www.example.org
48780+EOF
48781+ );
48782+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48783+ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
48784+
48785+$t->{REQUEST} = ( <<EOF
48786+GET /balance-hash/foo HTTP/1.0
48787+Host: www.example.org
48788+EOF
48789+ );
48790+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48791+ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
48792+
48793+$t->{REQUEST} = ( <<EOF
48794+GET /balance-hash/foo HTTP/1.0
48795+Host: www.example.org
48796+EOF
48797+ );
48798+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48799+ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
48800+
48801+$t->{REQUEST} = ( <<EOF
48802+GET /balance-hash/bar HTTP/1.0
48803+Host: www.example.org
48804+EOF
48805+ );
48806+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48807+ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
48808+
48809+$t->{REQUEST} = ( <<EOF
48810+GET /balance-hash/bar HTTP/1.0
48811+Host: www.example.org
48812+EOF
48813+ );
48814+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48815+ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
48816+
48817+## backend 1 stopping, failover
48818+ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
48819+
48820+$t->{REQUEST} = ( <<EOF
48821+GET /balance-hash/foo HTTP/1.0
48822+Host: www.example.org
48823+EOF
48824+ );
48825+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48826+ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
48827+
48828+$t->{REQUEST} = ( <<EOF
48829+GET /balance-hash/bar HTTP/1.0
48830+Host: www.example.org
48831+EOF
48832+ );
48833+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48834+ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
48835+
48836+$t->{REQUEST} = ( <<EOF
48837+GET /balance-rr/foo HTTP/1.0
48838+Host: www.example.org
48839+EOF
48840+ );
48841+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48842+ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
48843+
48844+$t->{REQUEST} = ( <<EOF
48845+GET /balance-fair/foo HTTP/1.0
48846+Host: www.example.org
48847+EOF
48848+ );
48849+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48850+ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
48851+
48852+
48853+ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
48854+
48855+ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
48856+
1175ccec 48857--- ../lighttpd-1.4.11/tests/proxy.conf 1970-01-01 03:00:00.000000000 +0300
36e2a29e 48858+++ lighttpd-1.4.12/tests/proxy.conf 2006-07-11 22:07:53.000000000 +0300
2519e6e5
ER
48859@@ -0,0 +1,26 @@
48860+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48861+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
48862+server.tag = "proxy"
48863+
48864+include "default.conf"
48865+
48866+## 127.0.0.1 and 127.0.0.2 are the same host
48867+proxy.server = (
48868+ "" => (( "host" => "127.0.0.1",
48869+ "port" => 2050 ),
48870+ ( "host" => "127.0.0.2",
48871+ "port" => 2051 )
48872+ ))
48873+
48874+$HTTP["url"] =~ "^/balance-rr/" {
48875+ proxy.balance = "round-robin"
48876+}
48877+
48878+$HTTP["url"] =~ "^/balance-hash/" {
48879+ proxy.balance = "hash"
48880+}
48881+
48882+$HTTP["url"] =~ "^/balance-fair/" {
48883+ proxy.balance = "fair"
48884+}
48885+
1175ccec 48886--- ../lighttpd-1.4.11/tests/var-include.conf 2005-08-27 17:44:19.000000000 +0300
36e2a29e 48887+++ lighttpd-1.4.12/tests/var-include.conf 2006-07-11 22:07:53.000000000 +0300
f26f9fd5
ER
48888@@ -2,15 +2,15 @@
48889 debug.log-request-handling = "enable"
48890 debug.log-condition-handling = "enable"
f673a614 48891
f26f9fd5
ER
48892-server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48893-server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48894+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48895+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
f673a614 48896
f26f9fd5
ER
48897 ## bind to port (default: 80)
48898 server.port = 2048
f673a614 48899
f26f9fd5
ER
48900 ## bind to localhost (default: all interfaces)
48901 server.bind = "localhost"
48902-server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48903+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48904 server.name = "www.example.org"
48905 server.tag = "Apache 1.3.29"
f673a614 48906
f26f9fd5
ER
48907@@ -21,19 +21,19 @@
48908 ######################## MODULE CONFIG ############################
f673a614 48909
f673a614 48910
f26f9fd5
ER
48911-accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48912+accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
f673a614 48913
f26f9fd5 48914 mimetype.assign = ( ".html" => "text/html" )
f673a614 48915
f26f9fd5 48916 url.redirect = ("^" => "/default")
f673a614 48917
f26f9fd5
ER
48918 $HTTP["host"] == "www.example.org" {
48919- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48920+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48921 server.name = "www.example.org"
48922 url.redirect = ("^" => "/redirect")
48923 }
48924 $HTTP["host"] == "test.example.org" {
48925- server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48926+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48927 server.name = "test.example.org"
48928 var.myvar = "good"
48929 var.one = 1
This page took 7.85484 seconds and 4 git commands to generate.