1 --- ../lighttpd-1.4.11/NEWS 2006-03-09 19:34:33.000000000 +0200
2 +++ lighttpd-1.4.12/NEWS 2006-07-11 22:07:54.000000000 +0300
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
26 * added ability to specify which ip address spawn-fci listens on
27 --- ../lighttpd-1.4.11/configure.in 2006-03-04 16:32:38.000000000 +0200
28 +++ lighttpd-1.4.12/configure.in 2006-07-15 22:43:22.000000000 +0300
31 # Process this file with autoconf to produce a configure script.
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])
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>])
48 AC_DEFINE([HAVE_SQLITE3], [1], [libsqlite3])
49 AC_DEFINE([HAVE_SQLITE3_H], [1], [sqlite3.h])
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])
57 + if test "$WITH_WEBDAV_LOCKS" != "no"; then
58 + AC_CHECK_LIB(uuid, uuid_unparse, [
59 + AC_CHECK_HEADERS([uuid/uuid.h],[
61 + AC_DEFINE([HAVE_UUID], [1], [libuuid])
62 + AC_DEFINE([HAVE_UUID_H], [1], [uuid/uuid.h is available])
72 AC_MSG_RESULT($WITH_LUA)
73 if test "$WITH_LUA" != "no"; then
74 - AC_PATH_PROG(LUACONFIG, lua-config)
76 - if test x"$LUACONFIG" != x; then
77 - LUA_CFLAGS=`$LUACONFIG --include`
78 - LUA_LIBS=`$LUACONFIG --libs --extralibs`
80 + PKG_CHECK_MODULES(LUA, lua >= 5.1, [
81 AC_DEFINE([HAVE_LUA], [1], [liblua])
82 AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
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])
93 - if test x"$LUA_LIBS" = x; then
95 - PKG_CHECK_MODULES(LUA, lua, [
96 - AC_DEFINE([HAVE_LUA], [1], [liblua])
97 - AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
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])
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"
120 plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
121 features="regex-conditionals"
123 disable_feature="$disable_feature $features"
126 +features="webdav-locks"
127 +if test "x$UUID_LIB" \!= x; then
128 + enable_feature="$enable_feature $features"
130 + disable_feature="$disable_feature $features"
137 --- ../lighttpd-1.4.11/cygwin/lighttpd.README 2006-03-07 14:22:19.000000000 +0200
138 +++ lighttpd-1.4.12/cygwin/lighttpd.README 2006-07-11 22:08:04.000000000 +0300
141 -------------------------------------------
\r
142 -A fast, secure and flexible webserver
\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
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
164 -Canonical homepage:
\r
165 - http://jan.kneschke.de/projects/lighttpd/
\r
167 -Canonical download:
\r
168 - http://jan.kneschke.de/projects/lighttpd/download
\r
170 -------------------------------------
\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
177 - ./lighttpd-1.4.11-<REL>.sh all
\r
180 - /usr/src/lighttpd-1.4.11-<REL>.tar.bz2
\r
181 - /usr/src/lighttpd-1.4.11-<REL>-src.tar.bz2
\r
183 -Or use './lighttpd-1.4.11-<REL>.sh prep' to get a patched source directory
\r
185 --------------------------------------------
\r
187 -Files included in the binary distribution:
\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
240 -------------------
\r
244 ----------- lighttpd-1.3.1-1 -----------
\r
248 ----------- lighttpd-1.3.0-1 -----------
\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
255 +------------------------------------------
256 +A fast, secure and flexible webserver
258 +Runtime requirements:
259 + cygwin-1.5.10 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
267 + cygwin-1.5.10 or newer
268 + gcc-3.3.1-3 or newer
269 + binutils-20030901-1 or newer
279 + http://jan.kneschke.de/projects/lighttpd/
282 + http://jan.kneschke.de/projects/lighttpd/download
284 +------------------------------------
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
291 + ./lighttpd-1.4.12-<REL>.sh all
294 + /usr/src/lighttpd-1.4.12-<REL>.tar.bz2
295 + /usr/src/lighttpd-1.4.12-<REL>-src.tar.bz2
297 +Or use './lighttpd-1.4.12-<REL>.sh prep' to get a patched source directory
299 +-------------------------------------------
301 +Files included in the binary distribution:
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
358 +---------- lighttpd-1.3.1-1 -----------
362 +---------- lighttpd-1.3.0-1 -----------
365 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
366 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
368 --- ../lighttpd-1.4.11/cygwin/lighttpd.README.in 2005-08-11 01:26:59.000000000 +0300
369 +++ lighttpd-1.4.12/cygwin/lighttpd.README.in 2006-07-11 22:07:53.000000000 +0300
372 -------------------------------------------
\r
373 -A fast, secure and flexible webserver
\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
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
395 -Canonical homepage:
\r
396 - http://jan.kneschke.de/projects/lighttpd/
\r
398 -Canonical download:
\r
399 - http://jan.kneschke.de/projects/lighttpd/download
\r
401 -------------------------------------
\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
408 - ./lighttpd-@VERSION@-<REL>.sh all
\r
411 - /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
\r
412 - /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
\r
414 -Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
\r
416 --------------------------------------------
\r
418 -Files included in the binary distribution:
\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
471 -------------------
\r
475 ----------- lighttpd-1.3.1-1 -----------
\r
479 ----------- lighttpd-1.3.0-1 -----------
\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
486 +------------------------------------------
487 +A fast, secure and flexible webserver
489 +Runtime requirements:
490 + cygwin-1.5.10 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
498 + cygwin-1.5.10 or newer
499 + gcc-3.3.1-3 or newer
500 + binutils-20030901-1 or newer
510 + http://jan.kneschke.de/projects/lighttpd/
513 + http://jan.kneschke.de/projects/lighttpd/download
515 +------------------------------------
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
522 + ./lighttpd-@VERSION@-<REL>.sh all
525 + /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
526 + /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
528 +Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
530 +-------------------------------------------
532 +Files included in the binary distribution:
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
589 +---------- lighttpd-1.3.1-1 -----------
593 +---------- lighttpd-1.3.0-1 -----------
596 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
597 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
599 --- ../lighttpd-1.4.11/doc/authentication.txt 2006-01-12 20:34:26.000000000 +0200
600 +++ lighttpd-1.4.12/doc/authentication.txt 2006-07-11 22:07:54.000000000 +0300
604 :Author: Jan Kneschke
606 -:Revision: $Revision$
608 +:Revision: $Revision$
611 The auth module provides ...
612 --- ../lighttpd-1.4.11/doc/compress.txt 2005-08-11 01:26:16.000000000 +0300
613 +++ lighttpd-1.4.12/doc/compress.txt 2006-07-11 22:07:54.000000000 +0300
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.
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
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.
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
639 +The names of the cache files are made of the filename, the compression method
640 +and the etag associated to the file.
642 +Cleaning the cache is left to the user. A cron job deleting files older than
643 +10 days should do fine.
648 +The module limits the compression of files to files larger than 128 Byte and
649 +smaller than 128 MByte.
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.
658 Default: not set, compress the file for every request
661 - mimetypes where might get compressed
662 + mimetypes which might get compressed
666 compress.filetype = ("text/plain", "text/html")
668 + Keep in mind that compressed JavaScript and CSS files are broken in some
673 +compress.max-file-size
674 + maximum size of the original file to be compressed kBytes.
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
680 + There is a hard upper limit of 128Mbyte.
682 + Default: unlimited (== hard-limit of 128MByte)
684 Compressing Dynamic Content
685 ===========================
687 --- ../lighttpd-1.4.11/doc/configuration.txt 2006-03-09 02:10:40.000000000 +0200
688 +++ lighttpd-1.4.12/doc/configuration.txt 2006-07-11 22:07:54.000000000 +0300
692 :Author: Jan Kneschke
694 -:Revision: $Revision$
696 +:Revision: $Revision$
699 the layout of the configuration file
702 debug.log-request-handling
705 +debug.log-condition-handling
708 +debug.log-condition-cache-handling
709 + for developers only
711 --- ../lighttpd-1.4.11/doc/fastcgi.txt 2006-02-16 17:03:52.000000000 +0200
712 +++ lighttpd-1.4.12/doc/fastcgi.txt 2006-07-11 22:07:54.000000000 +0300
714 PHP can extract PATH_INFO from it (default: disabled)
715 :"disable-time": time to wait before a disabled backend is checked
717 - :"allow-x-send-file": controls if X-LIGHTTPD-send-file headers
719 + :"allow-x-send-file": controls if X-LIGHTTPD-send-file and X-Sendfile
720 + headers are allowed
724 --- ../lighttpd-1.4.11/doc/lighttpd.conf 2006-03-04 14:41:12.000000000 +0200
725 +++ lighttpd-1.4.12/doc/lighttpd.conf 2006-07-11 22:07:54.000000000 +0300
726 @@ -172,10 +172,11 @@
727 #dir-listing.activate = "enable"
730 -#debug.log-request-header = "enable"
731 -#debug.log-response-header = "enable"
732 -#debug.log-request-handling = "enable"
733 -#debug.log-file-not-found = "enable"
734 +#debug.log-request-header = "enable"
735 +#debug.log-response-header = "enable"
736 +#debug.log-request-handling = "enable"
737 +#debug.log-file-not-found = "enable"
738 +#debug.log-condition-handling = "enable"
740 ### only root can use these options
742 --- ../lighttpd-1.4.11/doc/performance.txt 2006-02-02 13:01:08.000000000 +0200
743 +++ lighttpd-1.4.12/doc/performance.txt 2006-07-11 22:07:54.000000000 +0300
746 server.stat-cache-engine = "fam" # either fam, simple or disabled
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.
751 Platform-Specific Notes
752 =======================
753 --- ../lighttpd-1.4.11/doc/secdownload.txt 2005-12-20 15:58:58.000000000 +0200
754 +++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-11 22:07:54.000000000 +0300
756 $secret = "verysecret";
757 $uri_prefix = "/dl/";
760 + # filename, make sure it's started with a "/" or you'll get 404 in the browser
761 $f = "/secret-file.txt";
764 --- ../lighttpd-1.4.11/lighttpd.spec 2006-03-07 14:22:18.000000000 +0200
765 +++ lighttpd-1.4.12/lighttpd.spec 2006-07-11 22:07:58.000000000 +0300
767 Summary: A fast webserver with minimal memory-footprint (lighttpd)
772 Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
773 Packager: Jan Kneschke <jan@kneschke.de>
774 --- ../lighttpd-1.4.11/openwrt/control 2006-03-07 14:22:19.000000000 +0200
775 +++ lighttpd-1.4.12/openwrt/control 2006-07-11 22:08:05.000000000 +0300
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
787 --- ../lighttpd-1.4.11/openwrt/lighttpd.mk 2006-03-07 14:22:19.000000000 +0200
788 +++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-11 22:08:05.000000000 +0300
791 # For this example we'll use a fairly simple package that compiles easily
792 # and has sources available for download at sourceforge
793 -LIGHTTPD=lighttpd-1.4.11
794 +LIGHTTPD=lighttpd-1.4.12
795 LIGHTTPD_TARGET=.built
796 LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
797 LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
798 --- ../lighttpd-1.4.11/src/Makefile.am 2006-03-07 14:20:20.000000000 +0200
799 +++ lighttpd-1.4.12/src/Makefile.am 2006-07-15 22:43:21.000000000 +0300
802 configparser.y: lemon
803 mod_ssi_exprparser.y: lemon
804 +http_resp_parser.y: lemon
806 configparser.c configparser.h: configparser.y
808 - $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
809 + $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
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
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
821 configfile.c: configparser.h
822 mod_ssi_expr.c: mod_ssi_exprparser.h
823 +http_resp.c: http_resp_parser.h
825 common_src=buffer.c log.c \
828 network_write.c network_linux_sendfile.c \
829 network_freebsd_sendfile.c network_writev.c \
830 network_solaris_sendfilev.c network_openssl.c \
832 + splaytree.c http_resp.c http_resp_parser.c
834 src = server.c response.c connections.c network.c \
835 configfile.c configparser.c request.c proc_open.c
838 lib_LTLIBRARIES += mod_webdav.la
839 mod_webdav_la_SOURCES = mod_webdav.c
840 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
841 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
842 mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
843 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
844 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
846 lib_LTLIBRARIES += mod_cml.la
847 mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
849 mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
850 mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
852 +lib_LTLIBRARIES += mod_sql_vhost_core.la
853 +mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
854 +mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
855 +mod_sql_vhost_core_la_LIBADD = $(common_libadd)
857 lib_LTLIBRARIES += mod_cgi.la
858 mod_cgi_la_SOURCES = mod_cgi.c
859 mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
861 mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
862 configparser.h mod_ssi_exprparser.h \
863 sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
864 - splaytree.h proc_open.h
865 + splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h \
866 + sys-files.h sys-process.h sys-strings.h http_resp_parser.h
868 DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
873 noinst_HEADERS = $(hdr)
874 -EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c
875 +EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c http_resp_parser.y
876 --- ../lighttpd-1.4.11/src/array.c 2005-11-18 13:58:32.000000000 +0200
877 +++ lighttpd-1.4.12/src/array.c 2006-07-11 22:07:51.000000000 +0300
880 array *array_init(void) {
884 a = calloc(1, sizeof(*a));
888 a->next_power_of_2 = 1;
895 void array_free(array *a) {
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]);
907 if (a->data) free(a->data);
908 if (a->sorted) free(a->sorted);
914 void array_reset(array *a) {
919 if (!a->is_weakref) {
920 for (i = 0; i < a->used; i++) {
921 a->data[i]->reset(a->data[i]);
930 static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
935 if (key == NULL) return -1;
938 /* try to find the string */
939 for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
945 } else if (pos >= (int)a->used) {
948 cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
953 ndx = a->sorted[pos];
954 @@ -110,46 +110,46 @@
960 if (rndx) *rndx = pos;
966 data_unset *array_get_element(array *a, const char *key) {
970 if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
971 /* found, leave here */
982 data_unset *array_get_unused_element(array *a, data_type_t t) {
983 data_unset *ds = NULL;
988 if (a->size == 0) return NULL;
991 if (a->used == a->size) return NULL;
993 if (a->data[a->used]) {
994 ds = a->data[a->used];
997 a->data[a->used] = NULL;
1004 /* replace or insert data, return the old one with the same key */
1005 data_unset *array_replace(array *a, data_unset *du) {
1009 if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
1010 array_insert_unique(a, du);
1012 @@ -164,13 +164,13 @@
1017 - /* generate unique index if neccesary */
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;
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 @@
1038 if (a->used+1 > INT_MAX) {
1039 /* we can't handle more then INT_MAX entries: see array_get_index() */
1046 a->data = malloc(sizeof(*a->data) * a->size);
1047 @@ -204,27 +204,27 @@
1049 for (j = a->used; j < a->size; j++) a->data[j] = NULL;
1053 ndx = (int) a->used;
1056 a->data[a->used++] = str;
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)) {
1066 - /* move everything on step to the right */
1069 + /* move everything one step to the right */
1071 memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
1076 a->sorted[pos] = ndx;
1079 if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
1096 array_print_indent(depth);
1097 fprintf(stderr, ")");
1103 @@ -323,47 +323,47 @@
1115 ds = data_string_init();
1116 buffer_copy_string(ds->key, "abc");
1117 buffer_copy_string(ds->value, "alfrag");
1120 array_insert_unique(a, (data_unset *)ds);
1123 ds = data_string_init();
1124 buffer_copy_string(ds->key, "abc");
1125 buffer_copy_string(ds->value, "hameplman");
1128 array_insert_unique(a, (data_unset *)ds);
1131 ds = data_string_init();
1132 buffer_copy_string(ds->key, "123");
1133 buffer_copy_string(ds->value, "alfrag");
1136 array_insert_unique(a, (data_unset *)ds);
1139 dc = data_count_init();
1140 buffer_copy_string(dc->key, "def");
1143 array_insert_unique(a, (data_unset *)dc);
1146 dc = data_count_init();
1147 buffer_copy_string(dc->key, "def");
1150 array_insert_unique(a, (data_unset *)dc);
1159 fprintf(stderr, "%d\n",
1160 buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
1166 --- ../lighttpd-1.4.11/src/array.h 2005-09-23 21:24:18.000000000 +0300
1167 +++ lighttpd-1.4.12/src/array.h 2006-07-11 22:07:51.000000000 +0300
1169 #define DATA_UNSET \
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); \
1193 size_t next_power_of_2;
1194 int is_weakref; /* data is weakref, don't bother the data */
1223 COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP
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
1232 typedef struct _data_config data_config;
1233 struct _data_config {
1248 int context_ndx; /* more or less like an id */
1252 /* for chaining only */
1269 @@ -120,13 +120,13 @@
1275 unsigned short port;
1282 int usage; /* fair-balancing needs the no. of connections active on this host */
1283 int last_used_ndx; /* round robin */
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
1290 #include <sys/types.h>
1291 -#include <sys/time.h>
1292 #include <sys/stat.h>
1294 #ifdef HAVE_CONFIG_H
1296 #include "sys-socket.h"
1297 #include "splaytree.h"
1300 #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
1301 # define USE_OPENSSL
1302 -# include <openssl/ssl.h>
1303 +# include <openssl/ssl.h>
1311 -#ifndef O_LARGEFILE
1312 -# define O_LARGEFILE 0
1317 # define SIZE_MAX SIZE_T_MAX
1320 /* solaris and NetBSD 1.3.x again */
1321 #if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t))
1322 -# define uint32_t u_int32_t
1323 +/* # define uint32_t u_int32_t */
1324 +typedef unsigned __int32 uint32_t;
1330 #include "settings.h"
1332 -typedef enum { T_CONFIG_UNSET,
1338 +typedef enum { T_CONFIG_UNSET,
1345 } config_values_type_t;
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;
1359 config_values_type_t type;
1360 config_scope_type_t scope;
1362 @@ -118,18 +113,6 @@
1369 - struct sockaddr_in6 ipv6;
1371 - struct sockaddr_in ipv4;
1372 -#ifdef HAVE_SYS_UN_H
1373 - struct sockaddr_un un;
1375 - struct sockaddr plain;
1378 /* fcgi_response_header contains ... */
1379 #define HTTP_STATUS BV(0)
1380 #define HTTP_CONNECTION BV(1)
1381 @@ -142,40 +125,40 @@
1382 /* the request-line */
1390 http_method_t http_method;
1391 http_version_t http_version;
1394 buffer *request_line;
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;
1409 size_t content_length; /* returned by strtoul() */
1412 /* internal representation */
1413 int accept_encoding;
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 */
1424 + int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
1431 HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
1432 } transfer_encoding;
1434 @@ -191,21 +174,21 @@
1437 buffer *basedir; /* path = "(basedir)(.*)" */
1440 buffer *doc_root; /* path = doc_root + rel_path */
1465 - splay_tree *files; /* the nodes of the tree are stat_cache_entry's */
1467 + splay_tree *files; /* the nodes of the tree are stat_cache_entries */
1469 buffer *dir_name; /* for building the dirname from the filename */
1471 splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */
1478 /* virtual-servers */
1479 buffer *document_root;
1480 buffer *server_name;
1483 buffer *dirlist_encoding;
1484 buffer *errorfile_prefix;
1487 unsigned short max_keep_alive_requests;
1488 unsigned short max_keep_alive_idle;
1489 unsigned short max_read_idle;
1490 @@ -244,16 +227,17 @@
1491 unsigned short use_xattr;
1492 unsigned short follow_symlink;
1493 unsigned short range_requests;
1499 unsigned short log_file_not_found;
1500 unsigned short log_request_header;
1501 unsigned short log_request_handling;
1502 unsigned short log_response_header;
1503 unsigned short log_condition_handling;
1506 + unsigned short log_condition_cache_handling;
1510 buffer *ssl_pemfile;
1511 buffer *ssl_ca_file;
1512 @@ -268,22 +252,22 @@
1514 unsigned short global_kbytes_per_second; /* */
1516 - off_t global_bytes_per_second_cnt;
1517 + off_t global_bytes_per_second_cnt;
1518 /* server-wide traffic-shaper
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
1525 * as soon as global_kbytes_per_second gets below 0
1526 * the connected conns are "offline" a little bit
1529 - * we somehow have to loose our "we are writable" signal
1530 + * we somehow have to lose our "we are writable" signal
1535 off_t *global_bytes_per_second_cnt_ptr; /* */
1541 @@ -291,18 +275,18 @@
1543 /* the order of the items should be the same as they are processed
1544 * read before write as we use this later */
1546 - CON_STATE_CONNECT,
1547 - CON_STATE_REQUEST_START,
1549 - CON_STATE_REQUEST_END,
1550 - CON_STATE_READ_POST,
1551 - CON_STATE_HANDLE_REQUEST,
1552 - CON_STATE_RESPONSE_START,
1554 - CON_STATE_RESPONSE_END,
1558 + CON_STATE_CONNECT,
1559 + CON_STATE_REQUEST_START,
1561 + CON_STATE_REQUEST_END,
1562 + CON_STATE_READ_POST,
1563 + CON_STATE_HANDLE_REQUEST,
1564 + CON_STATE_RESPONSE_START,
1566 + CON_STATE_RESPONSE_END,
1569 } connection_state_t;
1571 typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
1572 @@ -315,88 +299,88 @@
1575 connection_state_t state;
1579 time_t read_idle_ts;
1580 time_t close_timeout_ts;
1581 time_t write_request_ts;
1584 time_t connection_start;
1585 time_t request_start;
1588 struct timeval start_tv;
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
1595 * used by mod_rewrite, mod_fastcgi, ... and others
1596 * this is self-protection
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] */
1609 - int keep_alive; /* only request.c can enable it, all other just disable */
1612 + int keep_alive; /* only request.c can enable it, all others just disable */
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 ]*/
1623 int traffic_limit_reached;
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 */
1636 buffer *dst_addr_buf;
1639 buffer *parse_request;
1640 unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */
1645 - physical physical;
1646 + physical physical;
1653 buffer *authed_user;
1654 array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
1664 connection_type mode;
1667 void **plugin_ctx; /* plugin connection specific config */
1670 specific_config conf; /* global connection specific config */
1671 cond_cache_t *cond_cache;
1674 buffer *server_name;
1678 buffer *error_handler;
1679 int error_handler_saved_status;
1680 int in_error_handler;
1683 void *srv_socket; /* reference to the server-socket (typecast to server_socket) */
1689 @@ -439,39 +423,48 @@
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;
1703 unsigned short port;
1707 buffer *errorlog_file;
1708 unsigned short errorlog_use_syslog;
1711 unsigned short dont_daemonize;
1720 buffer *event_handler;
1723 buffer *modules_dir;
1724 buffer *network_backend;
1726 array *upload_tempdirs;
1729 unsigned short max_worker;
1730 unsigned short max_fds;
1731 unsigned short max_conns;
1732 unsigned short max_request_size;
1735 unsigned short log_request_header_on_error;
1736 unsigned short log_state_handling;
1738 - enum { STAT_CACHE_ENGINE_UNSET,
1739 - STAT_CACHE_ENGINE_NONE,
1740 - STAT_CACHE_ENGINE_SIMPLE,
1741 - STAT_CACHE_ENGINE_FAM
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;
1750 @@ -480,14 +473,14 @@
1756 buffer *ssl_pemfile;
1757 buffer *ssl_ca_file;
1758 unsigned short use_ipv6;
1759 unsigned short is_ssl;
1768 @@ -495,37 +488,37 @@
1771 server_socket **ptr;
1776 } server_socket_array;
1778 typedef struct server {
1779 server_socket_array srv_sockets;
1784 enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
1785 buffer *errorlog_buf;
1788 fdevents *ev, *ev_ins;
1791 buffer_plugin plugins;
1805 int max_fds; /* max possible fds */
1806 int cur_fds; /* currently used fds */
1807 int want_fds; /* waiting fds */
1808 int sockets_disabled;
1814 @@ -533,13 +526,13 @@
1815 buffer *response_header;
1816 buffer *response_range;
1820 buffer *tmp_chunk_len;
1823 buffer *empty_string; /* is necessary for cond_match */
1825 buffer *cond_check_buf;
1830 inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
1831 @@ -547,31 +540,31 @@
1832 mtime_cache_type mtime_cache[FILE_CACHE_MAX];
1839 time_t last_generated_date_ts;
1840 time_t last_generated_debug_ts;
1844 buffer *ts_debug_str;
1845 buffer *ts_date_str;
1850 array *config_touched;
1853 array *config_context;
1854 specific_config **config_storage;
1857 server_config srvconf;
1860 int config_deprecated;
1864 connections *joblist;
1865 connections *fdwaitqueue;
1868 stat_cache *stat_cache;
1871 @@ -588,18 +581,20 @@
1872 * fastcgi.backend.<key>.disconnects = ...
1877 fdevent_handler_t event_handler;
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);
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);
1897 --- ../lighttpd-1.4.11/src/buffer.c 2006-01-13 00:00:45.000000000 +0200
1898 +++ lighttpd-1.4.12/src/buffer.c 2006-07-11 22:07:52.000000000 +0300
1909 buffer* buffer_init(void) {
1913 b = malloc(sizeof(*b));
1935 void buffer_free(buffer *b) {
1938 void buffer_reset(buffer *b) {
1942 /* limit don't reuse buffer larger than ... bytes */
1943 if (b->size > BUFFER_MAX_REUSE_SIZE) {
1956 - * allocate (if neccessary) enough space for 'size' bytes and
1958 + * allocate (if necessary) enough space for 'size' bytes and
1959 * set the 'used' counter to 0
1964 #define BUFFER_PIECE_SIZE 64
1966 int buffer_prepare_copy(buffer *b, size_t size) {
1969 - if ((0 == b->size) ||
1971 + if ((0 == b->size) ||
1973 if (b->size) free(b->ptr);
1978 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
1980 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
1981 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
1984 b->ptr = malloc(b->size);
1992 - * increase the internal buffer (if neccessary) to append another 'size' byte
1994 + * increase the internal buffer (if necessary) to append another 'size' byte
1995 * ->used isn't changed
2000 int buffer_prepare_append(buffer *b, size_t size) {
2007 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
2009 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
2010 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2013 b->ptr = malloc(b->size);
2016 } else if (b->used + size > b->size) {
2019 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
2021 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
2022 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2025 b->ptr = realloc(b->ptr, b->size);
2030 int buffer_copy_string(buffer *b, const char *s) {
2034 if (!s || !b) return -1;
2036 s_len = strlen(s) + 1;
2037 @@ -136,26 +136,26 @@
2039 int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
2040 if (!s || !b) return -1;
2042 - /* removed optimization as we have to keep the empty string
2044 + /* removed optimization as we have to keep the empty string
2045 * in some cases for the config handling
2048 * url.access-deny = ( "" )
2050 if (s_len == 0) return 0;
2053 buffer_prepare_copy(b, s_len + 1);
2056 memcpy(b->ptr, s, s_len);
2057 b->ptr[s_len] = '\0';
2058 b->used = s_len + 1;
2064 int buffer_copy_string_buffer(buffer *b, const buffer *src) {
2065 if (!src) return -1;
2068 if (src->used == 0) {
2071 @@ -201,10 +201,10 @@
2074 * append a string to the end of the buffer
2076 - * the resulting buffer is terminated with a '\0'
2077 - * s is treated as a un-terminated string (a \0 is handled a normal character)
2080 + * the resulting buffer is terminated with a '\0'
2081 + * s is treated as an un-terminated string (a \0 is handled as a normal character)
2084 * @param s the string
2085 * @param s_len size of the string (without the terminating \0)
2087 int buffer_append_string_buffer(buffer *b, const buffer *src) {
2088 if (!src) return -1;
2089 if (src->used == 0) return 0;
2092 return buffer_append_string_len(b, src->ptr, src->used - 1);
2097 int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
2098 if (!s || !b) return -1;
2104 return buffer_append_memory(b, s, s_len);
2107 @@ -402,46 +402,115 @@
2113 + * init the ptr buffer
2116 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer)
2118 + buffer_ptr *l = calloc(1, sizeof(buffer_ptr));
2125 + * free the buffer_array
2128 +void buffer_ptr_free(buffer_ptr *l)
2131 + buffer_ptr_clear(l);
2136 +void buffer_ptr_clear(buffer_ptr *l)
2138 + assert(NULL != l);
2140 + if (l->free && l->used) {
2142 + for (i = 0; i < l->used; i ++) {
2143 + l->free(l->ptr[i]);
2155 +void buffer_ptr_append(buffer_ptr* l, void *item)
2157 + assert(NULL != l);
2158 + if (l->ptr == NULL) {
2160 + l->ptr = (void **)malloc(sizeof(void *) * l->size);
2162 + else if (l->used == l->size) {
2164 + l->ptr = realloc(l->ptr, sizeof(void *) * l->size);
2166 + l->ptr[l->used++] = item;
2169 +void *buffer_ptr_pop(buffer_ptr* l)
2171 + assert(NULL != l && l->used > 0);
2172 + return l->ptr[--l->used];
2175 +void *buffer_ptr_top(buffer_ptr* l)
2177 + assert(NULL != l && l->used > 0);
2178 + return l->ptr[l->used-1];
2186 buffer_array* buffer_array_init(void) {
2190 b = malloc(sizeof(*b));
2202 void buffer_array_reset(buffer_array *b) {
2209 /* if they are too large, reduce them */
2210 for (i = 0; i < b->used; i++) {
2211 buffer_reset(b->ptr[i]);
2220 - * free the buffer_array
2222 + * free the buffer_array
2226 void buffer_array_free(buffer_array *b) {
2231 for (i = 0; i < b->size; i++) {
2232 if (b->ptr[i]) buffer_free(b->ptr[i]);
2236 buffer *buffer_array_append_get_buffer(buffer_array *b) {
2242 b->ptr = malloc(sizeof(*b->ptr) * b->size);
2243 @@ -467,13 +536,13 @@
2249 if (b->ptr[b->used] == NULL) {
2250 b->ptr[b->used] = buffer_init();
2254 b->ptr[b->used]->used = 0;
2257 return b->ptr[b->used++];
2260 @@ -482,23 +551,23 @@
2262 if (len == 0) return NULL;
2263 if (needle == NULL) return NULL;
2266 if (b->used < len) return NULL;
2269 for(i = 0; i < b->used - len; i++) {
2270 if (0 == memcmp(b->ptr + i, needle, len)) {
2279 buffer *buffer_init_string(const char *str) {
2280 buffer *b = buffer_init();
2283 buffer_copy_string(b, str);
2293 - * check if two buffer contain the same data
2295 + * check if two buffers contain the same data
2297 * HISTORY: this function was pretty much optimized, but didn't handled
2298 * alignment properly.
2300 @@ -522,100 +591,100 @@
2302 int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
2310 return buffer_is_equal(a, &b);
2313 /* simple-assumption:
2315 - * most parts are equal and doing a case conversion needs time
2318 + * most parts are equal and doing a case conversion takes time
2321 int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
2322 size_t ndx = 0, max_ndx;
2324 size_t mask = sizeof(*al) - 1;
2330 - /* is the alignment correct ? */
2332 + /* is the alignment correct? */
2333 if ( ((size_t)al & mask) == 0 &&
2334 ((size_t)bl & mask) == 0 ) {
2337 max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
2340 for (; ndx < max_ndx; ndx += sizeof(*al)) {
2341 if (*al != *bl) break;
2355 max_ndx = ((a_len < b_len) ? a_len : b_len);
2358 for (; ndx < max_ndx; ndx++) {
2359 char a1 = *a++, b1 = *b++;
2363 if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z'))
2365 else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z'))
2367 if ((a1 - b1) != 0) return (a1 - b1);
2379 * check if the rightmost bytes of the string are equal.
2386 int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
2387 /* no, len -> equal */
2388 if (len == 0) return 1;
2391 /* len > 0, but empty buffers -> not equal */
2392 if (b1->used == 0 || b2->used == 0) return 0;
2395 /* buffers too small -> not equal */
2396 - if (b1->used - 1 < len || b1->used - 1 < len) return 0;
2398 - if (0 == strncmp(b1->ptr + b1->used - 1 - len,
2399 + if (b1->used - 1 < len || b2->used - 1 < len) return 0;
2401 + if (0 == strncmp(b1->ptr + b1->used - 1 - len,
2402 b2->ptr + b2->used - 1 - len, len)) {
2410 int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
2415 if (in_len * 2 < in_len) return -1;
2418 buffer_prepare_copy(b, in_len * 2 + 1);
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];
2425 b->ptr[b->used++] = '\0';
2432 0 1 2 3 4 5 6 7 8 9 A B C D E F
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 */
2441 0 1 2 3 4 5 6 7 8 9 A B C D E F
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 */
2450 0 1 2 3 4 5 6 7 8 9 A B C D E F
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 */
2459 0 1 2 3 4 5 6 7 8 9 A B C D E F
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
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;
2489 const char *map = NULL;
2492 if (!s || !b) return -1;
2495 if (b->ptr[b->used - 1] != '\0') {
2500 if (s_len == 0) return 0;
2503 @@ -760,12 +829,12 @@
2504 map = encoded_chars_hex;
2506 case ENCODING_UNSET:
2508 + return buffer_append_string_len(b, s, s_len);
2511 assert(map != NULL);
2513 - /* count to-be-encoded-characters */
2515 + /* count to-be-encoded characters */
2516 for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2525 buffer_prepare_append(b, d_len);
2528 for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2531 @@ -820,16 +889,16 @@
2535 - /* terminate buffer and calculate new length */
2536 + /* terminate buffer and calculate new length */
2537 b->ptr[b->used + d_len - 1] = '\0';
2546 -/* decodes url-special-chars inplace.
2547 +/* decodes url-special chars in-place.
2548 * replaces non-printable characters with '_'
2551 @@ -854,10 +923,10 @@
2552 low = hex2int(*(src + 2));
2554 high = (high << 4) | low;
2556 - /* map control-characters out */
2558 + /* map out control characters */
2559 if (high < 32 || high == 127) high = '_';
2566 * /abc/./xyz gets /abc/xyz
2567 * /abc//xyz gets /abc/xyz
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.
2574 @@ -979,7 +1048,7 @@
2576 int light_isxdigit(int c) {
2577 if (light_isdigit(c)) return 1;
2581 return (c >= 'a' && c <= 'f');
2583 @@ -993,31 +1062,56 @@
2584 return light_isdigit(c) || light_isalpha(c);
2587 +#undef BUFFER_CTYPE_FUNC
2588 +#define BUFFER_CTYPE_FUNC(type) \
2589 + int buffer_is##type(buffer *b) { \
2591 + if (b->used < 2) return 0; \
2593 + len = b->used - 1; \
2594 + /* c-string only */ \
2595 + if (b->ptr[len] != '\0') { \
2598 + /* check on the whole string */ \
2599 + for (i = 0; i < len; i ++) { \
2600 + if (!light_is##type(b->ptr[i])) { \
2607 +BUFFER_CTYPE_FUNC(digit)
2608 +BUFFER_CTYPE_FUNC(xdigit)
2609 +BUFFER_CTYPE_FUNC(alpha)
2610 +BUFFER_CTYPE_FUNC(alnum)
2612 int buffer_to_lower(buffer *b) {
2616 if (b->used == 0) return 0;
2619 for (c = b->ptr; *c; c++) {
2620 if (*c >= 'A' && *c <= 'Z') {
2630 int buffer_to_upper(buffer *b) {
2634 if (b->used == 0) return 0;
2637 for (c = b->ptr; *c; c++) {
2638 if (*c >= 'a' && *c <= 'z') {
2646 --- ../lighttpd-1.4.11/src/buffer.h 2006-01-13 00:00:45.000000000 +0200
2647 +++ lighttpd-1.4.12/src/buffer.h 2006-07-11 22:07:52.000000000 +0300
2659 +typedef void (*buffer_ptr_free_t)(void *p);
2665 + buffer_ptr_free_t free;
2679 - size_t offset; /* input-pointer */
2681 - size_t used; /* output-pointer */
2683 + size_t offset; /* input pointer */
2685 + size_t used; /* output pointer */
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);
2696 buffer_array* buffer_array_init(void);
2697 void buffer_array_free(buffer_array *b);
2698 void buffer_array_reset(buffer_array *b);
2700 buffer* buffer_init_string(const char *str);
2701 void buffer_free(buffer *b);
2702 void buffer_reset(buffer *b);
2705 int buffer_prepare_copy(buffer *b, size_t size);
2706 int buffer_prepare_append(buffer *b, size_t size);
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 & 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 "&" 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);
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)
2731 #define BUFFER_APPEND_STRING_CONST(x, y) \
2732 buffer_append_string_len(x, y, sizeof(y) - 1)
2734 #define BUFFER_COPY_STRING_CONST(x, y) \
2735 buffer_copy_string_len(x, y, sizeof(y) - 1)
2737 -#define BUFFER_APPEND_SLASH(x) \
2738 - if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); }
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
2744 #define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0)
2745 #define UNUSED(x) ( (void)(x) )
2747 --- ../lighttpd-1.4.11/src/chunk.c 2005-11-18 15:18:19.000000000 +0200
2748 +++ lighttpd-1.4.12/src/chunk.c 2006-07-11 22:07:51.000000000 +0300
2751 * the network chunk-API
2758 #include <sys/types.h>
2759 #include <sys/stat.h>
2760 -#include <sys/mman.h>
2764 -#include <unistd.h>
2772 +#include "sys-mmap.h"
2773 +#include "sys-files.h"
2775 chunkqueue *chunkqueue_init(void) {
2779 cq = calloc(1, sizeof(*cq));
2792 static chunk *chunk_init(void) {
2796 c = calloc(1, sizeof(*c));
2799 c->mem = buffer_init();
2800 c->file.name = buffer_init();
2802 c->file.mmap.start = MAP_FAILED;
2809 static void chunk_free(chunk *c) {
2813 buffer_free(c->mem);
2814 buffer_free(c->file.name);
2818 static void chunk_reset(chunk *c) {
2822 buffer_reset(c->mem);
2824 if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
2825 unlink(c->file.name->ptr);
2829 buffer_reset(c->file.name);
2831 if (c->file.fd != -1) {
2834 void chunkqueue_free(chunkqueue *cq) {
2841 for (c = cq->first; c; ) {
2848 for (c = cq->unused; c; ) {
2858 static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) {
2861 - /* check if we have a unused chunk */
2863 + /* check if we have an unused chunk */
2867 @@ -109,18 +110,18 @@
2869 cq->unused_chunks--;
2876 static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
2877 c->next = cq->first;
2881 if (cq->last == NULL) {
2889 @@ -129,19 +130,19 @@
2895 if (cq->first == NULL) {
2903 void chunkqueue_reset(chunkqueue *cq) {
2905 /* move everything to the unused queue */
2907 - /* mark all read written */
2909 + /* mark all read written */
2910 for (c = cq->first; c; c = c->next) {
2915 c->offset = c->file.length;
2922 @@ -162,93 +163,93 @@
2924 int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
2928 if (len == 0) return 0;
2931 c = chunkqueue_get_unused_chunk(cq);
2934 c->type = FILE_CHUNK;
2937 buffer_copy_string_buffer(c->file.name, fn);
2938 c->file.start = offset;
2939 c->file.length = len;
2943 chunkqueue_append_chunk(cq, c);
2949 int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
2953 if (mem->used == 0) return 0;
2956 c = chunkqueue_get_unused_chunk(cq);
2957 c->type = MEM_CHUNK;
2959 buffer_copy_string_buffer(c->mem, mem);
2962 chunkqueue_append_chunk(cq, c);
2968 int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
2972 if (mem->used == 0) return 0;
2975 c = chunkqueue_get_unused_chunk(cq);
2976 c->type = MEM_CHUNK;
2978 buffer_copy_string_buffer(c->mem, mem);
2981 chunkqueue_prepend_chunk(cq, c);
2987 int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
2991 if (len == 0) return 0;
2994 c = chunkqueue_get_unused_chunk(cq);
2995 c->type = MEM_CHUNK;
2997 buffer_copy_string_len(c->mem, mem, len - 1);
3000 chunkqueue_append_chunk(cq, c);
3006 buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
3010 c = chunkqueue_get_unused_chunk(cq);
3013 c->type = MEM_CHUNK;
3015 buffer_reset(c->mem);
3018 chunkqueue_prepend_chunk(cq, c);
3024 buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
3028 c = chunkqueue_get_unused_chunk(cq);
3031 c->type = MEM_CHUNK;
3033 buffer_reset(c->mem);
3036 chunkqueue_append_chunk(cq, c);
3043 chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
3045 buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
3048 c = chunkqueue_get_unused_chunk(cq);
3050 c->type = FILE_CHUNK;
3051 @@ -273,12 +274,12 @@
3054 /* we have several tempdirs, only if all of them fail we jump out */
3057 for (i = 0; i < cq->tempdirs->used; i++) {
3058 data_string *ds = (data_string *)cq->tempdirs->data[i];
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");
3065 if (-1 != (c->file.fd = mkstemp(template->ptr))) {
3067 chunkqueue_append_chunk(cq, c);
3069 buffer_free(template);
3076 off_t chunkqueue_length(chunkqueue *cq) {
3081 for (c = cq->first; c; c = c->next) {
3084 @@ -321,14 +322,14 @@
3093 off_t chunkqueue_written(chunkqueue *cq) {
3098 for (c = cq->first; c; c = c->next) {
3111 if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
3114 - if (c->offset == c->file.length) is_finished = 1;
3115 + if (c->offset == c->file.length) is_finished = 1;
3122 --- ../lighttpd-1.4.11/src/chunk.h 2005-11-01 09:32:21.000000000 +0200
3123 +++ lighttpd-1.4.12/src/chunk.h 2006-07-11 22:07:51.000000000 +0300
3126 typedef struct chunk {
3127 enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
3130 buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
3134 off_t length; /* octets to send from the starting offset */
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 */
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 */
3149 - off_t offset; /* octets sent from this chunk
3150 - the size of the chunk is either
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
3168 size_t unused_chunks;
3170 --- ../lighttpd-1.4.11/src/configfile-glue.c 2006-03-03 20:14:56.000000000 +0200
3171 +++ lighttpd-1.4.12/src/configfile-glue.c 2006-07-11 22:07:51.000000000 +0300
3179 * are the external interface of lighttpd. The functions
3180 * are used by the server itself and the plugins.
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.
3193 int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
3198 for (i = 0; cv[i].key; i++) {
3201 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3209 switch (cv[i].type) {
3210 case T_CONFIG_ARRAY:
3211 if (du->type == TYPE_ARRAY) {
3213 data_array *da = (data_array *)du;
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();
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);
3231 array_insert_unique(cv[i].destination, (data_unset *)ds);
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);
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);
3245 log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
3251 case T_CONFIG_STRING:
3252 if (du->type == TYPE_STRING) {
3253 data_string *ds = (data_string *)du;
3256 buffer_copy_string_buffer(cv[i].destination, ds->value);
3257 + } else if (du->type == TYPE_INTEGER) {
3258 + data_integer *di = (data_integer *)du;
3260 + buffer_copy_long(cv[i].destination, di->value);
3262 log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
3270 case TYPE_INTEGER: {
3271 data_integer *di = (data_integer *)du;
3274 *((unsigned short *)(cv[i].destination)) = di->value;
3278 data_string *ds = (data_string *)du;
3281 + if (buffer_isdigit(ds->value)) {
3282 + *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
3286 log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
3292 @@ -100,19 +110,19 @@
3293 case T_CONFIG_BOOLEAN:
3294 if (du->type == TYPE_STRING) {
3295 data_string *ds = (data_string *)du;
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;
3303 log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
3309 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
3317 case T_CONFIG_DEPRECATED:
3318 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
3321 srv->config_deprecated = 1;
3327 @@ -133,25 +143,25 @@
3328 int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
3333 for (i = 0; cv[i].key; i++) {
3334 data_string *touched;
3337 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3346 touched = data_string_init();
3349 buffer_copy_string(touched->value, "");
3350 buffer_copy_string_buffer(touched->key, du->key);
3353 array_insert_unique(srv->config_touched, (data_unset *)touched);
3357 return config_insert_values_internal(srv, ca, cv);
3360 @@ -191,25 +201,25 @@
3363 /* pass the rules */
3367 case COMP_HTTP_HOST: {
3368 char *ck_colon = NULL, *val_colon = NULL;
3371 if (!buffer_is_empty(con->uri.authority)) {
3376 * append server-port to the HTTP_POST if necessary
3380 l = con->uri.authority;
3384 case CONFIG_COND_NE:
3385 case CONFIG_COND_EQ:
3386 ck_colon = strchr(dc->string->ptr, ':');
3387 val_colon = strchr(l->ptr, ':');
3390 if (ck_colon == val_colon) {
3391 /* nothing to do with it */
3393 @@ -230,21 +240,21 @@
3398 + l = srv->empty_string;
3402 case COMP_HTTP_REMOTEIP: {
3404 - /* handle remoteip limitations
3406 + /* handle remoteip limitations
3408 * "10.0.0.1" is provided for all comparisions
3411 * only for == and != we support
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 @@
3424 struct in_addr val_inp;
3427 + if (con->conf.log_condition_handling) {
3428 + l = srv->empty_string;
3430 + log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
3431 + "(", l, ") compare to", dc->string);
3434 if (*(nm_slash+1) == '\0') {
3435 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
3438 return COND_RESULT_FALSE;
3442 nm_bits = strtol(nm_slash + 1, &err, 10);
3446 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
3449 return COND_RESULT_FALSE;
3453 /* take IP convert to the native */
3454 buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
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);
3461 return COND_RESULT_FALSE;
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);
3469 return COND_RESULT_FALSE;
3475 nm = htonl(~((1 << (32 - nm_bits)) - 1));
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;
3483 case COMP_HTTP_REFERER: {
3487 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
3492 return COND_RESULT_FALSE;
3497 if (con->conf.log_condition_handling) {
3498 log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key,
3499 @@ -346,10 +363,10 @@
3501 return COND_RESULT_FALSE;
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);
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];
3519 #define elementsof(x) (sizeof(x) / sizeof(x[0]))
3521 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
3522 cache->matches, elementsof(cache->matches));
3525 cache->patterncount = n;
3527 cache->comp_value = l;
3534 return COND_RESULT_FALSE;
3538 cond_cache_t *caches = con->cond_cache;
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 ===");
3544 if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
3547 @@ -409,11 +429,11 @@
3549 if (con->conf.log_condition_handling) {
3550 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3551 - "(uncached) result:",
3553 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
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,
3560 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
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 ===");
3568 return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
3571 @@ -443,3 +460,85 @@
3575 +/* return <0 on error
3576 + * return 0-x if matched (and replaced)
3578 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result)
3582 + pcre_extra *extra;
3583 + const char *pattern;
3584 + size_t pattern_len;
3587 + pcre_keyvalue *kv;
3591 + for (i = 0; i < kvb->used; i++) {
3595 + extra = kv->key_extra;
3596 + pattern = kv->value->ptr;
3597 + pattern_len = kv->value->used - 1;
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) {
3604 + const char **list;
3605 + size_t start, end;
3609 + pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
3611 + /* search for $[0-9] */
3613 + buffer_reset(result);
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])) {
3621 + size_t num = pattern[k + 1] - '0';
3625 + buffer_append_string_len(result, pattern + start, end - start);
3627 + if (pattern[k] == '$') {
3628 + /* n is always > 0 */
3629 + if (num < (size_t)n) {
3630 + buffer_append_string(result, list[num]);
3633 + config_append_cond_match_buffer(con, context, result, num);
3641 + buffer_append_string_len(result, pattern + start, pattern_len - start);
3649 + return PCRE_ERROR_NOMATCH;
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
3663 -#include <unistd.h>
3672 -#include "license.h"
3675 #include "configparser.h"
3676 #include "configfile.h"
3677 #include "proc_open.h"
3679 +#include "sys-files.h"
3680 +#include "sys-process.h"
3684 +#define PATH_MAX 64
3687 static int config_insert(server *srv) {
3690 buffer *stat_cache_string;
3692 - config_values_t cv[] = {
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 */
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 */
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 */
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 */
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 */
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 */
3722 { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */
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 */
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 */
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 */
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 */
3745 + { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 46 */
3747 { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3748 { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3749 { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
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 },
3756 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
3762 cv[0].destination = srv->srvconf.bindhost;
3763 cv[1].destination = srv->srvconf.errorlog_file;
3764 @@ -102,33 +105,33 @@
3765 cv[4].destination = srv->srvconf.username;
3766 cv[5].destination = srv->srvconf.groupname;
3767 cv[6].destination = &(srv->srvconf.port);
3770 cv[9].destination = srv->srvconf.modules;
3771 cv[10].destination = srv->srvconf.event_handler;
3772 cv[11].destination = srv->srvconf.pid_file;
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);
3781 cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
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);
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 *));
3795 assert(srv->config_storage);
3798 for (i = 0; i < srv->config_context->used; i++) {
3802 s = calloc(1, sizeof(specific_config));
3804 s->document_root = buffer_init();
3805 @@ -154,17 +157,18 @@
3806 s->global_kbytes_per_second = 0;
3807 s->global_bytes_per_second_cnt = 0;
3808 s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
3811 cv[2].destination = s->errorfile_prefix;
3814 cv[7].destination = s->server_tag;
3815 cv[8].destination = &(s->use_ipv6);
3821 cv[14].destination = s->document_root;
3822 cv[15].destination = &(s->force_lowercase_filenames);
3823 cv[16].destination = &(s->log_condition_handling);
3824 + cv[46].destination = &(s->log_condition_cache_handling);
3825 cv[17].destination = &(s->max_keep_alive_requests);
3826 cv[18].destination = s->server_name;
3827 cv[19].destination = &(s->max_keep_alive_idle);
3828 @@ -179,23 +183,23 @@
3829 cv[28].destination = s->mimetypes;
3830 cv[29].destination = s->ssl_pemfile;
3831 cv[30].destination = &(s->is_ssl);
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);
3840 cv[35].destination = &(s->allow_http11);
3841 cv[38].destination = s->ssl_ca_file;
3842 cv[40].destination = &(s->range_requests);
3845 srv->config_storage[i] = s;
3848 if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
3854 if (buffer_is_empty(stat_cache_string)) {
3855 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
3856 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
3857 @@ -205,22 +209,22 @@
3858 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
3859 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
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;
3868 buffer_free(stat_cache_string);
3877 -#define PATCH(x) con->conf.x = s->x
3879 + con->conf.x = s->x
3880 int config_setup_connection(server *srv, connection *con) {
3881 specific_config *s = srv->config_storage[0];
3884 PATCH(allow_http11);
3886 PATCH(document_root);
3887 @@ -236,20 +240,21 @@
3888 PATCH(kbytes_per_second);
3889 PATCH(global_kbytes_per_second);
3890 PATCH(global_bytes_per_second_cnt);
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);
3897 PATCH(log_request_header);
3898 PATCH(log_response_header);
3899 PATCH(log_request_handling);
3900 PATCH(log_condition_handling);
3901 + PATCH(log_condition_cache_handling);
3902 PATCH(log_file_not_found);
3905 PATCH(range_requests);
3906 PATCH(force_lowercase_filenames);
3913 @@ -257,22 +262,22 @@
3915 int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
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];
3926 if (comp != dc->comp) continue;
3929 /* condition didn't match */
3930 if (!config_check_cond(srv, con, dc)) continue;
3934 for (j = 0; j < dc->value->used; j++) {
3935 data_unset *du = dc->value->data[j];
3938 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
3939 PATCH(document_root);
3940 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
3941 @@ -315,11 +320,13 @@
3942 PATCH(log_response_header);
3943 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
3944 PATCH(log_condition_handling);
3945 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-cache-handling"))) {
3946 + PATCH(log_condition_cache_handling);
3947 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
3948 PATCH(log_file_not_found);
3949 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
3950 PATCH(allow_http11);
3951 - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
3952 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
3953 PATCH(force_lowercase_filenames);
3954 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
3955 PATCH(global_kbytes_per_second);
3965 @@ -336,15 +343,15 @@
3971 const buffer *source;
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);
3994 t->size = t->s.size;
4003 static int config_skip_comment(tokenizer_t *t) {
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');
4011 @@ -411,44 +418,44 @@
4012 static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
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;
4026 if (t->input[t->offset + 1] == '>') {
4030 buffer_copy_string(token, "=>");
4033 tid = TK_ARRAY_ASSIGN;
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");
4043 } else if (t->in_cond) {
4044 if (t->input[t->offset + 1] == '=') {
4048 buffer_copy_string(token, "==");
4052 } else if (t->input[t->offset + 1] == '~') {
4056 buffer_copy_string(token, "=~");
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");
4069 @@ -456,51 +463,51 @@
4071 } else if (t->in_key) {
4075 buffer_copy_string_len(token, t->input + t->offset, 1);
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: =");
4095 if (t->input[t->offset + 1] == '=') {
4099 buffer_copy_string(token, "!=");
4103 } else if (t->input[t->offset + 1] == '~') {
4107 buffer_copy_string(token, "!~");
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");
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: !");
4136 @@ -546,10 +553,10 @@
4138 if (t->in_brace > 0) {
4142 buffer_copy_string(token, "(COMMA)");
4149 @@ -557,70 +564,70 @@
4150 /* search for the terminating " */
4151 start = t->input + t->offset + 1;
4152 buffer_copy_string(token, "");
4155 for (i = 1; t->input[t->offset + i]; i++) {
4156 if (t->input[t->offset + i] == '\\' &&
4157 t->input[t->offset + i + 1] == '"') {
4160 buffer_append_string_len(token, start, t->input + t->offset + i - start);
4163 start = t->input + t->offset + i + 1;
4174 if (t->input[t->offset + i] == '"') {
4178 buffer_append_string_len(token, start, t->input + t->offset + i - start);
4185 if (t->input[t->offset + i] == '\0') {
4188 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
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");
4202 t->line_pos += i + 1;
4214 buffer_copy_string(token, "(");
4224 buffer_copy_string(token, ")");
4235 buffer_copy_string(token, "$");
4241 @@ -637,96 +644,88 @@
4250 buffer_copy_string(token, "{");
4263 buffer_copy_string(token, "}");
4275 buffer_copy_string(token, "[");
4288 buffer_copy_string(token, "]");
4293 t->line_pos += config_skip_comment(t);
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])
4305 if (i && t->input[t->offset + i]) {
4306 tid = TK_SRVVARNAME;
4307 buffer_copy_string_len(token, t->input + t->offset, i);
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");
4322 } else if (isdigit((unsigned char)c)) {
4323 /* take all digits */
4324 for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
4327 /* was there it least a digit ? */
4328 - if (i && t->input[t->offset + i]) {
4333 buffer_copy_string_len(token, t->input + t->offset, i);
4340 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4341 - "source:", t->source,
4342 - "line:", t->line, "pos:", t->line_pos,
4343 - "unexpected EOF");
4348 /* the key might consist of [-.0-9a-z] */
4349 - for (i = 0; t->input[t->offset + i] &&
4350 - (isalnum((unsigned char)t->input[t->offset + i]) ||
4351 + for (i = 0; t->input[t->offset + i] &&
4352 + (isalnum((unsigned char)t->input[t->offset + i]) ||
4353 t->input[t->offset + i] == '.' ||
4354 t->input[t->offset + i] == '_' || /* for env.* */
4355 t->input[t->offset + i] == '-'
4359 if (i && t->input[t->offset + i]) {
4360 buffer_copy_string_len(token, t->input + t->offset, i);
4363 if (strcmp(token->ptr, "include") == 0) {
4365 } else if (strcmp(token->ptr, "include_shell") == 0) {
4366 @@ -738,14 +737,14 @@
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");
4384 @@ -753,16 +752,16 @@
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);
4402 } else if (t->offset < t->size) {
4403 fprintf(stderr, "%s.%d: %d, %s\n",
4404 @@ -781,10 +780,11 @@
4405 pParser = configparserAlloc( malloc );
4406 lasttoken = buffer_init();
4407 token = buffer_init();
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);
4414 token = buffer_init();
4417 @@ -797,14 +797,14 @@
4420 configparserFree(pParser, free);
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);
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));
4455 char oldpwd[PATH_MAX];
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));
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));
4472 @@ -896,13 +896,12 @@
4473 static void context_init(server *srv, config_t *context) {
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();
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);
4488 @@ -918,18 +917,15 @@
4489 context_init(srv, &context);
4490 context.all_configs = srv->config_context;
4499 + /* use the current dir as basedir for all other includes
4501 + pos = strrchr(fn, DIR_SEPERATOR);
4504 buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
4509 dc = data_config_init();
4510 buffer_copy_string(dc->key, "global");
4513 dpid->value = getpid();
4514 buffer_copy_string(dpid->key, "var.PID");
4515 array_insert_unique(srv->config, (data_unset *)dpid);
4518 dcwd = data_string_init();
4519 buffer_prepare_copy(dcwd->value, 1024);
4520 if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
4527 if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
4529 data_array *prepends;
4530 @@ -1026,22 +1022,23 @@
4531 buffer_copy_string(modules->key, "server.modules");
4532 array_insert_unique(srv->config, (data_unset *)modules);
4537 if (0 != config_insert(srv)) {
4546 int config_set_defaults(server *srv) {
4548 specific_config *s = srv->config_storage[0];
4549 struct stat st1, st2;
4551 - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4554 + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4556 /* - poll is most reliable
4557 * - select works everywhere
4558 * - linux-* are experimental
4559 @@ -1067,20 +1064,21 @@
4561 { FDEVENT_HANDLER_UNSET, NULL }
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");
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");
4580 if (buffer_is_empty(srv->srvconf.changeroot)) {
4581 - if (-1 == stat(s->document_root->ptr, &st1)) {
4582 - log_error_write(srv, __FILE__, __LINE__, "sb",
4583 + pathname_unix2local(s->document_root);
4584 + if (-1 == stat(s->document_root->ptr, &st1)) {
4585 + log_error_write(srv, __FILE__, __LINE__, "sbs",
4586 "base-docroot doesn't exist:",
4587 - s->document_root);
4588 + s->document_root, strerror(errno));
4592 @@ -1088,18 +1086,18 @@
4593 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
4594 buffer_append_string_buffer(srv->tmp_buf, s->document_root);
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:",
4609 - buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4611 - buffer_to_lower(srv->tmp_buf);
4612 + buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4614 + buffer_to_lower(srv->tmp_buf);
4616 if (0 == stat(srv->tmp_buf->ptr, &st1)) {
4618 @@ -1107,68 +1105,68 @@
4619 is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
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);
4625 - buffer_to_upper(srv->tmp_buf);
4626 + buffer_to_upper(srv->tmp_buf);
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/" */
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. */
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)) {
4642 + /* upper case exists too, doesn't the FS handle this ? */
4644 + /* upper and lower have the same inode -> case-insensitve FS */
4646 + if (st1.st_ino == st2.st_ino) {
4647 + /* upper and lower have the same inode -> case-insensitve FS */
4649 + s->force_lowercase_filenames = 1;
4654 - /* upper case exists too, doesn't the FS handle this ? */
4656 - /* upper and lower have the same inode -> case-insensitve FS */
4658 - if (st1.st_ino == st2.st_ino) {
4659 - /* upper and lower have the same inode -> case-insensitve FS */
4661 - s->force_lowercase_filenames = 1;
4666 if (srv->srvconf.port == 0) {
4667 srv->srvconf.port = s->is_ssl ? 443 : 80;
4671 if (srv->srvconf.event_handler->used == 0) {
4672 /* choose a good default
4674 - * the event_handler list is sorted by 'goodness'
4676 + * the event_handler list is sorted by 'goodness'
4677 * taking the first available should be the best solution
4679 srv->event_handler = event_handlers[0].et;
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");
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;
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 );
4715 @@ -1176,19 +1174,19 @@
4717 if (buffer_is_empty(s->ssl_pemfile)) {
4718 /* PEM file is require */
4720 - log_error_write(srv, __FILE__, __LINE__, "s",
4722 + log_error_write(srv, __FILE__, __LINE__, "s",
4723 "ssl.pemfile has to be set");
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");
4741 --- ../lighttpd-1.4.11/src/configfile.h 2005-08-23 17:36:12.000000000 +0300
4742 +++ lighttpd-1.4.12/src/configfile.h 2006-07-11 22:07:51.000000000 +0300
4747 - array *configs_stack; /* to parse nested block */
4748 + buffer_ptr *configs_stack; /* to parse nested block */
4749 data_config *current; /* current started with { */
4752 --- ../lighttpd-1.4.11/src/configparser.c 2006-02-01 19:51:15.000000000 +0200
4753 +++ lighttpd-1.4.12/src/configparser.c 2006-07-11 22:08:02.000000000 +0300
4755 dc->parent = ctx->current;
4756 array_insert_unique(dc->parent->childs, (data_unset *)dc);
4758 - array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
4759 + buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
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);
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) {
4775 - if (NULL != (env = getenv(key->ptr + 4))) {
4777 - ds = data_string_init();
4778 - buffer_append_string(ds->value, env);
4779 - return (data_unset *)ds;
4782 - fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
4793 - fprintf(stderr, "get var %s\n", key->ptr);
4794 + fprintf(stderr, "get var %s\n", key->ptr);
4796 - for (dc = ctx->current; dc; dc = dc->parent) {
4797 + for (dc = ctx->current; dc; dc = dc->parent) {
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);
4804 - if (NULL != (du = array_get_element(dc->value, key->ptr))) {
4805 - return du->copy(du);
4807 + if (NULL != (du = array_get_element(dc->value, key->ptr))) {
4808 + return du->copy(du);
4810 - fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
4817 /* op1 is to be eat/return by this function, op1->key is not cared
4818 @@ -124,14 +106,14 @@
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.
4829 ** These constants (all generated automatically by the parser generator)
4830 ** specify the various kinds of tokens (terminals) that the parser
4834 ** Each symbol here is a terminal symbol in the grammar.
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
4843 ** YYFALLBACK If defined, this indicates that one or more tokens
4844 ** have fall-back values which should be used if the
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
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
4860 +#define YYNSTATE 63
4862 #define YYERRORSYMBOL 26
4863 #define YYERRSYMDT yy95
4864 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
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
4872 ** Suppose the action integer is N. Then the action is determined as
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.
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.
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,
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,
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,
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,
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,
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,
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,
4986 #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
4988 /* The next table maps tokens into fallback tokens. If a construct
4989 ** like the following:
4992 ** %fallback ID X Y Z.
4994 ** appears in the grammer, then ID becomes a fallback token for X, Y,
4995 @@ -359,10 +343,10 @@
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
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",
5073 ** This function allocates a new parser.
5074 ** The only argument is a pointer to a function which works like
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.
5084 ** Note: during a reduce, the only symbols destroyed are those
5085 @@ -528,44 +513,44 @@
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"
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"
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"
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"
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"
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"
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"
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"
5144 default: break; /* If no destructor action specified: do nothing */
5152 ** Deallocate and destroy a parser. Destructors are all called for
5153 ** all stack elements before shutting the parser down.
5158 int stateno = pParser->yystack[pParser->yyidx].stateno;
5161 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
5162 i = yy_shift_ofst[stateno];
5163 if( i==YY_SHIFT_USE_DFLT ){
5167 int stateno = pParser->yystack[pParser->yyidx].stateno;
5170 i = yy_reduce_ofst[stateno];
5171 if( i==YY_REDUCE_USE_DFLT ){
5172 return yy_default[stateno];
5182 configparserARG_FETCH;
5183 yymsp = &yypParser->yystack[yypParser->yyidx];
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]);
5191 /* No destructor defined for global */
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);
5202 @@ -847,10 +833,15 @@
5203 yy_destructor(1,&yymsp[0].minor);
5206 -#line 162 "./configparser.y"
5207 +#line 145 "./configparser.y"
5209 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5210 - if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5211 + if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5212 + fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5213 + ctx->current->context_ndx,
5214 + ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
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;
5220 @@ -864,16 +855,21 @@
5221 buffer_free(yymsp[-2].minor.yy43);
5222 yymsp[-2].minor.yy43 = NULL;
5224 -#line 867 "configparser.c"
5225 +#line 858 "configparser.c"
5226 yy_destructor(2,&yymsp[-1].minor);
5229 -#line 179 "./configparser.y"
5230 +#line 167 "./configparser.y"
5232 array *vars = ctx->current->value;
5235 - if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5236 + if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5237 + fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5238 + ctx->current->context_ndx,
5239 + ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5241 + } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5242 /* exists in current block */
5243 du = configparser_merge_data(du, yymsp[0].minor.yy41);
5246 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5247 array_replace(vars, du);
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);
5253 @@ -892,22 +889,20 @@
5254 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5255 array_insert_unique(ctx->current->value, du);
5257 + yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5259 - fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
5260 - ctx->current->context_ndx,
5261 - ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
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);
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;
5271 -#line 906 "configparser.c"
5272 +#line 901 "configparser.c"
5273 yy_destructor(3,&yymsp[-1].minor);
5276 -#line 214 "./configparser.y"
5277 +#line 206 "./configparser.y"
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;
5285 -#line 922 "configparser.c"
5286 +#line 917 "configparser.c"
5289 -#line 226 "./configparser.y"
5290 +#line 218 "./configparser.y"
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;
5298 -#line 935 "configparser.c"
5299 +#line 930 "configparser.c"
5300 yy_destructor(5,&yymsp[-1].minor);
5303 -#line 236 "./configparser.y"
5304 +#line 228 "./configparser.y"
5306 yygotominor.yy41 = yymsp[0].minor.yy41;
5307 yymsp[0].minor.yy41 = NULL;
5309 -#line 944 "configparser.c"
5310 +#line 939 "configparser.c"
5313 -#line 241 "./configparser.y"
5314 +#line 233 "./configparser.y"
5316 - yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43);
5317 + if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5320 + if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) {
5322 + ds = data_string_init();
5323 + buffer_append_string(ds->value, env);
5324 + yygotominor.yy41 = (data_unset *)ds;
5327 + yygotominor.yy41 = NULL;
5328 + fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4);
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);
5335 if (!yygotominor.yy41) {
5336 /* make a dummy so it won't crash */
5337 yygotominor.yy41 = (data_unset *)data_string_init();
5338 @@ -954,50 +966,59 @@
5339 buffer_free(yymsp[0].minor.yy43);
5340 yymsp[0].minor.yy43 = NULL;
5342 -#line 957 "configparser.c"
5343 +#line 969 "configparser.c"
5346 -#line 251 "./configparser.y"
5347 +#line 260 "./configparser.y"
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;
5354 -#line 967 "configparser.c"
5355 +#line 979 "configparser.c"
5358 -#line 258 "./configparser.y"
5359 +#line 267 "./configparser.y"
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;
5366 -#line 977 "configparser.c"
5367 +#line 989 "configparser.c"
5370 -#line 264 "./configparser.y"
5371 +#line 273 "./configparser.y"
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;
5378 -#line 987 "configparser.c"
5379 +#line 999 "configparser.c"
5382 -#line 270 "./configparser.y"
5383 +#line 279 "./configparser.y"
5385 + yygotominor.yy40 = array_init();
5387 +#line 1006 "configparser.c"
5388 + yy_destructor(8,&yymsp[-1].minor);
5389 + yy_destructor(9,&yymsp[0].minor);
5392 +#line 282 "./configparser.y"
5394 yygotominor.yy40 = yymsp[-1].minor.yy40;
5395 yymsp[-1].minor.yy40 = NULL;
5397 -#line 995 "configparser.c"
5398 +#line 1016 "configparser.c"
5399 yy_destructor(8,&yymsp[-2].minor);
5400 yy_destructor(9,&yymsp[0].minor);
5403 -#line 275 "./configparser.y"
5405 +#line 287 "./configparser.y"
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;
5413 -#line 1017 "configparser.c"
5414 +#line 1038 "configparser.c"
5415 yy_destructor(10,&yymsp[-1].minor);
5418 -#line 292 "./configparser.y"
5420 +#line 304 "./configparser.y"
5422 yygotominor.yy40 = yymsp[-1].minor.yy40;
5423 yymsp[-1].minor.yy40 = NULL;
5425 -#line 1026 "configparser.c"
5426 +#line 1047 "configparser.c"
5427 yy_destructor(10,&yymsp[0].minor);
5430 -#line 297 "./configparser.y"
5432 +#line 309 "./configparser.y"
5434 yygotominor.yy40 = array_init();
5435 array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
5436 yymsp[0].minor.yy41 = NULL;
5438 -#line 1036 "configparser.c"
5439 +#line 1057 "configparser.c"
5442 -#line 303 "./configparser.y"
5444 +#line 315 "./configparser.y"
5446 yygotominor.yy41 = yymsp[0].minor.yy41;
5447 yymsp[0].minor.yy41 = NULL;
5449 -#line 1044 "configparser.c"
5450 +#line 1065 "configparser.c"
5453 -#line 307 "./configparser.y"
5455 +#line 319 "./configparser.y"
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;
5463 -#line 1056 "configparser.c"
5464 +#line 1077 "configparser.c"
5465 yy_destructor(11,&yymsp[-1].minor);
5468 - yy_destructor(1,&yymsp[0].minor);
5471 + yy_destructor(1,&yymsp[0].minor);
5474 -#line 319 "./configparser.y"
5477 +#line 331 "./configparser.y"
5480 dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
5482 configparser_push(ctx, dc, 0);
5484 -#line 1072 "configparser.c"
5485 +#line 1093 "configparser.c"
5486 yy_destructor(12,&yymsp[0].minor);
5489 -#line 326 "./configparser.y"
5491 +#line 338 "./configparser.y"
5495 @@ -1082,16 +1103,16 @@
5497 assert(cur && ctx->current);
5499 - yygotominor.yy0 = cur;
5500 + yygotominor.yy78 = cur;
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);
5510 -#line 337 "./configparser.y"
5512 +#line 349 "./configparser.y"
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;
5520 -#line 1103 "configparser.c"
5521 +#line 1124 "configparser.c"
5522 /* No destructor defined for eols */
5523 yy_destructor(15,&yymsp[-1].minor);
5526 -#line 346 "./configparser.y"
5528 +#line 358 "./configparser.y"
5530 yygotominor.yy78 = yymsp[0].minor.yy78;
5531 yymsp[0].minor.yy78 = NULL;
5533 -#line 1113 "configparser.c"
5534 +#line 1134 "configparser.c"
5537 -#line 351 "./configparser.y"
5539 +#line 363 "./configparser.y"
5543 @@ -1124,14 +1145,14 @@
5545 yygotominor.yy78 = cur;
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);
5555 -#line 362 "./configparser.y"
5557 +#line 374 "./configparser.y"
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;
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);
5572 -#line 496 "./configparser.y"
5574 +#line 508 "./configparser.y"
5576 yygotominor.yy27 = CONFIG_COND_EQ;
5578 -#line 1279 "configparser.c"
5579 +#line 1300 "configparser.c"
5580 yy_destructor(20,&yymsp[0].minor);
5583 -#line 499 "./configparser.y"
5585 +#line 511 "./configparser.y"
5587 yygotominor.yy27 = CONFIG_COND_MATCH;
5589 -#line 1287 "configparser.c"
5590 +#line 1308 "configparser.c"
5591 yy_destructor(21,&yymsp[0].minor);
5594 -#line 502 "./configparser.y"
5596 +#line 514 "./configparser.y"
5598 yygotominor.yy27 = CONFIG_COND_NE;
5600 -#line 1295 "configparser.c"
5601 +#line 1316 "configparser.c"
5602 yy_destructor(22,&yymsp[0].minor);
5605 -#line 505 "./configparser.y"
5607 +#line 517 "./configparser.y"
5609 yygotominor.yy27 = CONFIG_COND_NOMATCH;
5611 -#line 1303 "configparser.c"
5612 +#line 1324 "configparser.c"
5613 yy_destructor(23,&yymsp[0].minor);
5616 -#line 509 "./configparser.y"
5618 +#line 521 "./configparser.y"
5620 yygotominor.yy43 = NULL;
5622 @@ -1321,10 +1342,10 @@
5623 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5624 yymsp[0].minor.yy41 = NULL;
5626 -#line 1324 "configparser.c"
5627 +#line 1345 "configparser.c"
5630 -#line 526 "./configparser.y"
5632 +#line 538 "./configparser.y"
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;
5640 -#line 1337 "configparser.c"
5641 +#line 1358 "configparser.c"
5642 yy_destructor(24,&yymsp[-1].minor);
5645 -#line 536 "./configparser.y"
5647 +#line 548 "./configparser.y"
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;
5655 -#line 1351 "configparser.c"
5656 +#line 1372 "configparser.c"
5657 yy_destructor(25,&yymsp[-1].minor);
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
5664 -#line 125 "./configparser.y"
5665 +#line 107 "./configparser.y"
5669 -#line 1385 "configparser.c"
5670 +#line 1406 "configparser.c"
5671 configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
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".
5681 ** This is what we do if the grammar does define ERROR:
5683 --- ../lighttpd-1.4.11/src/configparser.y 2006-01-26 18:46:25.000000000 +0200
5684 +++ lighttpd-1.4.12/src/configparser.y 2006-07-11 22:07:53.000000000 +0300
5686 dc->parent = ctx->current;
5687 array_insert_unique(dc->parent->childs, (data_unset *)dc);
5689 - array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
5690 + buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
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);
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) {
5706 - if (NULL != (env = getenv(key->ptr + 4))) {
5708 - ds = data_string_init();
5709 - buffer_append_string(ds->value, env);
5710 - return (data_unset *)ds;
5713 - fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
5724 - fprintf(stderr, "get var %s\n", key->ptr);
5725 + fprintf(stderr, "get var %s\n", key->ptr);
5727 - for (dc = ctx->current; dc; dc = dc->parent) {
5728 + for (dc = ctx->current; dc; dc = dc->parent) {
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);
5735 - if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5736 - return du->copy(du);
5738 + if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5739 + return du->copy(du);
5741 - fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
5748 /* op1 is to be eat/return by this function, op1->key is not cared
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 @@
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);
5767 + } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
5768 array_insert_unique(ctx->current->value, B);
5771 @@ -180,7 +168,12 @@
5772 array *vars = ctx->current->value;
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);
5781 + } else if (NULL != (du = array_get_element(vars, A->ptr))) {
5782 /* exists in current block */
5783 du = configparser_merge_data(du, B);
5786 buffer_copy_string_buffer(du->key, A);
5787 array_replace(vars, du);
5790 } else if (NULL != (du = configparser_get_variable(ctx, A))) {
5791 du = configparser_merge_data(du, B);
5793 @@ -199,15 +193,13 @@
5794 buffer_copy_string_buffer(du->key, A);
5795 array_insert_unique(ctx->current->value, du);
5799 - fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
5800 - ctx->current->context_ndx,
5801 - ctx->current->key->ptr, A->ptr);
5803 + buffer_copy_string_buffer(B->key, A);
5804 + array_insert_unique(ctx->current->value, B);
5812 @@ -239,7 +231,24 @@
5815 value(A) ::= key(B). {
5816 - A = configparser_get_variable(ctx, B);
5817 + if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
5820 + if (NULL != (env = getenv(B->ptr + 4))) {
5822 + ds = data_string_init();
5823 + buffer_append_string(ds->value, env);
5824 + A = (data_unset *)ds;
5828 + fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
5831 + } else if (NULL == (A = configparser_get_variable(ctx, B))) {
5832 + fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
5836 /* make a dummy so it won't crash */
5837 A = (data_unset *)data_string_init();
5839 ((data_array *)(A))->value = B;
5842 +array(A) ::= LPARAN RPARAN. {
5845 array(A) ::= LPARAN aelements(B) RPARAN. {
5848 --- ../lighttpd-1.4.11/src/connections-glue.c 2005-09-12 10:04:23.000000000 +0300
5849 +++ lighttpd-1.4.12/src/connections-glue.c 2006-07-11 22:07:51.000000000 +0300
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)";
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";
5868 int connection_set_state(server *srv, connection *con, connection_state_t state) {
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
5884 -#include <unistd.h>
5889 #include "inet_ntop_cache.h"
5892 -# include <openssl/ssl.h>
5893 -# include <openssl/err.h>
5894 +# include <openssl/ssl.h>
5895 +# include <openssl/err.h>
5898 #ifdef HAVE_SYS_FILIO_H
5902 #include "sys-socket.h"
5903 +#include "sys-files.h"
5910 static connection *connections_get_new_connection(server *srv) {
5911 connections *conns = srv->conns;
5915 if (conns->size == 0) {
5919 } else if (conns->size == conns->used) {
5921 conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
5924 for (i = conns->used; i < conns->size; i++) {
5925 conns->ptr[i] = connection_init(srv);
5929 connection_reset(srv, conns->ptr[conns->used]);
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);
5936 fprintf(stderr, "\n");
5941 conns->ptr[conns->used]->ndx = conns->used;
5942 return conns->ptr[conns->used++];
5946 connections *conns = srv->conns;
5950 if (con == NULL) return -1;
5953 if (-1 == con->ndx) return -1;
5959 /* not last element */
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;
5968 conns->ptr[i]->ndx = i;
5969 conns->ptr[conns->used - 1]->ndx = -1;
5978 fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
5979 @@ -104,25 +104,23 @@
5980 fprintf(stderr, "%d ", conns->ptr[i]->fd);
5982 fprintf(stderr, "\n");
5988 int connection_close(server *srv, connection *con) {
5990 server_socket *srv_sock = con->srv_socket;
5995 if (srv_sock->is_ssl) {
5996 if (con->ssl) SSL_free(con->ssl);
6002 fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
6003 fdevent_unregister(srv->ev, con->fd);
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));
6017 log_error_write(srv, __FILE__, __LINE__, "sd",
6018 "closed()", con->fd);
6022 connection_del(srv, con);
6023 connection_set_state(srv, con, CON_STATE_CONNECT);
6030 static void dump_packet(const unsigned char *data, size_t len) {
6034 if (len == 0) return;
6037 for (i = 0; i < len; i++) {
6038 if (i % 16 == 0) fprintf(stderr, " ");
6041 fprintf(stderr, "%02x ", data[i]);
6044 if ((i + 1) % 16 == 0) {
6045 fprintf(stderr, " ");
6046 for (j = 0; j <= i % 16; j++) {
6050 if (i-15+j >= len) break;
6056 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6060 fprintf(stderr, "\n");
6065 if (len % 16 != 0) {
6066 for (j = i % 16; j < 16; j++) {
6067 fprintf(stderr, " ");
6071 fprintf(stderr, " ");
6072 for (j = i & ~0xf; j < len; j++) {
6077 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6079 fprintf(stderr, "\n");
6084 -static int connection_handle_read(server *srv, connection *con) {
6089 - server_socket *srv_sock = con->srv_socket;
6092 - b = chunkqueue_get_append_buffer(con->read_queue);
6093 - buffer_prepare_copy(b, 4096);
6094 +static network_status_t connection_handle_read(server *srv, connection *con) {
6095 + off_t oldlen, newlen;
6098 - if (srv_sock->is_ssl) {
6099 - len = SSL_read(con->ssl, b->ptr, b->size - 1);
6101 - if (ioctl(con->fd, FIONREAD, &toread)) {
6102 - log_error_write(srv, __FILE__, __LINE__, "sd",
6103 - "unexpected end-of-file:",
6107 - buffer_prepare_copy(b, toread);
6108 + oldlen = chunkqueue_length(con->read_queue);
6110 - len = read(con->fd, b->ptr, b->size - 1);
6112 -#elif defined(__WIN32)
6113 - len = recv(con->fd, b->ptr, b->size - 1, 0);
6115 - if (ioctl(con->fd, FIONREAD, &toread)) {
6116 - log_error_write(srv, __FILE__, __LINE__, "sd",
6117 - "unexpected end-of-file:",
6121 - buffer_prepare_copy(b, toread);
6123 - len = read(con->fd, b->ptr, b->size - 1);
6127 + switch(network_read_chunkqueue(srv, con, con->read_queue)) {
6128 + case NETWORK_STATUS_SUCCESS:
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:
6138 + con->is_readable = 0;
6139 + return NETWORK_STATUS_CONNECTION_CLOSE;
6140 + case NETWORK_STATUS_FATAL_ERROR:
6141 con->is_readable = 0;
6144 - if (srv_sock->is_ssl) {
6147 - switch ((r = SSL_get_error(con->ssl, len))) {
6148 - case SSL_ERROR_WANT_READ:
6150 - case SSL_ERROR_SYSCALL:
6152 - * man SSL_get_error()
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).
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));
6171 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
6178 - case SSL_ERROR_ZERO_RETURN:
6179 - /* clean shutdown on the remote side */
6182 - /* FIXME: later */
6185 - /* fall thourgh */
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));
6195 - if (errno == EAGAIN) return 0;
6196 - if (errno == EINTR) {
6197 - /* we have been interrupted before we could read */
6198 - con->is_readable = 1;
6202 - if (errno != ECONNRESET) {
6203 - /* expected for keep-alive */
6204 - log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6208 - if (errno == EAGAIN) return 0;
6209 - if (errno == EINTR) {
6210 - /* we have been interrupted before we could read */
6211 - con->is_readable = 1;
6215 - if (errno != ECONNRESET) {
6216 - /* expected for keep-alive */
6217 - log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6220 connection_set_state(srv, con, CON_STATE_ERROR);
6223 - } else if (len == 0) {
6224 - con->is_readable = 0;
6225 - /* the other end close the connection -> KEEP-ALIVE */
6226 + return NETWORK_STATUS_FATAL_ERROR;
6233 + newlen = chunkqueue_length(con->read_queue);
6236 - } else if ((size_t)len < b->size - 1) {
6237 - /* we got less then expected, wait for the next fd-event */
6239 - con->is_readable = 0;
6243 - b->ptr[b->used++] = '\0';
6245 - con->bytes_read += len;
6247 - dump_packet(b->ptr, len);
6251 + con->bytes_read += (newlen - oldlen);
6253 + return NETWORK_STATUS_SUCCESS;
6256 static int connection_handle_write_prepare(server *srv, connection *con) {
6258 case HTTP_METHOD_GET:
6259 case HTTP_METHOD_POST:
6260 case HTTP_METHOD_HEAD:
6262 case HTTP_METHOD_PUT:
6263 case HTTP_METHOD_MKCOL:
6264 case HTTP_METHOD_DELETE:
6265 @@ -350,12 +238,14 @@
6266 case HTTP_METHOD_MOVE:
6267 case HTTP_METHOD_PROPFIND:
6268 case HTTP_METHOD_PROPPATCH:
6269 + case HTTP_METHOD_LOCK:
6270 + case HTTP_METHOD_UNLOCK:
6272 case HTTP_METHOD_OPTIONS:
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
6277 + * 403 is from the response handler when noone else catched it
6280 if (con->uri.path->used &&
6281 con->uri.path->ptr[0] != '*') {
6282 @@ -381,55 +271,58 @@
6288 if (con->http_status == 0) {
6289 con->http_status = 403;
6293 switch(con->http_status) {
6294 case 400: /* class: header + custom body */
6310 if (con->mode != DIRECT) break;
6313 con->file_finished = 0;
6316 buffer_reset(con->physical.path);
6319 /* try to send static errorfile */
6320 if (!buffer_is_empty(con->conf.errorfile_prefix)) {
6321 stat_cache_entry *sce = NULL;
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));
6328 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
6329 con->file_finished = 1;
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));
6337 - if (!con->file_finished) {
6339 + if (!con->file_finished) {
6343 buffer_reset(con->physical.path);
6346 con->file_finished = 1;
6347 b = chunkqueue_get_append_buffer(con->write_queue);
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"
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));
6362 buffer_append_string(b,
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));
6370 - buffer_append_string(b,"</h1>\n"
6372 + buffer_append_string(b,"</h1>\n"
6378 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
6381 @@ -463,10 +356,10 @@
6387 case 206: /* write_queue is already prepared */
6388 con->file_finished = 1;
6392 case 205: /* class: header only */
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);
6400 con->file_finished = 1;
6406 if (con->file_finished) {
6407 - /* we have all the content and chunked encoding is not used, set a content-length */
6409 - if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6410 + /* we have all the content and chunked encoding is not used, set a content-length */
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));
6417 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
6420 @@ -495,74 +388,77 @@
6421 ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
6422 con->keep_alive = 0;
6426 if (0 == (con->parsed_response & HTTP_CONNECTION)) {
6427 /* (f)cgi did'nt send Connection: header
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 */
6437 con->keep_alive = 0;
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;
6445 /* FIXME: we have to drop the Connection: Header from the subrequest */
6451 if (con->request.http_method == HTTP_METHOD_HEAD) {
6452 chunkqueue_reset(con->write_queue);
6455 http_response_write_header(srv, con);
6461 static int connection_handle_write(server *srv, connection *con) {
6462 switch(network_write_chunkqueue(srv, con, con->write_queue)) {
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);
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);
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);
6483 + case NETWORK_STATUS_WAIT_FOR_EVENT:
6484 con->is_writable = 0;
6487 /* not finished yet -> WRITE */
6489 + case NETWORK_STATUS_INTERRUPTED:
6490 + con->is_writable = 1;
6492 + case NETWORK_STATUS_UNSET:
6502 connection *connection_init(server *srv) {
6508 con = calloc(1, sizeof(*con));
6514 @@ -573,32 +469,32 @@
6517 con->x = buffer_init();
6521 CLEAN(request.request_line);
6522 CLEAN(request.request);
6523 CLEAN(request.pathinfo);
6526 CLEAN(request.orig_uri);
6530 CLEAN(uri.authority);
6532 CLEAN(uri.path_raw);
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);
6546 CLEAN(error_handler);
6547 CLEAN(dst_addr_buf);
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();
6559 /* init plugin specific connection structures */
6562 con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
6565 con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
6566 config_setup_connection(srv, con);
6572 void connections_free(server *srv) {
6573 connections *conns = srv->conns;
6578 for (i = 0; i < conns->size; i++) {
6579 connection *con = conns->ptr[i];
6582 connection_reset(srv, con);
6585 chunkqueue_free(con->write_queue);
6586 chunkqueue_free(con->read_queue);
6587 chunkqueue_free(con->request_content_queue);
6588 @@ -637,27 +533,27 @@
6591 buffer_free(con->x);
6595 CLEAN(request.request_line);
6596 CLEAN(request.request);
6597 CLEAN(request.pathinfo);
6600 CLEAN(request.orig_uri);
6604 CLEAN(uri.authority);
6606 CLEAN(uri.path_raw);
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);
6620 CLEAN(error_handler);
6621 @@ -665,97 +561,97 @@
6623 free(con->plugin_ctx);
6624 free(con->cond_cache);
6635 int connection_reset(server *srv, connection *con) {
6639 plugins_call_connection_reset(srv, con);
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;
6650 con->parsed_response = 0;
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;
6660 con->request.http_method = HTTP_METHOD_UNSET;
6661 con->request.http_version = HTTP_VERSION_UNSET;
6664 con->request.http_if_modified_since = NULL;
6665 con->request.http_if_none_match = NULL;
6668 con->response.keep_alive = 0;
6669 con->response.content_length = -1;
6670 con->response.transfer_encoding = 0;
6677 if (con->x) buffer_reset(con->x);
6681 CLEAN(request.request_line);
6682 CLEAN(request.pathinfo);
6683 CLEAN(request.request);
6686 CLEAN(request.orig_uri);
6690 CLEAN(uri.authority);
6692 CLEAN(uri.path_raw);
6696 CLEAN(physical.doc_root);
6697 CLEAN(physical.path);
6698 CLEAN(physical.basedir);
6699 CLEAN(physical.rel_path);
6700 CLEAN(physical.etag);
6703 CLEAN(parse_request);
6708 CLEAN(error_handler);
6714 - if (con->x) con->x->used = 0;
6716 + if (con->x) con->x->used = 0;
6722 con->request.x = NULL;
6727 CLEAN(http_content_type);
6729 con->request.content_length = 0;
6732 array_reset(con->request.headers);
6733 array_reset(con->response.headers);
6734 array_reset(con->environment);
6737 chunkqueue_reset(con->write_queue);
6738 chunkqueue_reset(con->request_content_queue);
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;
6747 con->plugin_ctx[pd->id] = NULL;
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 @@
6756 memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
6760 con->header_len = 0;
6761 con->in_error_handler = 0;
6764 config_setup_connection(srv, con);
6772 - * search for \r\n\r\n
6775 + * search for \r\n\r\n
6777 * this is a special 32bit version which is using a sliding window for
6778 - * the comparisions
6780 + * the comparisions
6789 * cmpbuf: abcd != cdef
6790 * cmpbuf: bcde != cdef
6791 * cmpbuf: cdef == cdef -> return &c
6793 - * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
6795 + * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
6796 * maintain cmpbuf and rnrn
6801 char *buffer_search_rnrn(buffer *b) {
6802 uint32_t cmpbuf, rnrn;
6807 if (b->used < 4) return NULL;
6810 rnrn = ('\r' << 24) | ('\n' << 16) |
6811 ('\r' << 8) | ('\n' << 0);
6814 cmpbuf = (b->ptr[0] << 24) | (b->ptr[1] << 16) |
6815 (b->ptr[2] << 8) | (b->ptr[3] << 0);
6819 for (i = 0; i < b->used - 4; i++) {
6820 if (cmpbuf == rnrn) return cp - 4;
6823 cmpbuf = (cmpbuf << 8 | *(cp++)) & 0xffffffff;
6830 @@ -840,22 +736,25 @@
6832 chunkqueue *cq = con->read_queue;
6833 chunkqueue *dst_cq = con->request_content_queue;
6836 if (con->is_readable) {
6837 con->read_idle_ts = srv->cur_ts;
6840 switch(connection_handle_read(srv, con)) {
6842 + case NETWORK_STATUS_FATAL_ERROR:
6845 + case NETWORK_STATUS_CONNECTION_CLOSE:
6846 /* remote side closed the connection
6847 * if we still have content, handle it, if not leave here */
6849 if (cq->first == cq->last &&
6850 - cq->first->mem->used == 0) {
6851 + (NULL == cq->first ||
6852 + cq->first->mem->used == 0)) {
6854 /* conn-closed, leave here */
6855 connection_set_state(srv, con, CON_STATE_ERROR);
6861 @@ -891,14 +790,14 @@
6862 /* the last node was empty */
6863 if (c->next == NULL) {
6875 /* nothing to handle */
6876 if (cq->first == NULL) return 0;
6878 @@ -906,25 +805,26 @@
6879 case CON_STATE_READ:
6880 /* prepare con->request.request */
6884 /* check if we need the full package */
6885 if (con->request.request->used == 0) {
6889 b.ptr = c->mem->ptr + c->offset;
6890 b.used = c->mem->used - c->offset;
6893 if (NULL != (h_term = buffer_search_rnrn(&b))) {
6895 * - copy everything incl. the terminator to request.request
6898 - buffer_copy_string_len(con->request.request,
6901 + buffer_copy_string_len(con->request.request,
6903 h_term - b.ptr + 4);
6906 /* the buffer has been read up to the terminator */
6907 c->offset += h_term - b.ptr + 4;
6910 /* not found, copy everything */
6911 buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
6912 @@ -932,14 +832,14 @@
6915 /* have to take care of overlapping header terminators */
6918 size_t l = con->request.request->used - 2;
6919 char *s = con->request.request->ptr;
6923 b.ptr = c->mem->ptr + c->offset;
6924 b.used = c->mem->used - c->offset;
6927 if (con->request.request->used - 1 > 3 &&
6931 c->mem->ptr[0] == '\n') {
6932 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
6936 h_term = con->request.request->ptr;
6937 } else if (con->request.request->used - 1 > 2 &&
6940 c->mem->ptr[1] == '\n') {
6941 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
6945 h_term = con->request.request->ptr;
6946 } else if (con->request.request->used - 1 > 1 &&
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);
6954 h_term = con->request.request->ptr;
6955 } else if (NULL != (h_term = buffer_search_string_len(&b, "\r\n\r\n", 4))) {
6957 * - copy everything incl. the terminator to request.request
6960 - buffer_append_string_len(con->request.request,
6961 - c->mem->ptr + c->offset,
6963 + buffer_append_string_len(con->request.request,
6964 + c->mem->ptr + c->offset,
6965 c->offset + h_term - b.ptr + 4);
6968 /* the buffer has been read up to the terminator */
6969 c->offset += h_term - b.ptr + 4;
6971 @@ -999,16 +899,16 @@
6972 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
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;
6981 weWant = con->request.content_length - dst_cq->bytes_in;
6984 assert(c->mem->used);
6987 weHave = c->mem->used - c->offset - 1;
6990 toRead = weHave > weWant ? weWant : weHave;
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 */
6997 - * if the last chunk is
6998 + * if the last chunk is
6999 * - smaller than 1Mb (size < 1Mb)
7000 * - not read yet (offset == 0)
7003 - * -> create a new chunk
7005 + * -> create a new chunk
7010 @@ -1056,14 +956,14 @@
7011 /* we have a chunk, let's write to it */
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.
7018 * Instead of sending 500 we send 413 and say the request is too large
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));
7026 con->http_status = 413; /* Request-Entity too large */
7027 @@ -1074,15 +974,15 @@
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));
7039 con->http_status = 413; /* Request-Entity too large */
7040 con->keep_alive = 0;
7041 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7044 close(dst_c->file.fd);
7045 dst_c->file.fd = -1;
7047 @@ -1090,7 +990,7 @@
7050 dst_c->file.length += toRead;
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);
7062 c->offset += toRead;
7063 dst_cq->bytes_in += toRead;
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);
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;
7080 joblist_append(srv, con);
7083 if (revents & FDEVENT_IN) {
7084 con->is_readable = 1;
7086 @@ -1136,19 +1036,19 @@
7087 con->is_writable = 1;
7088 /* we don't need the event twice */
7094 if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
7095 /* looks like an error */
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;
7103 /* sigio reports the wrong event here
7105 - * there was no HUP at all
7107 + * there was no HUP at all
7109 #ifdef USE_LINUX_SIGIO
7110 if (srv->ev->in_sigio == 1) {
7111 @@ -1160,32 +1060,39 @@
7113 connection_set_state(srv, con, CON_STATE_ERROR);
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);
7124 connection_set_state(srv, con, CON_STATE_ERROR);
7126 log_error_write(srv, __FILE__, __LINE__, "sd",
7127 "connection closed: poll() -> ???", revents);
7133 if (con->state == CON_STATE_READ ||
7134 con->state == CON_STATE_READ_POST) {
7135 connection_handle_read_state(srv, con);
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.
7140 + * we have to call the state-engine to read the rest of the packet
7142 + if (con->is_readable) joblist_append(srv, con);
7146 if (con->state == CON_STATE_WRITE &&
7147 !chunkqueue_is_empty(con->write_queue) &&
7151 if (-1 == connection_handle_write(srv, con)) {
7152 connection_set_state(srv, con, CON_STATE_ERROR);
7155 log_error_write(srv, __FILE__, __LINE__, "ds",
7157 "handle write failed.");
7158 @@ -1193,30 +1100,30 @@
7159 con->write_request_ts = srv->cur_ts;
7164 if (con->state == CON_STATE_CLOSE) {
7165 /* flush the read buffers */
7169 if (ioctl(con->fd, FIONREAD, &b)) {
7170 log_error_write(srv, __FILE__, __LINE__, "ss",
7171 "ioctl() failed", strerror(errno));
7177 log_error_write(srv, __FILE__, __LINE__, "sdd",
7178 "CLOSE-read()", con->fd, b);
7182 read(con->fd, buf, sizeof(buf));
7184 /* nothing to read */
7187 con->close_timeout_ts = 0;
7192 return HANDLER_FINISHED;
7195 @@ -1229,63 +1136,68 @@
7198 /* accept it and register the fd */
7201 cnt_len = sizeof(cnt_addr);
7203 if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
7205 + errno = WSAGetLastError();
7207 if ((errno != EAGAIN) &&
7208 + (errno != EWOULDBLOCK) &&
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);
7221 /* ok, we have the connection, register it */
7223 log_error_write(srv, __FILE__, __LINE__, "sd",
7229 con = connections_get_new_connection(srv);
7235 gettimeofday(&(con->start_tv), NULL);
7238 fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
7241 connection_set_state(srv, con, CON_STATE_REQUEST_START);
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;
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);
7256 /* connect FD to SSL */
7257 if (srv_socket->is_ssl) {
7258 if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
7259 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7260 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7261 ERR_error_string(ERR_get_error(), NULL));
7263 + connection_close(srv, con);
7268 SSL_set_accept_state(con->ssl);
7272 if (1 != (SSL_set_fd(con->ssl, cnt))) {
7273 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7274 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7275 ERR_error_string(ERR_get_error(), NULL));
7276 + connection_close(srv, con);
7280 @@ -1300,10 +1212,10 @@
7282 server_socket *srv_sock = con->srv_socket;
7286 if (srv->srvconf.log_state_handling) {
7287 - log_error_write(srv, __FILE__, __LINE__, "sds",
7289 + log_error_write(srv, __FILE__, __LINE__, "sds",
7292 connection_get_state(con->state));
7294 @@ -1311,91 +1223,91 @@
7296 size_t ostate = con->state;
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));
7309 con->request_start = srv->cur_ts;
7310 con->read_idle_ts = srv->cur_ts;
7313 con->request_count++;
7314 con->loops_per_request = 0;
7317 connection_set_state(srv, con, CON_STATE_READ);
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));
7329 if (http_request_parse(srv, con)) {
7330 /* we have to read some data from the POST request */
7333 connection_set_state(srv, con, CON_STATE_READ_POST);
7339 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7343 case CON_STATE_HANDLE_REQUEST:
7346 * the request is parsed
7349 * decided what to do with the request
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));
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 */
7372 - if (con->in_error_handler == 0 &&
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 */
7380 con->error_handler_saved_status = con->http_status;
7381 con->http_status = 0;
7384 if (buffer_is_empty(con->error_handler)) {
7385 buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
7387 buffer_copy_string_buffer(con->request.uri, con->error_handler);
7389 buffer_reset(con->physical.path);
7392 con->in_error_handler = 1;
7395 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7400 } else if (con->in_error_handler) {
7401 /* error-handler is a 404 */
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;
7416 @@ -1403,26 +1315,26 @@
7417 /* error-handler is back and has generated content */
7418 /* if Status: was set, take it otherwise use 200 */
7422 if (con->http_status == 0) con->http_status = 200;
7425 /* we have something to send, go on */
7426 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
7428 case HANDLER_WAIT_FOR_FD:
7432 fdwaitqueue_append(srv, con);
7435 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7439 case HANDLER_COMEBACK:
7441 case HANDLER_WAIT_FOR_EVENT:
7442 /* come back here */
7443 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7448 /* something went wrong */
7449 @@ -1432,44 +1344,44 @@
7450 log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
7456 case CON_STATE_RESPONSE_START:
7459 * the decision is done
7460 * - create the HTTP-Response-Header
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));
7473 if (-1 == connection_handle_write_prepare(srv, con)) {
7474 connection_set_state(srv, con, CON_STATE_ERROR);
7481 connection_set_state(srv, con, CON_STATE_WRITE);
7483 case CON_STATE_RESPONSE_END: /* transient */
7484 /* log the request */
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));
7494 plugins_call_handle_request_done(srv, con);
7500 if (con->keep_alive) {
7501 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7506 con->request_start = srv->cur_ts;
7507 con->read_idle_ts = srv->cur_ts;
7509 @@ -1482,7 +1394,7 @@
7510 log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
7516 if (srv_sock->is_ssl) {
7517 switch (SSL_shutdown(con->ssl)) {
7518 @@ -1490,44 +1402,44 @@
7522 - /* wait for fd-event
7524 + /* wait for fd-event
7526 * FIXME: wait for fdevent and call SSL_shutdown again
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));
7540 connection_close(srv, con);
7547 connection_reset(srv, con);
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));
7559 chunkqueue_reset(con->read_queue);
7562 con->request_count = 0;
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));
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 @@
7579 log_error_write(srv, __FILE__, __LINE__, "sdd",
7580 "CLOSE-read()", con->fd, b);
7584 read(con->fd, buf, sizeof(buf));
7586 /* nothing to read */
7589 con->close_timeout_ts = 0;
7592 con->close_timeout_ts = 0;
7596 if (srv->cur_ts - con->close_timeout_ts > 1) {
7597 connection_close(srv, con);
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);
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));
7618 connection_handle_read_state(srv, con);
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));
7628 /* only try to write if we have something in the queue */
7629 if (!chunkqueue_is_empty(con->write_queue)) {
7631 @@ -1593,10 +1505,10 @@
7632 con->write_request_ts = srv->cur_ts;
7638 case CON_STATE_ERROR: /* transient */
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);
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));
7662 - log_error_write(srv, __FILE__, __LINE__, "sd",
7663 - "emergency exit: direct",
7664 + log_error_write(srv, __FILE__, __LINE__, "sd",
7665 + "emergency exit: direct",
7669 @@ -1639,35 +1551,35 @@
7675 connection_reset(srv, con);
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);
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);
7691 connection_close(srv, con);
7695 con->keep_alive = 0;
7703 - log_error_write(srv, __FILE__, __LINE__, "sdd",
7704 + log_error_write(srv, __FILE__, __LINE__, "sdd",
7705 "unknown state:", con->fd, con->state);
7714 } else if (ostate == con->state) {
7715 @@ -1676,12 +1588,12 @@
7718 if (srv->srvconf.log_state_handling) {
7719 - log_error_write(srv, __FILE__, __LINE__, "sds",
7721 + log_error_write(srv, __FILE__, __LINE__, "sds",
7724 connection_get_state(con->state));
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);
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
7741 - if (!chunkqueue_is_empty(con->write_queue) &&
7742 + if (!chunkqueue_is_empty(con->write_queue) &&
7743 (con->is_writable == 0) &&
7744 (con->traffic_limit_reached == 0)) {
7745 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
7746 --- ../lighttpd-1.4.11/src/crc32.h 2005-09-30 20:18:59.000000000 +0300
7747 +++ lighttpd-1.4.12/src/crc32.h 2006-07-11 22:07:53.000000000 +0300
7751 #include <sys/types.h>
7752 +#include <stdlib.h>
7754 #if defined HAVE_STDINT_H
7757 #include <inttypes.h>
7761 +#define uint32_t unsigned __int32
7764 uint32_t generate_crc32c(char *string, size_t length);
7767 --- ../lighttpd-1.4.11/src/data_array.c 2005-08-23 17:36:12.000000000 +0300
7768 +++ lighttpd-1.4.12/src/data_array.c 2006-07-11 22:07:52.000000000 +0300
7771 static void data_array_free(data_unset *d) {
7772 data_array *ds = (data_array *)d;
7775 buffer_free(ds->key);
7776 array_free(ds->value);
7782 static void data_array_reset(data_unset *d) {
7783 data_array *ds = (data_array *)d;
7786 /* reused array elements */
7787 buffer_reset(ds->key);
7788 array_reset(ds->value);
7800 data_array *data_array_init(void) {
7804 ds = calloc(1, sizeof(*ds));
7807 ds->key = buffer_init();
7808 ds->value = array_init();
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;
7821 --- ../lighttpd-1.4.11/src/data_config.c 2005-08-17 12:53:19.000000000 +0300
7822 +++ lighttpd-1.4.12/src/data_config.c 2006-07-11 22:07:51.000000000 +0300
7825 static void data_config_free(data_unset *d) {
7826 data_config *ds = (data_config *)d;
7829 buffer_free(ds->key);
7830 buffer_free(ds->op);
7831 buffer_free(ds->comp_key);
7834 array_free(ds->value);
7835 array_free(ds->childs);
7838 if (ds->string) buffer_free(ds->string);
7840 if (ds->regex) pcre_free(ds->regex);
7841 if (ds->regex_study) pcre_free(ds->regex_study);
7848 static void data_config_reset(data_unset *d) {
7849 data_config *ds = (data_config *)d;
7852 /* reused array elements */
7853 buffer_reset(ds->key);
7854 buffer_reset(ds->comp_key);
7857 static int data_config_insert_dup(data_unset *dst, data_unset *src) {
7868 array *a = (array *)ds->value;
7873 if (0 == ds->context_ndx) {
7874 fprintf(stderr, "config {\n");
7876 @@ -117,22 +117,22 @@
7878 data_config *data_config_init(void) {
7882 ds = calloc(1, sizeof(*ds));
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;
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;
7903 --- ../lighttpd-1.4.11/src/data_count.c 2005-08-23 17:36:12.000000000 +0300
7904 +++ lighttpd-1.4.12/src/data_count.c 2006-07-11 22:07:51.000000000 +0300
7907 static void data_count_free(data_unset *d) {
7908 data_count *ds = (data_count *)d;
7911 buffer_free(ds->key);
7917 static void data_count_reset(data_unset *d) {
7918 data_count *ds = (data_count *)d;
7921 buffer_reset(ds->key);
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;
7932 ds_dst->count += ds_src->count;
7941 static void data_count_print(const data_unset *d, int depth) {
7942 data_count *ds = (data_count *)d;
7946 fprintf(stderr, "count(%d)", ds->count);
7950 data_count *data_count_init(void) {
7954 ds = calloc(1, sizeof(*ds));
7957 ds->key = buffer_init();
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;
7971 --- ../lighttpd-1.4.11/src/data_fastcgi.c 2005-08-23 17:36:12.000000000 +0300
7972 +++ lighttpd-1.4.12/src/data_fastcgi.c 2006-07-11 22:07:53.000000000 +0300
7975 static void data_fastcgi_free(data_unset *d) {
7976 data_fastcgi *ds = (data_fastcgi *)d;
7979 buffer_free(ds->key);
7980 buffer_free(ds->host);
7986 static void data_fastcgi_reset(data_unset *d) {
7987 data_fastcgi *ds = (data_fastcgi *)d;
7990 buffer_reset(ds->key);
7991 buffer_reset(ds->host);
7996 static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
8005 static void data_fastcgi_print(const data_unset *d, int depth) {
8006 data_fastcgi *ds = (data_fastcgi *)d;
8010 fprintf(stderr, "fastcgi(%s)", ds->host->ptr);
8014 data_fastcgi *data_fastcgi_init(void) {
8018 ds = calloc(1, sizeof(*ds));
8021 ds->key = buffer_init();
8022 ds->host = buffer_init();
8024 ds->is_disabled = 0;
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;
8037 --- ../lighttpd-1.4.11/src/data_integer.c 2005-08-23 17:36:12.000000000 +0300
8038 +++ lighttpd-1.4.12/src/data_integer.c 2006-07-11 22:07:51.000000000 +0300
8041 static void data_integer_free(data_unset *d) {
8042 data_integer *ds = (data_integer *)d;
8045 buffer_free(ds->key);
8051 static void data_integer_reset(data_unset *d) {
8052 data_integer *ds = (data_integer *)d;
8055 /* reused integer elements */
8056 buffer_reset(ds->key);
8060 static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
8072 data_integer *data_integer_init(void) {
8076 ds = calloc(1, sizeof(*ds));
8079 ds->key = buffer_init();
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;
8093 --- ../lighttpd-1.4.11/src/data_string.c 2005-08-23 17:36:12.000000000 +0300
8094 +++ lighttpd-1.4.12/src/data_string.c 2006-07-11 22:07:53.000000000 +0300
8097 static void data_string_free(data_unset *d) {
8098 data_string *ds = (data_string *)d;
8101 buffer_free(ds->key);
8102 buffer_free(ds->value);
8108 static void data_string_reset(data_unset *d) {
8109 data_string *ds = (data_string *)d;
8112 /* reused array elements */
8113 buffer_reset(ds->key);
8114 buffer_reset(ds->value);
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;
8121 if (ds_dst->value->used) {
8122 buffer_append_string(ds_dst->value, ", ");
8123 buffer_append_string_buffer(ds_dst->value, ds_src->value);
8125 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
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;
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);
8145 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8157 data_string *data_string_init(void) {
8161 ds = calloc(1, sizeof(*ds));
8165 ds->key = buffer_init();
8166 ds->value = buffer_init();
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;
8180 data_string *data_response_init(void) {
8184 ds = data_string_init();
8185 ds->insert_dup = data_response_insert_dup;
8190 --- ../lighttpd-1.4.11/src/etag.c 2005-08-11 01:26:40.000000000 +0300
8191 +++ lighttpd-1.4.12/src/etag.c 2006-07-11 22:07:51.000000000 +0300
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);
8201 int etag_mutate(buffer *mut, buffer *etag) {
8205 for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
8209 buffer_copy_string_len(mut, CONST_STR_LEN("\""));
8210 buffer_append_long(mut, h);
8211 buffer_append_string_len(mut, CONST_STR_LEN("\""));
8216 --- ../lighttpd-1.4.11/src/etag.h 2005-08-11 01:26:40.000000000 +0300
8217 +++ lighttpd-1.4.12/src/etag.h 2006-07-11 22:07:51.000000000 +0300
8220 #include <sys/types.h>
8221 #include <sys/stat.h>
8222 -#include <unistd.h>
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);
8233 --- ../lighttpd-1.4.11/src/fastcgi.h 2005-08-11 01:26:40.000000000 +0300
8234 +++ lighttpd-1.4.12/src/fastcgi.h 2006-07-11 22:07:51.000000000 +0300
8240 * Defines for the FastCGI protocol.
8245 - unsigned char type;
8246 + unsigned char type;
8247 unsigned char reserved[7];
8248 } FCGI_UnknownTypeBody;
8250 --- ../lighttpd-1.4.11/src/fdevent.c 2005-11-15 10:51:05.000000000 +0200
8251 +++ lighttpd-1.4.12/src/fdevent.c 2006-07-11 22:07:53.000000000 +0300
8254 #include "settings.h"
8256 -#include <unistd.h>
8261 #include "fdevent.h"
8264 +#include "sys-socket.h"
8266 fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
8270 ev = calloc(1, sizeof(*ev));
8271 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
8272 ev->maxfds = maxfds;
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__);
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__);
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__);
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__);
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__);
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__);
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__);
8333 void fdevent_free(fdevents *ev) {
8338 if (ev->free) ev->free(ev);
8341 for (i = 0; i < ev->maxfds; i++) {
8342 if (ev->fdarray[i]) free(ev->fdarray[i]);
8350 int fdevent_reset(fdevents *ev) {
8351 if (ev->reset) return ev->reset(ev);
8357 fdnode *fdnode_init() {
8361 fdn = calloc(1, sizeof(*fdn));
8364 @@ -106,12 +107,12 @@
8366 int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
8370 fdn = fdnode_init();
8371 fdn->handler = handler;
8376 ev->fdarray[fd] = fdn;
8379 @@ -121,31 +122,31 @@
8382 fdn = ev->fdarray[fd];
8388 ev->fdarray[fd] = NULL;
8394 int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
8395 int fde = fde_ndx ? *fde_ndx : -1;
8398 if (ev->event_del) fde = ev->event_del(ev, fde, fd);
8401 if (fde_ndx) *fde_ndx = fde;
8407 int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
8408 int fde = fde_ndx ? *fde_ndx : -1;
8411 if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
8414 if (fde_ndx) *fde_ndx = fde;
8420 @@ -156,38 +157,43 @@
8422 int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
8423 if (ev->event_get_revent == NULL) SEGFAULT();
8426 return ev->event_get_revent(ev, ndx);
8429 int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
8430 if (ev->event_get_fd == NULL) SEGFAULT();
8433 return ev->event_get_fd(ev, ndx);
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();
8441 return ev->fdarray[fd]->handler;
8444 void * fdevent_get_context(fdevents *ev, int fd) {
8445 if (ev->fdarray[fd] == NULL) SEGFAULT();
8446 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8449 return ev->fdarray[fd]->ctx;
8452 int fdevent_fcntl_set(fdevents *ev, int fd) {
8457 /* close fd on exec (cgi) */
8458 fcntl(fd, F_SETFD, FD_CLOEXEC);
8460 if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
8463 return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
8464 +#elif defined _WIN32
8465 + return ioctlsocket(fd, FIONBIO, &i);
8471 int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
8472 if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
8478 --- ../lighttpd-1.4.11/src/fdevent.h 2005-09-27 11:26:33.000000000 +0300
8479 +++ lighttpd-1.4.12/src/fdevent.h 2006-07-11 22:07:51.000000000 +0300
8481 # include <sys/epoll.h>
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))
8493 # include <sys/poll.h>
8495 # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
8497 # include <signal.h>
8502 +# define HAVE_SELECT
8504 #if defined HAVE_SELECT
8507 # include <winsock2.h>
8511 #define FDEVENT_HUP BV(4)
8512 #define FDEVENT_NVAL BV(5)
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
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,
8534 * a mapping from fd to connection structure
8539 int fd; /**< the fd */
8540 @@ -98,41 +100,41 @@
8551 * array of unused fd's
8556 typedef struct _fdnode {
8557 fdevent_handler handler;
8562 struct _fdnode *prev, *next;
8574 * fd-event handler for select(), poll() and rt-signals on Linux 2.4
8578 typedef struct fdevents {
8579 fdevent_handler_t type;
8586 #ifdef USE_LINUX_SIGIO
8589 @@ -146,21 +148,21 @@
8592 struct pollfd *pollfds;
8603 fd_set select_write;
8604 fd_set select_error;
8607 fd_set select_set_read;
8608 fd_set select_set_write;
8609 fd_set select_set_error;
8614 #ifdef USE_SOLARIS_DEVPOLL
8615 @@ -177,16 +179,16 @@
8617 int (*reset)(struct fdevents *ev);
8618 void (*free)(struct fdevents *ev);
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);
8627 int (*event_next_fdndx)(struct fdevents *ev, int ndx);
8630 int (*poll)(struct fdevents *ev, int timeout_ms);
8633 int (*fcntl_set)(struct fdevents *ev, int fd);
8636 --- ../lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c 2005-09-01 10:46:24.000000000 +0300
8637 +++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c 2006-07-11 22:07:51.000000000 +0300
8639 #include <sys/types.h>
8641 -#include <unistd.h>
8660 ret = kevent(ev->kq_fd,
8669 if (filter == EVFILT_READ) {
8670 bitset_set_bit(ev->kq_bevents, fd);
8673 } else if (e == EVFILT_WRITE) {
8674 events |= FDEVENT_OUT;
8678 e = ev->kq_results[ndx].flags;
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));
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));
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
8706 #include <sys/types.h>
8708 -#include <unistd.h>
8713 #include "fdevent.h"
8714 #include "settings.h"
8716 +#include "sys-process.h"
8718 #ifdef USE_LINUX_SIGIO
8719 static void fdevent_linux_rtsig_free(fdevents *ev) {
8722 static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) {
8723 if (fde_ndx < 0) return -1;
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);
8732 if (ev->pollfds[fde_ndx].fd == fd) {
8736 ev->pollfds[k].fd = -1;
8738 bitset_clear_bit(ev->sigbset, fd);
8741 if (ev->unused.size == 0) {
8742 ev->unused.size = 16;
8743 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
8745 ev->unused.size += 16;
8746 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
8750 ev->unused.ptr[ev->unused.used++] = k;
8752 fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd);
8763 static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
8767 if (ev->used == 0) return 0;
8768 if (ev->unused.used != 0) return 0;
8771 for (j = ev->used - 1; j + 1 > 0; j--) {
8772 if (ev->pollfds[j].fd == -1) ev->used--;
8782 if (fde_ndx != -1) {
8783 if (ev->pollfds[fde_ndx].fd == fd) {
8784 ev->pollfds[fde_ndx].events = events;
8789 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
8794 if (ev->unused.used > 0) {
8795 int k = ev->unused.ptr[--ev->unused.used];
8798 ev->pollfds[k].fd = fd;
8799 ev->pollfds[k].events = events;
8801 bitset_set_bit(ev->sigbset, fd);
8806 if (ev->size == 0) {
8807 @@ -102,12 +102,12 @@
8809 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
8813 ev->pollfds[ev->used].fd = fd;
8814 ev->pollfds[ev->used].events = events;
8816 bitset_set_bit(ev->sigbset, fd);
8822 @@ -115,20 +115,20 @@
8823 static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
8829 fdevent_linux_rtsig_event_compress(ev);
8836 ts.tv_sec = timeout_ms / 1000;
8837 ts.tv_nsec = (timeout_ms % 1000) * 1000000;
8838 r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
8843 if (errno == EAGAIN) return 0;
8846 } else if (r == SIGIO) {
8847 struct sigaction act;
8850 /* re-enable the signal queue */
8851 act.sa_handler = SIG_DFL;
8852 sigaction(ev->signum, &act, NULL);
8856 r = poll(ev->pollfds, ev->used, timeout_ms);
8858 @@ -162,12 +162,12 @@
8859 if (ev->siginfo.si_band == POLLERR) {
8860 fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno));
8865 fprintf(stderr, "+\n");
8870 return ev->siginfo.si_band & 0x3f;
8872 if (ndx >= ev->used) {
8873 @@ -188,13 +188,13 @@
8875 static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
8876 static pid_t pid = 0;
8879 if (pid == 0) pid = getpid();
8882 if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
8885 if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
8888 return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
8891 @@ -205,12 +205,12 @@
8897 i = (ndx < 0) ? 0 : ndx + 1;
8898 for (; i < ev->used; i++) {
8899 if (ev->pollfds[i].revents) break;
8906 @@ -219,34 +219,34 @@
8907 ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
8909 ev->x = fdevent_linux_rtsig_##x;
8920 SET(event_next_fdndx);
8923 SET(event_get_revent);
8926 ev->signum = SIGRTMIN + 1;
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));
8943 ev->sigbset = bitset_init(ev->maxfds);
8949 --- ../lighttpd-1.4.11/src/fdevent_linux_sysepoll.c 2005-09-30 20:29:27.000000000 +0300
8950 +++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c 2006-07-11 22:07:53.000000000 +0300
8952 #include <sys/types.h>
8954 -#include <unistd.h>
8959 #include "settings.h"
8962 +#include "sys-files.h"
8964 #ifdef USE_LINUX_EPOLL
8965 static void fdevent_linux_sysepoll_free(fdevents *ev) {
8966 close(ev->epoll_fd);
8969 static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
8970 struct epoll_event ep;
8973 if (fde_ndx < 0) return -1;
8976 memset(&ep, 0, sizeof(ep));
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));
8999 static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9000 struct epoll_event ep;
9004 if (fde_ndx == -1) add = 1;
9007 memset(&ep, 0, sizeof(ep));
9013 if (events & FDEVENT_IN) ep.events |= EPOLLIN;
9014 if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
9022 ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
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));
9045 static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
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;
9062 fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
9066 return ev->epoll_events[ndx].data.fd;
9069 static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
9075 i = (ndx < 0) ? 0 : ndx + 1;
9081 @@ -116,17 +117,17 @@
9082 ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
9084 ev->x = fdevent_linux_sysepoll_##x;
9095 SET(event_next_fdndx);
9097 SET(event_get_revent);
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));
9105 fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9106 __FILE__, __LINE__);
9112 --- ../lighttpd-1.4.11/src/fdevent_poll.c 2005-11-18 13:59:16.000000000 +0200
9113 +++ lighttpd-1.4.12/src/fdevent_poll.c 2006-07-11 22:07:53.000000000 +0300
9115 #include <sys/types.h>
9117 -#include <unistd.h>
9123 static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
9124 if (fde_ndx < 0) return -1;
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);
9133 if (ev->pollfds[fde_ndx].fd == fd) {
9137 ev->pollfds[k].fd = -1;
9138 /* ev->pollfds[k].events = 0; */
9139 /* ev->pollfds[k].revents = 0; */
9142 if (ev->unused.size == 0) {
9143 ev->unused.size = 16;
9144 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9146 ev->unused.size += 16;
9147 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9151 ev->unused.ptr[ev->unused.used++] = k;
9161 static int fdevent_poll_event_compress(fdevents *ev) {
9165 if (ev->used == 0) return 0;
9166 if (ev->unused.used != 0) return 0;
9169 for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
9176 static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9180 if (fde_ndx != -1) {
9181 if (ev->pollfds[fde_ndx].fd == fd) {
9182 ev->pollfds[fde_ndx].events = events;
9187 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9192 if (ev->unused.used > 0) {
9193 int k = ev->unused.ptr[--ev->unused.used];
9196 ev->pollfds[k].fd = fd;
9197 ev->pollfds[k].events = events;
9202 if (ev->size == 0) {
9205 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9209 ev->pollfds[ev->used].fd = fd;
9210 ev->pollfds[ev->used].events = events;
9216 @@ -109,12 +108,12 @@
9218 if (ndx >= ev->used) {
9219 fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used);
9229 if (ev->pollfds[ndx].revents & POLLNVAL) {
9230 /* should never happen */
9233 if (poll_r & POLLHUP) r |= FDEVENT_HUP;
9234 if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
9235 if (poll_r & POLLPRI) r |= FDEVENT_PRI;
9238 return ev->pollfds[ndx].revents;
9241 @@ -141,12 +140,12 @@
9243 static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
9247 i = (ndx < 0) ? 0 : ndx + 1;
9248 for (; i < ev->used; i++) {
9249 if (ev->pollfds[i].revents) break;
9256 @@ -154,17 +153,17 @@
9257 ev->type = FDEVENT_HANDLER_POLL;
9259 ev->x = fdevent_poll_##x;
9270 SET(event_next_fdndx);
9272 SET(event_get_revent);
9278 --- ../lighttpd-1.4.11/src/fdevent_select.c 2005-08-31 11:12:46.000000000 +0300
9279 +++ lighttpd-1.4.12/src/fdevent_select.c 2006-07-11 22:07:53.000000000 +0300
9281 -#include <sys/time.h>
9282 #include <sys/types.h>
9284 -#include <unistd.h>
9293 #include "fdevent.h"
9294 #include "settings.h"
9297 +#include "sys-socket.h"
9301 static int fdevent_select_reset(fdevents *ev) {
9305 /* we should be protected by max-fds, but you never know */
9307 assert(fd < FD_SETSIZE);
9310 if (events & FDEVENT_IN) {
9311 FD_SET(fd, &(ev->select_set_read));
9313 FD_SET(fd, &(ev->select_set_write));
9315 FD_SET(fd, &(ev->select_set_error));
9318 if (fd > ev->select_max_fd) ev->select_max_fd = fd;
9324 static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
9328 tv.tv_sec = timeout_ms / 1000;
9329 tv.tv_usec = (timeout_ms % 1000) * 1000;
9332 ev->select_read = ev->select_set_read;
9333 ev->select_write = ev->select_set_write;
9334 ev->select_error = ev->select_set_error;
9337 return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
9340 static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
9344 if (FD_ISSET(ndx, &(ev->select_read))) {
9345 revents |= FDEVENT_IN;
9348 if (FD_ISSET(ndx, &(ev->select_error))) {
9349 revents |= FDEVENT_ERR;
9358 static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
9362 i = (ndx < 0) ? 0 : ndx + 1;
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;
9375 @@ -108,17 +111,17 @@
9376 ev->type = FDEVENT_HANDLER_SELECT;
9378 ev->x = fdevent_select_##x;
9389 SET(event_next_fdndx);
9391 SET(event_get_revent);
9397 --- ../lighttpd-1.4.11/src/fdevent_solaris_devpoll.c 2005-09-01 10:45:26.000000000 +0300
9398 +++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c 2006-07-11 22:07:51.000000000 +0300
9400 #include <sys/types.h>
9402 -#include <unistd.h>
9408 static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9412 if (fde_ndx < 0) return -1;
9416 pfd.events = POLLREMOVE;
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));
9435 static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9440 if (fde_ndx == -1) add = 1;
9444 pfd.events = events;
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));
9463 static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
9464 struct dvpoll dopoll;
9468 dopoll.dp_timeout = timeout_ms;
9469 dopoll.dp_nfds = ev->maxfds;
9470 dopoll.dp_fds = ev->devpollfds;
9473 ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
9481 static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
9487 i = (last_ndx < 0) ? 0 : last_ndx + 1;
9493 @@ -117,20 +116,20 @@
9494 ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
9496 ev->x = fdevent_solaris_devpoll_##x;
9508 SET(event_next_fdndx);
9510 SET(event_get_revent);
9513 ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
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));
9521 fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9522 __FILE__, __LINE__);
9528 --- ../lighttpd-1.4.11/src/http-header-glue.c 2006-02-08 15:31:36.000000000 +0200
9529 +++ lighttpd-1.4.12/src/http-header-glue.c 2006-07-11 22:07:53.000000000 +0300
9531 # ifdef HAVE_STRUCT_SOCKADDR_STORAGE
9532 static size_t get_sa_len(const struct sockaddr *addr) {
9533 switch (addr->sa_family) {
9538 return (sizeof (struct sockaddr_in));
9544 return (sizeof (struct sockaddr_in6));
9549 return (sizeof (struct sockaddr));
9554 # define SA_LEN(addr) (get_sa_len(addr))
9557 int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9563 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
9566 buffer_copy_string_len(ds->key, key, keylen);
9567 buffer_copy_string_len(ds->value, value, vallen);
9570 array_insert_unique(con->response.headers, (data_unset *)ds);
9576 int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
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);
9591 return response_header_insert(srv, con, key, keylen, value, vallen);
9594 int http_response_redirect_to_directory(server *srv, connection *con) {
9601 if (con->conf.is_ssl) {
9602 buffer_copy_string(o, "https://");
9604 @@ -123,36 +123,36 @@
9607 socklen_t our_addr_len;
9610 our_addr_len = sizeof(our_addr);
9613 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
9614 con->http_status = 500;
9617 log_error_write(srv, __FILE__, __LINE__, "ss",
9618 "can't get sockname", strerror(errno));
9628 /* Lookup name: secondly try to get hostname for bind address */
9629 switch(our_addr.plain.sa_family) {
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)) {
9639 char dst[INET6_ADDRSTRLEN];
9642 log_error_write(srv, __FILE__, __LINE__,
9643 "SSSS", "NOTICE: getnameinfo failed: ",
9644 strerror(errno), ", using ip-address instead");
9646 - buffer_append_string(o,
9647 - inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
9649 + buffer_append_string(o,
9650 + inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
9653 buffer_append_string(o, hbuf);
9655 log_error_write(srv, __FILE__, __LINE__,
9656 "SdSS", "NOTICE: gethostbyaddr failed: ",
9657 h_errno, ", using ip-address instead");
9660 buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
9662 buffer_append_string(o, he->h_name);
9663 @@ -173,12 +173,12 @@
9665 log_error_write(srv, __FILE__, __LINE__,
9666 "S", "ERROR: unsupported address-type");
9673 - if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
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);
9685 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
9688 con->http_status = 301;
9689 con->file_finished = 1;
9698 buffer * strftime_cache_get(server *srv, time_t last_mod) {
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;
9708 /* found empty slot */
9709 if (srv->mtime_cache[i].mtime == 0) break;
9713 if (i == FILE_CACHE_MAX) {
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++;
9728 return srv->mtime_cache[i].str;
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.
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) {
9745 /* check if etag + last-modified */
9746 if (con->request.http_if_modified_since) {
9751 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
9752 used_len = strlen(con->request.http_if_modified_since);
9754 used_len = semicolon - con->request.http_if_modified_since;
9758 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
9759 con->http_status = 304;
9760 return HANDLER_FINISHED;
9762 +#ifdef HAVE_STRPTIME
9763 char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
9764 + time_t t_header, t_file;
9767 - /* convert to timestamp */
9768 - if (used_len < sizeof(buf)) {
9769 - time_t t_header, t_file;
9772 - strncpy(buf, con->request.http_if_modified_since, used_len);
9773 - buf[used_len] = '\0';
9775 - strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9776 - t_header = mktime(&tm);
9778 - strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9779 - t_file = mktime(&tm);
9781 - if (t_file > t_header) {
9782 - con->http_status = 304;
9783 - return HANDLER_FINISHED;
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);
9795 con->http_status = 412;
9796 return HANDLER_FINISHED;
9800 + strncpy(buf, con->request.http_if_modified_since, used_len);
9801 + buf[used_len] = '\0';
9803 + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9804 + t_header = mktime(&tm);
9806 + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9807 + t_file = mktime(&tm);
9809 + if (t_file > t_header) return HANDLER_GO_ON;
9811 + con->http_status = 304;
9812 + return HANDLER_FINISHED;
9814 + return HANDLER_GO_ON;
9818 con->http_status = 304;
9819 @@ -302,16 +306,41 @@
9820 } else if (con->request.http_if_modified_since) {
9825 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
9826 used_len = strlen(con->request.http_if_modified_since);
9828 used_len = semicolon - con->request.http_if_modified_since;
9832 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
9833 con->http_status = 304;
9834 return HANDLER_FINISHED;
9836 +#ifdef HAVE_STRPTIME
9837 + char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
9838 + time_t t_header, t_file;
9841 + /* convert to timestamp */
9842 + if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
9844 + strncpy(buf, con->request.http_if_modified_since, used_len);
9845 + buf[used_len] = '\0';
9847 + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9848 + t_header = mktime(&tm);
9850 + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
9851 + t_file = mktime(&tm);
9853 + if (t_file > t_header) return HANDLER_GO_ON;
9855 + con->http_status = 304;
9856 + return HANDLER_FINISHED;
9858 + return HANDLER_GO_ON;
9863 --- ../lighttpd-1.4.11/src/http_auth.c 2006-02-01 13:02:52.000000000 +0200
9864 +++ lighttpd-1.4.12/src/http_auth.c 2006-07-11 22:07:53.000000000 +0300
9869 -#include <unistd.h>
9874 #include "http_auth_digest.h"
9877 +#include "sys-strings.h"
9880 # include <openssl/md5.h>
9887 -#include <security/pam_appl.h>
9888 -#include <security/pam_misc.h>
9890 -static struct pam_conv conv = {
9896 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
9898 static const char base64_pad = '=';
9900 unsigned char *result;
9905 size_t in_len = strlen(in);
9908 buffer_prepare_copy(out, in_len);
9911 result = (unsigned char *)out->ptr;
9915 /* run through the whole string, converting as we go */
9916 for (i = 0; i < in_len; i++) {
9920 if (ch == '\0') break;
9923 if (ch == base64_pad) break;
9926 ch = base64_reverse_table[ch];
9927 if (ch < 0) continue;
9932 result[j] = ch << 2;
9933 @@ -125,168 +115,168 @@
9945 static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
9949 if (!username->used|| !realm->used) return -1;
9952 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
9957 if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
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));
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;
9983 - * user:realm:md5(user:realm:password)
9985 + * user:realm:md5(user:realm:password)
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'");
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'");
10019 /* get pointers to the fields */
10020 - u_len = f_realm - f_user;
10021 + u_len = f_realm - f_user;
10023 r_len = f_pwd - f_realm;
10027 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10028 pwd_len = e - f_pwd;
10030 pwd_len = f.size - (f_pwd - f.start);
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))) {
10041 buffer_copy_string_len(password, f_pwd, pwd_len);
10058 } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
10059 p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10065 auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
10068 if (buffer_is_empty(auth_fn)) return -1;
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));
10084 while (f_line - f.start != f.size) {
10085 char *f_user, *f_pwd, *e;
10086 size_t u_len, pwd_len;
10097 * user:crypted passwd
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'");
10116 /* get pointers to the fields */
10117 - u_len = f_pwd - f_user;
10118 + u_len = f_pwd - f_user;
10122 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10123 pwd_len = e - f_pwd;
10125 pwd_len = f.size - (f_pwd - f.start);
10129 if (username->used - 1 == u_len &&
10130 (0 == strncmp(username->ptr, f_user, u_len))) {
10134 buffer_copy_string_len(password, f_pwd, pwd_len);
10151 } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10161 @@ -296,7 +286,7 @@
10163 data_string *require;
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;
10176 if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
10182 if (i == p->conf.auth_require->used) {
10185 @@ -317,72 +307,72 @@
10186 req = ((data_array *)(p->conf.auth_require->data[i]))->value;
10188 require = (data_string *)array_get_element(req, "require");
10191 /* if we get here, the user we got a authed user */
10192 if (0 == strcmp(require->value->ptr, "valid-user")) {
10197 /* user=name1|group=name3|host=name4 */
10200 /* seperate the string by | */
10202 log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
10207 username_len = username ? strlen(username) : 0;
10210 r = rules = require->value->ptr;
10215 const char *k, *v, *e;
10216 int k_len, v_len, r_len;
10219 e = strchr(r, '|');
10225 r_len = strlen(rules) - (r - rules);
10229 /* from r to r + r_len is a rule */
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",
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",
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",
10264 /* the part before the = is user|group|host */
10270 v_len = r_len - k_len - 1;
10274 if (0 == strncmp(k, "user", k_len)) {
10277 username_len == v_len &&
10278 0 == strncmp(username, v, v_len)) {
10280 @@ -404,19 +394,19 @@
10281 log_error_write(srv, __FILE__, __LINE__, "s", "unknown key");
10291 log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
10302 * @param password password-string from the auth-backend
10303 * @param pw password-string from the client
10305 @@ -426,16 +416,16 @@
10308 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10313 - * user:realm:md5(user:realm:password)
10315 + * user:realm:md5(user:realm:password)
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);
10336 if (0 == strcmp(password->ptr, a1)) {
10339 - } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
10341 + } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
10345 size_t salt_len = 0;
10351 * user:crypted password
10357 * CRYPT_STD_DES 2-character (Default)
10358 * CRYPT_EXT_DES 9-character
10359 @@ -478,7 +468,7 @@
10361 } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
10362 char *dollar = NULL;
10365 if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
10366 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10368 @@ -495,7 +485,7 @@
10369 strncpy(salt, password->ptr, salt_len);
10371 salt[salt_len] = '\0';
10374 crypted = crypt(pw, salt);
10376 if (0 == strcmp(password->ptr, crypted)) {
10377 @@ -503,40 +493,13 @@
10379 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10383 - } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10386 + } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10387 if (0 == strcmp(password->ptr, pw)) {
10390 - } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) {
10392 - pam_handle_t *pamh=NULL;
10395 - retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
10397 - if (retval == PAM_SUCCESS)
10398 - retval = pam_authenticate(pamh, 0); /* is user really user? */
10400 - if (retval == PAM_SUCCESS)
10401 - retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
10403 - /* This is where we have been authorized or not. */
10405 - if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
10407 - log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
10410 - if (retval == PAM_SUCCESS) {
10411 - log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
10414 - log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
10417 - } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10418 + } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10421 LDAPMessage *lm, *first;
10422 @@ -544,45 +507,45 @@
10424 char *attrs[] = { LDAP_NO_ATTRS, NULL };
10428 /* for now we stay synchronous */
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
10446 * we have to protect us againt username which modifies out filter in
10451 for (i = 0; i < username->used - 1; i++) {
10452 char c = username->ptr[i];
10458 - log_error_write(srv, __FILE__, __LINE__, "sbd",
10460 + log_error_write(srv, __FILE__, __LINE__, "sbd",
10461 "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
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);
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 @@
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))) {
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);
10498 if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
10499 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10509 if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
10510 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
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));
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));
10537 ldap_unbind_s(ldap);
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));
10549 ldap_unbind_s(ldap);
10558 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
10559 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10562 ldap_unbind_s(ldap);
10570 ldap_unbind_s(ldap);
10573 /* everything worked, good, access granted */
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;
10585 data_string *realm;
10588 realm = (data_string *)array_get_element(req, "realm");
10591 username = buffer_init();
10592 password = buffer_init();
10595 base64_decode(username, realm_str);
10598 /* r2 == user:password */
10599 if (NULL == (pw = strchr(username->ptr, ':'))) {
10600 buffer_free(username);
10603 log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
10613 username->used = pw - username->ptr;
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);
10622 log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed");
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);
10634 buffer_free(username);
10635 buffer_free(password);
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);
10648 log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
10655 /* remember the username */
10656 buffer_copy_string_buffer(p->auth_user, username);
10659 buffer_free(username);
10660 buffer_free(password);
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) {
10675 @@ -745,18 +708,18 @@
10682 const char *m = NULL;
10684 buffer *password, *b, *username_buf, *realm_buf;
10695 /* init pointers */
10697 @@ -771,11 +734,11 @@
10700 { S("response=") },
10708 dkv[0].ptr = &username;
10709 dkv[1].ptr = &realm;
10710 dkv[2].ptr = &nonce;
10711 @@ -786,24 +749,24 @@
10713 dkv[8].ptr = &respons;
10720 for (i = 0; dkv[i].key; i++) {
10721 *(dkv[i].ptr) = NULL;
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)");
10738 b = buffer_init_string(realm_str);
10741 /* parse credentials from client */
10742 for (c = b->ptr; *c; c++) {
10743 /* skip whitespaces */
10744 @@ -812,18 +775,18 @@
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;
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;
10765 /* value without "...", terminated by EOL */
10766 @@ -833,7 +796,7 @@
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);
10781 /* check if everything is transmitted */
10787 (qop && (!nc || !cnonce)) ||
10789 /* missing field */
10791 - log_error_write(srv, __FILE__, __LINE__, "s",
10793 + log_error_write(srv, __FILE__, __LINE__, "s",
10794 "digest: missing field");
10798 - m = get_http_method_name(con->request.http_method);
10799 + m = get_http_method_name(con->request.http_method);
10801 /* password-string == HA1 */
10802 password = buffer_init();
10803 @@ -873,10 +836,10 @@
10804 buffer_free(realm_buf);
10809 buffer_free(username_buf);
10810 buffer_free(realm_buf);
10813 if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10814 /* generate password from plain-text */
10816 @@ -890,16 +853,16 @@
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]);
10826 /* we already check that above */
10831 buffer_free(password);
10835 strcasecmp(algorithm, "md5-sess") == 0) {
10837 @@ -910,9 +873,9 @@
10838 MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
10839 MD5_Final(HA1, &Md5Ctx);
10846 /* calculate H(A2) */
10848 MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
10849 @@ -924,7 +887,7 @@
10851 MD5_Final(HA2, &Md5Ctx);
10852 CvtHex(HA2, HA2Hex);
10855 /* calculate response */
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);
10864 if (0 != strcmp(a2, respons)) {
10865 /* digest not ok */
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);
10874 - log_error_write(srv, __FILE__, __LINE__, "sss",
10876 + log_error_write(srv, __FILE__, __LINE__, "sss",
10877 "digest: auth failed for", username, "wrong password");
10885 /* value is our allow-rules */
10886 if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
10889 - log_error_write(srv, __FILE__, __LINE__, "s",
10891 + log_error_write(srv, __FILE__, __LINE__, "s",
10892 "digest: rules did match");
10899 /* remember the username */
10900 buffer_copy_string(p->auth_user, username);
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");
10912 @@ -985,23 +948,23 @@
10920 /* generate shared-secret */
10922 MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
10923 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
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));
10933 MD5_Final(h, &Md5Ctx);
10941 --- ../lighttpd-1.4.11/src/http_auth.h 2005-08-14 17:12:31.000000000 +0300
10942 +++ lighttpd-1.4.12/src/http_auth.h 2006-07-11 22:07:53.000000000 +0300
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;
10951 + AUTH_BACKEND_UNSET,
10952 + AUTH_BACKEND_PLAIN,
10953 + AUTH_BACKEND_LDAP,
10954 + AUTH_BACKEND_HTPASSWD,
10955 + AUTH_BACKEND_HTDIGEST
10960 array *auth_require;
10963 buffer *auth_plain_groupfile;
10964 buffer *auth_plain_userfile;
10967 buffer *auth_htdigest_userfile;
10968 buffer *auth_htpasswd_userfile;
10971 buffer *auth_backend_conf;
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;
10983 unsigned short auth_debug;
10987 auth_backend_t auth_backend;
10994 buffer *ldap_filter_pre;
10995 buffer *ldap_filter_post;
10997 @@ -49,15 +53,15 @@
11006 buffer *ldap_filter;
11010 mod_auth_plugin_config **config_storage;
11013 mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
11014 } mod_auth_plugin_data;
11016 --- ../lighttpd-1.4.11/src/http_auth_digest.h 2006-01-05 00:54:01.000000000 +0200
11017 +++ lighttpd-1.4.12/src/http_auth_digest.h 2006-07-11 22:07:53.000000000 +0300
11027 --- ../lighttpd-1.4.11/src/http_chunk.c 2005-08-11 01:26:50.000000000 +0300
11028 +++ lighttpd-1.4.12/src/http_chunk.c 2006-07-11 22:07:53.000000000 +0300
11031 * the HTTP chunk-API
11038 #include <sys/types.h>
11041 #include <stdlib.h>
11043 -#include <unistd.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;
11053 b = srv->tmp_chunk_len;
11057 buffer_copy_string(b, "0");
11059 for (i = 0; i < 8 && len; i++) {
11064 /* i is the number of hex digits we have */
11065 buffer_prepare_copy(b, i + 1);
11068 for (j = i-1, len = olen; j+1 > 0; j--) {
11069 b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
11071 @@ -43,61 +42,61 @@
11073 b->ptr[b->used++] = '\0';
11077 buffer_append_string(b, "\r\n");
11078 chunkqueue_append_buffer(con->write_queue, b);
11085 int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
11089 if (!con) return -1;
11092 cq = con->write_queue;
11095 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11096 http_chunk_append_len(srv, con, len);
11100 chunkqueue_append_file(cq, fn, offset, len);
11103 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
11104 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11111 int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
11115 if (!con) return -1;
11118 cq = con->write_queue;
11121 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11122 http_chunk_append_len(srv, con, mem->used - 1);
11126 chunkqueue_append_buffer(cq, mem);
11129 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
11130 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11137 int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
11141 if (!con) return -1;
11144 cq = con->write_queue;
11148 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11149 http_chunk_append_len(srv, con, 0);
11150 @@ -107,17 +106,17 @@
11156 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11157 http_chunk_append_len(srv, con, len - 1);
11161 chunkqueue_append_mem(cq, mem, len);
11164 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11165 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11172 @@ -125,9 +124,9 @@
11173 off_t http_chunkqueue_length(server *srv, connection *con) {
11175 log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
11182 return chunkqueue_length(con->write_queue);
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
11187 +#include <string.h>
11188 +#include <stdlib.h>
11189 +#include <stdio.h>
11190 +#include <assert.h>
11192 +#include "http_resp.h"
11193 +#include "http_resp_parser.h"
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 *);
11204 + chunk *c; /* current chunk in the chunkqueue */
11205 + size_t offset; /* current offset in current chunk */
11208 + size_t lookup_offset;
11211 + int is_statusline;
11212 +} http_resp_tokenizer_t;
11214 +http_resp *http_response_init(void) {
11215 + http_resp *resp = calloc(1, sizeof(*resp));
11217 + resp->reason = buffer_init();
11218 + resp->headers = array_init();
11223 +void http_response_reset(http_resp *resp) {
11224 + if (!resp) return;
11226 + buffer_reset(resp->reason);
11227 + array_reset(resp->headers);
11231 +void http_response_free(http_resp *resp) {
11232 + if (!resp) return;
11234 + buffer_free(resp->reason);
11235 + array_free(resp->headers);
11240 +static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11241 + if (t->offset == t->c->mem->used - 1) {
11242 + /* end of chunk, open next chunk */
11244 + if (!t->c->next) return -1;
11246 + t->c = t->c->next;
11250 + *c = t->c->mem->ptr[t->offset++];
11252 + t->lookup_offset = t->offset;
11253 + t->lookup_c = t->c;
11256 + fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
11262 +static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11263 + if (t->lookup_offset == t->lookup_c->mem->used - 1) {
11264 + /* end of chunk, open next chunk */
11266 + if (!t->lookup_c->next) return -1;
11268 + t->lookup_c = t->lookup_c->next;
11269 + t->lookup_offset = 0;
11272 + *c = t->lookup_c->mem->ptr[t->lookup_offset++];
11274 + fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
11281 +static int http_resp_tokenizer(
11282 + http_resp_tokenizer_t *t,
11289 + /* push the token to the parser */
11291 + while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
11305 + if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11310 + t->c = t->lookup_c;
11311 + t->offset = t->lookup_offset;
11313 + t->is_statusline = 0;
11316 + fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__);
11323 + t->is_statusline = 0;
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 */
11334 + if (c == ':') break; /* the : is the splitter between key and value */
11337 + if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11340 + if (t->c == t->lookup_c &&
11341 + t->offset == t->lookup_offset + 1) {
11343 + fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__);
11349 + /* the lookup points to the first invalid char */
11350 + t->lookup_offset--;
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);
11356 + /* first chunk */
11357 + buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
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;
11366 + buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
11369 + t->offset = t->lookup_offset;
11384 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
11385 + http_resp_tokenizer_t t;
11386 + void *pParser = NULL;
11387 + int token_id = 0;
11388 + buffer *token = NULL;
11389 + http_resp_ctx_t context;
11390 + parse_status_t ret = PARSE_UNSET;
11391 + int last_token_id = 0;
11395 + t.offset = t.c->offset;
11397 + t.is_statusline = 1;
11400 + context.errmsg = buffer_init();
11401 + context.resp = resp;
11403 + pParser = http_resp_parserAlloc( malloc );
11404 + token = buffer_init();
11406 + http_resp_parserTrace(stderr, "http-response: ");
11409 + while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) {
11410 + http_resp_parser(pParser, token_id, token, &context);
11412 + token = buffer_init();
11414 + /* CRLF CRLF ... the header end sequence */
11415 + if (last_token_id == TK_CRLF &&
11416 + token_id == TK_CRLF) break;
11418 + last_token_id = token_id;
11421 + /* oops, the parser failed */
11422 + if (context.ok == 0) {
11423 + ret = PARSE_ERROR;
11425 + fprintf(stderr, "%s.%d: parsing failed at: ...%20s\r\n",
11426 + __FILE__, __LINE__, t.c->mem->ptr + t.offset);
11429 + http_resp_parser(pParser, 0, token, &context);
11430 + http_resp_parserFree(pParser, free );
11432 + if (context.ok == 0) {
11433 + /* we are missing the some tokens */
11435 + if (!buffer_is_empty(context.errmsg)) {
11436 + fprintf(stderr, "%s.%d: hmm, %20s\r\n",
11437 + __FILE__, __LINE__, context.errmsg->ptr);
11440 + if (ret == PARSE_UNSET) {
11441 + ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR;
11446 + for (c = cq->first; c != t.c; c = c->next) {
11447 + c->offset = c->mem->used - 1;
11450 + c->offset = t.offset;
11452 + ret = PARSE_SUCCESS;
11455 + buffer_free(token);
11456 + buffer_free(context.errmsg);
11461 --- ../lighttpd-1.4.11/src/http_resp.h 1970-01-01 03:00:00.000000000 +0300
11462 +++ lighttpd-1.4.12/src/http_resp.h 2006-07-11 22:07:53.000000000 +0300
11464 +#ifndef _HTTP_RESP_H_
11465 +#define _HTTP_RESP_H_
11467 +#include "array.h"
11468 +#include "chunk.h"
11478 + int protocol; /* http/1.0, http/1.1 */
11479 + int status; /* e.g. 200 */
11480 + buffer *reason; /* e.g. Ok */
11489 +} http_resp_ctx_t;
11491 +http_resp *http_response_init(void);
11492 +void http_response_free(http_resp *resp);
11493 +void http_response_reset(http_resp *resp);
11495 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
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
11501 +/* Driver template for the LEMON parser generator.
11502 +** The author disclaims copyright to this source code.
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"
11509 +#include <assert.h>
11510 +#include <string.h>
11511 +#include "http_resp.h"
11512 +#include "keyvalue.h"
11513 +#include "array.h"
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.
11520 +** These constants (all generated automatically by the parser generator)
11521 +** specify the various kinds of tokens (terminals) that the parser
11524 +** Each symbol here is a terminal symbol in the grammar.
11526 +/* Make sure the INTERFACE macro is defined.
11529 +# define INTERFACE 1
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
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.
11565 +#define YYCODETYPE unsigned char
11566 +#define YYNOCODE 12
11567 +#define YYACTIONTYPE unsigned char
11568 +#define http_resp_parserTOKENTYPE buffer *
11570 + http_resp_parserTOKENTYPE yy0;
11572 + data_string * yy9;
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
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)
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.
11595 +** Suppose the action integer is N. Then the action is determined as
11598 +** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
11599 +** token onto the stack and goto state N.
11601 +** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
11603 +** N == YYNSTATE+YYNRULE A syntax error has occurred.
11605 +** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
11607 +** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
11608 +** slots in the yy_action[] table.
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
11613 +** yy_action[ yy_shift_ofst[S] + X ]
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.
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.
11626 +** The following are the tables generated in this section:
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.
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,
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,
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,
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,
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,
11661 +#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
11663 +/* The next table maps tokens into fallback tokens. If a construct
11664 +** like the following:
11666 +** %fallback ID X Y Z.
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.
11674 +static const YYCODETYPE yyFallback[] = {
11676 +#endif /* YYFALLBACK */
11678 +/* The following structure represents a single element of the
11679 +** parser's stack. Information stored includes:
11681 +** + The state number for the parser at this level of the stack.
11683 +** + The value of the token stored at this level of the stack.
11684 +** (In other words, the "major" token.)
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.
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 */
11697 +typedef struct yyStackEntry yyStackEntry;
11699 +/* The state of the parser is completely contained in an instance of
11700 +** the following structure */
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 */
11707 +typedef struct yyParser yyParser;
11710 +#include <stdio.h>
11711 +static FILE *yyTraceFILE = 0;
11712 +static char *yyTracePrompt = 0;
11713 +#endif /* NDEBUG */
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
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
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;
11739 +#endif /* 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",
11749 +#endif /* NDEBUG */
11752 +/* For tracing reduce actions, the names of all rules are required.
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",
11765 +#endif /* NDEBUG */
11768 +** This function returns the symbolic name associated with a token
11771 +const char *http_resp_parserTokenName(int tokenType){
11773 + if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
11774 + return yyTokenName[tokenType];
11776 + return "Unknown";
11784 +** This function allocates a new parser.
11785 +** The only argument is a pointer to a function which works like
11789 +** A pointer to the function used to allocate memory.
11792 +** A pointer to a parser. This pointer is used in subsequent calls
11793 +** to http_resp_parser and http_resp_parserFree.
11795 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t)){
11796 + yyParser *pParser;
11797 + pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
11799 + pParser->yyidx = -1;
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
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.
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.
11824 +#line 23 "./http_resp_parser.y"
11825 +{ buffer_free((yypminor->yy0)); }
11826 +#line 326 "http_resp_parser.c"
11828 + default: break; /* If no destructor action specified: do nothing */
11833 +** Pop the parser's stack once.
11835 +** If there is a destructor routine associated with the token which
11836 +** is popped from the stack, then call it.
11838 +** Return the major token number for the symbol popped.
11840 +static int yy_pop_parser_stack(yyParser *pParser){
11841 + YYCODETYPE yymajor;
11842 + yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
11844 + if( pParser->yyidx<0 ) return 0;
11846 + if( yyTraceFILE && pParser->yyidx>=0 ){
11847 + fprintf(yyTraceFILE,"%sPopping %s\n",
11849 + yyTokenName[yytos->major]);
11852 + yymajor = yytos->major;
11853 + yy_destructor( yymajor, &yytos->minor);
11854 + pParser->yyidx--;
11859 +** Deallocate and destroy a parser. Destructors are all called for
11860 +** all stack elements before shutting the parser down.
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
11870 +void http_resp_parserFree(
11871 + void *p, /* The parser to be deleted */
11872 + void (*freeProc)(void*) /* Function used to reclaim memory */
11874 + yyParser *pParser = (yyParser*)p;
11875 + if( pParser==0 ) return;
11876 + while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
11877 + (*freeProc)((void*)pParser);
11881 +** Find the appropriate action for a parser given the terminal
11882 +** look-ahead token iLookAhead.
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.
11888 +static int yy_find_shift_action(
11889 + yyParser *pParser, /* The parser */
11890 + int iLookAhead /* The look-ahead token */
11893 + int stateno = pParser->yystack[pParser->yyidx].stateno;
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];
11900 + if( iLookAhead==YYNOCODE ){
11901 + return YY_NO_ACTION;
11904 + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
11906 + int iFallback; /* Fallback token */
11907 + if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
11908 + && (iFallback = yyFallback[iLookAhead])!=0 ){
11910 + if( yyTraceFILE ){
11911 + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
11912 + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
11915 + return yy_find_shift_action(pParser, iFallback);
11918 + return yy_default[stateno];
11920 + return yy_action[i];
11925 +** Find the appropriate action for a parser given the non-terminal
11926 +** look-ahead token iLookAhead.
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.
11932 +static int yy_find_reduce_action(
11933 + yyParser *pParser, /* The parser */
11934 + int iLookAhead /* The look-ahead token */
11937 + int stateno = pParser->yystack[pParser->yyidx].stateno;
11939 + i = yy_reduce_ofst[stateno];
11940 + if( i==YY_REDUCE_USE_DFLT ){
11941 + return yy_default[stateno];
11943 + if( iLookAhead==YYNOCODE ){
11944 + return YY_NO_ACTION;
11947 + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
11948 + return yy_default[stateno];
11950 + return yy_action[i];
11955 +** Perform a shift action.
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 */
11963 + yyStackEntry *yytos;
11964 + yypParser->yyidx++;
11965 + if( yypParser->yyidx>=YYSTACKDEPTH ){
11966 + http_resp_parserARG_FETCH;
11967 + yypParser->yyidx--;
11969 + if( yyTraceFILE ){
11970 + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
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 */
11979 + yytos = &yypParser->yystack[yypParser->yyidx];
11980 + yytos->stateno = yyNewState;
11981 + yytos->major = yyMajor;
11982 + yytos->minor = *yypMinor;
11984 + if( yyTraceFILE && yypParser->yyidx>0 ){
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");
11995 +/* The following table contains information about every rule that
11996 +** is used during the reduce.
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[] = {
12013 +static void yy_accept(yyParser*); /* Forward Declaration */
12016 +** Perform a reduce action and the shift that must immediately
12017 +** follow the reduce.
12019 +static void yy_reduce(
12020 + yyParser *yypParser, /* The parser */
12021 + int yyruleno /* Number of the rule by which to reduce */
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];
12031 + if( yyTraceFILE && yyruleno>=0
12032 + && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
12033 + fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
12034 + yyRuleName[yyruleno]);
12036 +#endif /* NDEBUG */
12038 + switch( yyruleno ){
12039 + /* Beginning here are the reduction cases. A typical example
12042 + ** #line <lineno> <grammarfile>
12043 + ** { ... } // User supplied code
12044 + ** #line <lineno> <thisfile>
12048 +#line 26 "./http_resp_parser.y"
12050 + http_resp *resp = ctx->resp;
12053 + resp->protocol = HTTP_VERSION_UNSET;
12055 + buffer_copy_string(resp->reason, ""); /* no reason */
12056 + array_free(resp->headers);
12057 + resp->headers = yymsp[-1].minor.yy12;
12059 + if (NULL == (ds = (data_string *)array_get_element(yymsp[-1].minor.yy12, "Status"))) {
12060 + resp->status = 0;
12063 + resp->status = strtol(ds->value->ptr, &err, 10);
12065 + if (*err != '\0' && *err != ' ') {
12066 + buffer_copy_string(ctx->errmsg, "expected a number: ");
12067 + buffer_append_string_buffer(ctx->errmsg, ds->value);
12068 + buffer_append_string(ctx->errmsg, err);
12074 + yymsp[-1].minor.yy12 = NULL;
12076 +#line 576 "http_resp_parser.c"
12077 + yy_destructor(1,&yymsp[0].minor);
12080 +#line 54 "./http_resp_parser.y"
12082 + http_resp *resp = ctx->resp;
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);
12088 + array_free(resp->headers);
12090 + resp->headers = yymsp[-1].minor.yy12;
12092 + yymsp[-1].minor.yy12 = NULL;
12094 +#line 594 "http_resp_parser.c"
12095 + yy_destructor(1,&yymsp[-2].minor);
12096 + yy_destructor(1,&yymsp[0].minor);
12099 +#line 68 "./http_resp_parser.y"
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;
12106 + buffer_copy_string(ctx->errmsg, "unknown protocol: ");
12107 + buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12112 +#line 612 "http_resp_parser.c"
12115 +#line 81 "./http_resp_parser.y"
12118 + yygotominor.yy20 = strtol(yymsp[0].minor.yy0->ptr, &err, 10);
12120 + if (*err != '\0') {
12121 + buffer_copy_string(ctx->errmsg, "expected a number: ");
12122 + buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12127 +#line 627 "http_resp_parser.c"
12130 +#line 93 "./http_resp_parser.y"
12132 + yygotominor.yy0 = yymsp[0].minor.yy0;
12133 + yymsp[0].minor.yy0 = NULL;
12135 +#line 635 "http_resp_parser.c"
12138 +#line 98 "./http_resp_parser.y"
12140 + yygotominor.yy0 = yymsp[-1].minor.yy0;
12142 + buffer_append_string(yygotominor.yy0, " ");
12143 + buffer_append_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12145 + yymsp[-1].minor.yy0 = NULL;
12147 +#line 647 "http_resp_parser.c"
12150 +#line 107 "./http_resp_parser.y"
12152 + yygotominor.yy12 = yymsp[-1].minor.yy12;
12154 + array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12156 + yymsp[-1].minor.yy12 = NULL;
12158 +#line 658 "http_resp_parser.c"
12161 +#line 115 "./http_resp_parser.y"
12163 + yygotominor.yy12 = array_init();
12165 + array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12167 +#line 667 "http_resp_parser.c"
12170 +#line 120 "./http_resp_parser.y"
12172 + yygotominor.yy9 = data_string_init();
12174 + buffer_copy_string_buffer(yygotominor.yy9->key, yymsp[-3].minor.yy0);
12175 + buffer_copy_string_buffer(yygotominor.yy9->value, yymsp[-1].minor.yy0);
12177 +#line 677 "http_resp_parser.c"
12178 + yy_destructor(3,&yymsp[-2].minor);
12179 + yy_destructor(1,&yymsp[0].minor);
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);
12194 +** The following code executes when the parse fails
12196 +static void yy_parse_failed(
12197 + yyParser *yypParser /* The parser */
12199 + http_resp_parserARG_FETCH;
12201 + if( yyTraceFILE ){
12202 + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
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"
12212 +#line 712 "http_resp_parser.c"
12213 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12217 +** The following code executes when a syntax error first occurs.
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 */
12224 + http_resp_parserARG_FETCH;
12225 +#define TOKEN (yyminor.yy0)
12226 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12230 +** The following is executed when the parser accepts
12232 +static void yy_accept(
12233 + yyParser *yypParser /* The parser */
12235 + http_resp_parserARG_FETCH;
12237 + if( yyTraceFILE ){
12238 + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
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 */
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.
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.
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 */
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 */
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;
12287 + yyminorunion.yy0 = yyminor;
12288 + yyendofinput = (yymajor==0);
12289 + http_resp_parserARG_STORE;
12292 + if( yyTraceFILE ){
12293 + fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
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 ){
12305 + yymajor = YYNOCODE;
12307 + }else if( yyact < YYNSTATE + YYNRULE ){
12308 + yy_reduce(yypParser,yyact-YYNSTATE);
12309 + }else if( yyact == YY_ERROR_ACTION ){
12312 + if( yyTraceFILE ){
12313 + fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
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".
12321 + ** This is what we do if the grammar does define ERROR:
12323 + ** * Call the %syntax_error function.
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.
12329 + ** * Set the error count to three.
12331 + ** * Begin accepting and shifting new tokens. No new error
12332 + ** processing will occur until three tokens have been
12333 + ** shifted successfully.
12336 + if( yypParser->yyerrcnt<0 ){
12337 + yy_syntax_error(yypParser,yymajor,yyminorunion);
12339 + yymx = yypParser->yystack[yypParser->yyidx].major;
12340 + if( yymx==YYERRORSYMBOL || yyerrorhit ){
12342 + if( yyTraceFILE ){
12343 + fprintf(yyTraceFILE,"%sDiscard input token %s\n",
12344 + yyTracePrompt,yyTokenName[yymajor]);
12347 + yy_destructor(yymajor,&yyminorunion);
12348 + yymajor = YYNOCODE;
12351 + yypParser->yyidx >= 0 &&
12352 + yymx != YYERRORSYMBOL &&
12353 + (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
12355 + yy_pop_parser_stack(yypParser);
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 ){
12363 + u2.YYERRSYMDT = 0;
12364 + yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
12367 + yypParser->yyerrcnt = 3;
12369 +#else /* YYERRORSYMBOL is not defined */
12370 + /* This is what we do if the grammar does not define ERROR:
12372 + ** * Report an error message, and throw away the input token.
12374 + ** * If the input token is $, then fail the parse.
12376 + ** As before, subsequent error messages are suppressed until
12377 + ** three input tokens have been successfully shifted.
12379 + if( yypParser->yyerrcnt<=0 ){
12380 + yy_syntax_error(yypParser,yymajor,yyminorunion);
12382 + yypParser->yyerrcnt = 3;
12383 + yy_destructor(yymajor,&yyminorunion);
12384 + if( yyendofinput ){
12385 + yy_parse_failed(yypParser);
12387 + yymajor = YYNOCODE;
12390 + yy_accept(yypParser);
12391 + yymajor = YYNOCODE;
12393 + }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
12396 --- ../lighttpd-1.4.11/src/inet_ntop_cache.c 2005-08-11 01:26:38.000000000 +0300
12397 +++ lighttpd-1.4.12/src/inet_ntop_cache.c 2006-07-11 22:07:52.000000000 +0300
12399 #include "sys-socket.h"
12401 const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
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 */
12418 if (i == INET_NTOP_CACHE_MAX) {
12419 /* not found in cache */
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);
12432 srv->inet_ntop_cache[i].ts = srv->cur_ts;
12433 srv->inet_ntop_cache[i].family = addr->plain.sa_family;
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);
12444 return srv->inet_ntop_cache[i].b2;
12447 --- ../lighttpd-1.4.11/src/joblist.c 2005-08-11 01:26:41.000000000 +0300
12448 +++ lighttpd-1.4.12/src/joblist.c 2006-07-11 22:07:51.000000000 +0300
12451 int joblist_append(server *srv, connection *con) {
12452 if (con->in_joblist) return 0;
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);
12464 srv->joblist->ptr[srv->joblist->used++] = con;
12470 void joblist_free(server *srv, connections *joblist) {
12474 free(joblist->ptr);
12477 @@ -31,14 +31,14 @@
12478 connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
12485 if (fdwaitqueue->used == 0) return NULL;
12488 con = fdwaitqueue->ptr[0];
12491 memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
12498 srv->fdwaitqueue->size += 16;
12499 srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
12503 srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
12509 --- ../lighttpd-1.4.11/src/keyvalue.c 2006-03-02 16:08:06.000000000 +0200
12510 +++ lighttpd-1.4.12/src/keyvalue.c 2006-07-11 22:07:51.000000000 +0300
12512 { 504, "Gateway Timeout" },
12513 { 505, "HTTP Version Not Supported" },
12514 { 507, "Insufficient Storage" }, /* WebDAV */
12516 + { 509, "Bandwidth Limit exceeded" },
12521 @@ -102,12 +103,12 @@
12522 { 501, "501.html" },
12523 { 503, "503.html" },
12524 { 505, "505.html" },
12531 -const char *keyvalue_get_value(keyvalue *kv, int k) {
12532 +const char *keyvalue_get_value(keyvalue *kv, int k) {
12534 for (i = 0; kv[i].value; i++) {
12535 if (kv[i].key == k) return kv[i].value;
12536 @@ -115,7 +116,7 @@
12540 -int keyvalue_get_key(keyvalue *kv, const char *s) {
12541 +int keyvalue_get_key(keyvalue *kv, const char *s) {
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 @@
12547 keyvalue_buffer *keyvalue_buffer_init(void) {
12548 keyvalue_buffer *kvb;
12551 kvb = calloc(1, sizeof(*kvb));
12557 @@ -135,49 +136,49 @@
12559 if (kvb->size == 0) {
12563 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12566 for(i = 0; i < kvb->size; i++) {
12567 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12569 } else if (kvb->used == kvb->size) {
12573 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12576 for(i = kvb->used; i < kvb->size; i++) {
12577 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12582 kvb->kv[kvb->used]->key = key;
12583 kvb->kv[kvb->used]->value = strdup(value);
12592 void keyvalue_buffer_free(keyvalue_buffer *kvb) {
12596 for (i = 0; i < kvb->size; i++) {
12597 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12602 if (kvb->kv) free(kvb->kv);
12609 s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
12610 s_keyvalue_buffer *kvb;
12613 kvb = calloc(1, sizeof(*kvb));
12619 @@ -186,50 +187,50 @@
12620 if (kvb->size == 0) {
12625 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12628 for(i = 0; i < kvb->size; i++) {
12629 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12631 } else if (kvb->used == kvb->size) {
12635 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12638 for(i = kvb->used; i < kvb->size; i++) {
12639 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12644 kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
12645 kvb->kv[kvb->used]->value = strdup(value);
12654 void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
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);
12665 if (kvb->kv) free(kvb->kv);
12672 httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
12673 httpauth_keyvalue_buffer *kvb;
12676 kvb = calloc(1, sizeof(*kvb));
12682 @@ -237,42 +238,42 @@
12684 if (kvb->size == 0) {
12688 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12691 for(i = 0; i < kvb->size; i++) {
12692 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12694 } else if (kvb->used == kvb->size) {
12698 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12701 for(i = kvb->used; i < kvb->size; i++) {
12702 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12707 kvb->kv[kvb->used]->key = strdup(key);
12708 kvb->kv[kvb->used]->realm = strdup(realm);
12709 kvb->kv[kvb->used]->type = type;
12718 void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
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);
12729 if (kvb->kv) free(kvb->kv);
12735 @@ -306,9 +307,9 @@
12737 pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
12738 pcre_keyvalue_buffer *kvb;
12741 kvb = calloc(1, sizeof(*kvb));
12747 @@ -319,46 +320,46 @@
12753 if (!key) return -1;
12756 if (kvb->size == 0) {
12761 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12764 for(i = 0; i < kvb->size; i++) {
12765 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12767 } else if (kvb->used == kvb->size) {
12771 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12774 for(i = kvb->used; i < kvb->size; i++) {
12775 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12780 kv = kvb->kv[kvb->used];
12781 if (NULL == (kv->key = pcre_compile(key,
12782 0, &errptr, &erroff, NULL))) {
12785 fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
12789 - if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
12790 + if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
12796 kv->value = buffer_init_string(value);
12805 @@ -380,9 +381,9 @@
12806 if (kv->value) buffer_free(kv->value);
12811 if (kvb->kv) free(kvb->kv);
12817 --- ../lighttpd-1.4.11/src/keyvalue.h 2006-03-02 16:08:06.000000000 +0200
12818 +++ lighttpd-1.4.12/src/keyvalue.h 2006-07-11 22:07:52.000000000 +0300
12824 - HTTP_METHOD_UNSET = -1,
12826 - HTTP_METHOD_POST,
12827 - HTTP_METHOD_HEAD,
12828 - HTTP_METHOD_OPTIONS,
12830 + HTTP_METHOD_UNSET = -1,
12832 + HTTP_METHOD_POST,
12833 + HTTP_METHOD_HEAD,
12834 + HTTP_METHOD_OPTIONS,
12835 HTTP_METHOD_PROPFIND, /* WebDAV */
12836 - HTTP_METHOD_MKCOL,
12838 - HTTP_METHOD_DELETE,
12839 - HTTP_METHOD_COPY,
12840 - HTTP_METHOD_MOVE,
12841 - HTTP_METHOD_PROPPATCH,
12842 + HTTP_METHOD_MKCOL,
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 @@
12869 pcre_extra *key_extra;
12883 httpauth_type type;
12884 } httpauth_keyvalue;
12885 --- ../lighttpd-1.4.11/src/lemon.c 2005-09-01 00:21:34.000000000 +0300
12886 +++ lighttpd-1.4.12/src/lemon.c 2006-07-11 22:07:51.000000000 +0300
12887 @@ -579,7 +579,7 @@
12890 /* Find a precedence symbol of every rule in the grammar.
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;
12904 for(i=0; i<lemp->nstate; i++){
12905 @@ -900,7 +900,7 @@
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.
12914 @@ -1017,7 +1017,7 @@
12915 apx->type = RD_RESOLVED;
12920 apx->type==SH_RESOLVED ||
12921 apx->type==RD_RESOLVED ||
12922 apx->type==CONFLICT ||
12923 @@ -1350,7 +1350,7 @@
12924 OptInit(argv,options,stderr);
12926 printf("Lemon version 1.0\n");
12930 if( OptNArgs() < 1 ){
12931 fprintf(stderr,"Exactly one filename argument is required.\n");
12932 @@ -2031,7 +2031,7 @@
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 );
12940 ErrorMsg(psp->filename,psp->tokenlineno,
12941 @@ -2546,7 +2546,7 @@
12945 -/* Duplicate the input file without comments and without actions
12946 +/* Duplicate the input file without comments and without actions
12949 struct lemon *lemp;
12950 @@ -2822,7 +2822,7 @@
12951 PRIVATE FILE *tplt_open(lemp)
12952 struct lemon *lemp;
12959 @@ -2930,7 +2930,7 @@
12965 ** Generate code which executes when the rule "rp" is reduced. Write
12966 ** the code to "out". Make sure lineno stays up-to-date.
12968 @@ -3384,7 +3384,7 @@
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++;
12976 for(i=j=0; i<n; i++){
12977 @@ -3405,7 +3405,7 @@
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++;
12985 for(i=j=0; i<n; i++){
12986 @@ -3480,7 +3480,7 @@
12987 tplt_xfer(lemp->name,in,out,&lineno);
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)
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);
12999 - /* Generate the table of rule information
13000 + /* Generate the table of rule information
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);
13013 @@ -3630,7 +3630,7 @@
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 @@
13026 - x1a->tbl = (x1node*)malloc(
13027 + x1a->tbl = (x1node*)malloc(
13028 (sizeof(x1node) + sizeof(x1node*))*1024 );
13031 @@ -3943,7 +3943,7 @@
13035 - x2a->tbl = (x2node*)malloc(
13036 + x2a->tbl = (x2node*)malloc(
13037 (sizeof(x2node) + sizeof(x2node*))*128 );
13040 @@ -4149,7 +4149,7 @@
13044 - x3a->tbl = (x3node*)malloc(
13045 + x3a->tbl = (x3node*)malloc(
13046 (sizeof(x3node) + sizeof(x3node*))*128 );
13049 @@ -4295,7 +4295,7 @@
13053 - x4a->tbl = (x4node*)malloc(
13054 + x4a->tbl = (x4node*)malloc(
13055 (sizeof(x4node) + sizeof(x4node*))*64 );
13058 --- ../lighttpd-1.4.11/src/lempar.c 2005-08-11 01:26:40.000000000 +0300
13059 +++ lighttpd-1.4.12/src/lempar.c 2006-07-11 22:07:51.000000000 +0300
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.
13066 ** These constants (all generated automatically by the parser generator)
13067 ** specify the various kinds of tokens (terminals) that the parser
13071 ** Each symbol here is a terminal symbol in the grammar.
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
13080 ** YYFALLBACK If defined, this indicates that one or more tokens
13081 ** have fall-back values which should be used if the
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
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.
13098 ** Suppose the action integer is N. Then the action is determined as
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.
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 @@
13111 /* The next table maps tokens into fallback tokens. If a construct
13112 ** like the following:
13115 ** %fallback ID X Y Z.
13117 ** appears in the grammer, then ID becomes a fallback token for X, Y,
13118 @@ -163,10 +163,10 @@
13119 #endif /* NDEBUG */
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
13131 @@ -191,7 +191,7 @@
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[] = {
13139 #endif /* NDEBUG */
13140 @@ -220,7 +220,7 @@
13146 ** This function allocates a new parser.
13147 ** The only argument is a pointer to a function which works like
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.
13157 ** Note: during a reduce, the only symbols destroyed are those
13158 @@ -289,7 +289,7 @@
13164 ** Deallocate and destroy a parser. Destructors are all called for
13165 ** all stack elements before shutting the parser down.
13167 @@ -325,7 +325,7 @@
13170 int stateno = pParser->yystack[pParser->yyidx].stateno;
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 @@
13179 int stateno = pParser->yystack[pParser->yyidx].stateno;
13182 i = yy_reduce_ofst[stateno];
13183 if( i==YY_REDUCE_USE_DFLT ){
13184 return yy_default[stateno];
13185 @@ -455,7 +455,7 @@
13187 yymsp = &yypParser->yystack[yypParser->yyidx];
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".
13201 ** This is what we do if the grammar does define ERROR:
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
13209 -#include <unistd.h>
13210 #include <string.h>
13211 #include <stdlib.h>
13214 #include "config.h"
13218 +#undef HAVE_SYSLOG_H
13221 #ifdef HAVE_SYSLOG_H
13222 #include <syslog.h>
13228 +#include "sys-files.h"
13230 #ifdef HAVE_VALGRIND_VALGRIND_H
13231 #include <valgrind/valgrind.h>
13233 @@ -31,38 +36,38 @@
13234 # define O_LARGEFILE 0
13239 * open the errorlog
13242 * we have 3 possibilities:
13243 * - stderr (default)
13249 * if the open failed, report to the user and die
13254 int log_error_open(server *srv) {
13256 int close_stderr = 1;
13259 #ifdef HAVE_SYSLOG_H
13260 /* perhaps someone wants to use syslog() */
13261 openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
13263 srv->errorlog_mode = ERRORLOG_STDERR;
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;
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));
13282 @@ -71,15 +76,15 @@
13284 srv->errorlog_mode = ERRORLOG_FILE;
13288 log_error_write(srv, __FILE__, __LINE__, "s", "server started");
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;
13295 if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
13298 /* move stderr to /dev/null */
13299 if (close_stderr &&
13300 -1 != (fd = open("/dev/null", O_WRONLY))) {
13301 @@ -90,33 +95,33 @@
13307 * open the errorlog
13310 * if the open failed, report to the user and die
13311 * if no filename is given, use syslog instead
13316 int log_error_cycle(server *srv) {
13317 /* only cycle if we are not in syslog-mode */
13320 if (srv->errorlog_mode == ERRORLOG_FILE) {
13321 const char *logfile = srv->srvconf.errorlog_file->ptr;
13322 /* already check of opening time */
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()");
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;
13344 @@ -125,15 +130,15 @@
13345 srv->errorlog_fd = new_fd;
13350 log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
13356 int log_error_close(server *srv) {
13357 log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
13360 switch(srv->errorlog_mode) {
13361 case ERRORLOG_FILE:
13362 close(srv->errorlog_fd);
13363 @@ -146,13 +151,13 @@
13364 case ERRORLOG_STDERR:
13372 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
13376 switch(srv->errorlog_mode) {
13377 case ERRORLOG_FILE:
13378 case ERRORLOG_STDERR:
13379 @@ -161,7 +166,7 @@
13380 buffer_prepare_copy(srv->ts_debug_str, 255);
13381 strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
13382 srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
13385 srv->last_generated_debug_ts = srv->cur_ts;
13388 @@ -173,19 +178,19 @@
13389 BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
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, ") ");
13402 for(va_start(ap, fmt); *fmt; fmt++) {
13410 case 's': /* string */
13411 s = va_arg(ap, char *);
13412 @@ -227,7 +232,7 @@
13421 @@ -236,7 +241,7 @@
13427 switch(srv->errorlog_mode) {
13428 case ERRORLOG_FILE:
13429 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13430 @@ -246,11 +251,13 @@
13431 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13432 write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
13434 +#ifdef HAVE_SYSLOG_H
13435 case ERRORLOG_SYSLOG:
13436 syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
13445 --- ../lighttpd-1.4.11/src/log.h 2005-08-11 01:26:36.000000000 +0300
13446 +++ lighttpd-1.4.12/src/log.h 2006-07-11 22:07:53.000000000 +0300
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);
13454 --- ../lighttpd-1.4.11/src/md5.h 2005-11-17 16:20:40.000000000 +0200
13455 +++ lighttpd-1.4.12/src/md5.h 2006-07-11 22:07:53.000000000 +0300
13457 # include <inttypes.h>
13461 +#define UINT4 unsigned __int32
13462 +#define UINT2 unsigned __int16
13463 +#define POINTER unsigned char *
13465 #define UINT4 uint32_t
13466 #define UINT2 uint16_t
13467 #define POINTER unsigned char *
13472 --- ../lighttpd-1.4.11/src/mod_access.c 2006-01-14 19:44:54.000000000 +0200
13473 +++ lighttpd-1.4.12/src/mod_access.c 2006-07-11 22:07:53.000000000 +0300
13474 @@ -8,126 +8,125 @@
13476 #include "plugin.h"
13478 +#include "sys-strings.h"
13481 array *access_deny;
13488 plugin_config **config_storage;
13490 - plugin_config conf;
13492 + plugin_config conf;
13495 INIT_FUNC(mod_access_init) {
13499 p = calloc(1, sizeof(*p));
13505 FREE_FUNC(mod_access_free) {
13506 plugin_data *p = p_d;
13511 if (!p) return HANDLER_GO_ON;
13514 if (p->config_storage) {
13516 for (i = 0; i < srv->config_context->used; i++) {
13517 plugin_config *s = p->config_storage[i];
13520 array_free(s->access_deny);
13525 free(p->config_storage);
13532 return HANDLER_GO_ON;
13535 SETDEFAULTS_FUNC(mod_access_set_defaults) {
13536 plugin_data *p = p_d;
13539 - config_values_t cv[] = {
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 }
13547 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
13550 for (i = 0; i < srv->config_context->used; i++) {
13554 s = calloc(1, sizeof(plugin_config));
13555 s->access_deny = array_init();
13558 cv[0].destination = s->access_deny;
13561 p->config_storage[i] = s;
13564 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
13565 return HANDLER_ERROR;
13570 return HANDLER_GO_ON;
13573 -#define PATCH(x) \
13574 - p->conf.x = s->x;
13575 static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
13577 plugin_config *s = p->config_storage[0];
13579 - PATCH(access_deny);
13581 + PATCH_OPTION(access_deny);
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];
13589 /* condition didn't match */
13590 if (!config_check_cond(srv, con, dc)) continue;
13594 for (j = 0; j < dc->value->used; j++) {
13595 data_unset *du = dc->value->data[j];
13598 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
13599 - PATCH(access_deny);
13600 + PATCH_OPTION(access_deny);
13610 URIHANDLER_FUNC(mod_access_uri_handler) {
13611 plugin_data *p = p_d;
13616 if (con->uri.path->used == 0) return HANDLER_GO_ON;
13619 mod_access_patch_connection(srv, con, p);
13622 s_len = con->uri.path->used - 1;
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;
13630 if (ct_len > s_len) continue;
13633 if (ds->value->used == 0) continue;
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;
13642 return HANDLER_FINISHED;
13645 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13646 con->http_status = 403;
13649 return HANDLER_FINISHED;
13656 return HANDLER_GO_ON;
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");
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;
13675 --- ../lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200
13676 +++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-11 22:07:53.000000000 +0300
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 */
13688 #include "inet_ntop_cache.h"
13690 #include "sys-socket.h"
13691 +#include "sys-files.h"
13693 #ifdef HAVE_SYSLOG_H
13694 # include <syslog.h>
13702 FORMAT_UNSUPPORTED,
13706 FORMAT_BYTES_OUT_NO_HEADER,
13710 FORMAT_REMOTE_ADDR,
13713 @@ -59,20 +59,20 @@
13714 FORMAT_CONNECTION_STATUS,
13719 FORMAT_RESPONSE_HEADER
13728 * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
13733 -const format_mapping fmap[] =
13735 +const format_mapping fmap[] =
13737 { '%', FORMAT_PERCENT },
13738 { 'h', FORMAT_REMOTE_HOST },
13739 { 'l', FORMAT_REMOTE_IDENT },
13741 { 's', FORMAT_STATUS },
13742 { 'b', FORMAT_BYTES_OUT_NO_HEADER },
13743 { 'i', FORMAT_HEADER },
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 },
13755 { 'o', FORMAT_RESPONSE_HEADER },
13758 { '\0', FORMAT_UNSET }
13763 enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
13771 format_field **ptr;
13777 @@ -128,39 +128,39 @@
13778 buffer *access_logfile;
13780 unsigned short use_syslog;
13786 time_t last_generated_accesslog_ts;
13787 time_t *last_generated_accesslog_ts_ptr;
13792 buffer *access_logbuffer;
13793 buffer *ts_accesslog_str;
13796 format_fields *parsed_format;
13803 plugin_config **config_storage;
13804 - plugin_config conf;
13805 + plugin_config conf;
13808 INIT_FUNC(mod_accesslog_init) {
13812 p = calloc(1, sizeof(*p));
13818 int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
13819 size_t i, j, k = 0, start = 0;
13822 for (i = 0; i < format->used - 1; i++) {
13825 switch(format->ptr[i]) {
13828 @@ -173,19 +173,19 @@
13829 fields->size += 16;
13830 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
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();
13839 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
13848 /* we need a new field */
13851 if (fields->size == 0) {
13854 @@ -194,43 +194,43 @@
13855 fields->size += 16;
13856 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
13860 /* search for the terminating command */
13861 switch (format->ptr[i+1]) {
13867 for (j = 0; fmap[j].key != '\0'; j++) {
13868 if (fmap[j].key != format->ptr[i+2]) continue;
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;
13887 if (fmap[j].key == '\0') {
13888 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13898 /* go forward to } */
13901 for (k = i+2; k < format->used - 1; k++) {
13902 if (format->ptr[k] == '}') break;
13906 if (k == format->used - 1) {
13907 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13909 @@ -239,62 +239,62 @@
13910 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13915 for (j = 0; fmap[j].key != '\0'; j++) {
13916 if (fmap[j].key != format->ptr[k+1]) continue;
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();
13928 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
13938 if (fmap[j].key == '\0') {
13939 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
13949 for (j = 0; fmap[j].key != '\0'; j++) {
13950 if (fmap[j].key != format->ptr[i+1]) continue;
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;
13969 if (fmap[j].key == '\0') {
13970 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
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 * ));
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();
14001 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14011 FREE_FUNC(mod_accesslog_free) {
14012 plugin_data *p = p_d;
14016 if (!p) return HANDLER_GO_ON;
14019 if (p->config_storage) {
14022 for (i = 0; i < srv->config_context->used; i++) {
14023 plugin_config *s = p->config_storage[i];
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);
14037 if (s->log_access_fd != -1) close(s->log_access_fd);
14040 buffer_free(s->ts_accesslog_str);
14041 buffer_free(s->access_logbuffer);
14042 buffer_free(s->format);
14043 buffer_free(s->access_logfile);
14046 if (s->parsed_format) {
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);
14059 free(p->config_storage);
14066 return HANDLER_GO_ON;
14069 SETDEFAULTS_FUNC(log_access_open) {
14070 plugin_data *p = p_d;
14073 - config_values_t cv[] = {
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 }
14083 if (!p) return HANDLER_ERROR;
14086 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14089 for (i = 0; i < srv->config_context->used; i++) {
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);
14104 cv[0].destination = s->access_logfile;
14105 cv[1].destination = &(s->use_syslog);
14106 cv[2].destination = s->format;
14109 p->config_storage[i] = s;
14112 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14113 return HANDLER_ERROR;
14117 if (i == 0 && buffer_is_empty(s->format)) {
14118 /* set a default logfile string */
14121 buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
14128 if (s->format->used) {
14129 s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
14132 if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
14134 - log_error_write(srv, __FILE__, __LINE__, "sb",
14135 + log_error_write(srv, __FILE__, __LINE__, "sb",
14136 "parsing accesslog-definition failed:", s->format);
14138 return HANDLER_ERROR;
14143 for (j = 0; j < s->parsed_format->used; j++) {
14144 switch (s->parsed_format->ptr[j]->type) {
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 : "" );
14154 @@ -446,52 +446,52 @@
14160 if (s->use_syslog) {
14161 /* ignore the next checks */
14166 if (buffer_is_empty(s->access_logfile)) continue;
14169 if (s->access_logfile->ptr[0] == '|') {
14171 /* create write pipe and spawn process */
14178 if (pipe(to_log_fds)) {
14179 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
14180 return HANDLER_ERROR;
14185 switch (pid = fork()) {
14191 close(STDIN_FILENO);
14192 dup2(to_log_fds[0], STDIN_FILENO);
14193 close(to_log_fds[0]);
14195 close(to_log_fds[1]);
14198 /* we don't need the client socket */
14199 for (i = 3; i < 256; i++) {
14203 - /* exec the log-process (skip the | )
14206 + /* exec the log-process (skip the | )
14211 execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
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);
14223 @@ -500,27 +500,28 @@
14226 close(to_log_fds[0]);
14229 s->log_access_fd = to_log_fds[1];
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))) {
14241 - log_error_write(srv, __FILE__, __LINE__, "ssb",
14242 - "opening access-log failed:",
14244 + log_error_write(srv, __FILE__, __LINE__, "ssb",
14245 + "opening access-log failed:",
14246 strerror(errno), s->access_logfile);
14249 return HANDLER_ERROR;
14252 fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
14258 return HANDLER_GO_ON;
14261 @@ -529,7 +530,7 @@
14264 if (!p->config_storage) return HANDLER_GO_ON;
14267 for (i = 0; i < srv->config_context->used; i++) {
14268 plugin_config *s = p->config_storage[i];
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);
14276 buffer_reset(s->access_logbuffer);
14280 if (s->use_syslog == 0 &&
14281 !buffer_is_empty(s->access_logfile) &&
14282 s->access_logfile->ptr[0] != '|') {
14285 close(s->log_access_fd);
14287 - if (-1 == (s->log_access_fd =
14289 + if (-1 == (s->log_access_fd =
14290 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14293 log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
14296 return HANDLER_ERROR;
14302 return HANDLER_GO_ON;
14305 -#define PATCH(x) \
14306 - p->conf.x = s->x;
14307 static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
14309 plugin_config *s = p->config_storage[0];
14311 - PATCH(access_logfile);
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);
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);
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];
14336 /* condition didn't match */
14337 if (!config_check_cond(srv, con, dc)) continue;
14341 for (j = 0; j < dc->value->used; j++) {
14342 data_unset *du = dc->value->data[j];
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"))) {
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);
14373 REQUESTDONE_FUNC(log_access_write) {
14374 plugin_data *p = p_d;
14383 mod_accesslog_patch_connection(srv, con, p);
14386 b = p->conf.access_logbuffer;
14387 if (b->used == 0) {
14388 buffer_copy_string(b, "");
14392 for (j = 0; j < p->conf.parsed_format->used; j++) {
14393 switch(p->conf.parsed_format->ptr[j]->type) {
14395 @@ -636,14 +634,14 @@
14397 switch(p->conf.parsed_format->ptr[j]->field) {
14398 case FORMAT_TIMESTAMP:
14401 /* cache the generated timestamp */
14402 if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
14404 #if defined(HAVE_STRUCT_TM_GMTOFF)
14405 long scd, hrs, min;
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)));
14415 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14418 buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
14421 scd = abs(tm.tm_gmtoff);
14423 min = (scd % 3600) / 60;
14427 if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14428 buffer_append_long(p->conf.ts_accesslog_str, hrs);
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 @@
14436 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14440 *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
14445 buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
14449 case FORMAT_REMOTE_HOST:
14452 /* handle inet_ntop cache */
14455 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
14459 case FORMAT_REMOTE_IDENT:
14461 @@ -710,10 +708,10 @@
14462 case FORMAT_STATUS:
14463 buffer_append_long(b, con->http_status);
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);
14473 BUFFER_APPEND_STRING_CONST(b, "-");
14474 @@ -772,7 +770,7 @@
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");
14482 case FORMAT_REQUEST_METHOD:
14483 @@ -801,7 +799,7 @@
14484 { 'D', FORMAT_TIME_USED_MS },
14485 { 'e', FORMAT_ENV },
14492 @@ -809,7 +807,7 @@
14498 BUFFER_APPEND_STRING_CONST(b, "\n");
14500 if (p->conf.use_syslog || /* syslog doesn't cache */
14501 @@ -828,7 +826,7 @@
14507 return HANDLER_GO_ON;
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");
14516 p->init = mod_accesslog_init;
14517 p->set_defaults= log_access_open;
14518 p->cleanup = mod_accesslog_free;
14521 p->handle_request_done = log_access_write;
14522 p->handle_sighup = log_access_cycle;
14530 --- ../lighttpd-1.4.11/src/mod_alias.c 2006-03-01 23:18:51.000000000 +0200
14531 +++ lighttpd-1.4.12/src/mod_alias.c 2006-07-11 22:07:51.000000000 +0300
14533 #include "buffer.h"
14535 #include "plugin.h"
14536 +#include "sys-strings.h"
14538 /* plugin config for all request/connections */
14540 @@ -16,44 +17,44 @@
14546 plugin_config **config_storage;
14548 - plugin_config conf;
14550 + plugin_config conf;
14553 /* init the plugin data */
14554 INIT_FUNC(mod_alias_init) {
14558 p = calloc(1, sizeof(*p));
14568 /* detroy the plugin data */
14569 FREE_FUNC(mod_alias_free) {
14570 plugin_data *p = p_d;
14573 if (!p) return HANDLER_GO_ON;
14576 if (p->config_storage) {
14580 for (i = 0; i < srv->config_context->used; i++) {
14581 plugin_config *s = p->config_storage[i];
14584 array_free(s->alias);
14589 free(p->config_storage);
14596 return HANDLER_GO_ON;
14599 @@ -62,25 +63,25 @@
14600 SETDEFAULTS_FUNC(mod_alias_set_defaults) {
14601 plugin_data *p = p_d;
14604 - config_values_t cv[] = {
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 }
14612 if (!p) return HANDLER_ERROR;
14615 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14618 for (i = 0; i < srv->config_context->used; i++) {
14622 s = calloc(1, sizeof(plugin_config));
14623 - s->alias = array_init();
14624 + s->alias = array_init();
14625 cv[0].destination = s->alias;
14628 p->config_storage[i] = s;
14631 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14632 return HANDLER_ERROR;
14634 @@ -110,76 +111,73 @@
14640 return HANDLER_GO_ON;
14643 -#define PATCH(x) \
14644 - p->conf.x = s->x;
14645 static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
14647 plugin_config *s = p->config_storage[0];
14652 + PATCH_OPTION(alias);
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];
14660 /* condition didn't match */
14661 if (!config_check_cond(srv, con, dc)) continue;
14665 for (j = 0; j < dc->value->used; j++) {
14666 data_unset *du = dc->value->data[j];
14669 if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
14671 + PATCH_OPTION(alias);
14681 PHYSICALPATH_FUNC(mod_alias_physical_handler) {
14682 plugin_data *p = p_d;
14683 int uri_len, basedir_len;
14688 if (con->physical.path->used == 0) return HANDLER_GO_ON;
14691 mod_alias_patch_connection(srv, con, p);
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;
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;
14705 if (alias_len > uri_len) continue;
14706 if (ds->key->used == 0) continue;
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))) {
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);
14721 return HANDLER_GO_ON;
14727 return HANDLER_GO_ON;
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");
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;
14746 --- ../lighttpd-1.4.11/src/mod_auth.c 2006-02-15 20:01:31.000000000 +0200
14747 +++ lighttpd-1.4.12/src/mod_auth.c 2006-07-11 22:07:53.000000000 +0300
14748 @@ -5,168 +5,167 @@
14749 #include <string.h>
14752 -#include <unistd.h>
14754 #include "plugin.h"
14755 #include "http_auth.h"
14757 #include "response.h"
14759 +#include "sys-strings.h"
14760 +#include "sys-files.h"
14762 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
14766 * the basic and digest auth framework
14769 * - config handling
14770 * - protocol handling
14773 - * http_auth_digest.c
14777 + * http_auth_digest.c
14782 INIT_FUNC(mod_auth_init) {
14783 mod_auth_plugin_data *p;
14786 p = calloc(1, sizeof(*p));
14789 p->tmp_buf = buffer_init();
14792 p->auth_user = buffer_init();
14794 p->ldap_filter = buffer_init();
14801 FREE_FUNC(mod_auth_free) {
14802 mod_auth_plugin_data *p = p_d;
14807 if (!p) return HANDLER_GO_ON;
14810 buffer_free(p->tmp_buf);
14811 buffer_free(p->auth_user);
14813 buffer_free(p->ldap_filter);
14817 if (p->config_storage) {
14819 for (i = 0; i < srv->config_context->used; i++) {
14820 mod_auth_plugin_config *s = p->config_storage[i];
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);
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);
14843 buffer_free(s->ldap_filter_pre);
14844 buffer_free(s->ldap_filter_post);
14847 if (s->ldap) ldap_unbind_s(s->ldap);
14853 free(p->config_storage);
14860 return HANDLER_GO_ON;
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) {
14867 mod_auth_plugin_config *s = p->config_storage[0];
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);
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);
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];
14913 /* condition didn't match */
14914 if (!config_check_cond(srv, con, dc)) continue;
14918 for (j = 0; j < dc->value->used; j++) {
14919 data_unset *du = dc->value->data[j];
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);
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);
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);
14975 static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
14977 @@ -175,22 +174,22 @@
14979 mod_auth_plugin_data *p = p_d;
14983 /* select the right config */
14984 mod_auth_patch_connection(srv, con, p);
14987 if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
14997 /* do we have to ask for auth ? */
15001 auth_satisfied = 0;
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 @@
15013 /* nothing to do for us */
15014 if (auth_required == 0) return HANDLER_GO_ON;
15017 req = ((data_array *)(p->conf.auth_require->data[k]))->value;
15020 /* try to get Authorization-header */
15023 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
15024 http_authorization = ds->value->ptr;
15028 if (ds && ds->value && ds->value->used) {
15030 data_string *method;
15033 method = (data_string *)array_get_element(req, "method");
15036 /* parse auth-header */
15037 if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
15038 int auth_type_len = auth_realm - http_authorization;
15041 if ((auth_type_len == 5) &&
15042 (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
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);
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;
15054 /* a field was missing */
15057 return HANDLER_FINISHED;
15061 - log_error_write(srv, __FILE__, __LINE__, "ss",
15062 + log_error_write(srv, __FILE__, __LINE__, "ss",
15063 "unknown authentification type:",
15064 http_authorization);
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");
15076 con->http_status = 401;
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, "\"");
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")) {
15088 http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
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\"");
15098 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15101 @@ -289,18 +288,18 @@
15102 return HANDLER_FINISHED;
15104 /* the REMOTE_USER header */
15107 buffer_copy_string_buffer(con->authed_user, p->auth_user);
15111 return HANDLER_GO_ON;
15114 SETDEFAULTS_FUNC(mod_auth_set_defaults) {
15115 mod_auth_plugin_data *p = p_d;
15118 - config_values_t cv[] = {
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 }
15130 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15132 for (i = 0; i < srv->config_context->used; i++) {
15133 @@ -325,14 +324,14 @@
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();
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;
15156 s->auth_require = array_init();
15160 s->ldap_filter_pre = buffer_init();
15161 s->ldap_filter_post = buffer_init();
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);
15175 p->config_storage[i] = s;
15176 ca = ((data_config *)srv->config_context->data[i])->value;
15179 if (0 != config_insert_values_global(srv, ca, cv)) {
15180 return HANDLER_ERROR;
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;
15190 log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
15193 return HANDLER_ERROR;
15197 /* no auth.require for this section */
15198 if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
15201 if (da->type != TYPE_ARRAY) continue;
15204 for (n = 0; n < da->value->used; n++) {
15206 data_array *da_file = (data_array *)da->value->data[n];
15207 const char *method, *realm, *require;
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 = ( \"...\" => ( ..., ...) )");
15217 return HANDLER_ERROR;
15221 method = realm = require = NULL;
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;
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;
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 "\" <- => \"...\" ) )");
15251 return HANDLER_ERROR;
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;
15264 @@ -450,60 +449,60 @@
15265 return HANDLER_ERROR;
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;
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;
15290 if (method && realm && require) {
15295 a = data_array_init();
15296 buffer_copy_string_buffer(a->key, da_file->key);
15299 ds = data_string_init();
15302 buffer_copy_string(ds->key, "method");
15303 buffer_copy_string(ds->value, method);
15306 array_insert_unique(a->value, (data_unset *)ds);
15309 ds = data_string_init();
15312 buffer_copy_string(ds->key, "realm");
15313 buffer_copy_string(ds->value, realm);
15316 array_insert_unique(a->value, (data_unset *)ds);
15319 ds = data_string_init();
15322 buffer_copy_string(ds->key, "require");
15323 buffer_copy_string(ds->value, require);
15326 array_insert_unique(a->value, (data_unset *)ds);
15329 array_insert_unique(s->auth_require, (data_unset *)a);
15334 switch(s->auth_backend) {
15335 case AUTH_BACKEND_PLAIN:
15336 if (s->auth_plain_userfile->used) {
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 @@
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 @@
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) {
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");
15373 return HANDLER_ERROR;
15378 if (s->auth_ldap_filter->used) {
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 '$'");
15389 return HANDLER_ERROR;
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);
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));
15403 return HANDLER_ERROR;
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));
15412 return HANDLER_ERROR;
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));
15428 return HANDLER_ERROR;
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));
15437 return HANDLER_ERROR;
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));
15450 return HANDLER_ERROR;
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));
15457 return HANDLER_ERROR;
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;
15471 --- ../lighttpd-1.4.11/src/mod_cgi.c 2006-02-22 15:15:10.000000000 +0200
15472 +++ lighttpd-1.4.12/src/mod_cgi.c 2006-07-11 22:07:51.000000000 +0300
15474 #include <sys/types.h>
15476 -#include <winsock2.h>
15478 -#include <sys/socket.h>
15479 -#include <sys/wait.h>
15480 -#include <sys/mman.h>
15482 -#include <netinet/in.h>
15484 -#include <arpa/inet.h>
15487 -#include <unistd.h>
15489 #include <stdlib.h>
15490 #include <string.h>
15491 -#include <fdevent.h>
15492 #include <signal.h>
15494 #include <assert.h>
15496 #include "connections.h"
15497 #include "joblist.h"
15498 #include "http_chunk.h"
15499 +#include "fdevent.h"
15501 #include "plugin.h"
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"
15509 #ifdef HAVE_SYS_FILIO_H
15510 # include <sys/filio.h>
15512 @@ -40,11 +34,12 @@
15526 @@ -58,23 +53,23 @@
15529 buffer_pid_t cgi_pid;
15533 buffer *parse_response;
15536 plugin_config **config_storage;
15538 - plugin_config conf;
15540 + plugin_config conf;
15546 int fde_ndx; /* index into the fd-event buffer */
15549 connection *remote_conn; /* dumb pointer */
15550 plugin_data *plugin_data; /* dumb pointer */
15554 buffer *response_header;
15556 @@ -83,17 +78,17 @@
15557 handler_ctx *hctx = calloc(1, sizeof(*hctx));
15562 hctx->response = buffer_init();
15563 hctx->response_header = buffer_init();
15569 static void cgi_handler_ctx_free(handler_ctx *hctx) {
15570 buffer_free(hctx->response);
15571 buffer_free(hctx->response_header);
15577 @@ -101,14 +96,14 @@
15579 INIT_FUNC(mod_cgi_init) {
15583 p = calloc(1, sizeof(*p));
15588 p->tmp_buf = buffer_init();
15589 p->parse_response = buffer_init();
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);
15604 if (p->config_storage) {
15606 for (i = 0; i < srv->config_context->used; i++) {
15607 plugin_config *s = p->config_storage[i];
15610 array_free(s->cgi);
15615 free(p->config_storage);
15620 if (r->ptr) free(r->ptr);
15623 buffer_free(p->tmp_buf);
15624 buffer_free(p->parse_response);
15630 return HANDLER_GO_ON;
15633 SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
15634 plugin_data *p = p_d;
15637 - config_values_t cv[] = {
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}
15644 if (!p) return HANDLER_ERROR;
15647 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15650 for (i = 0; i < srv->config_context->used; i++) {
15654 s = calloc(1, sizeof(plugin_config));
15658 s->cgi = array_init();
15661 cv[0].destination = s->cgi;
15664 p->config_storage[i] = s;
15667 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
15668 return HANDLER_ERROR;
15673 return HANDLER_GO_ON;
15676 @@ -180,13 +175,13 @@
15679 buffer_pid_t *r = &(p->cgi_pid);
15684 for (i = 0; i < r->used; i++) {
15685 if (r->ptr[i] > m) m = r->ptr[i];
15689 if (r->size == 0) {
15691 r->ptr = malloc(sizeof(*r->ptr) * r->size);
15692 @@ -194,31 +189,31 @@
15694 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
15698 r->ptr[r->used++] = pid;
15704 static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
15706 buffer_pid_t *r = &(p->cgi_pid);
15711 for (i = 0; i < r->used; i++) {
15712 if (r->ptr[i] == pid) break;
15716 if (i != r->used) {
15720 if (i != r->used - 1) {
15721 r->ptr[i] = r->ptr[r->used - 1];
15730 @@ -226,32 +221,32 @@
15739 buffer_copy_string_buffer(p->parse_response, in);
15741 - for (s = p->parse_response->ptr;
15742 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
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;
15757 0 == strncmp(s, "HTTP/1.", 7)) {
15758 /* non-parsed header ... we parse them anyway */
15761 if ((s[7] == '1' ||
15765 /* after the space should be a status code for us */
15768 status = strtol(s+9, NULL, 10);
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 @@
15781 if (NULL == (value = strchr(s, ':'))) {
15782 /* we expect: "<key>: <value>\r\n" */
15787 key_len = value - key;
15792 while (*value == ' ' || *value == '\t') value++;
15795 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
15796 ds = data_response_init();
15798 buffer_copy_string_len(ds->key, key, key_len);
15799 buffer_copy_string(ds->value, value);
15802 array_insert_unique(con->response.headers, (data_unset *)ds);
15807 if (0 == strncasecmp(key, "Date", key_len)) {
15808 @@ -315,13 +310,13 @@
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;
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;
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;
15844 /* read finished */
15847 con->file_finished = 1;
15850 /* send final chunk */
15851 http_chunk_append_mem(srv, con, NULL, 0);
15852 joblist_append(srv, con);
15855 return FDEVENT_HANDLED_FINISHED;
15859 hctx->response->ptr[n] = '\0';
15860 hctx->response->used = n+1;
15863 /* split header from body */
15866 if (con->file_started == 0) {
15869 int header_end = 0;
15870 int cp, eol = EOL_UNSET;
15874 buffer_append_string_buffer(hctx->response_header, hctx->response);
15877 /* nph (non-parsed headers) */
15878 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
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 */
15895 if (eol == EOL_UNSET) eol = EOL_N;
15898 if (*(c+1) == '\n') {
15904 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
15905 if (in_header == 0) {
15906 /* got a response without a response header */
15915 if (eol == EOL_UNSET) eol = EOL_RN;
15919 - *(c+2) == '\r' &&
15920 + *(c+2) == '\r' &&
15937 /* no header, but a body */
15940 if (con->request.http_version == HTTP_VERSION_1_1) {
15941 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
15945 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
15946 joblist_append(srv, con);
15948 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
15949 size_t blen = hctx->response_header->used - hlen - 1;
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';
15957 /* parse the response header */
15958 cgi_response_parse(srv, con, p, hctx->response_header, eol);
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;
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);
15975 con->file_started = 1;
15978 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
15979 joblist_append(srv, con);
15985 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
15990 return FDEVENT_HANDLED_NOT_FINISHED;
15993 @@ -470,45 +465,46 @@
15999 if (NULL == hctx) return HANDLER_GO_ON;
16002 p = hctx->plugin_data;
16003 con = hctx->remote_conn;
16006 if (con->mode != p->id) return HANDLER_GO_ON;
16012 /* the connection to the browser went away, but we still have a connection
16013 - * to the CGI script
16014 + * to the CGI script
16016 * close cgi-connection
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);
16026 if (close(hctx->fd)) {
16027 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16032 hctx->fde_ndx = -1;
16039 con->plugin_ctx[p->id] = NULL;
16042 /* is this a good idea ? */
16043 cgi_handler_ctx_free(hctx);
16046 /* if waitpid hasn't been called by response.c yet, do it here */
16048 /* check if the CGI-script is already gone */
16050 switch(waitpid(pid, &status, WNOHANG)) {
16052 /* not finished yet */
16053 @@ -519,19 +515,19 @@
16056 if (errno == EINTR) break;
16059 - * errno == ECHILD happens if _subrequest catches the process-status before
16062 + * errno == ECHILD happens if _subrequest catches the process-status before
16063 * we have read the response of the cgi process
16067 * -> WAIT_FOR_EVENT
16069 * -> we get here with waitpid == ECHILD
16073 if (errno == ECHILD) return HANDLER_GO_ON;
16076 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16077 return HANDLER_ERROR;
16079 @@ -541,13 +537,13 @@
16080 con->http_status = 500;
16081 con->mode = DIRECT;
16085 if (WIFEXITED(status)) {
16087 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
16092 return HANDLER_GO_ON;
16094 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
16095 @@ -555,20 +551,20 @@
16096 return HANDLER_GO_ON;
16103 kill(pid, SIGTERM);
16106 /* cgi-script is still alive, queue the PID for removal */
16107 cgi_pid_add(srv, p, pid);
16111 return HANDLER_GO_ON;
16114 static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
16115 plugin_data *p = p_d;
16118 return cgi_connection_close(srv, con->plugin_ctx[p->id]);
16121 @@ -577,43 +573,43 @@
16122 server *srv = (server *)s;
16123 handler_ctx *hctx = ctx;
16124 connection *con = hctx->remote_conn;
16127 joblist_append(srv, con);
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");
16134 return HANDLER_ERROR;
16138 if (revents & FDEVENT_IN) {
16139 switch (cgi_demux_response(srv, hctx)) {
16140 case FDEVENT_HANDLED_NOT_FINISHED:
16142 case FDEVENT_HANDLED_FINISHED:
16147 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
16149 cgi_connection_close(srv, hctx);
16151 - /* if we get a IN|HUP and have read everything don't exec the close twice */
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;
16161 log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
16167 if (revents & FDEVENT_OUT) {
16168 /* nothing to do */
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);
16181 if (con->file_finished == 0) {
16182 http_chunk_append_mem(srv, con, NULL, 0);
16183 joblist_append(srv, con);
16187 con->file_finished = 1;
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);
16194 /* used the write-handler to finish the request on demand */
16201 log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
16205 /* rtsigs didn't liked the close */
16206 cgi_connection_close(srv, hctx);
16207 } else if (revents & FDEVENT_ERR) {
16208 con->file_finished = 1;
16211 /* kill all connections to the cgi process */
16212 cgi_connection_close(srv, hctx);
16214 log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
16217 return HANDLER_ERROR;
16221 return HANDLER_FINISHED;
16225 static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
16229 if (!key || !val) return -1;
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);
16239 if (env->size == 0) {
16241 env->ptr = malloc(env->size * sizeof(*env->ptr));
16242 @@ -678,45 +674,45 @@
16244 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
16248 env->ptr[env->used++] = dst;
16254 static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
16259 char b2[INET6_ADDRSTRLEN + 1];
16264 int from_cgi_fds[2];
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));
16284 if (pipe(to_cgi_fds)) {
16285 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16290 if (pipe(from_cgi_fds)) {
16291 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16297 switch (pid = fork()) {
16299 @@ -730,22 +726,22 @@
16302 server_socket *srv_sock = con->srv_socket;
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]);
16310 close(from_cgi_fds[0]);
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]);
16318 close(to_cgi_fds[1]);
16323 * this is not nice, but it works
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);
16332 /* create environment */
16338 cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
16340 if (!buffer_is_empty(con->server_name)) {
16341 cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
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),
16351 @@ -779,10 +775,10 @@
16352 cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
16354 s = get_http_version_name(con->request.http_version);
16357 cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
16363 ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
16365 @@ -790,10 +786,10 @@
16368 cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
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),
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));
16384 + /* set a empty QUERY_STRING */
16385 + cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
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));
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),
16402 @@ -828,7 +827,7 @@
16404 cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
16409 ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
16411 @@ -836,19 +835,19 @@
16414 cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
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));
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));
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));
16440 for (n = 0; n < con->request.headers->used; n++) {
16444 ds = (data_string *)con->request.headers->data[n];
16447 if (ds->value->used && ds->key->used) {
16451 buffer_reset(p->tmp_buf);
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_ */
16460 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16463 for (j = 0; j < ds->key->used - 1; j++) {
16465 if (light_isalpha(ds->key->ptr[j])) {
16466 @@ -893,46 +892,46 @@
16467 p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
16469 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16472 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16477 for (n = 0; n < con->environment->used; n++) {
16481 ds = (data_string *)con->environment->data[n];
16484 if (ds->value->used && ds->key->used) {
16488 buffer_reset(p->tmp_buf);
16491 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
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]) : '_';
16501 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16504 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16509 if (env.size == env.used) {
16511 env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
16515 env.ptr[env.used] = NULL;
16520 args = malloc(sizeof(*args) * argc);
16524 if (cgi_handler->used > 1) {
16525 args[i++] = cgi_handler->ptr;
16527 @@ -942,7 +941,7 @@
16528 /* search for the last / */
16529 if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
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);
16543 execve(args[0], args, env.ptr);
16546 log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
16552 @@ -974,11 +973,11 @@
16554 close(from_cgi_fds[1]);
16555 close(to_cgi_fds[0]);
16558 if (con->request.content_length) {
16559 chunkqueue *cq = con->request_content_queue;
16563 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
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));
16572 close(from_cgi_fds[0]);
16573 close(to_cgi_fds[1]);
16577 c->file.mmap.length = c->file.length;
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);
16585 close(from_cgi_fds[0]);
16586 @@ -1012,7 +1011,7 @@
16592 /* chunk_reset() or chunk_free() will cleanup for us */
16595 @@ -1020,7 +1019,7 @@
16598 con->http_status = 507;
16603 con->http_status = 403;
16604 @@ -1033,7 +1032,7 @@
16607 con->http_status = 507;
16612 con->http_status = 403;
16613 @@ -1056,103 +1055,100 @@
16616 close(to_cgi_fds[1]);
16619 /* register PID and wait for them asyncronously */
16621 buffer_reset(con->physical.path);
16624 hctx = cgi_handler_ctx_init();
16627 hctx->remote_conn = con;
16628 hctx->plugin_data = p;
16630 hctx->fd = from_cgi_fds[0];
16631 hctx->fde_ndx = -1;
16634 con->plugin_ctx[p->id] = hctx;
16637 fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
16638 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
16641 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
16642 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
16645 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16646 fdevent_unregister(srv->ev, hctx->fd);
16649 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
16655 cgi_handler_ctx_free(hctx);
16658 con->plugin_ctx[p->id] = NULL;
16676 -#define PATCH(x) \
16677 - p->conf.x = s->x;
16678 static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
16680 plugin_config *s = p->config_storage[0];
16685 + PATCH_OPTION(cgi);
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];
16693 /* condition didn't match */
16694 if (!config_check_cond(srv, con, dc)) continue;
16698 for (j = 0; j < dc->value->used; j++) {
16699 data_unset *du = dc->value->data[j];
16702 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
16704 + PATCH_OPTION(cgi);
16714 URIHANDLER_FUNC(cgi_is_handled) {
16716 plugin_data *p = p_d;
16717 buffer *fn = con->physical.path;
16720 if (fn->used == 0) return HANDLER_GO_ON;
16723 mod_cgi_patch_connection(srv, con, p);
16726 s_len = fn->used - 1;
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;
16734 if (ds->key->used == 0) continue;
16735 if (s_len < ct_len) continue;
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;
16743 buffer_reset(con->physical.path);
16744 return HANDLER_FINISHED;
16746 @@ -1160,7 +1156,7 @@
16752 return HANDLER_GO_ON;
16755 @@ -1168,11 +1164,11 @@
16756 plugin_data *p = p_d;
16758 /* the trigger handle only cares about lonely PID which we have to wait for */
16762 for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
16766 switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
16768 /* not finished yet */
16769 @@ -1182,7 +1178,7 @@
16772 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16775 return HANDLER_ERROR;
16778 @@ -1193,16 +1189,16 @@
16780 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
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
16795 return HANDLER_GO_ON;
16798 @@ -1210,15 +1206,15 @@
16800 plugin_data *p = p_d;
16801 handler_ctx *hctx = con->plugin_ctx[p->id];
16804 if (con->mode != p->id) return HANDLER_GO_ON;
16805 if (NULL == hctx) return HANDLER_GO_ON;
16809 log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
16812 if (hctx->pid == 0) return HANDLER_FINISHED;
16815 switch(waitpid(hctx->pid, &status, WNOHANG)) {
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;
16821 if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
16824 if (errno == ECHILD && con->file_started == 0) {
16826 - * second round but still not response
16827 + * second round but still not response
16829 - return HANDLER_WAIT_FOR_EVENT;
16830 + return HANDLER_WAIT_FOR_EVENT;
16834 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16835 con->mode = DIRECT;
16836 con->http_status = 500;
16842 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16843 fdevent_unregister(srv->ev, hctx->fd);
16846 if (close(hctx->fd)) {
16847 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16851 cgi_handler_ctx_free(hctx);
16854 con->plugin_ctx[p->id] = NULL;
16857 return HANDLER_FINISHED;
16859 - /* cgi process exited cleanly
16861 - * check if we already got the response
16862 + /* cgi process exited cleanly
16864 + * check if we already got the response
16868 if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
16871 if (WIFEXITED(status)) {
16874 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
16877 con->mode = DIRECT;
16878 con->http_status = 500;
16887 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16888 fdevent_unregister(srv->ev, hctx->fd);
16891 if (close(hctx->fd)) {
16892 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16896 cgi_handler_ctx_free(hctx);
16899 con->plugin_ctx[p->id] = NULL;
16900 return HANDLER_FINISHED;
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;
16913 --- ../lighttpd-1.4.11/src/mod_cml.c 2006-01-30 13:51:48.000000000 +0200
16914 +++ lighttpd-1.4.12/src/mod_cml.c 2006-07-11 22:07:51.000000000 +0300
16916 #include <stdlib.h>
16917 #include <string.h>
16919 -#include <unistd.h>
16922 #include "buffer.h"
16923 @@ -20,50 +19,50 @@
16924 /* init the plugin data */
16925 INIT_FUNC(mod_cml_init) {
16929 p = calloc(1, sizeof(*p));
16932 p->basedir = buffer_init();
16933 p->baseurl = buffer_init();
16934 p->trigger_handler = buffer_init();
16940 /* detroy the plugin data */
16941 FREE_FUNC(mod_cml_free) {
16942 plugin_data *p = p_d;
16947 if (!p) return HANDLER_GO_ON;
16950 if (p->config_storage) {
16952 for (i = 0; i < srv->config_context->used; i++) {
16953 plugin_config *s = p->config_storage[i];
16956 buffer_free(s->ext);
16959 buffer_free(s->mc_namespace);
16960 buffer_free(s->power_magnet);
16961 array_free(s->mc_hosts);
16964 #if defined(HAVE_MEMCACHE_H)
16965 if (s->mc) mc_free(s->mc);
16971 free(p->config_storage);
16975 buffer_free(p->trigger_handler);
16976 buffer_free(p->basedir);
16977 buffer_free(p->baseurl);
16983 return HANDLER_GO_ON;
16986 @@ -72,22 +71,22 @@
16987 SETDEFAULTS_FUNC(mod_cml_set_defaults) {
16988 plugin_data *p = p_d;
16991 - config_values_t cv[] = {
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 }
17002 if (!p) return HANDLER_ERROR;
17005 p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
17008 for (i = 0; i < srv->config_context->used; i++) {
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)
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;
17027 p->config_storage[i] = s;
17030 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
17031 return HANDLER_ERROR;
17035 if (s->mc_hosts->used) {
17036 #if defined(HAVE_MEMCACHE_H)
17041 for (k = 0; k < s->mc_hosts->used; k++) {
17042 data_string *ds = (data_string *)s->mc_hosts->data[k];
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:",
17053 return HANDLER_ERROR;
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;
17066 return HANDLER_GO_ON;
17069 -#define PATCH(x) \
17070 - p->conf.x = s->x;
17071 static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
17073 plugin_config *s = p->config_storage[0];
17077 + PATCH_OPTION(ext);
17078 #if defined(HAVE_MEMCACHE_H)
17080 + PATCH_OPTION(mc);
17082 - PATCH(mc_namespace);
17083 - PATCH(power_magnet);
17085 + PATCH_OPTION(mc_namespace);
17086 + PATCH_OPTION(power_magnet);
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];
17094 /* condition didn't match */
17095 if (!config_check_cond(srv, con, dc)) continue;
17099 for (j = 0; j < dc->value->used; j++) {
17100 data_unset *du = dc->value->data[j];
17103 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
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)
17109 + PATCH_OPTION(mc);
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);
17126 int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
17128 @@ -187,57 +183,57 @@
17130 buffer_copy_string_buffer(b, con->uri.path);
17131 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17135 b->used = c - b->ptr + 2;
17141 buffer_copy_string_buffer(b, con->physical.path);
17142 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17146 b->used = c - b->ptr + 2;
17152 /* prepare variables
17154 * - get-param-based
17158 return cache_parse_lua(srv, con, p, cml_file);
17163 URIHANDLER_FUNC(mod_cml_power_magnet) {
17164 plugin_data *p = p_d;
17167 mod_cml_patch_connection(srv, con, p);
17170 buffer_reset(p->basedir);
17171 buffer_reset(p->baseurl);
17172 buffer_reset(p->trigger_handler);
17174 if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
17180 * cml.power-magnet = server.docroot + "/rewrite.cml"
17182 * is called on EACH request, take the original REQUEST_URI and modifies the
17183 - * request header as neccesary.
17184 + * request header as neccesary.
17187 * if file_exists("/maintainance.html") {
17188 * output_include = ( "/maintainance.html" )
17189 - * return CACHE_HIT
17190 + * return CACHE_HIT
17193 * as we only want to rewrite HTML like requests we should cover it in a conditional
17198 switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
17199 @@ -266,20 +262,20 @@
17201 URIHANDLER_FUNC(mod_cml_is_handled) {
17202 plugin_data *p = p_d;
17205 if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
17208 mod_cml_patch_connection(srv, con, p);
17211 buffer_reset(p->basedir);
17212 buffer_reset(p->baseurl);
17213 buffer_reset(p->trigger_handler);
17215 if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
17218 if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
17219 return HANDLER_GO_ON;
17223 switch(cache_call_lua(srv, con, p, con->physical.path)) {
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");
17231 p->init = mod_cml_init;
17232 p->cleanup = mod_cml_free;
17233 p->set_defaults = mod_cml_set_defaults;
17236 p->handle_subrequest_start = mod_cml_is_handled;
17237 p->handle_physical = mod_cml_power_magnet;
17245 --- ../lighttpd-1.4.11/src/mod_cml.h 2006-01-30 13:51:35.000000000 +0200
17246 +++ lighttpd-1.4.12/src/mod_cml.h 2006-07-11 22:07:51.000000000 +0300
17247 @@ -16,10 +16,10 @@
17254 buffer *mc_namespace;
17255 -#if defined(HAVE_MEMCACHE_H)
17256 +#if defined(HAVE_MEMCACHE_H)
17257 struct memcache *mc;
17259 buffer *power_magnet;
17260 @@ -27,15 +27,15 @@
17270 buffer *trigger_handler;
17273 plugin_config **config_storage;
17275 - plugin_config conf;
17277 + plugin_config conf;
17280 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
17281 --- ../lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200
17282 +++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-11 22:07:52.000000000 +0300
17284 #include <stdlib.h>
17285 #include <string.h>
17287 -#include <unistd.h>
17288 -#include <dirent.h>
17292 #include "buffer.h"
17295 #include "plugin.h"
17296 #include "response.h"
17297 +#include "sys-files.h"
17299 #include "mod_cml.h"
17300 #include "mod_cml_funcs.h"
17310 @@ -42,29 +42,29 @@
17313 int n = lua_gettop(L);
17318 b.size = sizeof(hex);
17322 lua_pushstring(L, "md5: expected one argument");
17327 if (!lua_isstring(L, 1)) {
17328 lua_pushstring(L, "md5: argument has to be a string");
17334 MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
17335 MD5_Final(HA1, &Md5Ctx);
17338 buffer_copy_string_hex(&b, (char *)HA1, 16);
17341 lua_pushstring(L, b.ptr);
17347 @@ -72,37 +72,37 @@
17348 int f_file_mtime(lua_State *L) {
17350 int n = lua_gettop(L);
17354 lua_pushstring(L, "file_mtime: expected one argument");
17359 if (!lua_isstring(L, 1)) {
17360 lua_pushstring(L, "file_mtime: argument has to be a string");
17365 if (-1 == stat(lua_tostring(L, 1), &st)) {
17371 lua_pushnumber(L, st.st_mtime);
17378 int f_dir_files_iter(lua_State *L) {
17383 d = lua_touserdata(L, lua_upvalueindex(1));
17386 if (NULL == (de = readdir(d))) {
17393 lua_pushstring(L, de->d_name);
17394 @@ -113,75 +113,75 @@
17395 int f_dir_files(lua_State *L) {
17397 int n = lua_gettop(L);
17401 lua_pushstring(L, "dir_files: expected one argument");
17406 if (!lua_isstring(L, 1)) {
17407 lua_pushstring(L, "dir_files: argument has to be a string");
17411 - /* check if there is a valid DIR handle on the stack */
17413 + /* check if there is a valid DIR handle on the stack */
17414 if (NULL == (d = opendir(lua_tostring(L, 1)))) {
17420 /* push d into registry */
17421 lua_pushlightuserdata(L, d);
17422 lua_pushcclosure(L, f_dir_files_iter, 1);
17429 int f_file_isreg(lua_State *L) {
17431 int n = lua_gettop(L);
17435 lua_pushstring(L, "file_isreg: expected one argument");
17440 if (!lua_isstring(L, 1)) {
17441 lua_pushstring(L, "file_isreg: argument has to be a string");
17446 if (-1 == stat(lua_tostring(L, 1), &st)) {
17452 lua_pushnumber(L, S_ISREG(st.st_mode));
17458 int f_file_isdir(lua_State *L) {
17460 int n = lua_gettop(L);
17464 lua_pushstring(L, "file_isreg: expected one argument");
17469 if (!lua_isstring(L, 1)) {
17470 lua_pushstring(L, "file_isreg: argument has to be a string");
17475 if (-1 == stat(lua_tostring(L, 1), &st)) {
17481 lua_pushnumber(L, S_ISDIR(st.st_mode));
17487 @@ -192,33 +192,33 @@
17489 int n = lua_gettop(L);
17490 struct memcache *mc;
17493 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17494 lua_pushstring(L, "where is my userdata ?");
17499 mc = lua_touserdata(L, lua_upvalueindex(1));
17503 lua_pushstring(L, "expected one argument");
17508 if (!lua_isstring(L, 1)) {
17509 lua_pushstring(L, "argument has to be a string");
17513 - if (NULL == (r = mc_aget(mc,
17515 + if (NULL == (r = mc_aget(mc,
17516 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17519 lua_pushboolean(L, 0);
17527 lua_pushboolean(L, 1);
17530 @@ -226,74 +226,74 @@
17531 int f_memcache_get_string(lua_State *L) {
17533 int n = lua_gettop(L);
17536 struct memcache *mc;
17539 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17540 lua_pushstring(L, "where is my userdata ?");
17545 mc = lua_touserdata(L, lua_upvalueindex(1));
17551 lua_pushstring(L, "expected one argument");
17556 if (!lua_isstring(L, 1)) {
17557 lua_pushstring(L, "argument has to be a string");
17561 - if (NULL == (r = mc_aget(mc,
17563 + if (NULL == (r = mc_aget(mc,
17564 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17570 lua_pushstring(L, r);
17579 int f_memcache_get_long(lua_State *L) {
17581 int n = lua_gettop(L);
17584 struct memcache *mc;
17587 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17588 lua_pushstring(L, "where is my userdata ?");
17593 mc = lua_touserdata(L, lua_upvalueindex(1));
17599 lua_pushstring(L, "expected one argument");
17604 if (!lua_isstring(L, 1)) {
17605 lua_pushstring(L, "argument has to be a string");
17609 - if (NULL == (r = mc_aget(mc,
17611 + if (NULL == (r = mc_aget(mc,
17612 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17618 lua_pushnumber(L, strtol(r, NULL, 10));
17627 --- ../lighttpd-1.4.11/src/mod_cml_lua.c 2006-01-30 13:56:40.000000000 +0200
17628 +++ lighttpd-1.4.12/src/mod_cml_lua.c 2006-07-11 22:07:53.000000000 +0300
17641 #include <lualib.h>
17642 +#include <lauxlib.h>
17646 @@ -39,11 +40,11 @@
17648 static const char * load_file(lua_State *L, void *data, size_t *size) {
17655 if (rm->done) return 0;
17658 *size = rm->st.size;
17660 return rm->st.start;
17661 @@ -51,47 +52,47 @@
17663 static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
17667 lua_pushstring(L, varname);
17670 curelem = lua_gettop(L);
17671 lua_gettable(L, LUA_GLOBALSINDEX);
17674 /* it should be a table */
17675 if (!lua_isstring(L, curelem)) {
17676 lua_settop(L, curelem - 1);
17683 buffer_copy_string(b, lua_tostring(L, curelem));
17689 assert(curelem - 1 == lua_gettop(L));
17695 static int lua_to_c_is_table(lua_State *L, const char *varname) {
17699 lua_pushstring(L, varname);
17702 curelem = lua_gettop(L);
17703 lua_gettable(L, LUA_GLOBALSINDEX);
17706 /* it should be a table */
17707 if (!lua_istable(L, curelem)) {
17708 lua_settop(L, curelem - 1);
17715 lua_settop(L, curelem - 1);
17718 assert(curelem - 1 == lua_gettop(L));
17725 lua_pushlstring(L, key, key_len);
17726 lua_pushlstring(L, val, val_len);
17727 lua_settable(L, tbl);
17733 @@ -108,21 +109,21 @@
17736 char *key = NULL, *val = NULL;
17742 /* we need the \0 */
17743 for (i = 0; i < qrystr->used; i++) {
17744 switch(qrystr->ptr[i]) {
17747 val = qrystr->ptr + i + 1;
17750 qrystr->ptr[i] = '\0';
17759 case '\0': /* fin symbol */
17760 @@ -131,19 +132,19 @@
17762 /* terminate the value */
17763 qrystr->ptr[i] = '\0';
17765 - c_to_lua_push(L, tbl,
17767 + c_to_lua_push(L, tbl,
17773 key = qrystr->ptr + i + 1;
17784 @@ -151,21 +152,21 @@
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;
17798 if (!DATA_IS_STRING(d)) return -1;
17799 if (ds->value->used == 0) return -1;
17802 if (ds->value->ptr[0] == '\0' ||
17803 ds->value->ptr[0] == '=' ||
17804 ds->value->ptr[0] == ';') return -1;
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 @@
17823 buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
17830 @@ -204,48 +205,43 @@
17840 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
17845 buffer *b = buffer_init();
17846 int header_tbl = 0;
17850 stream_open(&rm.st, fn);
17853 /* push the lua file to the interpreter and see what happends */
17857 - luaopen_table(L);
17858 - luaopen_string(L);
17862 + L = luaL_newstate();
17863 + luaL_openlibs(L);
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);
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);
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);
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");
17892 lua_settable(L, LUA_GLOBALSINDEX);
17895 lua_pushliteral(L, "request");
17896 header_tbl = lua_gettop(L);
17897 lua_gettable(L, LUA_GLOBALSINDEX);
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));
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));
17913 /* register GET parameter */
17914 lua_pushliteral(L, "get");
17916 lua_settable(L, LUA_GLOBALSINDEX);
17919 lua_pushliteral(L, "get");
17920 header_tbl = lua_gettop(L);
17921 lua_gettable(L, LUA_GLOBALSINDEX);
17924 buffer_copy_string_buffer(b, con->uri.query);
17925 cache_export_get_params(L, header_tbl, b);
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);
17935 lua_pushliteral(L, "CACHE_MISS");
17936 lua_pushboolean(L, 1);
17937 lua_settable(L, LUA_GLOBALSINDEX);
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));
17950 /* get return value */
17951 ret = (int)lua_tonumber(L, -1);
17954 - /* fetch the data from lua */
17956 + /* fetch the data from lua */
17957 lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
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));
17966 /* up to now it is a cache-hit, check if all files exist */
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");
17983 lua_pushstring(L, "output_include");
17986 curelem = lua_gettop(L);
17987 lua_gettable(L, LUA_GLOBALSINDEX);
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
17996 * The mtime of the content is the mtime of the freshest base file
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 */
18008 if (lua_isstring(L, -1)) {
18009 const char *s = lua_tostring(L, -1);
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 */
18017 log_error_write(srv, __FILE__, __LINE__, "s",
18018 "a file is missing, calling handler");
18023 /* handler not set -> 500 */
18027 log_error_write(srv, __FILE__, __LINE__, "s",
18028 "a file missing and no handler set");
18034 @@ -393,12 +389,12 @@
18040 lua_pop(L, 1); /* removes value'; keeps key' for next iteration */
18044 lua_settop(L, curelem - 1);
18049 char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
18050 @@ -410,9 +406,9 @@
18052 /* no Last-Modified specified */
18053 if ((mtime) && (NULL == ds)) {
18056 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
18059 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
18062 @@ -428,9 +424,9 @@
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 */
18073 chunkqueue_reset(con->write_queue);
18074 @@ -440,24 +436,24 @@
18075 chunkqueue_reset(con->write_queue);
18080 if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
18082 buffer_copy_string_buffer(con->uri.path, p->baseurl);
18083 buffer_append_string_buffer(con->uri.path, p->trigger_handler);
18086 buffer_copy_string_buffer(con->physical.path, p->basedir);
18087 buffer_append_string_buffer(con->physical.path, p->trigger_handler);
18090 chunkqueue_reset(con->write_queue);
18098 stream_close(&rm.st);
18102 return ret /* cache-error */;
18105 --- ../lighttpd-1.4.11/src/mod_compress.c 2005-11-18 13:49:14.000000000 +0200
18106 +++ lighttpd-1.4.12/src/mod_compress.c 2006-07-11 22:07:53.000000000 +0300
18108 #include <sys/stat.h>
18111 -#include <unistd.h>
18113 #include <stdlib.h>
18114 #include <string.h>
18116 #include "buffer.h"
18117 #include "response.h"
18118 #include "stat_cache.h"
18119 +#include "http_chunk.h"
18121 #include "plugin.h"
18126 #include "sys-mmap.h"
18127 +#include "sys-files.h"
18129 /* request: accept-encoding */
18130 #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
18131 @@ -55,97 +56,127 @@
18137 plugin_config **config_storage;
18138 - plugin_config conf;
18139 + plugin_config conf;
18142 INIT_FUNC(mod_compress_init) {
18146 p = calloc(1, sizeof(*p));
18149 p->ofn = buffer_init();
18150 p->b = buffer_init();
18156 FREE_FUNC(mod_compress_free) {
18157 plugin_data *p = p_d;
18162 if (!p) return HANDLER_GO_ON;
18165 buffer_free(p->ofn);
18169 if (p->config_storage) {
18171 for (i = 0; i < srv->config_context->used; i++) {
18172 plugin_config *s = p->config_storage[i];
18177 array_free(s->compress);
18178 buffer_free(s->compress_cache_dir);
18183 free(p->config_storage);
18192 return HANDLER_GO_ON;
18195 +void mkdir_recursive(const char *dir) {
18197 + char dir_copy[256];
18198 + char *p = dir_copy;
18200 + if (!dir || !dir[0])
18203 + strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
18205 + while ((p = strchr(p + 1, '/')) != NULL) {
18208 + if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
18214 + mkdir(dir, 0700);
18217 SETDEFAULTS_FUNC(mod_compress_setdefaults) {
18218 plugin_data *p = p_d;
18221 - config_values_t cv[] = {
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 }
18231 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
18234 for (i = 0; i < srv->config_context->used; i++) {
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;
18244 cv[0].destination = s->compress_cache_dir;
18245 cv[1].destination = s->compress;
18246 cv[2].destination = &(s->compress_max_filesize);
18249 p->config_storage[i] = s;
18252 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18253 return HANDLER_ERROR;
18257 if (!buffer_is_empty(s->compress_cache_dir)) {
18259 if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18260 - log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
18262 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
18263 s->compress_cache_dir, strerror(errno));
18265 - return HANDLER_ERROR;
18266 + mkdir_recursive(s->compress_cache_dir->ptr);
18268 + if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18270 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
18271 + s->compress_cache_dir, strerror(errno));
18273 + return HANDLER_ERROR;
18280 return HANDLER_GO_ON;
18286 @@ -153,32 +184,32 @@
18299 - if (Z_OK != deflateInit2(&z,
18301 + if (Z_OK != deflateInit2(&z,
18302 Z_DEFAULT_COMPRESSION,
18305 -MAX_WBITS, /* supress zlib-header */
18307 Z_DEFAULT_STRATEGY)) {
18312 z.next_in = (unsigned char *)start;
18313 z.avail_in = st_size;
18319 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
18322 /* write gzip header */
18325 c = (unsigned char *)p->b->ptr;
18328 @@ -190,24 +221,24 @@
18329 c[7] = (mtime >> 24) & 0xff;
18330 c[8] = 0x00; /* extra flags */
18331 c[9] = 0x03; /* UNIX */
18335 z.next_out = (unsigned char *)p->b->ptr + p->b->used;
18336 z.avail_out = p->b->size - p->b->used - 8;
18340 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18347 p->b->used += z.total_out;
18350 crc = generate_crc32c(start, st_size);
18353 c = (unsigned char *)p->b->ptr + p->b->used;
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)) {
18368 static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18379 - if (Z_OK != deflateInit2(&z,
18381 + if (Z_OK != deflateInit2(&z,
18382 Z_DEFAULT_COMPRESSION,
18385 -MAX_WBITS, /* supress zlib-header */
18387 Z_DEFAULT_STRATEGY)) {
18393 z.avail_in = st_size;
18397 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
18400 z.next_out = (unsigned char *)p->b->ptr;
18401 z.avail_out = p->b->size;
18405 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18412 p->b->used += z.total_out;
18415 if (Z_OK != deflateEnd(&z)) {
18423 @@ -274,48 +305,48 @@
18425 static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18436 - if (BZ_OK != BZ2_bzCompressInit(&bz,
18438 + if (BZ_OK != BZ2_bzCompressInit(&bz,
18439 9, /* blocksize = 900k */
18441 0)) { /* workFactor: default */
18446 bz.next_in = (char *)start;
18447 bz.avail_in = st_size;
18448 bz.total_in_lo32 = 0;
18449 bz.total_in_hi32 = 0;
18452 buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
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;
18461 if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
18462 BZ2_bzCompressEnd(&bz);
18467 /* file is too large for now */
18468 if (bz.total_out_hi32) return -1;
18472 p->b->used = bz.total_out_lo32;
18475 if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
18483 @@ -326,47 +357,50 @@
18485 const char *filename = fn->ptr;
18488 + stat_cache_entry *compressed_sce = NULL;
18490 + if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
18493 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18495 - /* don't mmap files > 128Mb
18498 + /* don't mmap files > 128Mb
18500 * we could use a sliding window, but currently there is no need for it
18504 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18507 buffer_reset(p->ofn);
18508 buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
18509 - BUFFER_APPEND_SLASH(p->ofn);
18511 + PATHNAME_APPEND_SLASH(p->ofn);
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;
18518 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
18521 buffer_copy_string_buffer(p->b, p->ofn);
18525 for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
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));
18542 buffer_append_string_buffer(p->ofn, con->uri.path);
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);
18555 buffer_append_string_buffer(p->ofn, sce->etag);
18559 + if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
18560 + /* file exists */
18562 + http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
18563 + con->file_finished = 1;
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 */
18572 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
18574 - buffer_copy_string_buffer(con->physical.path, p->ofn);
18580 - log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
18583 + log_error_write(srv, __FILE__, __LINE__, "sbss",
18584 + "creating cachefile", p->ofn,
18585 + "failed", strerror(errno));
18590 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
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));
18596 + log_error_write(srv, __FILE__, __LINE__, "sbss",
18597 + "opening plain-file", fn,
18598 + "failed", strerror(errno));
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));
18612 + log_error_write(srv, __FILE__, __LINE__, "sbss",
18614 + "failed", strerror(errno));
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);
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);
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);
18639 @@ -437,26 +480,27 @@
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);
18654 if ((size_t)r != p->b->used) {
18660 munmap(start, sce->st.st_size);
18665 if (ret != 0) return -1;
18667 - buffer_copy_string_buffer(con->physical.path, p->ofn);
18670 + http_chunk_append_file(srv, con, p->ofn, 0, r);
18671 + con->file_finished = 1;
18676 @@ -465,43 +509,44 @@
18683 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18686 /* don't mmap files > 128M
18689 * we could use a sliding window, but currently there is no need for it
18693 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
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));
18705 - if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18707 + start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
18711 + if (MAP_FAILED == start) {
18712 log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
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);
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);
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);
18737 @@ -509,69 +554,64 @@
18743 munmap(start, sce->st.st_size);
18747 if (ret != 0) return -1;
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);
18755 buffer_reset(con->physical.path);
18758 con->file_finished = 1;
18759 con->file_started = 1;
18766 -#define PATCH(x) \
18767 - p->conf.x = s->x;
18768 static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
18770 plugin_config *s = p->config_storage[0];
18772 - PATCH(compress_cache_dir);
18774 - PATCH(compress_max_filesize);
18776 + PATCH_OPTION(compress_cache_dir);
18777 + PATCH_OPTION(compress);
18778 + PATCH_OPTION(compress_max_filesize);
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];
18786 /* condition didn't match */
18787 if (!config_check_cond(srv, con, dc)) continue;
18791 for (j = 0; j < dc->value->used; j++) {
18792 data_unset *du = dc->value->data[j];
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"))) {
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);
18813 PHYSICALPATH_FUNC(mod_compress_physical) {
18814 plugin_data *p = p_d;
18817 stat_cache_entry *sce = NULL;
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;
18826 @@ -579,46 +619,49 @@
18827 if (buffer_is_empty(con->physical.path)) {
18828 return HANDLER_GO_ON;
18832 mod_compress_patch_connection(srv, con, p);
18835 max_fsize = p->conf.compress_max_filesize;
18837 stat_cache_get_entry(srv, con, con->physical.path, &sce);
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;
18843 + /* compressing the file might lead to larger files instead */
18844 + if (sce->st.st_size < 128) return HANDLER_GO_ON;
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];
18851 if (!compress_ds) {
18852 log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
18855 return HANDLER_GO_ON;
18859 if (buffer_is_equal(compress_ds->value, sce->content_type)) {
18860 /* mimetype found */
18864 /* the response might change according to Accept-Encoding */
18865 response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
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;
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;
18883 /* get server side supported ones */
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;
18892 /* find matching entries */
18893 matched_encodings = accept_encoding & srv_encodings;
18896 if (matched_encodings) {
18897 const char *dflt_gzip = "gzip";
18898 const char *dflt_deflate = "deflate";
18899 const char *dflt_bzip2 = "bzip2";
18902 const char *compression_name = NULL;
18903 int compression_type = 0;
18907 + mtime = strftime_cache_get(srv, sce->st.st_mtime);
18908 + etag_mutate(con->physical.etag, sce->etag);
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));
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;
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;
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)) {
18933 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
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));
18938 - etag_mutate(con->physical.etag, sce->etag);
18939 - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
18941 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
18943 - return HANDLER_GO_ON;
18945 - } else if (0 == deflate_file_to_buffer(srv, con, p,
18946 - con->physical.path, sce, compression_type)) {
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));
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)) {
18958 + response_header_overwrite(srv, con,
18959 + CONST_STR_LEN("Content-Encoding"),
18960 + compression_name, strlen(compression_name));
18962 + response_header_overwrite(srv, con,
18963 + CONST_STR_LEN("Content-Type"),
18964 + CONST_BUF_LEN(sce->content_type));
18966 return HANDLER_FINISHED;
18969 @@ -682,20 +728,20 @@
18975 return HANDLER_GO_ON;
18978 int mod_compress_plugin_init(plugin *p) {
18979 p->version = LIGHTTPD_VERSION_ID;
18980 p->name = buffer_init_string("compress");
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;
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
18998 #include <stdlib.h>
18999 #include <string.h>
19000 -#include <dirent.h>
19001 #include <assert.h>
19004 -#include <unistd.h>
19009 #include "response.h"
19010 #include "stat_cache.h"
19011 #include "stream.h"
19014 +#include "sys-strings.h"
19017 * this is a dirlisting for a lighttpd plugin
19018 @@ -27,10 +28,13 @@
19019 #include <sys/syslimits.h>
19022 -#ifdef HAVE_ATTR_ATTRIBUTES_H
19024 #include <attr/attributes.h>
19027 +#include "sys-files.h"
19028 +#include "sys-strings.h"
19030 /* plugin config for all request/connections */
19034 unsigned short hide_readme_file;
19035 unsigned short show_header;
19036 unsigned short hide_header_file;
19039 excludes_buffer *excludes;
19041 buffer *external_css;
19042 @@ -63,13 +67,14 @@
19049 buffer *content_charset;
19053 plugin_config **config_storage;
19055 - plugin_config conf;
19057 + plugin_config conf;
19060 excludes_buffer *excludes_buffer_init(void) {
19061 @@ -146,44 +151,46 @@
19062 /* init the plugin data */
19063 INIT_FUNC(mod_dirlisting_init) {
19067 p = calloc(1, sizeof(*p));
19069 p->tmp_buf = buffer_init();
19070 p->content_charset = buffer_init();
19072 + p->path = buffer_init();
19077 /* detroy the plugin data */
19078 FREE_FUNC(mod_dirlisting_free) {
19079 plugin_data *p = p_d;
19084 if (!p) return HANDLER_GO_ON;
19087 if (p->config_storage) {
19089 for (i = 0; i < srv->config_context->used; i++) {
19090 plugin_config *s = p->config_storage[i];
19096 excludes_buffer_free(s->excludes);
19097 buffer_free(s->external_css);
19098 buffer_free(s->encoding);
19103 free(p->config_storage);
19107 buffer_free(p->tmp_buf);
19108 + buffer_free(p->path);
19109 buffer_free(p->content_charset);
19115 return HANDLER_GO_ON;
19118 @@ -215,10 +222,10 @@
19119 if (0 != excludes_buffer_append(s->excludes,
19120 ((data_string *)(da->value->data[j]))->value)) {
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);
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");
19131 @@ -233,8 +240,8 @@
19132 SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
19133 plugin_data *p = p_d;
19136 - config_values_t cv[] = {
19138 + config_values_t cv[] = {
19139 { "dir-listing.exclude", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
19140 { "dir-listing.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
19141 { "dir-listing.hide-dotfiles", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
19142 @@ -245,18 +252,18 @@
19143 { "dir-listing.show-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
19144 { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
19145 { "server.dir-listing", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
19148 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19152 if (!p) return HANDLER_ERROR;
19155 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19158 for (i = 0; i < srv->config_context->used; i++) {
19163 s = calloc(1, sizeof(plugin_config));
19164 s->excludes = excludes_buffer_init();
19165 s->dir_listing = 0;
19166 @@ -267,7 +274,7 @@
19167 s->show_header = 0;
19168 s->hide_header_file = 0;
19169 s->encoding = buffer_init();
19172 cv[0].destination = s->excludes;
19173 cv[1].destination = &(s->dir_listing);
19174 cv[2].destination = &(s->hide_dot_files);
19175 @@ -292,60 +299,57 @@
19176 return HANDLER_GO_ON;
19179 -#define PATCH(x) \
19180 - p->conf.x = s->x;
19181 static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
19183 plugin_config *s = p->config_storage[0];
19185 - PATCH(dir_listing);
19186 - PATCH(external_css);
19187 - PATCH(hide_dot_files);
19189 - PATCH(show_readme);
19190 - PATCH(hide_readme_file);
19191 - PATCH(show_header);
19192 - PATCH(hide_header_file);
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);
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];
19211 /* condition didn't match */
19212 if (!config_check_cond(srv, con, dc)) continue;
19216 for (j = 0; j < dc->value->used; j++) {
19217 data_unset *du = dc->value->data[j];
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"))) {
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"))) {
19247 + PATCH_OPTION(excludes);
19259 @@ -432,7 +436,7 @@
19261 static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
19265 BUFFER_APPEND_STRING_CONST(out,
19266 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
19267 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
19268 @@ -492,11 +496,11 @@
19269 if (p->conf.show_header) {
19271 /* if we have a HEADER file, display it in <pre class="header"></pre> */
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");
19280 if (-1 != stream_open(&s, p->tmp_buf)) {
19281 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
19282 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19283 @@ -531,21 +535,21 @@
19285 static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
19289 BUFFER_APPEND_STRING_CONST(out,
19296 if (p->conf.show_readme) {
19298 /* if we have a README file, display it in <pre class="readme"></pre> */
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");
19307 if (-1 != stream_open(&s, p->tmp_buf)) {
19308 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
19309 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19310 @@ -553,7 +557,7 @@
19316 BUFFER_APPEND_STRING_CONST(out,
19317 "<div class=\"foot\">"
19319 @@ -576,7 +580,6 @@
19321 struct dirent *dent;
19323 - char *path, *path_file;
19325 int hide_dotfiles = p->conf.hide_dot_files;
19326 dirls_list_t dirs, files, *list;
19327 @@ -586,6 +589,7 @@
19329 const char *content_type;
19335 @@ -594,10 +598,10 @@
19339 - if (dir->used == 0) return -1;
19341 - i = dir->used - 1;
19342 + /* empty pathname, never ... */
19343 + if (buffer_is_empty(dir)) return -1;
19345 + /* max-length for the opendir */
19346 #ifdef HAVE_PATHCONF
19347 if (-1 == (name_max = pathconf(dir->ptr, _PC_NAME_MAX))) {
19349 @@ -606,22 +610,24 @@
19350 name_max = 256; /* stupid default */
19353 -#elif defined __WIN32
19354 +#elif defined _WIN32
19355 name_max = FILENAME_MAX;
19357 name_max = NAME_MAX;
19360 - path = malloc(dir->used + name_max);
19362 - strcpy(path, dir->ptr);
19363 - path_file = path + i;
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);
19371 + /* append *.* to the path */
19372 + buffer_append_string(path, "*.*");
19375 + if (NULL == (dp = opendir(p->path->ptr))) {
19376 + log_error_write(srv, __FILE__, __LINE__, "sbs",
19377 "opendir failed:", dir, strerror(errno));
19383 @@ -633,7 +639,7 @@
19385 files.size = DIRLIST_BLOB_SIZE;
19389 while ((dent = readdir(dp)) != NULL) {
19390 unsigned short exclude_match = 0;
19392 @@ -686,15 +692,21 @@
19395 i = strlen(dent->d_name);
19398 /* NOTE: the manual says, d_name is never more than NAME_MAX
19399 * so this should actually not be a buffer-overflow-risk
19401 if (i > (size_t)name_max) continue;
19403 - memcpy(path_file, dent->d_name, i + 1);
19404 - if (stat(path, &st) != 0)
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);
19411 + if (stat(p->path->ptr, &st) != 0) {
19412 + fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, p->path->ptr, strerror(errno));
19417 if (S_ISDIR(st.st_mode))
19418 @@ -740,7 +752,7 @@
19420 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
19424 BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
19425 buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
19426 BUFFER_APPEND_STRING_CONST(out, "/\">");
19427 @@ -757,18 +769,22 @@
19428 tmp = files.ent[i];
19430 content_type = NULL;
19434 if (con->conf.use_xattr) {
19435 - memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
19436 + /* build the dirname */
19437 + buffer_copy_string_buffer(p->path, dir);
19438 + PATHNAME_APPEND_SLASH(p->path);
19439 + buffer_append_string_len(p->path, DIRLIST_ENT_NAME(tmp), tmp->namelen);
19441 attrlen = sizeof(attrval) - 1;
19442 - if (attr_get(path, "Content-Type", attrval, &attrlen, 0) == 0) {
19443 + if (attr_get(p->path->ptr, "Content-Type", attrval, &attrlen, 0) == 0) {
19444 attrval[attrlen] = '\0';
19445 content_type = attrval;
19451 if (content_type == NULL) {
19452 content_type = "application/octet-stream";
19453 for (k = 0; k < con->conf.mimetypes->used; k++) {
19454 @@ -788,7 +804,7 @@
19460 #ifdef HAVE_LOCALTIME_R
19461 localtime_r(&(tmp->mtime), &tm);
19462 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
19463 @@ -814,7 +830,6 @@
19469 http_list_directory_footer(srv, con, p, out);
19471 @@ -837,36 +852,55 @@
19472 URIHANDLER_FUNC(mod_dirlisting_subrequest) {
19473 plugin_data *p = p_d;
19474 stat_cache_entry *sce = NULL;
19478 - if (con->physical.path->used == 0) return HANDLER_GO_ON;
19479 - if (con->uri.path->used == 0) return HANDLER_GO_ON;
19483 + if (con->uri.path->used < 2) return HANDLER_GO_ON;
19484 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
19486 + if (con->physical.path->used == 0) return HANDLER_GO_ON;
19488 mod_dirlisting_patch_connection(srv, con, p);
19490 if (!p->conf.dir_listing) return HANDLER_GO_ON;
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;
19498 + if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
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);
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);
19509 + /* perhaps this a cachable request
19510 + * - we use the etag of the directory
19513 + etag_mutate(con->physical.etag, sce->etag);
19514 + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
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));
19521 + mtime = ds->value;
19524 - if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
19527 + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
19528 + return HANDLER_FINISHED;
19531 if (http_list_directory(srv, con, p, con->physical.path)) {
19532 /* dirlisting failed */
19533 con->http_status = 403;
19537 buffer_reset(con->physical.path);
19541 return HANDLER_FINISHED;
19543 @@ -876,13 +910,13 @@
19544 int mod_dirlisting_plugin_init(plugin *p) {
19545 p->version = LIGHTTPD_VERSION_ID;
19546 p->name = buffer_init_string("dirlisting");
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;
19560 --- ../lighttpd-1.4.11/src/mod_evasive.c 2006-01-04 15:24:51.000000000 +0200
19561 +++ lighttpd-1.4.12/src/mod_evasive.c 2006-07-11 22:07:53.000000000 +0300
19562 @@ -31,100 +31,97 @@
19568 plugin_config **config_storage;
19570 - plugin_config conf;
19572 + plugin_config conf;
19575 INIT_FUNC(mod_evasive_init) {
19579 p = calloc(1, sizeof(*p));
19585 FREE_FUNC(mod_evasive_free) {
19586 plugin_data *p = p_d;
19591 if (!p) return HANDLER_GO_ON;
19594 if (p->config_storage) {
19596 for (i = 0; i < srv->config_context->used; i++) {
19597 plugin_config *s = p->config_storage[i];
19602 free(p->config_storage);
19609 return HANDLER_GO_ON;
19612 SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
19613 plugin_data *p = p_d;
19616 - config_values_t cv[] = {
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 }
19624 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19627 for (i = 0; i < srv->config_context->used; i++) {
19631 s = calloc(1, sizeof(plugin_config));
19635 cv[0].destination = &(s->max_conns);
19638 p->config_storage[i] = s;
19641 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19642 return HANDLER_ERROR;
19647 return HANDLER_GO_ON;
19650 -#define PATCH(x) \
19651 - p->conf.x = s->x;
19652 static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
19654 plugin_config *s = p->config_storage[0];
19656 - PATCH(max_conns);
19658 + PATCH_OPTION(max_conns);
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];
19666 /* condition didn't match */
19667 if (!config_check_cond(srv, con, dc)) continue;
19671 for (j = 0; j < dc->value->used; j++) {
19672 data_unset *du = dc->value->data[j];
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);
19687 URIHANDLER_FUNC(mod_evasive_uri_handler) {
19688 plugin_data *p = p_d;
19689 @@ -132,10 +129,10 @@
19692 if (con->uri.path->used == 0) return HANDLER_GO_ON;
19695 mod_evasive_patch_connection(srv, con, p);
19697 - /* no limit set, nothing to block */
19699 + /* no limit set, nothing to block */
19700 if (p->conf.max_conns == 0) return HANDLER_GO_ON;
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) {
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 @@
19718 return HANDLER_GO_ON;
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");
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;
19738 --- ../lighttpd-1.4.11/src/mod_evhost.c 2005-08-17 10:42:03.000000000 +0300
19739 +++ lighttpd-1.4.12/src/mod_evhost.c 2006-07-11 22:07:51.000000000 +0300
19741 #include "response.h"
19742 #include "stat_cache.h"
19744 +#include "sys-files.h"
19747 /* unparsed pieces */
19748 buffer *path_pieces_raw;
19751 /* pieces for path creation */
19753 buffer **path_pieces;
19754 @@ -21,14 +23,14 @@
19757 plugin_config **config_storage;
19758 - plugin_config conf;
19759 + plugin_config conf;
19762 INIT_FUNC(mod_evhost_init) {
19766 p = calloc(1, sizeof(*p));
19769 p->tmp_buf = buffer_init();
19772 @@ -36,34 +38,34 @@
19774 FREE_FUNC(mod_evhost_free) {
19775 plugin_data *p = p_d;
19780 if (!p) return HANDLER_GO_ON;
19783 if (p->config_storage) {
19785 for (i = 0; i < srv->config_context->used; i++) {
19786 plugin_config *s = p->config_storage[i];
19791 if(s->path_pieces) {
19793 for (j = 0; j < s->len; j++) {
19794 buffer_free(s->path_pieces[j]);
19798 free(s->path_pieces);
19802 buffer_free(s->path_pieces_raw);
19807 free(p->config_storage);
19811 buffer_free(p->tmp_buf);
19814 @@ -73,30 +75,30 @@
19816 static void mod_evhost_parse_pattern(plugin_config *s) {
19817 char *ptr = s->path_pieces_raw->ptr,*pos;
19820 s->path_pieces = NULL;
19823 for(pos=ptr;*ptr;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();
19830 buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
19834 buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
19843 s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
19844 s->path_pieces[s->len] = buffer_init();
19847 buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
19853 @@ -104,9 +106,9 @@
19854 SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
19855 plugin_data *p = p_d;
19863 * # define a pattern for the host url finding
19865 @@ -117,39 +119,39 @@
19866 * # %4 => subdomain 2 name
19868 * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
19873 - config_values_t cv[] = {
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 }
19881 if (!p) return HANDLER_ERROR;
19884 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19887 for (i = 0; i < srv->config_context->used; i++) {
19891 s = calloc(1, sizeof(plugin_config));
19892 s->path_pieces_raw = buffer_init();
19893 s->path_pieces = NULL;
19897 cv[0].destination = s->path_pieces_raw;
19900 p->config_storage[i] = s;
19903 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19904 return HANDLER_ERROR;
19908 if (s->path_pieces_raw->used != 0) {
19909 mod_evhost_parse_pattern(s);
19914 return HANDLER_GO_ON;
19917 @@ -158,7 +160,7 @@
19918 * - %0 - full hostname (authority w/o port)
19920 * - %2 - domain.tld
19925 static int mod_evhost_parse_host(connection *con,array *host) {
19926 @@ -168,7 +170,7 @@
19932 /* first, find the domain + tld */
19933 for(;ptr > con->uri.authority->ptr;ptr--) {
19935 @@ -179,18 +181,18 @@
19941 ds = data_string_init();
19942 buffer_copy_string(ds->key,"%0");
19945 /* if we stopped at a dot, skip the dot */
19946 if (*ptr == '.') ptr++;
19947 buffer_copy_string_len(ds->value, ptr, colon-ptr);
19950 array_insert_unique(host,(data_unset *)ds);
19953 /* if the : is not the start of the authority, go on parsing the hostname */
19956 if (colon != con->uri.authority->ptr) {
19957 for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; 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);
19965 array_insert_unique(host,(data_unset *)ds);
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);
19980 array_insert_unique(host,(data_unset *)ds);
19988 -#define PATCH(x) \
19989 - p->conf.x = s->x;
19990 static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
19992 plugin_config *s = p->config_storage[0];
19994 - PATCH(path_pieces);
19998 + PATCH_OPTION(path_pieces);
19999 + PATCH_OPTION(len);
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];
20007 /* condition didn't match */
20008 if (!config_check_cond(srv, con, dc)) continue;
20012 for (j = 0; j < dc->value->used; j++) {
20013 data_unset *du = dc->value->data[j];
20016 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
20017 - PATCH(path_pieces);
20019 + PATCH_OPTION(path_pieces);
20020 + PATCH_OPTION(len);
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;
20036 stat_cache_entry *sce = NULL;
20039 /* not authority set */
20040 if (con->uri.authority->used == 0) return HANDLER_GO_ON;
20043 mod_evhost_patch_connection(srv, con, p);
20046 /* missing even default(global) conf */
20047 if (0 == p->conf.len) {
20048 return HANDLER_GO_ON;
20051 parsed_host = array_init();
20054 mod_evhost_parse_host(con, parsed_host);
20057 /* build document-root */
20058 buffer_reset(p->tmp_buf);
20061 for (i = 0; i < p->conf.len; i++) {
20062 ptr = p->conf.path_pieces[i]->ptr;
20067 if (*(ptr+1) == '%') {
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]);
20075 - BUFFER_APPEND_SLASH(p->tmp_buf);
20078 + PATHNAME_APPEND_SLASH(p->tmp_buf);
20080 array_free(parsed_host);
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);
20086 @@ -310,11 +308,11 @@
20087 log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
20093 buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
20097 return HANDLER_GO_ON;
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;
20112 --- ../lighttpd-1.4.11/src/mod_expire.c 2005-11-03 09:52:13.000000000 +0200
20113 +++ lighttpd-1.4.12/src/mod_expire.c 2006-07-11 22:07:52.000000000 +0300
20115 #include "stat_cache.h"
20118 - * this is a expire module for a lighttpd
20120 + * this is a expire module for a lighttpd
20122 * set 'Expires:' HTTP Headers on demand
20125 @@ -27,51 +27,51 @@
20131 buffer *expire_tstmp;
20134 plugin_config **config_storage;
20136 - plugin_config conf;
20138 + plugin_config conf;
20141 /* init the plugin data */
20142 INIT_FUNC(mod_expire_init) {
20146 p = calloc(1, sizeof(*p));
20149 p->expire_tstmp = buffer_init();
20152 buffer_prepare_copy(p->expire_tstmp, 255);
20158 /* detroy the plugin data */
20159 FREE_FUNC(mod_expire_free) {
20160 plugin_data *p = p_d;
20165 if (!p) return HANDLER_GO_ON;
20168 buffer_free(p->expire_tstmp);
20171 if (p->config_storage) {
20173 for (i = 0; i < srv->config_context->used; i++) {
20174 plugin_config *s = p->config_storage[i];
20177 array_free(s->expire_url);
20182 free(p->config_storage);
20189 return HANDLER_GO_ON;
20192 @@ -79,25 +79,25 @@
20205 * '(access|modification) [plus] {<num> <type>}*'
20208 * e.g. 'access 1 years'
20212 if (expire->used == 0) {
20213 - log_error_write(srv, __FILE__, __LINE__, "s",
20214 + log_error_write(srv, __FILE__, __LINE__, "s",
20223 if (0 == strncmp(ts, "access ", 7)) {
20226 @@ -110,39 +110,39 @@
20227 "invalid <base>:", ts);
20232 if (0 == strncmp(ts, "plus ", 5)) {
20233 /* skip the optional plus */
20238 /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
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);
20252 num = strtol(ts, &err, 10);
20254 - log_error_write(srv, __FILE__, __LINE__, "ss",
20255 + log_error_write(srv, __FILE__, __LINE__, "ss",
20256 "missing <type> after <num>:", ts);
20264 if (NULL != (space = strchr(ts, ' '))) {
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)) {
20281 - log_error_write(srv, __FILE__, __LINE__, "ss",
20282 + log_error_write(srv, __FILE__, __LINE__, "ss",
20283 "unknown type:", ts);
20293 if (0 == strcmp(ts, "years")) {
20294 @@ -183,19 +183,19 @@
20295 } else if (0 == strcmp(ts, "seconds")) {
20298 - log_error_write(srv, __FILE__, __LINE__, "ss",
20299 + log_error_write(srv, __FILE__, __LINE__, "ss",
20300 "unknown type:", ts);
20313 if (offset != NULL) *offset = retts;
20319 @@ -205,102 +205,99 @@
20320 SETDEFAULTS_FUNC(mod_expire_set_defaults) {
20321 plugin_data *p = p_d;
20324 - config_values_t cv[] = {
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 }
20332 if (!p) return HANDLER_ERROR;
20335 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20338 for (i = 0; i < srv->config_context->used; i++) {
20342 s = calloc(1, sizeof(plugin_config));
20343 s->expire_url = array_init();
20346 cv[0].destination = s->expire_url;
20349 p->config_storage[i] = s;
20352 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
20353 return HANDLER_ERROR;
20357 for (k = 0; k < s->expire_url->used; k++) {
20358 data_string *ds = (data_string *)s->expire_url->data[k];
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;
20374 return HANDLER_GO_ON;
20377 -#define PATCH(x) \
20378 - p->conf.x = s->x;
20379 static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
20381 plugin_config *s = p->config_storage[0];
20383 - PATCH(expire_url);
20386 + PATCH_OPTION(expire_url);
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];
20394 /* condition didn't match */
20395 if (!config_check_cond(srv, con, dc)) continue;
20399 for (j = 0; j < dc->value->used; j++) {
20400 data_unset *du = dc->value->data[j];
20403 if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
20404 - PATCH(expire_url);
20405 + PATCH_OPTION(expire_url);
20415 URIHANDLER_FUNC(mod_expire_path_handler) {
20416 plugin_data *p = p_d;
20421 if (con->uri.path->used == 0) return HANDLER_GO_ON;
20424 mod_expire_patch_connection(srv, con, p);
20427 s_len = con->uri.path->used - 1;
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;
20435 if (ct_len > s_len) continue;
20436 if (ds->key->used == 0) continue;
20439 if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
20443 stat_cache_entry *sce = NULL;
20446 stat_cache_get_entry(srv, con, con->physical.path, &sce);
20449 switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
20452 @@ -308,38 +305,38 @@
20458 t = (ts + sce->st.st_mtime);
20461 /* -1 is handled at parse-time */
20466 - if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
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 */
20474 return HANDLER_GO_ON;
20480 p->expire_tstmp->used = len + 1;
20485 response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
20489 buffer_copy_string(p->expire_tstmp, "max-age=");
20490 buffer_append_long(p->expire_tstmp, ts);
20493 response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
20496 return HANDLER_GO_ON;
20502 return HANDLER_GO_ON;
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");
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;
20521 --- ../lighttpd-1.4.11/src/mod_fastcgi.c 2006-03-09 13:18:39.000000000 +0200
20522 +++ lighttpd-1.4.12/src/mod_fastcgi.c 2006-07-11 22:07:53.000000000 +0300
20524 #include <sys/types.h>
20525 -#include <unistd.h>
20528 #include <string.h>
20530 #include "inet_ntop_cache.h"
20531 #include "stat_cache.h"
20533 -#include <fastcgi.h>
20534 +#include "fastcgi.h"
20537 #ifdef HAVE_SYS_FILIO_H
20541 #include "sys-socket.h"
20542 +#include "sys-files.h"
20543 +#include "sys-strings.h"
20544 +#include "sys-process.h"
20546 +#include "http_resp.h"
20548 #ifndef UNIX_PATH_MAX
20549 # define UNIX_PATH_MAX 108
20550 @@ -45,14 +48,13 @@
20551 #include <sys/wait.h>
20561 * - add timeout for a connect to a non-fastcgi process
20562 * (use state_timestamp + state)
20567 typedef struct fcgi_proc {
20569 unsigned port; /* config.port + pno */
20571 buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
20574 pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
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 */
20583 time_t disabled_until; /* this proc is disabled until, use something else until than */
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 */
20603 @@ -94,20 +96,20 @@
20604 * sorted by lowest load
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
20611 - fcgi_proc *first;
20612 - fcgi_proc *unused_procs;
20613 + fcgi_proc *first;
20614 + fcgi_proc *unused_procs;
20618 * spawn at least min_procs, at max_procs.
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
20630 unsigned short min_procs;
20631 @@ -119,44 +121,44 @@
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.
20643 unsigned short idle_timeout;
20647 * time after a disabled remote connection is tried to be re-enabled
20655 unsigned short disable_time;
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.
20664 size_t max_requests_per_proc;
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
20679 * if tcp/ip should be used host AND port have
20680 - * to be specified
20684 + * to be specified
20688 unsigned short port;
20691 @@ -169,7 +171,7 @@
20693 buffer *unixsocket;
20695 - /* if socket is local we can start the fastcgi
20696 + /* if socket is local we can start the fastcgi
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
20704 - buffer *bin_path;
20706 - /* bin-path is set bin-environment is taken to
20707 + buffer *bin_path;
20709 + /* bin-path is set bin-environment is taken to
20710 * create the environement before starting the
20718 array *bin_env_copy;
20722 - * docroot-translation between URL->phys and the
20723 + * docroot-translation between URL->phys and the
20727 @@ -208,7 +210,7 @@
20728 unsigned short mode;
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 @@
20739 * append PATH_INFO to SCRIPT_FILENAME
20742 * php needs this if cgi.fix_pathinfo is provied
20748 unsigned short break_scriptfilename_for_php;
20751 @@ -231,12 +233,12 @@
20754 unsigned short allow_xsendfile;
20757 ssize_t load; /* replace by host->load */
20759 size_t max_id; /* corresponds most of the time to
20763 only if a process is killed max_id waits for the process itself
20764 to die and decrements its afterwards */
20766 @@ -245,17 +247,17 @@
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)
20774 * ext -> host -> procs
20777 - * if the fastcgi process is remote that whole goes down
20778 + * if the fastcgi process is remote that whole goes down
20781 * ext -> host -> procs
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 @@
20790 fcgi_extension_host **hosts;
20796 @@ -282,10 +284,10 @@
20803 array *ext_mapping;
20809 @@ -297,7 +299,7 @@
20818 @@ -306,44 +308,44 @@
20821 buffer_uint fcgi_request_id;
20828 - buffer *parse_response;
20835 plugin_config **config_storage;
20838 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
20841 /* connection specific data */
20846 - FCGI_STATE_CONNECT_DELAYED,
20847 - FCGI_STATE_PREPARE_WRITE,
20848 - FCGI_STATE_WRITE,
20851 + FCGI_STATE_CONNECT_DELAYED,
20852 + FCGI_STATE_PREPARE_WRITE,
20853 + FCGI_STATE_WRITE,
20855 } fcgi_connection_state_t;
20859 fcgi_extension_host *host;
20860 fcgi_extension *ext;
20863 fcgi_connection_state_t state;
20864 time_t state_timestamp;
20867 int reconnects; /* number of reconnect attempts */
20869 - chunkqueue *rb; /* read queue */
20871 + chunkqueue *rb; /* the raw fcgi read-queue */
20872 + chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
20873 chunkqueue *wb; /* write queue */
20875 - buffer *response_header;
20879 int fd; /* fd to the fastcgi process */
20880 int fde_ndx; /* index into the fd-event buffer */
20881 @@ -352,9 +354,9 @@
20884 int send_content_body;
20887 plugin_config conf;
20890 connection *remote_conn; /* dumb pointer */
20891 plugin_data *plugin_data; /* dumb pointer */
20893 @@ -380,7 +382,7 @@
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");
20910 fastcgi_status_copy_procname(b, host, NULL); \
20911 @@ -438,33 +440,32 @@
20921 static handler_ctx * handler_ctx_init() {
20922 handler_ctx * hctx;
20925 hctx = calloc(1, sizeof(*hctx));
20929 hctx->fde_ndx = -1;
20931 - hctx->response_header = buffer_init();
20934 hctx->request_id = 0;
20935 hctx->state = FCGI_STATE_INIT;
20942 hctx->reconnects = 0;
20943 hctx->send_content_body = 1;
20945 hctx->rb = chunkqueue_init();
20946 + hctx->http_rb = chunkqueue_init();
20947 hctx->wb = chunkqueue_init();
20953 @@ -473,10 +474,9 @@
20954 hctx->host->load--;
20958 - buffer_free(hctx->response_header);
20960 chunkqueue_free(hctx->rb);
20961 + chunkqueue_free(hctx->http_rb);
20962 chunkqueue_free(hctx->wb);
20965 @@ -488,21 +488,21 @@
20966 f = calloc(1, sizeof(*f));
20967 f->unixsocket = buffer_init();
20968 f->connection_name = buffer_init();
20978 void fastcgi_process_free(fcgi_proc *f) {
20982 fastcgi_process_free(f->next);
20985 buffer_free(f->unixsocket);
20986 buffer_free(f->connection_name);
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();
21001 void fastcgi_host_free(fcgi_extension_host *h) {
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);
21014 fastcgi_process_free(h->first);
21015 fastcgi_process_free(h->unused_procs);
21023 fcgi_exts *fastcgi_extensions_init() {
21026 f = calloc(1, sizeof(*f));
21032 void fastcgi_extensions_free(fcgi_exts *f) {
21039 for (i = 0; i < f->used; i++) {
21040 fcgi_extension *fe;
21047 for (j = 0; j < fe->used; j++) {
21048 fcgi_extension_host *h;
21054 fastcgi_host_free(h);
21058 buffer_free(fe->key);
21072 @@ -625,24 +625,25 @@
21076 - fe->hosts[fe->used++] = fh;
21077 + fe->hosts[fe->used++] = fh;
21084 INIT_FUNC(mod_fastcgi_init) {
21088 p = calloc(1, sizeof(*p));
21091 p->fcgi_env = buffer_init();
21094 p->path = buffer_init();
21095 - p->parse_response = buffer_init();
21097 + p->resp = http_response_init();
21099 p->statuskey = buffer_init();
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);
21113 if (r->ptr) free(r->ptr);
21116 buffer_free(p->fcgi_env);
21117 buffer_free(p->path);
21118 - buffer_free(p->parse_response);
21119 buffer_free(p->statuskey);
21122 + http_response_free(p->resp);
21124 if (p->config_storage) {
21126 for (i = 0; i < srv->config_context->used; i++) {
21127 plugin_config *s = p->config_storage[i];
21136 for (j = 0; j < exts->used; j++) {
21137 fcgi_extension *ex;
21140 ex = exts->exts[j];
21143 for (n = 0; n < ex->used; n++) {
21145 fcgi_extension_host *host;
21148 host = ex->hosts[n];
21151 for (proc = host->first; proc; proc = proc->next) {
21152 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21154 - if (proc->is_local &&
21156 + if (proc->is_local &&
21157 !buffer_is_empty(proc->unixsocket)) {
21158 unlink(proc->unixsocket->ptr);
21163 for (proc = host->unused_procs; proc; proc = proc->next) {
21164 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21166 - if (proc->is_local &&
21168 + if (proc->is_local &&
21169 !buffer_is_empty(proc->unixsocket)) {
21170 unlink(proc->unixsocket->ptr);
21177 fastcgi_extensions_free(s->exts);
21178 array_free(s->ext_mapping);
21183 free(p->config_storage);
21190 return HANDLER_GO_ON;
21193 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
21197 if (!key || !val) return -1;
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);
21207 if (env->size == 0) {
21209 env->ptr = malloc(env->size * sizeof(*env->ptr));
21210 @@ -732,9 +734,9 @@
21212 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21216 env->ptr[env->used++] = dst;
21222 @@ -753,15 +755,15 @@
21223 if (env->size == 0) {
21225 env->ptr = malloc(env->size * sizeof(*env->ptr));
21226 - } else if (env->size == env->used) {
21227 + } else if (env->size == env->used) {
21229 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21235 env->ptr[env->used++] = start;
21238 start = b->ptr + i + 1;
21241 @@ -794,7 +796,7 @@
21245 -static int fcgi_spawn_connection(server *srv,
21246 +static int fcgi_spawn_connection(server *srv,
21248 fcgi_extension_host *host,
21250 @@ -806,31 +808,27 @@
21252 struct sockaddr_in fcgi_addr_in;
21253 struct sockaddr *fcgi_addr;
21264 if (p->conf.debug) {
21265 log_error_write(srv, __FILE__, __LINE__, "sdb",
21266 "new proc, socket:", proc->port, proc->unixsocket);
21270 if (!buffer_is_empty(proc->unixsocket)) {
21271 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
21274 #ifdef HAVE_SYS_UN_H
21275 fcgi_addr_un.sun_family = AF_UNIX;
21276 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
21280 servlen = SUN_LEN(&fcgi_addr_un);
21282 - /* stevens says: */
21283 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
21286 socket_type = AF_UNIX;
21287 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
21289 @@ -844,108 +842,108 @@
21292 fcgi_addr_in.sin_family = AF_INET;
21295 if (buffer_is_empty(host->host)) {
21296 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21298 struct hostent *he;
21301 /* set a usefull default */
21302 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
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);
21317 if (he->h_addrtype != AF_INET) {
21318 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
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);
21329 memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
21333 fcgi_addr_in.sin_port = htons(proc->port);
21334 servlen = sizeof(fcgi_addr_in);
21337 socket_type = AF_INET;
21338 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
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);
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));
21356 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
21357 /* server is not up, spawn in */
21361 - if (errno != ENOENT &&
21363 + if (errno != ENOENT &&
21364 !buffer_is_empty(proc->unixsocket)) {
21365 unlink(proc->unixsocket->ptr);
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));
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));
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,
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));
21412 switch ((child = fork())) {
21420 /* create environment */
21429 @@ -955,18 +953,18 @@
21430 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
21435 /* we don't need the client socket */
21436 for (i = 3; i < 256; i++) {
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];
21448 if (NULL != (ge = getenv(ds->value->ptr))) {
21449 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
21451 @@ -974,39 +972,39 @@
21453 for (i = 0; environ[i]; i++) {
21457 if (NULL != (eq = strchr(environ[i], '='))) {
21458 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
21464 /* create environment */
21465 for (i = 0; i < host->bin_env->used; i++) {
21466 data_string *ds = (data_string *)host->bin_env->data[i];
21469 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
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;
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"));
21485 env.ptr[env.used] = NULL;
21487 parse_binpath(&arg, host->bin_path);
21490 /* chdir into the base of the bin-path,
21491 * search for the last / */
21492 if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
21496 /* change to the physical directory */
21497 if (-1 == chdir(arg.ptr[0])) {
21499 @@ -1018,12 +1016,12 @@
21502 execve(arg.ptr[0], arg.ptr, env.ptr);
21504 - log_error_write(srv, __FILE__, __LINE__, "sbs",
21506 + log_error_write(srv, __FILE__, __LINE__, "sbs",
21507 "execve failed for:", host->bin_path, strerror(errno));
21516 @@ -1031,17 +1029,17 @@
21523 select(0, NULL, NULL, NULL, &tv);
21526 switch (waitpid(child, &status, WNOHANG)) {
21528 /* child still running after timeout, good */
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));
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:",
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.");
21566 - log_error_write(srv, __FILE__, __LINE__, "sd",
21567 - "child died somehow:",
21568 + log_error_write(srv, __FILE__, __LINE__, "sd",
21569 + "child died somehow:",
21573 @@ -1082,26 +1080,26 @@
21575 proc->last_used = srv->cur_ts;
21576 proc->is_local = 1;
21583 proc->is_local = 0;
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);
21595 proc->state = PROC_STATE_RUNNING;
21596 host->active_procs++;
21605 @@ -1111,93 +1109,93 @@
21608 buffer *fcgi_mode = buffer_init();
21610 - config_values_t cv[] = {
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 }
21620 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21623 for (i = 0; i < srv->config_context->used; i++) {
21628 s = malloc(sizeof(plugin_config));
21629 s->exts = fastcgi_extensions_init();
21631 s->ext_mapping = array_init();
21634 cv[0].destination = s->exts;
21635 cv[1].destination = &(s->debug);
21636 cv[2].destination = s->ext_mapping;
21639 p->config_storage[i] = s;
21640 ca = ((data_config *)srv->config_context->data[i])->value;
21643 if (0 != config_insert_values_global(srv, ca, cv)) {
21644 return HANDLER_ERROR;
21654 if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
21656 data_array *da = (data_array *)du;
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");
21665 return HANDLER_ERROR;
21670 - * fastcgi.server = ( "<ext>" => ( ... ),
21674 + * fastcgi.server = ( "<ext>" => ( ... ),
21675 * "<ext>" => ( ... ) )
21679 for (j = 0; j < da->value->used; j++) {
21681 data_array *da_ext = (data_array *)da->value->data[j];
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)");
21692 return HANDLER_ERROR;
21696 - * da_ext->key == name of the extension
21699 + * da_ext->key == name of the extension
21703 - * fastcgi.server = ( "<ext>" =>
21704 - * ( "<host>" => ( ... ),
21707 + * fastcgi.server = ( "<ext>" =>
21708 + * ( "<host>" => ( ... ),
21709 * "<host>" => ( ... )
21716 for (n = 0; n < da_ext->value->used; n++) {
21717 data_array *da_host = (data_array *)da_ext->value->data[n];
21720 fcgi_extension_host *host;
21722 - config_values_t fcv[] = {
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 */
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 */
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 */
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 */
21750 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
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)");
21764 return HANDLER_ERROR;
21768 host = fastcgi_host_init();
21771 buffer_copy_string_buffer(host->id, da_host->key);
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 */
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;
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);
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;
21803 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
21804 return HANDLER_ERROR;
21807 - if ((!buffer_is_empty(host->host) || host->port) &&
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:",
21816 da_ext->key, " => (",
21817 da_host->key, " ( ...");
21819 return HANDLER_ERROR;
21823 if (!buffer_is_empty(host->unixsocket)) {
21824 /* unix domain socket */
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:",
21833 da_ext->key, " => (",
21834 da_host->key, " ( ...");
21836 @@ -1288,37 +1286,37 @@
21841 - if (buffer_is_empty(host->host) &&
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:",
21850 da_ext->key, " => (",
21851 da_host->key, " ( ...");
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:",
21861 da_ext->key, " => (",
21862 da_host->key, " ( ...");
21864 return HANDLER_ERROR;
21868 - if (!buffer_is_empty(host->bin_path)) {
21870 + if (!buffer_is_empty(host->bin_path)) {
21871 /* a local socket + self spawning */
21874 /* HACK: just to make sure the adaptive spawing is disabled */
21875 host->min_procs = host->max_procs;
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;
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);
21891 for (pno = 0; pno < host->min_procs; pno++) {
21894 @@ -1343,7 +1341,7 @@
21895 buffer_append_string(proc->unixsocket, "-");
21896 buffer_append_long(proc->unixsocket, pno);
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);
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 @@
21915 fastcgi_status_init(srv, p->statuskey, host, proc);
21918 proc->next = host->first;
21919 if (host->first) host->first->prev = proc;
21922 host->first = proc;
21928 proc = fastcgi_process_init();
21929 proc->id = host->num_procs++;
21931 host->active_procs++;
21932 proc->state = PROC_STATE_RUNNING;
21935 if (buffer_is_empty(host->unixsocket)) {
21936 proc->port = host->port;
21938 buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
21942 fastcgi_status_init(srv, p->statuskey, host, proc);
21944 host->first = proc;
21947 host->min_procs = 1;
21948 host->max_procs = 1;
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 @@
21961 buffer_free(fcgi_mode);
21964 return HANDLER_GO_ON;
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;
21975 @@ -1429,13 +1427,13 @@
21978 buffer_uint *r = &(p->fcgi_request_id);
21983 for (i = 0; i < r->used; i++) {
21984 if (r->ptr[i] > m) m = r->ptr[i];
21988 if (r->size == 0) {
21990 r->ptr = malloc(sizeof(*r->ptr) * r->size);
21991 @@ -1443,54 +1441,54 @@
21993 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
21997 r->ptr[r->used++] = ++m;
22003 static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
22005 buffer_uint *r = &(p->fcgi_request_id);
22010 for (i = 0; i < r->used; i++) {
22011 if (r->ptr[i] == request_id) break;
22015 if (i != r->used) {
22019 if (i != r->used - 1) {
22020 r->ptr[i] = r->ptr[r->used - 1];
22028 void fcgi_connection_close(server *srv, handler_ctx *hctx) {
22033 if (NULL == hctx) return;
22036 p = hctx->plugin_data;
22037 con = hctx->remote_conn;
22040 if (con->mode != p->id) {
22046 if (hctx->fd != -1) {
22047 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
22048 fdevent_unregister(srv->ev, hctx->fd);
22054 if (hctx->request_id != 0) {
22055 fcgi_requestid_del(srv, p, hctx->request_id);
22057 @@ -1499,7 +1497,7 @@
22058 if (hctx->got_proc) {
22059 /* after the connect the process gets a load */
22060 hctx->proc->load--;
22063 status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
22065 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
22066 @@ -1509,39 +1507,39 @@
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);
22083 handler_ctx_free(hctx);
22084 - con->plugin_ctx[p->id] = NULL;
22085 + con->plugin_ctx[p->id] = NULL;
22088 static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
22089 plugin_data *p = hctx->plugin_data;
22100 * connect was ok, connection was accepted
22101 * but the php accept loop checks after the accept if it should die or not.
22103 - * if yes we can only detect it at a write()
22106 + * if yes we can only detect it at a write()
22108 * next step is resetting this attemp and setup a connection again
22111 * if we have more then 5 reconnects for the same request, die
22118 * we have a connection but the child died by some other reason
22123 if (hctx->fd != -1) {
22124 @@ -1551,59 +1549,59 @@
22130 fcgi_requestid_del(srv, p, hctx->request_id);
22133 fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
22136 hctx->request_id = 0;
22137 hctx->reconnects++;
22140 if (p->conf.debug > 2) {
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);
22147 log_error_write(srv, __FILE__, __LINE__, "sb",
22148 - "release proc for reconnect:",
22149 + "release proc for reconnect:",
22150 hctx->host->unixsocket);
22154 - if (hctx->proc && hctx->got_proc) {
22155 + if (hctx->proc && hctx->got_proc) {
22156 hctx->proc->load--;
22159 /* perhaps another host gives us more luck */
22160 hctx->host->load--;
22168 static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
22169 plugin_data *p = p_d;
22172 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
22175 return HANDLER_GO_ON;
22179 static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
22183 if (!key || !val) return -1;
22186 len = key_len + val_len;
22189 len += key_len > 127 ? 4 : 1;
22190 len += val_len > 127 ? 4 : 1;
22193 buffer_prepare_append(env, len);
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 @@
22201 env->ptr[env->used++] = (key_len >> 0) & 0xff;
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 @@
22210 env->ptr[env->used++] = (val_len >> 0) & 0xff;
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;
22223 @@ -1639,11 +1637,11 @@
22224 header->contentLengthB1 = (contentLength >> 8) & 0xff;
22225 header->paddingLength = paddingLength;
22226 header->reserved = 0;
22237 @@ -1665,26 +1663,23 @@
22238 struct sockaddr_un fcgi_addr_un;
22243 fcgi_extension_host *host = hctx->host;
22244 fcgi_proc *proc = hctx->proc;
22245 int fcgi_fd = hctx->fd;
22248 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
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);
22258 servlen = SUN_LEN(&fcgi_addr_un);
22260 - /* stevens says: */
22261 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
22264 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
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 @@
22273 fcgi_addr_in.sin_family = AF_INET;
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");
22286 fcgi_addr_in.sin_port = htons(proc->port);
22287 servlen = sizeof(fcgi_addr_in);
22290 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
22292 if (buffer_is_empty(proc->connection_name)) {
22293 @@ -1715,20 +1712,20 @@
22294 buffer_append_long(proc->connection_name, proc->port);
22299 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
22300 - if (errno == EINPROGRESS ||
22301 + if (errno == EINPROGRESS ||
22302 errno == EALREADY ||
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);
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 @@
22321 return CONNECTION_OVERLOADED;
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);
22330 @@ -1747,7 +1744,7 @@
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);
22339 @@ -1756,21 +1753,21 @@
22341 static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
22345 for (i = 0; i < con->request.headers->used; i++) {
22349 ds = (data_string *)con->request.headers->data[i];
22352 if (ds->value->used && ds->key->used) {
22354 buffer_reset(srv->tmp_buf);
22357 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
22358 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
22359 srv->tmp_buf->used--;
22363 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22364 for (j = 0; j < ds->key->used - 1; j++) {
22366 @@ -1784,20 +1781,20 @@
22367 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22369 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22372 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22377 for (i = 0; i < con->environment->used; i++) {
22381 ds = (data_string *)con->environment->data[i];
22384 if (ds->value->used && ds->key->used) {
22386 buffer_reset(srv->tmp_buf);
22389 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22390 for (j = 0; j < ds->key->used - 1; j++) {
22392 @@ -1811,11 +1808,11 @@
22393 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22395 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22398 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22406 @@ -1824,24 +1821,24 @@
22407 FCGI_BeginRequestRecord beginRecord;
22408 FCGI_Header header;
22415 char b2[INET6_ADDRSTRLEN + 1];
22419 plugin_data *p = hctx->plugin_data;
22420 fcgi_extension_host *host= hctx->host;
22422 connection *con = hctx->remote_conn;
22423 server_socket *srv_sock = con->srv_socket;
22426 sock_addr our_addr;
22427 socklen_t our_addr_len;
22430 /* send FCGI_BEGIN_REQUEST */
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));
22439 b = chunkqueue_get_append_buffer(hctx->wb);
22442 buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
22445 /* send FCGI_PARAMS */
22446 buffer_prepare_copy(p->fcgi_env, 1024);
22449 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
22452 if (con->server_name->used) {
22453 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
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),
22463 @@ -1872,50 +1869,50 @@
22465 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
22469 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
22475 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
22477 ntohs(srv_sock->addr.ipv4.sin_port)
22482 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
22485 /* get the server-side of the connection to the client */
22486 our_addr_len = sizeof(our_addr);
22489 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
22490 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
22492 s = inet_ntop_cache_get_ip(srv, &(our_addr));
22494 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
22500 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
22502 ntohs(con->dst_addr.ipv4.sin_port)
22507 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
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));
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));
22520 if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
22521 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
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 @@
22530 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
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));
22537 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
22540 if (!buffer_is_empty(host->docroot)) {
22541 buffer_copy_string_buffer(p->path, host->docroot);
22543 @@ -1957,27 +1954,27 @@
22546 if (!buffer_is_empty(host->docroot)) {
22548 - * rewrite SCRIPT_FILENAME
22551 + * rewrite SCRIPT_FILENAME
22556 buffer_copy_string_buffer(p->path, host->docroot);
22557 buffer_append_string_buffer(p->path, con->uri.path);
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));
22563 buffer_copy_string_buffer(p->path, con->physical.path);
22565 - /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22568 + /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22570 * see src/sapi/cgi_main.c, init_request_info()
22572 if (host->break_scriptfilename_for_php) {
22573 buffer_append_string_buffer(p->path, con->request.pathinfo);
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));
22580 @@ -1987,7 +1984,7 @@
22584 - * stripping /app1 or /app1/ should lead to
22585 + * stripping /app1 or /app1/ should lead to
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 */
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));
22598 @@ -2018,26 +2015,26 @@
22600 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
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));
22612 if (srv_sock->is_ssl) {
22613 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
22620 fcgi_env_add_request_headers(srv, con, p);
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);
22628 fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
22629 buffer_append_memory(b, (const char *)&header, sizeof(header));
22631 @@ -2057,7 +2054,7 @@
22633 /* we announce toWrite octects
22634 * now take all the request_content chunk that we need to fill this request
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;
22643 if (p->conf.debug > 10) {
22644 - fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22645 - __FILE__, __LINE__,
22648 - req_c->file.length,
22649 + fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22650 + __FILE__, __LINE__,
22653 + req_c->file.length,
22654 req_c->file.name->ptr);
22657 assert(weHave != 0);
22660 chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
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
22672 @@ -2141,7 +2138,7 @@
22673 req_c->offset += weHave;
22674 req_cq->bytes_out += weHave;
22678 hctx->wb->bytes_in += weHave;
22680 if (req_c->offset == req_c->mem->used - 1) {
22681 @@ -2155,12 +2152,12 @@
22687 b->used++; /* add virtual \0 */
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) {
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] : '.');
22704 fprintf(stderr, "\n");
22712 -static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
22715 - handler_ctx *hctx = con->plugin_ctx[p->id];
22716 - fcgi_extension_host *host= hctx->host;
22720 - buffer_copy_string_buffer(p->parse_response, in);
22722 - /* search for \n */
22723 - for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
22724 - char *key, *value;
22728 - /* a good day. Someone has read the specs and is sending a \r\n to us */
22730 - if (ns > p->parse_response->ptr &&
22731 - *(ns-1) == '\r') {
22738 - if (NULL == (value = strchr(s, ':'))) {
22739 - /* we expect: "<key>: <value>\n" */
22743 - key_len = value - key;
22747 - while (*value == ' ' || *value == '\t') value++;
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 */
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();
22759 - buffer_copy_string_len(ds->key, key, key_len);
22760 - buffer_copy_string(ds->value, value);
22762 - array_insert_unique(con->response.headers, (data_unset *)ds);
22766 - switch(key_len) {
22768 - if (0 == strncasecmp(key, "Date", key_len)) {
22769 - con->parsed_response |= HTTP_DATE;
22773 - if (0 == strncasecmp(key, "Status", key_len)) {
22774 - con->http_status = strtol(value, NULL, 10);
22775 - con->parsed_response |= HTTP_STATUS;
22779 - if (0 == strncasecmp(key, "Location", key_len)) {
22780 - con->parsed_response |= HTTP_LOCATION;
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;
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;
22794 - if (con->response.content_length < 0) con->response.content_length = 0;
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;
22817 @@ -2327,9 +2225,9 @@
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);
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;
22832 if (weHave > weWant) weHave = weWant;
22835 buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
22837 /* we only skipped the first 8 bytes as they are the fcgi header */
22838 @@ -2380,65 +2278,37 @@
22841 chunkqueue_remove_finished_chunks(hctx->rb);
22847 static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
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;
22860 - * check how much we have to read
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):",
22869 - /* init read-buffer */
22871 - if (toread > 0) {
22874 - b = chunkqueue_get_append_buffer(hctx->rb);
22875 - buffer_prepare_copy(b, toread + 1);
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));
22885 - /* this should be catched by the b > 0 above */
22888 - b->used = r + 1; /* one extra for the fake \0 */
22889 - b->ptr[b->used - 1] = '\0';
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):",
22898 "socket:", proc->connection_name);
22901 + case NETWORK_STATUS_SUCCESS:
22904 + log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
22909 * parse the fastcgi packets and forward the content to the write-queue
22914 fastcgi_response_packet packet;
22916 @@ -2454,92 +2324,135 @@
22918 /* is the header already finished */
22919 if (0 == con->file_started) {
22924 - /* search for header terminator
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
22932 - if (hctx->response_header->used == 0) {
22933 - buffer_copy_string_buffer(hctx->response_header, packet.b);
22935 - buffer_append_string_buffer(hctx->response_header, packet.b);
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 */
22947 - /* no luck, no header found */
22948 + int have_content_length = 0;
22949 + int need_more = 0;
22952 + /* append the current packet to the chunk queue */
22953 + chunkqueue_append_buffer(hctx->http_rb, packet.b);
22954 + http_response_reset(p->resp);
22956 + switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
22957 + case PARSE_ERROR:
22958 + /* parsing the response header failed */
22960 + con->http_status = 502; /* Bad Gateway */
22963 + case PARSE_NEED_MORE:
22965 + break; /* leave the loop */
22966 + case PARSE_SUCCESS:
22969 + /* should not happen */
22973 - /* parse the response header */
22974 - fcgi_response_parse(srv, con, p, hctx->response_header);
22975 + if (need_more) break;
22977 - con->file_started = 1;
22978 + chunkqueue_remove_finished_chunks(hctx->http_rb);
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;
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;
22991 - if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
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;
22999 + /* handle the header fields */
23000 + if (host->mode == FCGI_AUTHORIZER) {
23001 + /* auth mode is a bit different */
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;
23010 + /* copy the http-headers */
23011 + for (i = 0; i < p->resp->headers->used; i++) {
23012 + const char *ign[] = { "Status", NULL };
23016 + data_string *header = (data_string *)p->resp->headers->data[i];
23018 + /* ignore all headers in AUTHORIZER mode */
23019 + if (host->mode == FCGI_AUTHORIZER) continue;
23021 + /* some headers are ignored by default */
23022 + for (j = 0; ign[j]; j++) {
23023 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
23025 + if (ign[j]) continue;
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"))) {
23035 + stat_cache_entry *sce;
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 */
23044 + joblist_append(srv, con);
23047 + continue; /* ignore header */
23050 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
23051 + ds = data_response_init();
23053 + buffer_copy_string_buffer(ds->key, header->key);
23054 + buffer_copy_string_buffer(ds->value, header->value);
23056 + array_insert_unique(con->response.headers, (data_unset *)ds);
23059 + /* header is complete ... go on with the body */
23061 + con->file_started = 1;
23063 + if (hctx->send_content_body) {
23064 + chunk *c = hctx->http_rb->first;
23066 + /* if we don't have a content-length enable chunked encoding
23069 + * TODO: move this to a later stage in the filter-queue
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;
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;
23085 + chunkqueue_remove_finished_chunks(hctx->http_rb);
23086 joblist_append(srv, con);
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;
23095 http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
23096 joblist_append(srv, con);
23100 - log_error_write(srv, __FILE__, __LINE__, "sb",
23101 + log_error_write(srv, __FILE__, __LINE__, "sb",
23102 "FastCGI-stderr:", packet.b);
23106 case FCGI_END_REQUEST:
23107 con->file_finished = 1;
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);
23122 - log_error_write(srv, __FILE__, __LINE__, "sd",
23123 + log_error_write(srv, __FILE__, __LINE__, "sd",
23124 "FastCGI: header.type not handled: ", packet.type);
23127 buffer_free(packet.b);
23134 static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
23138 for (proc = host->first; proc; proc = proc->next) {
23141 if (p->conf.debug > 2) {
23142 - log_error_write(srv, __FILE__, __LINE__, "sbdddd",
23144 + log_error_write(srv, __FILE__, __LINE__, "sbdddd",
23146 proc->connection_name,
23156 * if the remote side is overloaded, we check back after <n> seconds
23160 switch (proc->state) {
23161 case PROC_STATE_KILLED:
23162 @@ -2592,13 +2505,13 @@
23164 case PROC_STATE_OVERLOADED:
23165 if (srv->cur_ts <= proc->disabled_until) break;
23168 proc->state = PROC_STATE_RUNNING;
23169 host->active_procs++;
23171 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
23172 - "fcgi-server re-enabled:",
23173 - host->host, host->port,
23175 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
23176 + "fcgi-server re-enabled:",
23177 + host->host, host->port,
23180 case PROC_STATE_DIED_WAIT_FOR_PID:
23181 @@ -2606,7 +2519,7 @@
23182 if (!proc->is_local) break;
23184 /* the child should not terminate at all */
23187 switch(waitpid(proc->pid, &status, WNOHANG)) {
23189 /* child is still alive */
23190 @@ -2616,45 +2529,45 @@
23192 if (WIFEXITED(status)) {
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));
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:",
23206 - log_error_write(srv, __FILE__, __LINE__, "sd",
23207 - "child died somehow:",
23208 + log_error_write(srv, __FILE__, __LINE__, "sd",
23209 + "child died somehow:",
23214 proc->state = PROC_STATE_DIED;
23219 /* fall through if we have a dead proc now */
23220 if (proc->state != PROC_STATE_DIED) break;
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 */
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;
23234 /* restart the child */
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);
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 @@
23251 if (srv->cur_ts <= proc->disabled_until) break;
23254 proc->state = PROC_STATE_RUNNING;
23255 host->active_procs++;
23257 - log_error_write(srv, __FILE__, __LINE__, "sb",
23258 - "fcgi-server re-enabled:",
23260 + log_error_write(srv, __FILE__, __LINE__, "sb",
23261 + "fcgi-server re-enabled:",
23262 proc->connection_name);
23272 @@ -2682,19 +2595,19 @@
23273 fcgi_extension_host *host= hctx->host;
23274 connection *con = hctx->remote_conn;
23280 - /* sanity check */
23281 + /* sanity check */
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",
23290 host->unixsocket->used);
23293 hctx->proc->disabled_until = srv->cur_ts + 10;
23294 hctx->proc->state = PROC_STATE_DIED;
23296 @@ -2705,12 +2618,12 @@
23297 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23299 socklen_t socket_error_len = sizeof(socket_error);
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));
23309 hctx->proc->disabled_until = srv->cur_ts + 10;
23310 hctx->proc->state = PROC_STATE_DIED;
23312 @@ -2719,12 +2632,12 @@
23313 if (socket_error != 0) {
23314 if (!hctx->proc->is_local || p->conf.debug) {
23315 /* local procs get restarted */
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);
23325 hctx->proc->disabled_until = srv->cur_ts + 5;
23327 if (hctx->proc->is_local) {
23328 @@ -2732,17 +2645,17 @@
23330 hctx->proc->state = PROC_STATE_DIED;
23334 hctx->proc->state = PROC_STATE_DIED;
23337 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23338 buffer_append_string(p->statuskey, ".died");
23340 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23343 return HANDLER_ERROR;
23345 - /* go on with preparing the request */
23346 + /* go on with preparing the request */
23347 hctx->state = FCGI_STATE_PREPARE_WRITE;
23350 @@ -2755,14 +2668,14 @@
23351 /* do we have a running process for this host (max-procs) ? */
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);
23361 /* all childs are dead */
23362 if (proc == NULL) {
23363 hctx->fde_ndx = -1;
23366 return HANDLER_ERROR;
23369 @@ -2775,50 +2688,50 @@
23372 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
23375 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
23376 if (errno == EMFILE ||
23378 - log_error_write(srv, __FILE__, __LINE__, "sd",
23379 + log_error_write(srv, __FILE__, __LINE__, "sd",
23380 "wait for fd at connection:", con->fd);
23383 return HANDLER_WAIT_FOR_FD;
23386 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
23388 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
23389 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
23390 return HANDLER_ERROR;
23392 hctx->fde_ndx = -1;
23398 fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
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));
23407 return HANDLER_ERROR;
23411 if (hctx->proc->is_local) {
23412 hctx->pid = hctx->proc->pid;
23416 switch (fcgi_establish_connection(srv, hctx)) {
23417 case CONNECTION_DELAYED:
23418 /* connection is in progress, wait for an event and call getsockopt() below */
23421 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
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
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");
23438 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23441 return HANDLER_ERROR;
23442 case CONNECTION_DEAD:
23443 /* we got a hard error from the backend like
23444 @@ -2840,19 +2753,19 @@
23446 * for check if the host is back in 5 seconds
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;
23454 hctx->proc->state = PROC_STATE_DIED;
23457 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
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);
23465 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23466 buffer_append_string(p->statuskey, ".died");
23468 @@ -2863,19 +2776,19 @@
23469 /* everything is ok, go on */
23471 fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
23475 case CONNECTION_UNSET:
23480 case FCGI_STATE_PREPARE_WRITE:
23481 /* ok, we have the connection */
23484 hctx->proc->load++;
23485 hctx->proc->last_used = srv->cur_ts;
23486 hctx->got_proc = 1;
23489 status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
23490 status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
23492 @@ -2898,9 +2811,9 @@
23494 if (p->conf.debug) {
23495 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
23497 - "pid:", hctx->proc->pid,
23498 - "socket:", hctx->proc->connection_name,
23500 + "pid:", hctx->proc->pid,
23501 + "socket:", hctx->proc->connection_name,
23502 "load:", hctx->proc->load);
23505 @@ -2908,62 +2821,63 @@
23506 if (hctx->request_id == 0) {
23507 hctx->request_id = fcgi_requestid_new(srv, p);
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);
23516 fcgi_create_env(srv, hctx, hctx->request_id);
23519 fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
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);
23527 chunkqueue_remove_finished_chunks(hctx->wb);
23533 - /* the connection got dropped after accept()
23535 - * this is most of the time a PHP which dies
23536 + /* the connection got dropped after accept()
23538 + * this is most of the time a PHP which dies
23539 * after PHP_FCGI_MAX_REQUESTS
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
23549 + usleep(10000); /* take away the load of the webserver
23550 + * to let the php a chance to restart
23554 fcgi_reconnect(srv, hctx);
23557 return HANDLER_WAIT_FOR_FD;
23561 /* not reconnected ... why
23564 * far@#lighttpd report this for FreeBSD
23569 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
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);
23577 return HANDLER_ERROR;
23580 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23583 return HANDLER_WAIT_FOR_EVENT;
23585 - log_error_write(srv, __FILE__, __LINE__, "ssd",
23586 + log_error_write(srv, __FILE__, __LINE__, "ssd",
23587 "write failed:", strerror(errno), errno);
23590 return HANDLER_ERROR;
23593 @@ -2975,7 +2889,7 @@
23594 fcgi_set_state(srv, hctx, FCGI_STATE_READ);
23596 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23599 return HANDLER_WAIT_FOR_EVENT;
23602 @@ -2987,7 +2901,7 @@
23603 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
23604 return HANDLER_ERROR;
23608 return HANDLER_WAIT_FOR_EVENT;
23611 @@ -2996,18 +2910,18 @@
23613 SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
23614 plugin_data *p = p_d;
23617 handler_ctx *hctx = con->plugin_ctx[p->id];
23619 fcgi_extension_host *host;
23622 if (NULL == hctx) return HANDLER_GO_ON;
23626 if (con->mode != p->id) return HANDLER_GO_ON;
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) {
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];
23640 /* we should have at least one proc that can do something */
23641 if (host->active_procs == 0) continue;
23643 if (used == -1 || host->load < used) {
23652 /* found a server */
23654 /* all hosts are down */
23656 fcgi_connection_close(srv, hctx);
23659 con->http_status = 500;
23660 con->mode = DIRECT;
23662 @@ -3040,16 +2954,16 @@
23665 host = hctx->ext->hosts[ndx];
23668 - * if check-local is disabled, use the uri.path handler
23672 + * if check-local is disabled, use the uri.path handler
23677 /* init handler-context */
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
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:
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;
23697 fcgi_connection_close(srv, hctx);
23700 buffer_reset(con->physical.path);
23701 con->mode = DIRECT;
23702 con->http_status = 500;
23703 @@ -3088,12 +3002,12 @@
23706 fcgi_connection_close(srv, hctx);
23709 buffer_reset(con->physical.path);
23710 con->mode = DIRECT;
23711 con->http_status = 503;
23712 joblist_append(srv, con); /* really ? */
23715 return HANDLER_FINISHED;
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;
23724 fcgi_proc *proc = hctx->proc;
23725 fcgi_extension_host *host= hctx->host;
23727 @@ -3125,8 +3039,8 @@
23732 - if (host->mode == FCGI_AUTHORIZER &&
23734 + if (host->mode == FCGI_AUTHORIZER &&
23735 (con->http_status == 200 ||
23736 con->http_status == 0)) {
23738 @@ -3136,26 +3050,26 @@
23741 buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
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);
23749 con->mode = DIRECT;
23750 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
23753 fcgi_connection_close(srv, hctx);
23757 joblist_append(srv, con);
23758 return HANDLER_FINISHED;
23760 if (proc->pid && proc->state != PROC_STATE_DIED) {
23764 /* only fetch the zombie if it is not already done */
23767 switch(waitpid(proc->pid, &status, WNOHANG)) {
23769 /* child is still alive */
23770 @@ -3165,60 +3079,61 @@
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:",
23785 - log_error_write(srv, __FILE__, __LINE__, "sd",
23786 - "child died somehow:",
23787 + log_error_write(srv, __FILE__, __LINE__, "sd",
23788 + "child died somehow:",
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);
23801 if (fcgi_spawn_connection(srv, p, host, proc)) {
23802 /* respawning failed, retry later */
23803 proc->state = PROC_STATE_DIED;
23805 - log_error_write(srv, __FILE__, __LINE__, "s",
23806 + log_error_write(srv, __FILE__, __LINE__, "s",
23807 "respawning failed, will retry later");
23816 if (con->file_started == 0) {
23817 /* nothing has been send out yet, try to use another child */
23820 if (hctx->wb->bytes_out == 0 &&
23821 hctx->reconnects < 5) {
23822 fcgi_reconnect(srv, hctx);
23824 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
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");
23833 return HANDLER_WAIT_FOR_FD;
23836 - log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
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");
23845 fcgi_connection_close(srv, hctx);
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 @@
23853 /* response might have been already started, kill the connection */
23854 fcgi_connection_close(srv, hctx);
23856 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
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");
23865 connection_set_state(srv, con, CON_STATE_ERROR);
23873 joblist_append(srv, con);
23874 return HANDLER_FINISHED;
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
23885 * 1. in a unfinished connect() call
23886 * 2. in a unfinished write() call (long POST request)
23888 return mod_fastcgi_handle_subrequest(srv, con, p);
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:",
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 ?)
23904 - * if we are in connect we might get a EINPROGRESS
23905 - * in the first call and a FDEVENT_HUP in the
23907 + * if we are in connect we might get a EINPROGRESS
23908 + * in the first call and a FDEVENT_HUP in the
23912 * FIXME: as it is a bit ugly.
23916 return mod_fastcgi_handle_subrequest(srv, con, p);
23917 } else if (hctx->state == FCGI_STATE_READ &&
23918 hctx->proc->port == 0) {
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
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",
23931 - "(no fastcgi process on host:",
23932 + "(no fastcgi process on host:",
23941 connection_set_state(srv, con, CON_STATE_ERROR);
23942 fcgi_connection_close(srv, hctx);
23943 joblist_append(srv, con);
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 */
23951 @@ -3304,45 +3219,42 @@
23952 fcgi_connection_close(srv, hctx);
23953 joblist_append(srv, con);
23957 return HANDLER_FINISHED;
23959 -#define PATCH(x) \
23960 - p->conf.x = s->x;
23962 static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
23964 plugin_config *s = p->config_storage[0];
23968 - PATCH(ext_mapping);
23971 + PATCH_OPTION(exts);
23972 + PATCH_OPTION(debug);
23973 + PATCH_OPTION(ext_mapping);
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];
23981 /* condition didn't match */
23982 if (!config_check_cond(srv, con, dc)) continue;
23986 for (j = 0; j < dc->value->used; j++) {
23987 data_unset *du = dc->value->data[j];
23990 if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
23992 + PATCH_OPTION(exts);
23993 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.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);
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 @@
24013 fcgi_extension *extension = NULL;
24014 fcgi_extension_host *host = NULL;
24017 /* Possibly, we processed already this request */
24018 if (con->file_started == 1) return HANDLER_GO_ON;
24020 fn = uri_path_handler ? con->uri.path : con->physical.path;
24022 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
24025 s_len = fn->used - 1;
24028 fcgi_patch_connection(srv, con, p);
24030 /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
24031 @@ -3368,24 +3280,24 @@
24032 * fastcgi.map-extensions = ( ".php3" => ".php" )
24034 * fastcgi.server = ( ".php" => ... )
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 */
24045 if (ds->key->used == 0) continue;
24048 ct_len = ds->key->used - 1;
24051 if (s_len < ct_len) continue;
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 */
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 */
24068 extension = p->conf.exts->exts[k];
24071 if (extension->key->used == 0) continue;
24074 ct_len = extension->key->used - 1;
24077 if (s_len < ct_len) continue;
24080 /* check extension in the form "/fcgi_pattern" */
24081 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
24083 @@ -3441,10 +3353,10 @@
24087 - /* we found one host that is alive */
24088 + /* we found one host that is alive */
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,
24102 return HANDLER_FINISHED;
24105 /* a note about no handler is not sent yey */
24106 extension->note_is_sent = 0;
24109 - * if check-local is disabled, use the uri.path handler
24112 + * if check-local is disabled, use the uri.path handler
24117 /* init handler-context */
24118 if (uri_path_handler) {
24119 if (host->check_local == 0) {
24124 hctx = handler_ctx_init();
24127 hctx->remote_conn = con;
24128 hctx->plugin_data = p;
24130 hctx->ext = extension;
24134 hctx->conf.exts = p->conf.exts;
24135 hctx->conf.debug = p->conf.debug;
24138 con->plugin_ctx[p->id] = hctx;
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");
24150 - /* the prefix is the SCRIPT_NAME,
24152 + /* the prefix is the SCRIPT_NAME,
24153 * everthing from start to the next slash
24154 * this is important for check-local = "disable"
24157 * if prefix = /admin.fcgi
24160 * /admin.fcgi/foo/bar
24163 * SCRIPT_NAME = /admin.fcgi
24164 * PATH_INFO = /foo/bar
24167 * if prefix = /fcgi-bin/
24170 * /fcgi-bin/foo/bar
24173 * SCRIPT_NAME = /fcgi-bin/foo
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 */
24186 + /* rewrite uri.path and pathinfo */
24188 buffer_copy_string(con->request.pathinfo, pathinfo);
24191 con->uri.path->used -= con->request.pathinfo->used - 1;
24192 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
24194 @@ -3532,19 +3444,19 @@
24197 hctx = handler_ctx_init();
24200 hctx->remote_conn = con;
24201 hctx->plugin_data = p;
24203 hctx->ext = extension;
24206 hctx->conf.exts = p->conf.exts;
24207 hctx->conf.debug = p->conf.debug;
24210 con->plugin_ctx[p->id] = hctx;
24216 if (con->conf.log_request_handling) {
24217 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
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];
24225 if (hctx == NULL) return HANDLER_GO_ON;
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);
24234 case FCGI_STATE_CONNECT_DELAYED:
24235 case FCGI_STATE_WRITE:
24236 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24240 case FCGI_STATE_INIT:
24242 @@ -3595,7 +3507,7 @@
24244 static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
24245 plugin_data *p = p_d;
24248 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
24250 return HANDLER_GO_ON;
24251 @@ -3604,16 +3516,39 @@
24252 TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
24253 plugin_data *p = p_d;
24259 /* perhaps we should kill a connect attempt after 10-15 seconds
24262 * currently we wait for the TCP timeout which is on Linux 180 seconds
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];
24273 + /* if a connection is ours and is in handle-req for more than max-request-time
24274 + * kill the connection */
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;
24280 + /* the request is waiting for a FCGI_STDOUT since 60 seconds */
24282 + /* kill the connection */
24284 + log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
24286 + fcgi_connection_close(srv, hctx);
24288 + con->mode = DIRECT;
24289 + con->http_status = 500;
24291 + joblist_append(srv, con);
24294 /* check all childs if they are still up */
24296 for (i = 0; i < srv->config_context->used; i++) {
24297 @@ -3628,45 +3563,45 @@
24298 fcgi_extension *ex;
24300 ex = exts->exts[j];
24303 for (n = 0; n < ex->used; n++) {
24307 unsigned long sum_load = 0;
24308 fcgi_extension_host *host;
24311 host = ex->hosts[n];
24314 fcgi_restart_dead_procs(srv, p, host);
24317 for (proc = host->first; proc; proc = proc->next) {
24318 sum_load += proc->load;
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");
24333 for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
24337 if (proc == host->unused_procs) host->unused_procs = proc->next;
24340 if (proc->next) proc->next->prev = NULL;
24345 proc = fastcgi_process_init();
24346 proc->id = host->max_id++;
24353 if (buffer_is_empty(host->unixsocket)) {
24354 proc->port = host->port + proc->id;
24356 @@ -3674,13 +3609,13 @@
24357 buffer_append_string(proc->unixsocket, "-");
24358 buffer_append_long(proc->unixsocket, proc->id);
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;
24370 proc->next = host->first;
24372 @@ -3688,56 +3623,56 @@
24374 host->first = proc;
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;
24384 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
24385 /* a proc is idling for a long time now,
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,
24402 if (proc->next) proc->next->prev = proc->prev;
24403 if (proc->prev) proc->prev->next = proc->next;
24406 if (proc->prev == NULL) host->first = proc->next;
24410 proc->next = host->unused_procs;
24413 if (host->unused_procs) host->unused_procs->prev = proc;
24414 host->unused_procs = proc;
24417 kill(proc->pid, SIGTERM);
24420 proc->state = PROC_STATE_KILLED;
24422 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24424 - "socket:", proc->connection_name,
24426 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24428 + "socket:", proc->connection_name,
24435 /* proc is now in unused, let the next second handle the next process */
24442 for (proc = host->unused_procs; proc; proc = proc->next) {
24446 if (proc->pid == 0) continue;
24449 switch (waitpid(proc->pid, &status, WNOHANG)) {
24451 /* child still running after timeout, good */
24452 @@ -3745,10 +3680,10 @@
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));
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",
24471 + log_error_write(srv, __FILE__, __LINE__, "sdb",
24473 WEXITSTATUS(status), proc->connection_name);
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:",
24484 - log_error_write(srv, __FILE__, __LINE__, "sd",
24485 - "child died somehow:",
24486 + log_error_write(srv, __FILE__, __LINE__, "sd",
24487 + "child died somehow:",
24491 proc->state = PROC_STATE_UNSET;
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;
24509 --- ../lighttpd-1.4.11/src/mod_flv_streaming.c 2006-03-07 14:06:26.000000000 +0200
24510 +++ lighttpd-1.4.12/src/mod_flv_streaming.c 2006-07-11 22:07:52.000000000 +0300
24511 @@ -23,35 +23,35 @@
24521 plugin_config **config_storage;
24523 - plugin_config conf;
24525 + plugin_config conf;
24528 /* init the plugin data */
24529 INIT_FUNC(mod_flv_streaming_init) {
24533 p = calloc(1, sizeof(*p));
24536 p->query_str = buffer_init();
24537 p->get_params = array_init();
24543 /* detroy the plugin data */
24544 FREE_FUNC(mod_flv_streaming_free) {
24545 plugin_data *p = p_d;
24550 if (!p) return HANDLER_GO_ON;
24553 if (p->config_storage) {
24556 @@ -59,19 +59,19 @@
24557 plugin_config *s = p->config_storage[i];
24562 array_free(s->extensions);
24567 free(p->config_storage);
24571 buffer_free(p->query_str);
24572 array_free(p->get_params);
24578 return HANDLER_GO_ON;
24581 @@ -80,83 +80,80 @@
24582 SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
24583 plugin_data *p = p_d;
24586 - config_values_t cv[] = {
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 }
24594 if (!p) return HANDLER_ERROR;
24597 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24600 for (i = 0; i < srv->config_context->used; i++) {
24604 s = calloc(1, sizeof(plugin_config));
24605 s->extensions = array_init();
24608 cv[0].destination = s->extensions;
24611 p->config_storage[i] = s;
24614 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24615 return HANDLER_ERROR;
24620 return HANDLER_GO_ON;
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) {
24627 plugin_config *s = p->config_storage[0];
24629 - PATCH(extensions);
24632 + PATCH_OPTION(extensions);
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];
24640 /* condition didn't match */
24641 if (!config_check_cond(srv, con, dc)) continue;
24645 for (j = 0; j < dc->value->used; j++) {
24646 data_unset *du = dc->value->data[j];
24649 if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
24650 - PATCH(extensions);
24651 + PATCH_OPTION(extensions);
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) {
24665 char *key = NULL, *val = NULL;
24671 /* we need the \0 */
24672 for (i = 0; i < qrystr->used; i++) {
24673 switch(qrystr->ptr[i]) {
24676 val = qrystr->ptr + i + 1;
24679 qrystr->ptr[i] = '\0';
24688 case '\0': /* fin symbol */
24689 @@ -167,7 +164,7 @@
24690 /* terminate the value */
24691 qrystr->ptr[i] = '\0';
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();
24697 buffer_copy_string_len(ds->key, key, strlen(key));
24698 @@ -175,14 +172,14 @@
24700 array_insert_unique(get_params, (data_unset *)ds);
24704 key = qrystr->ptr + i + 1;
24715 @@ -190,34 +187,34 @@
24716 plugin_data *p = p_d;
24723 if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
24726 mod_flv_streaming_patch_connection(srv, con, p);
24728 s_len = con->physical.path->used - 1;
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;
24736 if (ct_len > s_len) continue;
24737 if (ds->value->used == 0) continue;
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;
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 */
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);
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;
24764 return HANDLER_GO_ON;
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");
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;
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
24787 #include "stat_cache.h"
24789 +#include "sys-strings.h"
24790 +#include "sys-files.h"
24791 /* plugin config for all request/connections */
24794 @@ -20,51 +22,51 @@
24803 plugin_config **config_storage;
24805 - plugin_config conf;
24807 + plugin_config conf;
24810 /* init the plugin data */
24811 INIT_FUNC(mod_indexfile_init) {
24815 p = calloc(1, sizeof(*p));
24818 p->tmp_buf = buffer_init();
24824 /* detroy the plugin data */
24825 FREE_FUNC(mod_indexfile_free) {
24826 plugin_data *p = p_d;
24831 if (!p) return HANDLER_GO_ON;
24834 if (p->config_storage) {
24836 for (i = 0; i < srv->config_context->used; i++) {
24837 plugin_config *s = p->config_storage[i];
24842 array_free(s->indexfiles);
24847 free(p->config_storage);
24851 buffer_free(p->tmp_buf);
24857 return HANDLER_GO_ON;
24860 @@ -73,131 +75,139 @@
24861 SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
24862 plugin_data *p = p_d;
24865 - config_values_t cv[] = {
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 }
24874 if (!p) return HANDLER_ERROR;
24877 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24880 for (i = 0; i < srv->config_context->used; i++) {
24884 s = calloc(1, sizeof(plugin_config));
24885 s->indexfiles = array_init();
24888 cv[0].destination = s->indexfiles;
24889 cv[1].destination = s->indexfiles; /* old name for [0] */
24892 p->config_storage[i] = s;
24895 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24896 return HANDLER_ERROR;
24901 return HANDLER_GO_ON;
24904 -#define PATCH(x) \
24905 - p->conf.x = s->x;
24906 static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
24908 plugin_config *s = p->config_storage[0];
24910 - PATCH(indexfiles);
24913 + PATCH_OPTION(indexfiles);
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];
24921 /* condition didn't match */
24922 if (!config_check_cond(srv, con, dc)) continue;
24926 for (j = 0; j < dc->value->used; j++) {
24927 data_unset *du = dc->value->data[j];
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);
24945 URIHANDLER_FUNC(mod_indexfile_subrequest) {
24946 plugin_data *p = p_d;
24948 stat_cache_entry *sce = NULL;
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;
24955 mod_indexfile_patch_connection(srv, con, p);
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;
24963 + if (!S_ISDIR(sce->st.st_mode)) {
24964 + return HANDLER_GO_ON;
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);
24975 for (k = 0; k < p->conf.indexfiles->used; k++) {
24976 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
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);
24985 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
24986 + PATHNAME_APPEND_SLASH(p->tmp_buf);
24988 buffer_append_string_buffer(p->tmp_buf, ds->value);
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);
24997 return HANDLER_FINISHED;
25001 if (errno != ENOENT &&
25002 errno != ENOTDIR) {
25003 /* we have no idea what happend. let's tell the user so. */
25006 con->http_status = 500;
25009 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
25010 "file not found ... or so: ", strerror(errno),
25012 "->", con->physical.path);
25015 buffer_reset(con->physical.path);
25018 return HANDLER_FINISHED;
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);
25029 /* fce is already set up a few lines above */
25032 return HANDLER_GO_ON;
25037 return HANDLER_GO_ON;
25039 @@ -207,13 +217,13 @@
25040 int mod_indexfile_plugin_init(plugin *p) {
25041 p->version = LIGHTTPD_VERSION_ID;
25042 p->name = buffer_init_string("indexfile");
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;
25056 --- ../lighttpd-1.4.11/src/mod_mysql_vhost.c 2006-01-14 20:35:10.000000000 +0200
25057 +++ lighttpd-1.4.12/src/mod_mysql_vhost.c 2006-07-11 22:07:52.000000000 +0300
25059 -#include <unistd.h>
25063 -#include <strings.h>
25064 +#include <string.h>
25066 #ifdef HAVE_CONFIG_H
25067 #include "config.h"
25070 +#ifdef HAVE_MYSQL_H
25071 +# ifdef HAVE_LIBMYSQL
25072 +# define HAVE_MYSQL
25079 @@ -16,61 +21,40 @@
25082 #include "stat_cache.h"
25083 -#ifdef DEBUG_MOD_MYSQL_VHOST
25086 +#include "sys-files.h"
25089 - * Plugin for lighttpd to use MySQL
25090 - * for domain to directory lookups,
25091 - * i.e virtual hosts (vhosts).
25093 - * Optionally sets fcgi_offset and fcgi_arg
25094 - * in preparation for fcgi.c to handle
25095 - * per-user fcgi chroot jails.
25097 - * /ada@riksnet.se 2004-12-06
25099 +#include "mod_sql_vhost_core.h"
25103 +#define CORE_PLUGIN "mod_sql_vhost_core"
25113 - buffer *hostname;
25114 - unsigned short port;
25118 buffer *mysql_post;
25120 + mod_sql_vhost_core_plugin_config *core;
25123 /* global plugin data */
25131 plugin_config **config_storage;
25133 - plugin_config conf;
25135 + plugin_config conf;
25138 -/* per connection plugin data */
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);
25147 /* init the plugin data */
25148 INIT_FUNC(mod_mysql_vhost_init) {
25152 p = calloc(1, sizeof(*p));
25154 p->tmp_buf = buffer_init();
25155 @@ -83,144 +67,77 @@
25156 plugin_data *p = p_d;
25161 - log_error_write(srv, __FILE__, __LINE__, "ss",
25162 - "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
25165 if (!p) return HANDLER_GO_ON;
25168 if (p->config_storage) {
25170 for (i = 0; i < srv->config_context->used; i++) {
25171 plugin_config *s = p->config_storage[i];
25176 mysql_close(s->mysql);
25178 - buffer_free(s->mydb);
25179 - buffer_free(s->myuser);
25180 - buffer_free(s->mypass);
25181 - buffer_free(s->mysock);
25183 buffer_free(s->mysql_pre);
25184 buffer_free(s->mysql_post);
25189 free(p->config_storage);
25191 buffer_free(p->tmp_buf);
25195 - return HANDLER_GO_ON;
25198 -/* handle the plugin per connection data */
25199 -static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
25201 - plugin_data *p = p_d;
25202 - plugin_connection_data *c = con->plugin_ctx[p->id];
25207 - log_error_write(srv, __FILE__, __LINE__, "ss",
25208 - "mod_mysql_connection_data", c ? "old" : "NEW");
25212 - c = calloc(1, sizeof(*c));
25214 - c->server_name = buffer_init();
25215 - c->document_root = buffer_init();
25216 - c->fcgi_arg = buffer_init();
25217 - c->fcgi_offset = 0;
25219 - return con->plugin_ctx[p->id] = c;
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];
25230 - log_error_write(srv, __FILE__, __LINE__, "ss",
25231 - "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
25234 - if (!c) return HANDLER_GO_ON;
25236 - buffer_free(c->server_name);
25237 - buffer_free(c->document_root);
25238 - buffer_free(c->fcgi_arg);
25239 - c->fcgi_offset = 0;
25244 - con->plugin_ctx[p->id] = NULL;
25245 return HANDLER_GO_ON;
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;
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 }
25267 + /* our very own plugin storage, one entry for each conditional
25269 + * srv->config_context->used is the number of conditionals
25271 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25274 + /* get the config of the core-plugin */
25275 + core_config = plugin_get_config(srv, CORE_PLUGIN);
25278 + /* walk through all conditionals and check for assignments */
25279 for (i = 0; i < srv->config_context->used; i++) {
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();
25297 + s->core = core_config->config_storage[i];
25301 s->mysql_pre = buffer_init();
25302 s->mysql_post = buffer_init();
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);
25313 p->config_storage[i] = s;
25315 - if (config_insert_values_global(srv,
25316 - ((data_config *)srv->config_context->data[i])->value,
25317 - cv)) return HANDLER_ERROR;
25319 - s->mysql_pre = buffer_init();
25320 - s->mysql_post = buffer_init();
25323 + /* check if we are the plugin for this backend */
25324 + if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
25326 + /* attach us to the core-plugin */
25327 + s->core->backend_data = p;
25328 + s->core->get_vhost = mod_mysql_vhost_get_vhost;
25330 + sel = buffer_init();
25331 + buffer_copy_string_buffer(sel, s->core->select_vhost);
25333 if (sel->used && (qmark = index(sel->ptr, '?'))) {
25335 buffer_copy_string(s->mysql_pre, sel->ptr);
25336 @@ -228,35 +145,35 @@
25338 buffer_copy_string_buffer(s->mysql_pre, sel);
25349 * - password, default: empty
25350 * - socket, default: mysql default
25351 * - hostname, if set overrides socket
25352 * - port, default: 3306
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))) {
25365 if (NULL == (s->mysql = mysql_init(NULL))) {
25366 log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
25369 return HANDLER_ERROR;
25371 -#define FOO(x) (s->x->used ? s->x->ptr : NULL)
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)
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));
25382 return HANDLER_ERROR;
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))) {
25389 - fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25390 + fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25399 return HANDLER_GO_ON;
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) {
25407 plugin_config *s = p->config_storage[0];
25409 - PATCH(mysql_pre);
25410 - PATCH(mysql_post);
25416 + PATCH_OPTION(mysql_pre);
25417 + PATCH_OPTION(mysql_post);
25418 + PATCH_OPTION(mysql);
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];
25426 /* condition didn't match */
25427 if (!config_check_cond(srv, con, dc)) continue;
25429 - /* merge config */
25430 - for (j = 0; j < dc->value->used; j++) {
25431 - data_unset *du = dc->value->data[j];
25433 - if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
25434 - PATCH(mysql_pre);
25435 - PATCH(mysql_post);
25442 + PATCH_OPTION(mysql);
25443 + PATCH_OPTION(mysql_pre);
25444 + PATCH_OPTION(mysql_post);
25454 -/* handle document root request */
25455 -CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
25457 + * get the vhost info from the database
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;
25466 @@ -332,13 +235,6 @@
25468 if (!p->conf.mysql) return HANDLER_GO_ON;
25470 - /* sets up connection data if not done yet */
25471 - c = mod_mysql_vhost_connection_data(srv, con, p_d);
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;
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 @@
25482 if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
25483 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
25486 + mysql_free_result(result);
25487 + return HANDLER_GO_ON;
25489 result = mysql_store_result(p->conf.mysql);
25490 cols = mysql_num_fields(result);
25491 row = mysql_fetch_row(result);
25493 if (!row || cols < 1) {
25494 /* no such virtual host */
25495 mysql_free_result(result);
25496 return HANDLER_GO_ON;
25499 - /* sanity check that really is a directory */
25500 - buffer_copy_string(p->tmp_buf, row[0]);
25501 - BUFFER_APPEND_SLASH(p->tmp_buf);
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);
25507 - if (!S_ISDIR(sce->st.st_mode)) {
25508 - log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
25511 + buffer_copy_string(docroot, row[0]);
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);
25517 - /* fcgi_offset and fcgi_arg are optional */
25518 - if (cols > 1 && row[1]) {
25519 - c->fcgi_offset = atoi(row[1]);
25521 - if (cols > 2 && row[2]) {
25522 - buffer_copy_string(c->fcgi_arg, row[2]);
25524 - c->fcgi_arg->used = 0;
25527 - c->fcgi_offset = c->fcgi_arg->used = 0;
25529 mysql_free_result(result);
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);
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);
25541 - return HANDLER_GO_ON;
25543 -ERR500: if (result) mysql_free_result(result);
25544 - con->http_status = 500; /* Internal Error */
25545 - return HANDLER_FINISHED;
25546 + return HANDLER_GO_ON;
25549 /* this function is called at dlopen() time and inits the callbacks */
25550 int mod_mysql_vhost_plugin_init(plugin *p) {
25553 p->version = LIGHTTPD_VERSION_ID;
25554 p->name = buffer_init_string("mysql_vhost");
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;
25560 p->set_defaults = mod_mysql_vhost_set_defaults;
25561 - p->handle_docroot = mod_mysql_vhost_handle_docroot;
25563 + ds = data_string_init();
25564 + buffer_copy_string(ds->value, CORE_PLUGIN);
25565 + array_insert_unique(p->required_plugins, (data_unset *)ds);
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
25573 #include <sys/types.h>
25575 -#include <unistd.h>
25578 #include <string.h>
25581 #include "inet_ntop_cache.h"
25583 +#include "network.h"
25585 +#include "http_resp.h"
25592 #include "sys-socket.h"
25593 +#include "sys-files.h"
25594 +#include "sys-strings.h"
25596 #define data_proxy data_fastcgi
25597 #define data_proxy_init data_fastcgi_init
25598 @@ -38,22 +42,25 @@
25599 #define PROXY_RETRY_TIMEOUT 60
25603 - * the proxy module is based on the fastcgi module
25606 + * the proxy module is based on the fastcgi module
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.
25616 * TODO: - delay upstream read if write_queue is too large
25617 * (to prevent memory eating, like in apache). Shoud be
25619 * - persistent connection with upstream servers
25626 PROXY_BALANCE_UNSET,
25627 PROXY_BALANCE_FAIR,
25628 @@ -66,26 +73,33 @@
25631 proxy_balance_t balance;
25633 + array *last_used_backends; /* "extension" : last_used_backend */
25640 buffer *parse_response;
25641 buffer *balance_buf;
25646 + array *ignore_headers;
25648 plugin_config **config_storage;
25651 plugin_config conf;
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
25662 + PROXY_STATE_INIT,
25663 + PROXY_STATE_CONNECT,
25664 + PROXY_STATE_PREPARE_WRITE,
25665 + PROXY_STATE_WRITE,
25666 + PROXY_STATE_RESPONSE_HEADER,
25667 + PROXY_STATE_RESPONSE_CONTENT,
25668 + PROXY_STATE_ERROR
25669 } proxy_connection_state_t;
25671 enum { PROXY_STDOUT, PROXY_END_REQUEST };
25672 @@ -93,19 +107,17 @@
25674 proxy_connection_state_t state;
25675 time_t state_timestamp;
25680 - buffer *response;
25681 - buffer *response_header;
25687 int fd; /* fd to the proxy process */
25688 int fde_ndx; /* index into the fd-event buffer */
25690 size_t path_info_offset; /* start of path_info in uri.path */
25693 connection *remote_conn; /* dump pointer */
25694 plugin_data *plugin_data; /* dump pointer */
25696 @@ -116,69 +128,88 @@
25698 static handler_ctx * handler_ctx_init() {
25699 handler_ctx * hctx;
25703 hctx = calloc(1, sizeof(*hctx));
25706 hctx->state = PROXY_STATE_INIT;
25709 - hctx->response = buffer_init();
25710 - hctx->response_header = buffer_init();
25712 hctx->wb = chunkqueue_init();
25713 + hctx->rb = chunkqueue_init();
25716 hctx->fde_ndx = -1;
25722 static void handler_ctx_free(handler_ctx *hctx) {
25723 - buffer_free(hctx->response);
25724 - buffer_free(hctx->response_header);
25725 chunkqueue_free(hctx->wb);
25727 + chunkqueue_free(hctx->rb);
25732 INIT_FUNC(mod_proxy_init) {
25737 + char *hop2hop_headers[] = {
25744 p = calloc(1, sizeof(*p));
25746 - p->parse_response = buffer_init();
25748 p->balance_buf = buffer_init();
25750 + p->ignore_headers = array_init();
25751 + p->resp = http_response_init();
25753 + for (i = 0; hop2hop_headers[i]; i++) {
25756 + if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
25757 + ds = data_string_init();
25760 + buffer_copy_string(ds->key, hop2hop_headers[i]);
25761 + buffer_copy_string(ds->value, hop2hop_headers[i]);
25762 + array_insert_unique(p->ignore_headers, (data_unset *)ds);
25769 FREE_FUNC(mod_proxy_free) {
25770 plugin_data *p = p_d;
25775 - buffer_free(p->parse_response);
25776 - buffer_free(p->balance_buf);
25778 if (p->config_storage) {
25780 for (i = 0; i < srv->config_context->used; i++) {
25781 plugin_config *s = p->config_storage[i];
25786 array_free(s->extensions);
25788 + array_free(s->last_used_backends);
25793 free(p->config_storage);
25797 + array_free(p->ignore_headers);
25798 + buffer_free(p->balance_buf);
25799 + http_response_free(p->resp);
25804 return HANDLER_GO_ON;
25807 @@ -186,37 +217,38 @@
25808 plugin_data *p = p_d;
25812 - config_values_t cv[] = {
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 }
25822 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25825 for (i = 0; i < srv->config_context->used; i++) {
25830 s = malloc(sizeof(plugin_config));
25831 - s->extensions = array_init();
25832 + s->extensions = array_init();
25833 + s->last_used_backends = array_init();
25837 cv[0].destination = s->extensions;
25838 cv[1].destination = &(s->debug);
25839 cv[2].destination = p->balance_buf;
25841 buffer_reset(p->balance_buf);
25844 p->config_storage[i] = s;
25845 ca = ((data_config *)srv->config_context->data[i])->value;
25848 if (0 != config_insert_values_global(srv, ca, cv)) {
25849 return HANDLER_ERROR;
25853 if (buffer_is_empty(p->balance_buf)) {
25854 s->balance = PROXY_BALANCE_FAIR;
25855 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
25856 @@ -226,99 +258,99 @@
25857 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
25858 s->balance = PROXY_BALANCE_HASH;
25860 - log_error_write(srv, __FILE__, __LINE__, "sb",
25861 - "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
25862 + log_error_write(srv, __FILE__, __LINE__, "sb",
25863 + "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
25864 return HANDLER_ERROR;
25867 if (NULL != (du = array_get_element(ca, "proxy.server"))) {
25869 data_array *da = (data_array *)du;
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");
25878 return HANDLER_ERROR;
25884 * proxy.server = ( "<ext>" => ...,
25889 for (j = 0; j < da->value->used; j++) {
25890 data_array *da_ext = (data_array *)da->value->data[j];
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)");
25902 return HANDLER_ERROR;
25906 - * proxy.server = ( "<ext>" =>
25907 - * ( "<host>" => ( ... ),
25910 + * proxy.server = ( "<ext>" =>
25911 + * ( "<host>" => ( ... ),
25912 * "<host>" => ( ... )
25919 for (n = 0; n < da_ext->value->used; n++) {
25920 data_array *da_host = (data_array *)da_ext->value->data[n];
25926 - config_values_t pcv[] = {
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 }
25935 if (da_host->type != TYPE_ARRAY) {
25936 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
25937 - "unexpected type for key:",
25939 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
25940 + "unexpected type for key:",
25942 "[", da_ext->value->data[n]->key, "](string)");
25945 return HANDLER_ERROR;
25949 df = data_proxy_init();
25955 buffer_copy_string_buffer(df->key, da_host->key);
25958 pcv[0].destination = df->host;
25959 pcv[1].destination = &(df->port);
25962 if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
25963 return HANDLER_ERROR;
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):",
25978 return HANDLER_ERROR;
25982 /* if extension already exists, take it */
25985 if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
25986 dfa = data_array_init();
25989 buffer_copy_string_buffer(dfa->key, da_ext->key);
25992 array_insert_unique(dfa->value, (data_unset *)df);
25993 array_insert_unique(s->extensions, (data_unset *)dfa);
25995 @@ -328,19 +360,19 @@
26001 return HANDLER_GO_ON;
26004 void proxy_connection_close(server *srv, handler_ctx *hctx) {
26009 if (NULL == hctx) return;
26012 p = hctx->plugin_data;
26013 con = hctx->remote_conn;
26016 if (hctx->fd != -1) {
26017 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26018 fdevent_unregister(srv->ev, hctx->fd);
26019 @@ -348,47 +380,56 @@
26025 handler_ctx_free(hctx);
26026 - con->plugin_ctx[p->id] = NULL;
26027 + con->plugin_ctx[p->id] = NULL;
26030 static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
26031 struct sockaddr *proxy_addr;
26032 struct sockaddr_in proxy_addr_in;
26036 plugin_data *p = hctx->plugin_data;
26037 data_proxy *host= hctx->host;
26038 int proxy_fd = hctx->fd;
26041 memset(&proxy_addr, 0, sizeof(proxy_addr));
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);
26050 proxy_addr = (struct sockaddr *) &proxy_addr_in;
26053 if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
26054 - if (errno == EINPROGRESS || errno == EALREADY) {
26056 + errno = WSAGetLastError();
26060 + case WSAEWOULDBLOCK:
26062 + case EINPROGRESS:
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);
26074 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
26077 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
26078 "connect failed:", proxy_fd, strerror(errno), errno);
26084 + fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
26085 if (p->conf.debug) {
26086 - log_error_write(srv, __FILE__, __LINE__, "sd",
26087 + log_error_write(srv, __FILE__, __LINE__, "sd",
26088 "connect succeeded: ", proxy_fd);
26091 @@ -396,51 +437,52 @@
26094 void proxy_set_header(connection *con, const char *key, const char *value) {
26095 - data_string *ds_dst;
26096 + data_string *ds_dst;
26098 - if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26099 - ds_dst = data_string_init();
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();
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);
26114 void proxy_append_header(connection *con, const char *key, const char *value) {
26115 - data_string *ds_dst;
26116 + data_string *ds_dst;
26118 - if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26119 - ds_dst = data_string_init();
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();
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);
26135 static int proxy_create_env(server *srv, handler_ctx *hctx) {
26139 connection *con = hctx->remote_conn;
26140 + plugin_data *p = hctx->plugin_data;
26146 b = chunkqueue_get_append_buffer(hctx->wb);
26150 buffer_copy_string(b, get_http_method_name(con->request.http_method));
26151 BUFFER_APPEND_STRING_CONST(b, " ");
26154 buffer_append_string_buffer(b, con->request.uri);
26155 BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
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);
26166 @@ -449,24 +491,25 @@
26167 /* request header */
26168 for (i = 0; i < con->request.headers->used; i++) {
26172 ds = (data_string *)con->request.headers->data[i];
26174 - if (ds->value->used && ds->key->used) {
26175 - if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
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");
26183 + if (buffer_is_empty(ds->value) || buffer_is_empty(ds->key)) continue;
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;
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");
26195 BUFFER_APPEND_STRING_CONST(b, "\r\n");
26198 hctx->wb->bytes_in += b->used - 1;
26202 if (con->request.content_length) {
26203 chunkqueue *req_cq = con->request_content_queue;
26205 @@ -479,7 +522,7 @@
26207 /* we announce toWrite octects
26208 * now take all the request_content chunk that we need to fill this request
26212 switch (req_c->type) {
26214 @@ -507,223 +550,161 @@
26216 req_c->offset += weHave;
26217 req_cq->bytes_out += weHave;
26220 hctx->wb->bytes_in += weHave;
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;
26246 -static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
26248 - int http_response_status = -1;
26251 +static void chunkqueue_print(chunkqueue *cq) {
26254 - /* \r\n -> \0\0 */
26256 - buffer_copy_string_buffer(p->parse_response, in);
26258 - for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
26259 - char *key, *value;
26267 - if (-1 == http_response_status) {
26268 - /* The first line of a Response message is the Status-Line */
26270 - for (key=s; *key && *key != ' '; key++);
26273 - http_response_status = (int) strtol(key, NULL, 10);
26274 - if (http_response_status <= 0) http_response_status = 502;
26276 - http_response_status = 502;
26279 - con->http_status = http_response_status;
26280 - con->parsed_response |= HTTP_STATUS;
26284 - if (NULL == (value = strchr(s, ':'))) {
26285 - /* now we expect: "<key>: <value>\n" */
26291 - key_len = value - key;
26295 - while (*value == ' ' || *value == '\t') value++;
26299 - switch(key_len) {
26301 - if (0 == strncasecmp(key, "Date", key_len)) {
26302 - con->parsed_response |= HTTP_DATE;
26306 - if (0 == strncasecmp(key, "Location", key_len)) {
26307 - con->parsed_response |= HTTP_LOCATION;
26311 - if (0 == strncasecmp(key, "Connection", key_len)) {
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;
26325 - if (copy_header) {
26326 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26327 - ds = data_response_init();
26329 - buffer_copy_string_len(ds->key, key, key_len);
26330 - buffer_copy_string(ds->value, value);
26332 - array_insert_unique(con->response.headers, (data_unset *)ds);
26334 + for (c = cq->first; c; c = c->next) {
26335 + fprintf(stderr, "%s", c->mem->ptr + c->offset);
26339 + fprintf(stderr, "\r\n");
26343 static int proxy_demux_response(server *srv, handler_ctx *hctx) {
26348 plugin_data *p = hctx->plugin_data;
26349 connection *con = hctx->remote_conn;
26350 int proxy_fd = hctx->fd;
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: ",
26357 + chunkqueue *next_queue = NULL;
26360 + switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
26361 + case NETWORK_STATUS_SUCCESS:
26362 + /* we got content */
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;
26371 + /* close the chunk-queue with a empty chunk */
26379 + /* looks like we got some content
26381 + * split off the header from the incoming stream
26384 - if (p->conf.debug) {
26385 - log_error_write(srv, __FILE__, __LINE__, "sd",
26386 - "proxy - have to read:", b);
26388 + if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
26390 + int have_content_length = 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;
26398 - buffer_prepare_append(hctx->response, hctx->response->used + b);
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));
26408 - /* this should be catched by the b > 0 above */
26411 - hctx->response->used += r;
26412 - hctx->response->ptr[hctx->response->used - 1] = '\0';
26415 - log_error_write(srv, __FILE__, __LINE__, "sdsbs",
26416 - "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
26418 + http_response_reset(p->resp);
26420 - if (0 == con->got_response) {
26421 - con->got_response = 1;
26422 - buffer_prepare_copy(hctx->response_header, 128);
26425 - if (0 == con->file_started) {
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;
26434 - buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
26436 - log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
26438 - /* parse the response header */
26439 - proxy_response_parse(srv, con, p, hctx->response_header);
26441 - /* enable chunked-transfer-encoding */
26442 - if (con->request.http_version == HTTP_VERSION_1_1 &&
26443 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
26444 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26445 + /* the response header is not fully received yet,
26447 + * extract the http-response header from the rb-cq
26449 + switch (http_response_parse_cq(hctx->rb, p->resp)) {
26450 + case PARSE_ERROR:
26451 + /* parsing failed */
26453 + con->http_status = 502; /* Bad Gateway */
26455 + case PARSE_NEED_MORE:
26457 + case PARSE_SUCCESS:
26458 + con->http_status = p->resp->status;
26460 + chunkqueue_remove_finished_chunks(hctx->rb);
26462 + /* copy the http-headers */
26463 + for (i = 0; i < p->resp->headers->used; i++) {
26464 + const char *ign[] = { "Status", "Connection", NULL };
26468 + data_string *header = (data_string *)p->resp->headers->data[i];
26470 + /* some headers are ignored by default */
26471 + for (j = 0; ign[j]; j++) {
26472 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
26475 - con->file_started = 1;
26477 - http_chunk_append_mem(srv, con, c + 4, blen + 1);
26478 - joblist_append(srv, con);
26479 + if (ign[j]) continue;
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;
26487 - hctx->response->used = 0;
26489 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26490 + ds = data_response_init();
26492 + buffer_copy_string_buffer(ds->key, header->key);
26493 + buffer_copy_string_buffer(ds->value, header->value);
26495 + array_insert_unique(con->response.headers, (data_unset *)ds);
26498 - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
26499 - joblist_append(srv, con);
26500 - hctx->response->used = 0;
26502 + con->file_started = 1;
26504 + if (con->request.http_version == HTTP_VERSION_1_1 &&
26505 + !have_content_length) {
26506 + con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26509 + hctx->state = PROXY_STATE_RESPONSE_CONTENT;
26514 - /* reading from upstream done */
26515 - con->file_finished = 1;
26517 - http_chunk_append_mem(srv, con, NULL, 0);
26518 - joblist_append(srv, con);
26525 + /* FIXME: pass the response-header to the other plugins to
26526 + * setup the filter-queue
26528 + * - use next-queue instead of con->write_queue
26531 + next_queue = con->write_queue;
26533 + assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
26535 + /* FIXME: if we have a content-length or chunked-encoding
26538 + * for now we wait for EOF on the socket */
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);
26544 + c->offset = c->mem->used - 1;
26547 + chunkqueue_remove_finished_chunks(hctx->rb);
26548 + joblist_append(srv, con);
26554 @@ -731,12 +712,12 @@
26555 data_proxy *host= hctx->host;
26556 plugin_data *p = hctx->plugin_data;
26557 connection *con = hctx->remote_conn;
26563 - (!host->host->used || !host->port)) return -1;
26567 + (!host->host->used || !host->port)) return -1;
26569 switch(hctx->state) {
26570 case PROXY_STATE_INIT:
26571 if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
26572 @@ -744,19 +725,19 @@
26573 return HANDLER_ERROR;
26575 hctx->fde_ndx = -1;
26581 fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
26584 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
26585 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
26588 return HANDLER_ERROR;
26595 case PROXY_STATE_CONNECT:
26596 /* try to finish the connect() */
26597 if (hctx->state == PROXY_STATE_INIT) {
26598 @@ -764,16 +745,16 @@
26599 switch (proxy_establish_connection(srv, hctx)) {
26601 proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
26604 /* connection is in progress, wait for an event and call getsockopt() below */
26607 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26610 return HANDLER_WAIT_FOR_EVENT;
26612 /* if ECONNREFUSED choose another connection -> FIXME */
26613 hctx->fde_ndx = -1;
26616 return HANDLER_ERROR;
26618 /* everything is ok, go on */
26619 @@ -782,152 +763,152 @@
26622 socklen_t socket_error_len = sizeof(socket_error);
26624 - /* we don't need it anymore */
26626 + /* we don't need it anymore */
26627 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
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));
26636 return HANDLER_ERROR;
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);
26645 return HANDLER_ERROR;
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");
26654 proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
26656 case PROXY_STATE_PREPARE_WRITE:
26657 proxy_create_env(srv, hctx);
26660 proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
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);
26668 chunkqueue_remove_finished_chunks(hctx->wb);
26671 - if (errno != EAGAIN &&
26672 - errno != EINTR) {
26673 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26675 - return HANDLER_ERROR;
26677 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26679 + case NETWORK_STATUS_FATAL_ERROR:
26680 + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26682 - return HANDLER_WAIT_FOR_EVENT;
26684 + return HANDLER_ERROR;
26685 + case NETWORK_STATUS_WAIT_FOR_EVENT:
26687 + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26689 + return HANDLER_WAIT_FOR_EVENT;
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);
26696 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26697 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
26699 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26702 return HANDLER_WAIT_FOR_EVENT;
26706 return HANDLER_WAIT_FOR_EVENT;
26707 - case PROXY_STATE_READ:
26708 + case PROXY_STATE_RESPONSE_CONTENT:
26709 + case PROXY_STATE_RESPONSE_HEADER:
26710 /* waiting for a response */
26712 return HANDLER_WAIT_FOR_EVENT;
26714 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
26715 return HANDLER_ERROR;
26719 return HANDLER_GO_ON;
26722 -#define PATCH(x) \
26723 - p->conf.x = s->x;
26724 static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
26726 plugin_config *s = p->config_storage[0];
26728 - PATCH(extensions);
26733 + PATCH_OPTION(extensions);
26734 + PATCH_OPTION(debug);
26735 + PATCH_OPTION(balance);
26736 + PATCH_OPTION(last_used_backends);
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];
26744 /* condition didn't match */
26745 if (!config_check_cond(srv, con, dc)) continue;
26749 for (j = 0; j < dc->value->used; j++) {
26750 data_unset *du = dc->value->data[j];
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"))) {
26758 + PATCH_OPTION(debug);
26759 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
26761 + PATCH_OPTION(balance);
26762 + PATCH_OPTION(last_used_backends);
26772 SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
26773 plugin_data *p = p_d;
26776 handler_ctx *hctx = con->plugin_ctx[p->id];
26780 if (NULL == hctx) return HANDLER_GO_ON;
26782 mod_proxy_patch_connection(srv, con, p);
26789 if (con->mode != p->id) return HANDLER_GO_ON;
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:",
26802 /* disable this server */
26803 host->is_disabled = 1;
26804 host->disable_ts = srv->cur_ts;
26807 proxy_connection_close(srv, hctx);
26809 - /* reset the enviroment and restart the sub-request */
26811 + /* reset the enviroment and restart the sub-request */
26812 buffer_reset(con->physical.path);
26813 con->mode = DIRECT;
26815 joblist_append(srv, con);
26817 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26818 - * and hope that the childs will be restarted
26820 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26821 + * and hope that the childs will be restarted
26825 return HANDLER_WAIT_FOR_FD;
26826 @@ -938,7 +919,7 @@
26832 if (con->file_started == 1) {
26833 return HANDLER_FINISHED;
26835 @@ -951,13 +932,14 @@
26836 handler_ctx *hctx = ctx;
26837 connection *con = hctx->remote_conn;
26838 plugin_data *p = hctx->plugin_data;
26843 if ((revents & FDEVENT_IN) &&
26844 - hctx->state == PROXY_STATE_READ) {
26845 + (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
26846 + hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
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);
26854 @@ -965,11 +947,15 @@
26858 + log_error_write(srv, __FILE__, __LINE__, "sd",
26859 + "proxy: request done", hctx->fd);
26860 hctx->host->usage--;
26863 + http_chunk_append_mem(srv, con, NULL, 0);
26866 proxy_connection_close(srv, hctx);
26869 joblist_append(srv, con);
26870 return HANDLER_FINISHED;
26872 @@ -982,53 +968,53 @@
26873 /* response might have been already started, kill the connection */
26874 connection_set_state(srv, con, CON_STATE_ERROR);
26878 joblist_append(srv, con);
26879 return HANDLER_FINISHED;
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);
26891 if (hctx->state == PROXY_STATE_CONNECT ||
26892 hctx->state == PROXY_STATE_WRITE) {
26893 /* we are allowed to send something out
26896 * 1. in a unfinished connect() call
26897 * 2. in a unfinished write() call (long POST request)
26899 return mod_proxy_handle_subrequest(srv, con, p);
26901 - log_error_write(srv, __FILE__, __LINE__, "sd",
26902 + log_error_write(srv, __FILE__, __LINE__, "sd",
26903 "proxy: out", hctx->state);
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);
26917 if (hctx->state == PROXY_STATE_CONNECT) {
26918 /* connect() -> EINPROGRESS -> HUP */
26922 - * what is proxy is doing if it can't reach the next hop ?
26924 + * what is proxy is doing if it can't reach the next hop ?
26929 proxy_connection_close(srv, hctx);
26930 joblist_append(srv, con);
26933 con->http_status = 503;
26934 con->mode = DIRECT;
26937 return HANDLER_FINISHED;
26940 @@ -1038,13 +1024,13 @@
26941 joblist_append(srv, con);
26942 } else if (revents & FDEVENT_ERR) {
26943 /* kill all connections to the proxy process */
26946 log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
26948 joblist_append(srv, con);
26949 proxy_connection_close(srv, hctx);
26953 return HANDLER_FINISHED;
26956 @@ -1058,44 +1044,48 @@
26958 data_array *extension = NULL;
26959 size_t path_info_offset;
26961 + data_integer *last_used_backend;
26962 + data_proxy *host = NULL;
26963 + handler_ctx *hctx = NULL;
26965 + array *backends = NULL;
26967 /* Possibly, we processed already this request */
26968 if (con->file_started == 1) return HANDLER_GO_ON;
26971 mod_proxy_patch_connection(srv, con, p);
26974 fn = con->uri.path;
26976 if (fn->used == 0) {
26977 return HANDLER_ERROR;
26981 s_len = fn->used - 1;
26985 path_info_offset = 0;
26987 - if (p->conf.debug) {
26988 + if (p->conf.debug) {
26989 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - start");
26992 /* check if extension matches */
26993 for (k = 0; k < p->conf.extensions->used; k++) {
26997 extension = (data_array *)p->conf.extensions->data[k];
27000 if (extension->key->used == 0) continue;
27003 ct_len = extension->key->used - 1;
27006 if (s_len < ct_len) continue;
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) {
27015 if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
27016 path_info_offset = pi_offset - fn->ptr;
27018 @@ -1106,12 +1096,14 @@
27024 if (k == p->conf.extensions->used) {
27025 return HANDLER_GO_ON;
27028 - if (p->conf.debug) {
27029 + backends = extension->value;
27031 + if (p->conf.debug) {
27032 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found");
27035 @@ -1120,34 +1112,34 @@
27036 /* hash balancing */
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);
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;
27050 - if (host->is_disabled) continue;
27052 + data_proxy *cur = (data_proxy *)backends->data[k];
27054 + if (cur->is_disabled) continue;
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));
27062 if (p->conf.debug) {
27063 - log_error_write(srv, __FILE__, __LINE__, "sbbbd",
27064 + log_error_write(srv, __FILE__, __LINE__, "sbbbd",
27065 "proxy - election:",
27069 con->uri.authority,
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;
27083 @@ -1155,19 +1147,20 @@
27084 case PROXY_BALANCE_FAIR:
27085 /* fair balancing */
27086 if (p->conf.debug) {
27087 - log_error_write(srv, __FILE__, __LINE__, "s",
27088 + log_error_write(srv, __FILE__, __LINE__, "s",
27089 "proxy - used fair balancing");
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];
27095 - if (host->is_disabled) continue;
27097 - if (host->usage < max_usage) {
27098 - max_usage = host->usage;
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];
27105 + if (cur->is_disabled) continue;
27107 + if (NULL == host || cur->usage < max_usage) {
27108 + max_usage = cur->usage;
27114 @@ -1175,89 +1168,100 @@
27115 case PROXY_BALANCE_RR:
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");
27123 /* just to be sure */
27124 - assert(extension->value->used < INT_MAX);
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];
27129 - if (host->is_disabled) continue;
27131 - /* first usable ndx */
27132 - if (max_usage == INT_MAX) {
27135 + assert(backends->used < INT_MAX);
27137 - /* get next ndx */
27138 - if ((int)k > host->last_used_ndx) {
27140 - host->last_used_ndx = k;
27141 + /* send each request to another host:
27145 + * if we have three hosts it is
27147 + * 1 .. 2 .. 3 .. 1 .. 2 .. 3
27153 + /* walk through the list */
27154 + last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
27156 + if (NULL == last_used_backend) {
27157 + last_used_backend = data_integer_init();
27159 + buffer_copy_string_buffer(last_used_backend->key, extension->key);
27160 + last_used_backend->value = 0;
27162 + array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
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];
27170 + if (cur->is_disabled) continue;
27174 + last_used_backend->value = k;
27179 - /* didn't found a higher id, wrap to the start */
27180 - if (ndx != -1 && max_usage != INT_MAX) {
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];
27188 + if (host->is_disabled) host = NULL;
27196 - /* found a server */
27198 - data_proxy *host = (data_proxy *)extension->value->data[ndx];
27201 - * if check-local is disabled, use the uri.path handler
27205 - /* init handler-context */
27206 - handler_ctx *hctx;
27207 - hctx = handler_ctx_init();
27209 - hctx->path_info_offset = path_info_offset;
27210 - hctx->remote_conn = con;
27211 - hctx->plugin_data = p;
27212 - hctx->host = host;
27214 - con->plugin_ctx[p->id] = hctx;
27218 - con->mode = p->id;
27220 - if (p->conf.debug) {
27221 - log_error_write(srv, __FILE__, __LINE__, "sbd",
27222 - "proxy - found a host",
27223 - host->host, host->port);
27226 - return HANDLER_GO_ON;
27228 - /* no handler found */
27229 + /* we havn't found a host */
27230 + if (NULL == host) {
27231 con->http_status = 500;
27233 - log_error_write(srv, __FILE__, __LINE__, "sb",
27234 - "no proxy-handler found for:",
27236 + log_error_write(srv, __FILE__, __LINE__, "sb",
27237 + "no proxy-handler found for:",
27241 return HANDLER_FINISHED;
27244 + /* init handler-context */
27245 + hctx = handler_ctx_init();
27247 + hctx->path_info_offset = path_info_offset;
27248 + hctx->remote_conn = con;
27249 + hctx->plugin_data = p;
27250 + hctx->host = host;
27252 + con->plugin_ctx[p->id] = hctx;
27256 + /* we handle this request */
27257 + con->mode = p->id;
27259 + if (p->conf.debug) {
27260 + log_error_write(srv, __FILE__, __LINE__, "sbd",
27261 + "proxy - found a host",
27262 + host->host, host->port);
27265 return HANDLER_GO_ON;
27268 static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
27269 plugin_data *p = p_d;
27272 proxy_connection_close(srv, con->plugin_ctx[p->id]);
27274 return HANDLER_GO_ON;
27275 @@ -1276,11 +1280,11 @@
27277 for (i = 0; i < srv->config_context->used; i++) {
27278 plugin_config *s = p->config_storage[i];
27280 - if (!s) continue;
27282 + if (!s) continue;
27284 /* get the extensions for all configs */
27287 for (k = 0; k < s->extensions->used; k++) {
27288 data_array *extension = (data_array *)s->extensions->data[k];
27290 @@ -1290,8 +1294,8 @@
27292 if (!host->is_disabled ||
27293 srv->cur_ts - host->disable_ts < 5) continue;
27295 - log_error_write(srv, __FILE__, __LINE__, "sbd",
27297 + log_error_write(srv, __FILE__, __LINE__, "sbd",
27298 "proxy - re-enabled:",
27299 host->host, host->port);
27301 @@ -1317,8 +1321,8 @@
27302 p->handle_uri_clean = mod_proxy_check_extension;
27303 p->handle_subrequest = mod_proxy_handle_subrequest;
27304 p->handle_trigger = mod_proxy_trigger;
27312 --- ../lighttpd-1.4.11/src/mod_redirect.c 2006-02-08 15:38:06.000000000 +0200
27313 +++ lighttpd-1.4.12/src/mod_redirect.c 2006-07-11 22:07:52.000000000 +0300
27314 @@ -22,35 +22,35 @@
27320 plugin_config **config_storage;
27322 - plugin_config conf;
27324 + plugin_config conf;
27327 INIT_FUNC(mod_redirect_init) {
27331 p = calloc(1, sizeof(*p));
27334 p->match_buf = buffer_init();
27335 p->location = buffer_init();
27341 FREE_FUNC(mod_redirect_free) {
27342 plugin_data *p = p_d;
27345 if (!p) return HANDLER_GO_ON;
27347 if (p->config_storage) {
27349 for (i = 0; i < srv->config_context->used; i++) {
27350 plugin_config *s = p->config_storage[i];
27353 pcre_keyvalue_buffer_free(s->redirect);
27358 free(p->config_storage);
27361 buffer_free(p->match_buf);
27362 buffer_free(p->location);
27368 return HANDLER_GO_ON;
27371 @@ -69,195 +69,137 @@
27372 plugin_data *p = p_d;
27376 - config_values_t cv[] = {
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 }
27384 if (!p) return HANDLER_ERROR;
27388 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27391 for (i = 0; i < srv->config_context->used; i++) {
27395 data_array *da = (data_array *)du;
27398 s = calloc(1, sizeof(plugin_config));
27399 s->redirect = pcre_keyvalue_buffer_init();
27402 cv[0].destination = s->redirect;
27405 p->config_storage[i] = s;
27406 ca = ((data_config *)srv->config_context->data[i])->value;
27409 if (0 != config_insert_values_global(srv, ca, cv)) {
27410 return HANDLER_ERROR;
27414 if (NULL == (du = array_get_element(ca, "url.redirect"))) {
27415 /* no url.redirect defined */
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");
27426 return HANDLER_ERROR;
27430 da = (data_array *)du;
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: ",
27438 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
27439 + "unexpected type for key: ",
27441 "[", da->value->data[j]->key, "](string)");
27444 return HANDLER_ERROR;
27447 - if (0 != pcre_keyvalue_buffer_append(s->redirect,
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)) {
27453 - log_error_write(srv, __FILE__, __LINE__, "sb",
27455 + log_error_write(srv, __FILE__, __LINE__, "sb",
27456 "pcre-compile failed for", da->value->data[j]->key);
27462 return HANDLER_GO_ON;
27465 static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
27467 plugin_config *s = p->config_storage[0];
27470 p->conf.redirect = s->redirect;
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];
27479 /* condition didn't match */
27480 if (!config_check_cond(srv, con, dc)) continue;
27484 for (j = 0; j < dc->value->used; j++) {
27485 data_unset *du = dc->value->data[j];
27488 if (0 == strcmp(du->key->ptr, "url.redirect")) {
27489 p->conf.redirect = s->redirect;
27490 p->conf.context = dc;
27499 static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
27501 plugin_data *p = p_data;
27510 * e.g. redirect /base/ to /index.php?section=base
27516 mod_redirect_patch_connection(srv, con, p);
27519 buffer_copy_string_buffer(p->match_buf, con->request.uri);
27521 - for (i = 0; i < p->conf.redirect->used; i++) {
27523 - pcre_extra *extra;
27524 - const char *pattern;
27525 - size_t pattern_len;
27527 - pcre_keyvalue *kv = p->conf.redirect->kv[i];
27532 - extra = kv->key_extra;
27533 - pattern = kv->value->ptr;
27534 - pattern_len = kv->value->used - 1;
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;
27543 - const char **list;
27544 - size_t start, end;
27548 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
27550 - /* search for $[0-9] */
27552 - buffer_reset(p->location);
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])) {
27560 - size_t num = pattern[k + 1] - '0';
27564 - buffer_append_string_len(p->location, pattern + start, end - start);
27566 - if (pattern[k] == '$') {
27567 - /* n is always > 0 */
27568 - if (num < (size_t)n) {
27569 - buffer_append_string(p->location, list[num]);
27572 - config_append_cond_match_buffer(con, p->conf.context, p->location, num);
27580 - buffer_append_string_len(p->location, pattern + start, pattern_len - start);
27584 - response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27586 - con->http_status = 301;
27587 - con->file_finished = 1;
27589 - return HANDLER_FINISHED;
27591 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
27594 + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27596 + con->http_status = 301;
27597 + con->file_finished = 1;
27599 + return HANDLER_FINISHED;
27601 + else if (i != PCRE_ERROR_NOMATCH) {
27602 + log_error_write(srv, __FILE__, __LINE__, "s",
27603 + "execution error while matching", i);
27615 return HANDLER_GO_ON;
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");
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;
27635 --- ../lighttpd-1.4.11/src/mod_rewrite.c 2005-09-29 20:59:10.000000000 +0300
27636 +++ lighttpd-1.4.12/src/mod_rewrite.c 2006-07-11 22:07:51.000000000 +0300
27641 -#ifdef HAVE_PCRE_H
27651 - rewrite_rule **ptr;
27655 -} rewrite_rule_buffer;
27658 - rewrite_rule_buffer *rewrite;
27659 + pcre_keyvalue_buffer *rewrite;
27661 data_config *context; /* to which apply me */
27664 @@ -42,20 +26,20 @@
27670 plugin_config **config_storage;
27672 - plugin_config conf;
27674 + plugin_config conf;
27677 static handler_ctx * handler_ctx_init() {
27678 handler_ctx * hctx;
27681 hctx = calloc(1, sizeof(*hctx));
27684 hctx->state = REWRITE_STATE_UNSET;
27691 @@ -63,207 +47,136 @@
27695 -rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
27696 - rewrite_rule_buffer *kvb;
27698 - kvb = calloc(1, sizeof(*kvb));
27703 -int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
27704 -#ifdef HAVE_PCRE_H
27706 - const char *errptr;
27709 - if (!key) return -1;
27711 - if (kvb->size == 0) {
27715 - kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
27717 - for(i = 0; i < kvb->size; i++) {
27718 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27720 - } else if (kvb->used == kvb->size) {
27723 - kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
27725 - for(i = kvb->used; i < kvb->size; i++) {
27726 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27730 - if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
27731 - 0, &errptr, &erroff, NULL))) {
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;
27753 -void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
27754 -#ifdef HAVE_PCRE_H
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]);
27763 - if (kvb->ptr) free(kvb->ptr);
27770 INIT_FUNC(mod_rewrite_init) {
27774 p = calloc(1, sizeof(*p));
27777 p->match_buf = buffer_init();
27783 FREE_FUNC(mod_rewrite_free) {
27784 plugin_data *p = p_d;
27789 if (!p) return HANDLER_GO_ON;
27792 buffer_free(p->match_buf);
27793 if (p->config_storage) {
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);
27799 + pcre_keyvalue_buffer_free(s->rewrite);
27800 + buffer_free(s->once);
27804 free(p->config_storage);
27811 return HANDLER_GO_ON;
27814 static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
27818 if (NULL != (du = array_get_element(ca, option))) {
27819 data_array *da = (data_array *)du;
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");
27829 return HANDLER_ERROR;
27833 da = (data_array *)du;
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: ",
27841 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
27842 + "unexpected type for key: ",
27844 "[", da->value->data[j]->key, "](string)");
27847 return HANDLER_ERROR;
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,
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)) {
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);
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");
27870 + buffer_append_string_len(s->once, CONST_STR_LEN("1"));
27872 + buffer_append_string_len(s->once, CONST_STR_LEN("0"));
27881 SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
27882 plugin_data *p = p_d;
27885 - config_values_t cv[] = {
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 */
27891 - /* old names, still supported
27894 + /* old names, still supported
27896 * url.rewrite remapped to url.rewrite-once
27897 * url.rewrite-final is url.rewrite-once
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 }
27907 if (!p) return HANDLER_ERROR;
27911 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27914 for (i = 0; i < srv->config_context->used; i++) {
27919 s = calloc(1, sizeof(plugin_config));
27920 - s->rewrite = rewrite_rule_buffer_init();
27922 - cv[0].destination = s->rewrite;
27923 - cv[1].destination = s->rewrite;
27924 - cv[2].destination = s->rewrite;
27926 + s->rewrite = pcre_keyvalue_buffer_init();
27927 + s->once = buffer_init();
27929 p->config_storage[i] = s;
27930 ca = ((data_config *)srv->config_context->data[i])->value;
27933 if (0 != config_insert_values_global(srv, ca, cv)) {
27934 return HANDLER_ERROR;
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);
27945 return HANDLER_GO_ON;
27948 @@ -271,157 +184,107 @@
27950 plugin_config *s = p->config_storage[0];
27951 p->conf.rewrite = s->rewrite;
27953 + p->conf.once = s->once;
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];
27961 if (COMP_HTTP_URL == dc->comp) continue;
27964 /* condition didn't match */
27965 if (!config_check_cond(srv, con, dc)) continue;
27969 for (j = 0; j < dc->value->used; j++) {
27970 data_unset *du = dc->value->data[j];
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;
27997 URIHANDLER_FUNC(mod_rewrite_con_reset) {
27998 plugin_data *p = p_d;
28004 if (con->plugin_ctx[p->id]) {
28005 handler_ctx_free(con->plugin_ctx[p->id]);
28006 con->plugin_ctx[p->id] = NULL;
28010 return HANDLER_GO_ON;
28013 URIHANDLER_FUNC(mod_rewrite_uri_handler) {
28015 plugin_data *p = p_d;
28025 * e.g. rewrite /base/ to /index.php?section=base
28031 if (con->plugin_ctx[p->id]) {
28032 hctx = con->plugin_ctx[p->id];
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");
28041 return HANDLER_ERROR;
28045 if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
28049 mod_rewrite_patch_connection(srv, con, p);
28051 if (!p->conf.rewrite) return HANDLER_GO_ON;
28054 buffer_copy_string_buffer(p->match_buf, con->request.uri);
28056 - for (i = 0; i < p->conf.rewrite->used; i++) {
28058 - const char *pattern;
28059 - size_t pattern_len;
28061 - rewrite_rule *rule = p->conf.rewrite->ptr[i];
28065 - match = rule->key;
28066 - pattern = rule->value->ptr;
28067 - pattern_len = rule->value->used - 1;
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;
28076 - const char **list;
28077 - size_t start, end;
28081 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
28083 - /* search for $[0-9] */
28085 - buffer_reset(con->request.uri);
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])) {
28093 - size_t num = pattern[k + 1] - '0';
28097 - buffer_append_string_len(con->request.uri, pattern + start, end - start);
28099 - if (pattern[k] == '$') {
28100 - /* n is always > 0 */
28101 - if (num < (size_t)n) {
28102 - buffer_append_string(con->request.uri, list[num]);
28105 - config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
28113 - buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
28117 - hctx = handler_ctx_init();
28119 - con->plugin_ctx[p->id] = hctx;
28121 - if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
28123 - return HANDLER_COMEBACK;
28125 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
28128 + hctx = handler_ctx_init();
28130 + con->plugin_ctx[p->id] = hctx;
28132 + if (p->conf.once->ptr[i] == '1')
28133 + hctx->state = REWRITE_STATE_FINISHED;
28135 + return HANDLER_COMEBACK;
28137 + else if (i != PCRE_ERROR_NOMATCH) {
28138 + log_error_write(srv, __FILE__, __LINE__, "s",
28139 + "execution error while matching", i);
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");
28153 p->init = mod_rewrite_init;
28154 /* it has to stay _raw as we are matching on uri + querystring
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;
28169 --- ../lighttpd-1.4.11/src/mod_rrdtool.c 2005-08-22 01:52:24.000000000 +0300
28170 +++ lighttpd-1.4.12/src/mod_rrdtool.c 2006-07-11 22:07:52.000000000 +0300
28172 #include <stdlib.h>
28174 #include <string.h>
28175 -#include <unistd.h>
28179 @@ -20,10 +19,14 @@
28180 /* no need for waitpid if we don't have fork */
28181 #include <sys/wait.h>
28184 +#include "sys-files.h"
28185 +#include "sys-process.h"
28188 buffer *path_rrdtool_bin;
28192 double requests, *requests_ptr;
28193 double bytes_written, *bytes_written_ptr;
28194 double bytes_read, *bytes_read_ptr;
28195 @@ -31,84 +34,84 @@
28205 int read_fd, write_fd;
28209 int rrdtool_running;
28212 plugin_config **config_storage;
28213 plugin_config conf;
28216 INIT_FUNC(mod_rrd_init) {
28220 p = calloc(1, sizeof(*p));
28223 p->resp = buffer_init();
28224 p->cmd = buffer_init();
28230 FREE_FUNC(mod_rrd_free) {
28231 plugin_data *p = p_d;
28235 if (!p) return HANDLER_GO_ON;
28238 if (p->config_storage) {
28239 for (i = 0; i < srv->config_context->used; i++) {
28240 plugin_config *s = p->config_storage[i];
28243 buffer_free(s->path_rrdtool_bin);
28244 buffer_free(s->path_rrd);
28250 buffer_free(p->cmd);
28251 buffer_free(p->resp);
28254 free(p->config_storage);
28257 if (p->rrdtool_pid) {
28260 close(p->write_fd);
28263 /* collect status */
28264 waitpid(p->rrdtool_pid, &status, 0);
28272 return HANDLER_GO_ON;
28275 int mod_rrd_create_pipe(server *srv, plugin_data *p) {
28279 int to_rrdtool_fds[2];
28280 int from_rrdtool_fds[2];
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));
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));
28300 switch (pid = fork()) {
28302 @@ -117,33 +120,33 @@
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]);
28313 close(from_rrdtool_fds[0]);
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]);
28321 close(to_rrdtool_fds[1]);
28324 close(STDERR_FILENO);
28327 if (srv->errorlog_mode == ERRORLOG_FILE) {
28328 dup2(srv->errorlog_fd, STDERR_FILENO);
28329 close(srv->errorlog_fd);
28335 args = malloc(sizeof(*args) * argc);
28339 args[i++] = p->conf.path_rrdtool_bin->ptr;
28342 @@ -152,12 +155,12 @@
28343 for (i = 3; i < 256; i++) {
28349 execv(args[0], args);
28352 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
28358 @@ -168,19 +171,19 @@
28364 close(from_rrdtool_fds[1]);
28365 close(to_rrdtool_fds[0]);
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;
28382 @@ -189,19 +192,19 @@
28384 static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
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;
28399 /* create a new one */
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");
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));
28417 return HANDLER_ERROR;
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));
28428 return HANDLER_ERROR;
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);
28442 return HANDLER_ERROR;
28447 return HANDLER_GO_ON;
28450 -#define PATCH(x) \
28451 - p->conf.x = s->x;
28452 static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
28454 plugin_config *s = p->config_storage[0];
28456 - PATCH(path_rrdtool_bin);
28460 + PATCH_OPTION(path_rrdtool_bin);
28461 + PATCH_OPTION(path_rrd);
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);
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];
28474 /* condition didn't match */
28475 if (!config_check_cond(srv, con, dc)) continue;
28479 for (j = 0; j < dc->value->used; j++) {
28480 data_unset *du = dc->value->data[j];
28483 if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
28485 + PATCH_OPTION(path_rrd);
28486 /* get pointers to double values */
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);
28501 SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
28502 plugin_data *p = p_d;
28505 - config_values_t cv[] = {
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 }
28514 if (!p) return HANDLER_ERROR;
28517 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28520 for (i = 0; i < srv->config_context->used; i++) {
28524 s = calloc(1, sizeof(plugin_config));
28525 s->path_rrdtool_bin = buffer_init();
28526 s->path_rrd = buffer_init();
28528 s->bytes_written = 0;
28532 cv[0].destination = s->path_rrdtool_bin;
28533 cv[1].destination = s->path_rrd;
28536 p->config_storage[i] = s;
28539 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
28540 return HANDLER_ERROR;
28544 if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
28545 /* path_rrdtool_bin is a global option */
28547 - log_error_write(srv, __FILE__, __LINE__, "s",
28549 + log_error_write(srv, __FILE__, __LINE__, "s",
28550 "rrdtool.binary can only be set as a global option.");
28553 return HANDLER_ERROR;
28560 p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
28561 p->rrdtool_running = 0;
28564 /* check for dir */
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;
28575 /* open the pipe to rrdtool */
28576 if (mod_rrd_create_pipe(srv, p)) {
28577 return HANDLER_ERROR;
28581 p->rrdtool_running = 1;
28584 return HANDLER_GO_ON;
28587 TRIGGER_FUNC(mod_rrd_trigger) {
28588 plugin_data *p = p_d;
28592 if (!p->rrdtool_running) return HANDLER_GO_ON;
28593 if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
28596 for (i = 0; i < srv->config_context->used; i++) {
28597 plugin_config *s = p->config_storage[i];
28601 if (buffer_is_empty(s->path_rrd)) continue;
28604 /* write the data down every minute */
28607 if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
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");
28619 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28620 p->rrdtool_running = 0;
28622 - log_error_write(srv, __FILE__, __LINE__, "ss",
28624 + log_error_write(srv, __FILE__, __LINE__, "ss",
28625 "rrdtool-write: failed", strerror(errno));
28628 return HANDLER_ERROR;
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;
28636 - log_error_write(srv, __FILE__, __LINE__, "ss",
28638 + log_error_write(srv, __FILE__, __LINE__, "ss",
28639 "rrdtool-read: failed", strerror(errno));
28642 return HANDLER_ERROR;
28649 if (p->resp->ptr[0] != 'O' ||
28650 p->resp->ptr[1] != 'K') {
28651 p->rrdtool_running = 0;
28653 - log_error_write(srv, __FILE__, __LINE__, "sbb",
28655 + log_error_write(srv, __FILE__, __LINE__, "sbb",
28656 "rrdtool-response:", p->cmd, p->resp);
28659 return HANDLER_ERROR;
28662 s->bytes_written = 0;
28667 return HANDLER_GO_ON;
28670 REQUESTDONE_FUNC(mod_rrd_account) {
28671 plugin_data *p = p_d;
28674 mod_rrd_patch_connection(srv, con, p);
28677 *(p->conf.requests_ptr) += 1;
28678 *(p->conf.bytes_written_ptr) += con->bytes_written;
28679 *(p->conf.bytes_read_ptr) += con->bytes_read;
28682 return HANDLER_GO_ON;
28685 int mod_rrdtool_plugin_init(plugin *p) {
28686 p->version = LIGHTTPD_VERSION_ID;
28687 p->name = buffer_init_string("rrd");
28690 p->init = mod_rrd_init;
28691 p->cleanup = mod_rrd_free;
28692 p->set_defaults= mod_rrd_set_defaults;
28695 p->handle_trigger = mod_rrd_trigger;
28696 p->handle_request_done = mod_rrd_account;
28704 --- ../lighttpd-1.4.11/src/mod_scgi.c 2006-03-04 17:15:26.000000000 +0200
28705 +++ lighttpd-1.4.12/src/mod_scgi.c 2006-07-11 22:07:51.000000000 +0300
28707 #include <sys/types.h>
28708 -#include <unistd.h>
28711 #include <string.h>
28715 #include "sys-socket.h"
28717 +#include "sys-files.h"
28718 +#include "sys-strings.h"
28719 +#include "sys-process.h"
28721 #ifndef UNIX_PATH_MAX
28722 # define UNIX_PATH_MAX 108
28723 @@ -46,30 +47,29 @@
28724 enum {EOL_UNSET, EOL_N, EOL_RN};
28732 * - add timeout for a connect to a non-scgi process
28733 * (use state_timestamp + state)
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 */
28743 - pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
28745 + pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
28747 size_t load; /* number of requests waiting on this process */
28749 time_t last_used; /* see idle_timeout */
28750 size_t requests; /* see max_requests */
28751 struct scgi_proc *prev, *next; /* see first */
28754 time_t disable_ts; /* replace by host->something */
28759 enum { PROC_STATE_UNSET, /* init-phase */
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 */
28769 @@ -86,20 +86,20 @@
28770 * sorted by lowest load
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
28777 - scgi_proc *first;
28778 - scgi_proc *unused_procs;
28779 + scgi_proc *first;
28780 + scgi_proc *unused_procs;
28784 * spawn at least min_procs, at max_procs.
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
28796 unsigned short min_procs;
28797 @@ -111,44 +111,44 @@
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.
28809 unsigned short idle_timeout;
28813 * time after a disabled remote connection is tried to be re-enabled
28821 unsigned short disable_time;
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.
28830 size_t max_requests_per_proc;
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
28845 * if tcp/ip should be used host AND port have
28846 - * to be specified
28850 + * to be specified
28854 unsigned short port;
28857 @@ -161,7 +161,7 @@
28859 buffer *unixsocket;
28861 - /* if socket is local we can start the scgi
28862 + /* if socket is local we can start the scgi
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
28870 - buffer *bin_path;
28872 - /* bin-path is set bin-environment is taken to
28873 + buffer *bin_path;
28875 + /* bin-path is set bin-environment is taken to
28876 * create the environement before starting the
28884 array *bin_env_copy;
28888 - * docroot-translation between URL->phys and the
28889 + * docroot-translation between URL->phys and the
28893 @@ -192,7 +192,7 @@
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 @@
28905 * append PATH_INFO to SCRIPT_FILENAME
28908 * php needs this if cgi.fix_pathinfo is provied
28914 ssize_t load; /* replace by host->load */
28916 size_t max_id; /* corresponds most of the time to
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;
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)
28930 * ext -> host -> procs
28933 - * if the scgi process is remote that whole goes down
28934 + * if the scgi process is remote that whole goes down
28937 * ext -> host -> procs
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 */
28946 scgi_extension_host **hosts;
28952 @@ -253,14 +253,14 @@
28970 @@ -268,52 +268,51 @@
28971 /* generic plugin data, shared between all connections */
28980 buffer *parse_response;
28983 plugin_config **config_storage;
28986 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
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;
28997 - buffer *response;
28998 + buffer *response;
28999 size_t response_len;
29001 int response_padding;
29005 scgi_extension_host *host;
29008 scgi_connection_state_t state;
29009 time_t state_timestamp;
29012 int reconnects; /* number of reconnect attempts */
29019 buffer *response_header;
29022 int delayed; /* flag to mark that the connect() is delayed */
29026 int fd; /* fd to the scgi process */
29027 int fde_ndx; /* index into the fd-event buffer */
29033 plugin_config conf;
29036 connection *remote_conn; /* dumb pointer */
29037 plugin_data *plugin_data; /* dumb pointer */
29039 @@ -328,28 +327,28 @@
29041 static handler_ctx * handler_ctx_init() {
29042 handler_ctx * hctx;
29045 hctx = calloc(1, sizeof(*hctx));
29049 hctx->fde_ndx = -1;
29052 hctx->response = buffer_init();
29053 hctx->response_header = buffer_init();
29056 hctx->request_id = 0;
29057 hctx->state = FCGI_STATE_INIT;
29061 hctx->response_len = 0;
29062 hctx->response_type = 0;
29063 hctx->response_padding = 0;
29067 hctx->reconnects = 0;
29069 hctx->wb = chunkqueue_init();
29075 @@ -358,12 +357,12 @@
29076 buffer_free(hctx->response_header);
29078 chunkqueue_free(hctx->wb);
29082 if (hctx->rb->ptr) free(hctx->rb->ptr);
29090 @@ -372,20 +371,20 @@
29092 f = calloc(1, sizeof(*f));
29093 f->socket = buffer_init();
29103 void scgi_process_free(scgi_proc *f) {
29107 scgi_process_free(f->next);
29110 buffer_free(f->socket);
29116 @@ -400,62 +399,62 @@
29117 f->bin_path = buffer_init();
29118 f->bin_env = array_init();
29119 f->bin_env_copy = array_init();
29125 void scgi_host_free(scgi_extension_host *h) {
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);
29137 scgi_process_free(h->first);
29138 scgi_process_free(h->unused_procs);
29146 scgi_exts *scgi_extensions_init() {
29149 f = calloc(1, sizeof(*f));
29155 void scgi_extensions_free(scgi_exts *f) {
29162 for (i = 0; i < f->used; i++) {
29163 scgi_extension *fe;
29170 for (j = 0; j < fe->used; j++) {
29171 scgi_extension_host *h;
29181 buffer_free(fe->key);
29195 @@ -504,99 +503,103 @@
29199 - fe->hosts[fe->used++] = fh;
29200 + fe->hosts[fe->used++] = fh;
29207 INIT_FUNC(mod_scgi_init) {
29211 p = calloc(1, sizeof(*p));
29214 p->scgi_env = buffer_init();
29217 p->path = buffer_init();
29218 p->parse_response = buffer_init();
29225 FREE_FUNC(mod_scgi_free) {
29226 plugin_data *p = p_d;
29231 buffer_free(p->scgi_env);
29232 buffer_free(p->path);
29233 buffer_free(p->parse_response);
29236 if (p->config_storage) {
29238 for (i = 0; i < srv->config_context->used; i++) {
29239 plugin_config *s = p->config_storage[i];
29248 for (j = 0; j < exts->used; j++) {
29249 scgi_extension *ex;
29252 ex = exts->exts[j];
29255 for (n = 0; n < ex->used; n++) {
29257 scgi_extension_host *host;
29260 host = ex->hosts[n];
29263 for (proc = host->first; proc; proc = proc->next) {
29265 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29267 - if (proc->is_local &&
29270 + if (proc->is_local &&
29271 !buffer_is_empty(proc->socket)) {
29272 unlink(proc->socket->ptr);
29277 for (proc = host->unused_procs; proc; proc = proc->next) {
29279 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29281 - if (proc->is_local &&
29284 + if (proc->is_local &&
29285 !buffer_is_empty(proc->socket)) {
29286 unlink(proc->socket->ptr);
29293 scgi_extensions_free(s->exts);
29298 free(p->config_storage);
29305 return HANDLER_GO_ON;
29308 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
29312 if (!key || !val) return -1;
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);
29322 if (env->size == 0) {
29324 env->ptr = malloc(env->size * sizeof(*env->ptr));
29325 @@ -604,13 +607,13 @@
29327 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
29331 env->ptr[env->used++] = dst;
29337 -static int scgi_spawn_connection(server *srv,
29338 +static int scgi_spawn_connection(server *srv,
29340 scgi_extension_host *host,
29342 @@ -622,31 +625,27 @@
29344 struct sockaddr_in scgi_addr_in;
29345 struct sockaddr *scgi_addr;
29356 if (p->conf.debug) {
29357 log_error_write(srv, __FILE__, __LINE__, "sdb",
29358 "new proc, socket:", proc->port, proc->socket);
29362 if (!buffer_is_empty(proc->socket)) {
29363 memset(&scgi_addr, 0, sizeof(scgi_addr));
29366 #ifdef HAVE_SYS_UN_H
29367 scgi_addr_un.sun_family = AF_UNIX;
29368 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
29372 servlen = SUN_LEN(&scgi_addr_un);
29374 - /* stevens says: */
29375 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
29378 socket_type = AF_UNIX;
29379 scgi_addr = (struct sockaddr *) &scgi_addr_un;
29381 @@ -656,115 +655,115 @@
29384 scgi_addr_in.sin_family = AF_INET;
29387 if (buffer_is_empty(host->host)) {
29388 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29390 struct hostent *he;
29393 /* set a usefull default */
29394 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
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);
29409 if (he->h_addrtype != AF_INET) {
29410 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
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);
29421 memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
29425 scgi_addr_in.sin_port = htons(proc->port);
29426 servlen = sizeof(scgi_addr_in);
29429 socket_type = AF_INET;
29430 scgi_addr = (struct sockaddr *) &scgi_addr_in;
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));
29442 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
29443 /* server is not up, spawn in */
29448 if (!buffer_is_empty(proc->socket)) {
29449 unlink(proc->socket->ptr);
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));
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));
29474 /* create socket */
29475 if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
29476 - log_error_write(srv, __FILE__, __LINE__, "sbds",
29477 - "bind failed for:",
29480 + log_error_write(srv, __FILE__, __LINE__, "sbds",
29481 + "bind failed for:",
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));
29499 switch ((child = fork())) {
29509 /* create environment */
29515 /* we don't need the client socket */
29516 for (fd = 3; fd < 256; fd++) {
29517 if (fd != 2 && fd != scgi_fd) close(fd);
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];
29528 if (NULL != (ge = getenv(ds->value->ptr))) {
29529 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
29531 @@ -772,44 +771,44 @@
29533 for (i = 0; environ[i]; i++) {
29537 if (NULL != (eq = strchr(environ[i], '='))) {
29538 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
29544 /* create environment */
29545 for (i = 0; i < host->bin_env->used; i++) {
29546 data_string *ds = (data_string *)host->bin_env->data[i];
29549 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
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;
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"));
29565 env.ptr[env.used] = NULL;
29569 buffer_copy_string(b, "exec ");
29570 buffer_append_string_buffer(b, host->bin_path);
29574 execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
29576 - log_error_write(srv, __FILE__, __LINE__, "sbs",
29578 + log_error_write(srv, __FILE__, __LINE__, "sbs",
29579 "execl failed for:", host->bin_path, strerror(errno));
29588 @@ -817,32 +816,32 @@
29595 select(0, NULL, NULL, NULL, &tv);
29598 switch (waitpid(child, &status, WNOHANG)) {
29600 /* child still running after timeout, good */
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));
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:",
29623 - log_error_write(srv, __FILE__, __LINE__, "sd",
29624 - "child died somehow:",
29625 + log_error_write(srv, __FILE__, __LINE__, "sd",
29626 + "child died somehow:",
29630 @@ -852,26 +851,26 @@
29632 proc->last_used = srv->cur_ts;
29633 proc->is_local = 1;
29640 proc->is_local = 0;
29644 if (p->conf.debug) {
29645 log_error_write(srv, __FILE__, __LINE__, "sb",
29646 "(debug) socket is already used, won't spawn:",
29652 proc->state = PROC_STATE_RUNNING;
29653 host->active_procs++;
29662 @@ -880,89 +879,89 @@
29663 plugin_data *p = p_d;
29667 - config_values_t cv[] = {
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 }
29676 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
29679 for (i = 0; i < srv->config_context->used; i++) {
29684 s = malloc(sizeof(plugin_config));
29685 s->exts = scgi_extensions_init();
29689 cv[0].destination = s->exts;
29690 cv[1].destination = &(s->debug);
29693 p->config_storage[i] = s;
29694 ca = ((data_config *)srv->config_context->data[i])->value;
29697 if (0 != config_insert_values_global(srv, ca, cv)) {
29698 return HANDLER_ERROR;
29708 if (NULL != (du = array_get_element(ca, "scgi.server"))) {
29710 data_array *da = (data_array *)du;
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");
29719 return HANDLER_ERROR;
29724 - * scgi.server = ( "<ext>" => ( ... ),
29728 + * scgi.server = ( "<ext>" => ( ... ),
29729 * "<ext>" => ( ... ) )
29733 for (j = 0; j < da->value->used; j++) {
29735 data_array *da_ext = (data_array *)da->value->data[j];
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)");
29746 return HANDLER_ERROR;
29750 - * da_ext->key == name of the extension
29753 + * da_ext->key == name of the extension
29757 - * scgi.server = ( "<ext>" =>
29758 - * ( "<host>" => ( ... ),
29761 + * scgi.server = ( "<ext>" =>
29762 + * ( "<host>" => ( ... ),
29763 * "<host>" => ( ... )
29770 for (n = 0; n < da_ext->value->used; n++) {
29771 data_array *da_host = (data_array *)da_ext->value->data[n];
29774 scgi_extension_host *df;
29776 - config_values_t fcv[] = {
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 */
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 */
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 */
29800 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29804 if (da_host->type != TYPE_ARRAY) {
29805 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29806 - "unexpected type for key:",
29808 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29809 + "unexpected type for key:",
29811 "[", da_host->key, "](string)");
29814 return HANDLER_ERROR;
29818 df = scgi_host_init();
29821 df->check_local = 1;
29824 df->max_load_per_proc = 1;
29825 df->idle_timeout = 60;
29826 df->disable_time = 60;
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;
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);
29844 fcv[11].destination = df->bin_env;
29845 fcv[12].destination = df->bin_env_copy;
29850 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
29851 return HANDLER_ERROR;
29854 - if ((!buffer_is_empty(df->host) || df->port) &&
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");
29863 return HANDLER_ERROR;
29867 if (!buffer_is_empty(df->unixsocket)) {
29868 /* unix domain socket */
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;
29880 - if (buffer_is_empty(df->host) &&
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):",
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):",
29903 @@ -1056,14 +1055,14 @@
29904 return HANDLER_ERROR;
29908 - if (!buffer_is_empty(df->bin_path)) {
29910 + if (!buffer_is_empty(df->bin_path)) {
29911 /* a local socket + self spawning */
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;
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);
29928 for (pno = 0; pno < df->min_procs; pno++) {
29931 @@ -1088,7 +1087,7 @@
29932 buffer_append_string(proc->socket, "-");
29933 buffer_append_long(proc->socket, pno);
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);
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;
29953 proc->next = df->first;
29954 if (df->first) df->first->prev = proc;
29963 fp = scgi_process_init();
29964 fp->id = df->num_procs++;
29966 df->active_procs++;
29967 fp->state = PROC_STATE_RUNNING;
29970 if (buffer_is_empty(df->unixsocket)) {
29971 fp->port = df->port;
29973 buffer_copy_string_buffer(fp->socket, df->unixsocket);
29985 /* if extension already exists, take it */
29986 scgi_extension_insert(s->exts, da_ext->key, df);
29993 return HANDLER_GO_ON;
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;
30004 @@ -1150,34 +1149,34 @@
30005 void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
30010 if (NULL == hctx) return;
30013 p = hctx->plugin_data;
30014 con = hctx->remote_conn;
30017 if (con->mode != p->id) {
30023 if (hctx->fd != -1) {
30024 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30025 fdevent_unregister(srv->ev, hctx->fd);
30031 if (hctx->host && hctx->proc) {
30032 hctx->host->load--;
30035 if (hctx->got_proc) {
30036 /* after the connect the process gets a load */
30037 hctx->proc->load--;
30040 if (p->conf.debug) {
30041 log_error_write(srv, __FILE__, __LINE__, "sddb",
30045 hctx->proc->pid, hctx->proc->socket);
30047 @@ -1186,87 +1185,87 @@
30048 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30053 handler_ctx_free(hctx);
30054 - con->plugin_ctx[p->id] = NULL;
30055 + con->plugin_ctx[p->id] = NULL;
30058 static int scgi_reconnect(server *srv, handler_ctx *hctx) {
30059 plugin_data *p = hctx->plugin_data;
30070 * connect was ok, connection was accepted
30071 * but the php accept loop checks after the accept if it should die or not.
30073 - * if yes we can only detect it at a write()
30076 + * if yes we can only detect it at a write()
30078 * next step is resetting this attemp and setup a connection again
30081 * if we have more then 5 reconnects for the same request, die
30088 * we have a connection but the child died by some other reason
30094 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30095 fdevent_unregister(srv->ev, hctx->fd);
30100 scgi_set_state(srv, hctx, FCGI_STATE_INIT);
30103 hctx->request_id = 0;
30104 hctx->reconnects++;
30107 if (p->conf.debug) {
30108 log_error_write(srv, __FILE__, __LINE__, "sddb",
30112 hctx->proc->pid, hctx->proc->socket);
30116 hctx->proc->load--;
30117 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30124 static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
30125 plugin_data *p = p_d;
30128 scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
30131 return HANDLER_GO_ON;
30135 static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
30139 if (!key || !val) return -1;
30142 len = key_len + val_len + 2;
30145 buffer_prepare_append(env, len);
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;
30165 @@ -1280,24 +1279,21 @@
30166 struct sockaddr_un scgi_addr_un;
30171 scgi_extension_host *host = hctx->host;
30172 scgi_proc *proc = hctx->proc;
30173 int scgi_fd = hctx->fd;
30176 memset(&scgi_addr, 0, sizeof(scgi_addr));
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);
30186 servlen = SUN_LEN(&scgi_addr_un);
30188 - /* stevens says: */
30189 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
30192 scgi_addr = (struct sockaddr *) &scgi_addr_un;
30195 @@ -1305,105 +1301,105 @@
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");
30208 scgi_addr_in.sin_port = htons(proc->port);
30209 servlen = sizeof(scgi_addr_in);
30212 scgi_addr = (struct sockaddr *) &scgi_addr_in;
30216 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
30217 - if (errno == EINPROGRESS ||
30218 + if (errno == EINPROGRESS ||
30219 errno == EALREADY ||
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);
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);
30237 if (errno == EAGAIN) {
30238 /* this is Linux only */
30240 - log_error_write(srv, __FILE__, __LINE__, "s",
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.");
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);
30264 static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
30268 for (i = 0; i < con->request.headers->used; i++) {
30272 ds = (data_string *)con->request.headers->data[i];
30275 if (ds->value->used && ds->key->used) {
30277 buffer_reset(srv->tmp_buf);
30280 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
30281 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
30282 srv->tmp_buf->used--;
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 : '_';
30294 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30297 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30302 for (i = 0; i < con->environment->used; i++) {
30306 ds = (data_string *)con->environment->data[i];
30309 if (ds->value->used && ds->key->used) {
30311 buffer_reset(srv->tmp_buf);
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]) : '_';
30322 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30325 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30333 @@ -1415,20 +1411,20 @@
30334 char b2[INET6_ADDRSTRLEN + 1];
30339 plugin_data *p = hctx->plugin_data;
30340 scgi_extension_host *host= hctx->host;
30342 connection *con = hctx->remote_conn;
30343 server_socket *srv_sock = con->srv_socket;
30346 sock_addr our_addr;
30347 socklen_t our_addr_len;
30350 buffer_prepare_copy(p->scgi_env, 1024);
30352 /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
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 @@
30361 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
30364 if (con->server_name->used) {
30365 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
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),
30375 @@ -1451,47 +1447,47 @@
30377 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
30381 scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
30387 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
30389 ntohs(srv_sock->addr.ipv4.sin_port)
30394 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
30397 /* get the server-side of the connection to the client */
30398 our_addr_len = sizeof(our_addr);
30401 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
30402 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
30404 s = inet_ntop_cache_get_ip(srv, &(our_addr));
30406 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
30412 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
30414 ntohs(con->dst_addr.ipv4.sin_port)
30419 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
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));
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));
30434 * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
30435 @@ -1500,12 +1496,12 @@
30438 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
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));
30445 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
30448 if (!buffer_is_empty(host->docroot)) {
30449 buffer_copy_string_buffer(p->path, host->docroot);
30451 @@ -1526,19 +1522,19 @@
30454 if (!buffer_is_empty(host->docroot)) {
30456 - * rewrite SCRIPT_FILENAME
30459 + * rewrite SCRIPT_FILENAME
30464 buffer_copy_string_buffer(p->path, host->docroot);
30465 buffer_append_string_buffer(p->path, con->uri.path);
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));
30471 buffer_copy_string_buffer(p->path, con->physical.path);
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));
30477 @@ -1551,30 +1547,30 @@
30479 scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
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));
30491 if (srv_sock->is_ssl) {
30492 scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
30497 scgi_env_add_request_headers(srv, con, p);
30499 b = chunkqueue_get_append_buffer(hctx->wb);
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(","));
30507 hctx->wb->bytes_in += b->used - 1;
30510 if (con->request.content_length) {
30511 chunkqueue *req_cq = con->request_content_queue;
30513 @@ -1587,7 +1583,7 @@
30515 /* we announce toWrite octects
30516 * now take all the request_content chunk that we need to fill this request
30520 switch (req_c->type) {
30522 @@ -1615,32 +1611,32 @@
30524 req_c->offset += weHave;
30525 req_cq->bytes_out += weHave;
30528 hctx->wb->bytes_in += weHave;
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) {
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] : '.');
30551 fprintf(stderr, "\n");
30560 @@ -1648,32 +1644,32 @@
30569 buffer_copy_string_buffer(p->parse_response, in);
30571 - for (s = p->parse_response->ptr;
30572 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
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;
30587 0 == strncmp(s, "HTTP/1.", 7)) {
30588 /* non-parsed header ... we parse them anyway */
30591 if ((s[7] == '1' ||
30595 /* after the space should be a status code for us */
30598 status = strtol(s+9, NULL, 10);
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 @@
30611 if (NULL == (value = strchr(s, ':'))) {
30612 /* we expect: "<key>: <value>\r\n" */
30617 key_len = value - key;
30622 while (*value == ' ' || *value == '\t') value++;
30625 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
30626 ds = data_response_init();
30628 buffer_copy_string_len(ds->key, key, key_len);
30629 buffer_copy_string(ds->value, value);
30632 array_insert_unique(con->response.headers, (data_unset *)ds);
30637 if (0 == strncasecmp(key, "Date", key_len)) {
30638 @@ -1737,13 +1733,13 @@
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;
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;
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);
30674 /* read finished */
30677 con->file_finished = 1;
30680 /* send final chunk */
30681 http_chunk_append_mem(srv, con, NULL, 0);
30682 joblist_append(srv, con);
30689 hctx->response->ptr[n] = '\0';
30690 hctx->response->used = n+1;
30693 /* split header from body */
30696 if (con->file_started == 0) {
30699 int header_end = 0;
30700 int cp, eol = EOL_UNSET;
30704 buffer_append_string_buffer(hctx->response_header, hctx->response);
30707 /* nph (non-parsed headers) */
30708 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
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 */
30725 if (eol == EOL_UNSET) eol = EOL_N;
30728 if (*(c+1) == '\n') {
30734 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
30735 if (in_header == 0) {
30736 /* got a response without a response header */
30745 if (eol == EOL_UNSET) eol = EOL_RN;
30749 - *(c+2) == '\r' &&
30750 + *(c+2) == '\r' &&
30767 /* no header, but a body */
30770 if (con->request.http_version == HTTP_VERSION_1_1) {
30771 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30775 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
30776 joblist_append(srv, con);
30778 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
30779 size_t blen = hctx->response_header->used - hlen - 1;
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';
30787 /* parse the response header */
30788 scgi_response_parse(srv, con, p, hctx->response_header, eol);
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;
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);
30805 con->file_started = 1;
30808 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
30809 joblist_append(srv, con);
30815 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
30824 int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30830 - /* we have been the smallest of the current list
30831 - * and we want to insert the node sorted as soon
30833 + /* we have been the smallest of the current list
30834 + * and we want to insert the node sorted as soon
30847 /* nothing to sort, only one element */
30848 @@ -1909,9 +1905,9 @@
30850 for (p = proc; p->next && p->next->load < proc->load; p = p->next);
30852 - /* no need to move something
30853 + /* no need to move something
30860 @@ -1930,16 +1926,16 @@
30862 if (proc->prev) proc->prev->next = proc->next;
30863 if (proc->next) proc->next->prev = proc->prev;
30866 /* proc should be right of p */
30869 proc->next = p->next;
30871 if (p->next) p->next->prev = proc;
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",
30880 @@ -1951,21 +1947,21 @@
30882 int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30888 - /* we have been the smallest of the current list
30889 - * and we want to insert the node sorted as soon
30891 + /* we have been the smallest of the current list
30892 + * and we want to insert the node sorted as soon
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.
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);
30921 - /* no need to move something
30922 + /* no need to move something
30931 if (p == proc) return 0;
30934 /* we have to move left. If we are already the first element
30936 if (host->first == proc) return 0;
30937 @@ -2009,9 +2005,9 @@
30940 if (proc->prev == NULL) host->first = proc;
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",
30949 @@ -2023,41 +2019,42 @@
30951 static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
30955 for (proc = host->first; proc; proc = proc->next) {
30956 if (p->conf.debug) {
30957 - log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
30959 - host->host, proc->port,
30960 + log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
30962 + host->host, proc->port,
30971 if (0 == proc->is_local) {
30973 - * external servers might get disabled
30975 - * enable the server again, perhaps it is back again
30977 + * external servers might get disabled
30979 + * enable the server again, perhaps it is back again
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++;
30988 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
30989 - "fcgi-server re-enabled:",
30990 - host->host, host->port,
30992 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
30993 + "fcgi-server re-enabled:",
30994 + host->host, host->port,
30998 /* the child should not terminate at all */
31002 if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
31004 switch(waitpid(proc->pid, &status, WNOHANG)) {
31006 /* child is still alive */
31007 @@ -2067,33 +2064,34 @@
31009 if (WIFEXITED(status)) {
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));
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:",
31023 - log_error_write(srv, __FILE__, __LINE__, "sd",
31024 - "child died somehow:",
31025 + log_error_write(srv, __FILE__, __LINE__, "sd",
31026 + "child died somehow:",
31031 proc->state = PROC_STATE_DIED;
31040 * local servers might died, but we restart them
31044 if (proc->state == PROC_STATE_DIED &&
31046 /* restart the child */
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);
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;
31065 scgi_proclist_sort_down(srv, host, proc);
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;
31082 - /* sanity check */
31083 + /* sanity check */
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",
31091 @@ -2135,179 +2133,180 @@
31092 host->unixsocket->used);
31093 return HANDLER_ERROR;
31098 switch(hctx->state) {
31099 case FCGI_STATE_INIT:
31100 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
31103 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
31104 if (errno == EMFILE ||
31106 - log_error_write(srv, __FILE__, __LINE__, "sd",
31107 + log_error_write(srv, __FILE__, __LINE__, "sd",
31108 "wait for fd at connection:", con->fd);
31111 return HANDLER_WAIT_FOR_FD;
31114 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
31116 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
31117 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
31118 return HANDLER_ERROR;
31120 hctx->fde_ndx = -1;
31126 fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
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));
31135 return HANDLER_ERROR;
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);
31149 /* all childs are dead */
31150 if (hctx->proc == NULL) {
31151 hctx->fde_ndx = -1;
31154 return HANDLER_ERROR;
31158 if (hctx->proc->is_local) {
31159 hctx->pid = hctx->proc->pid;
31163 switch (scgi_establish_connection(srv, hctx)) {
31165 scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
31168 /* connection is in progress, wait for an event and call getsockopt() below */
31171 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31174 return HANDLER_WAIT_FOR_EVENT;
31176 /* if ECONNREFUSED choose another connection -> FIXME */
31177 hctx->fde_ndx = -1;
31180 return HANDLER_ERROR;
31182 /* everything is ok, go on */
31190 socklen_t socket_error_len = sizeof(socket_error);
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));
31200 return HANDLER_ERROR;
31202 if (socket_error != 0) {
31203 if (!hctx->proc->is_local || p->conf.debug) {
31204 /* local procs get restarted */
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);
31214 return HANDLER_ERROR;
31219 /* ok, we have the connection */
31222 hctx->proc->load++;
31223 hctx->proc->last_used = srv->cur_ts;
31224 hctx->got_proc = 1;
31227 if (p->conf.debug) {
31228 log_error_write(srv, __FILE__, __LINE__, "sddbdd",
31233 - hctx->proc->socket,
31235 + hctx->proc->socket,
31240 /* move the proc-list entry down the list */
31241 scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
31244 scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
31246 case FCGI_STATE_PREPARE_WRITE:
31247 scgi_create_env(srv, hctx);
31250 scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
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);
31258 chunkqueue_remove_finished_chunks(hctx->wb);
31262 if (errno == ENOTCONN) {
31263 - /* the connection got dropped after accept()
31265 - * this is most of the time a PHP which dies
31266 + /* the connection got dropped after accept()
31268 + * this is most of the time a PHP which dies
31269 * after PHP_FCGI_MAX_REQUESTS
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
31279 + usleep(10000); /* take away the load of the webserver
31280 + * to let the php a chance to restart
31284 scgi_reconnect(srv, hctx);
31287 return HANDLER_WAIT_FOR_FD;
31291 /* not reconnected ... why
31294 * far@#lighttpd report this for FreeBSD
31299 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
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);
31307 return HANDLER_ERROR;
31311 if ((errno != EAGAIN) &&
31312 (errno != EINTR)) {
31314 - log_error_write(srv, __FILE__, __LINE__, "ssd",
31316 + log_error_write(srv, __FILE__, __LINE__, "ssd",
31317 "write failed:", strerror(errno), errno);
31320 return HANDLER_ERROR;
31322 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31325 return HANDLER_WAIT_FOR_EVENT;
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);
31336 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31339 return HANDLER_WAIT_FOR_EVENT;
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;
31352 return HANDLER_WAIT_FOR_EVENT;
31355 SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
31356 plugin_data *p = p_d;
31359 handler_ctx *hctx = con->plugin_ctx[p->id];
31361 scgi_extension_host *host;
31364 if (NULL == hctx) return HANDLER_GO_ON;
31368 if (con->mode != p->id) return HANDLER_GO_ON;
31371 /* ok, create the request */
31372 switch(scgi_write_request(srv, hctx)) {
31373 case HANDLER_ERROR:
31380 0 == proc->is_local &&
31381 proc->state != PROC_STATE_DISABLED) {
31382 /* only disable remote servers as we don't manage them*/
31384 - log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
31386 + log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
31392 /* disable this server */
31393 proc->disable_ts = srv->cur_ts;
31394 proc->state = PROC_STATE_DISABLED;
31395 host->active_procs--;
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
31406 if (proc && proc->is_local) {
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:",
31418 * several hctx might reference the same proc
31421 * Only one of them should mark the proc as dead all the other
31422 * ones should just take a new one.
31425 * If a new proc was started with the old struct this might lead
31426 * the mark a perfect proc as dead otherwise
31430 if (proc->state == PROC_STATE_RUNNING &&
31431 hctx->pid == proc->pid) {
31432 @@ -2395,25 +2394,25 @@
31435 scgi_restart_dead_procs(srv, p, host);
31438 scgi_connection_cleanup(srv, hctx);
31441 buffer_reset(con->physical.path);
31442 con->mode = DIRECT;
31443 joblist_append(srv, con);
31445 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31446 - * and hope that the childs will be restarted
31449 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31450 + * and hope that the childs will be restarted
31453 return HANDLER_WAIT_FOR_FD;
31455 scgi_connection_cleanup(srv, hctx);
31458 buffer_reset(con->physical.path);
31459 con->mode = DIRECT;
31460 con->http_status = 503;
31463 return HANDLER_FINISHED;
31465 case HANDLER_WAIT_FOR_EVENT:
31466 @@ -2433,23 +2432,23 @@
31467 static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
31472 if (NULL == hctx) return HANDLER_GO_ON;
31475 p = hctx->plugin_data;
31476 con = hctx->remote_conn;
31479 if (con->mode != p->id) return HANDLER_GO_ON;
31481 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31482 - "emergency exit: scgi:",
31484 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31485 + "emergency exit: scgi:",
31486 "connection-fd:", con->fd,
31487 "fcgi-fd:", hctx->fd);
31494 scgi_connection_cleanup(srv, hctx);
31497 return HANDLER_FINISHED;
31500 @@ -2459,7 +2458,7 @@
31501 handler_ctx *hctx = ctx;
31502 connection *con = hctx->remote_conn;
31503 plugin_data *p = hctx->plugin_data;
31506 scgi_proc *proc = hctx->proc;
31507 scgi_extension_host *host= hctx->host;
31509 @@ -2471,15 +2470,15 @@
31512 scgi_connection_cleanup(srv, hctx);
31515 joblist_append(srv, con);
31516 return HANDLER_FINISHED;
31518 if (proc->pid && proc->state != PROC_STATE_DIED) {
31522 /* only fetch the zombie if it is not already done */
31525 switch(waitpid(proc->pid, &status, WNOHANG)) {
31527 /* child is still alive */
31528 @@ -2489,19 +2488,19 @@
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:",
31543 - log_error_write(srv, __FILE__, __LINE__, "sd",
31544 - "child died somehow:",
31545 + log_error_write(srv, __FILE__, __LINE__, "sd",
31546 + "child died somehow:",
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);
31560 if (scgi_spawn_connection(srv, p, host, proc)) {
31562 proc->state = PROC_STATE_DIED;
31564 scgi_proclist_sort_down(srv, host, proc);
31573 if (con->file_started == 0) {
31574 /* nothing has been send out yet, try to use another child */
31577 if (hctx->wb->bytes_out == 0 &&
31578 hctx->reconnects < 5) {
31579 scgi_reconnect(srv, hctx);
31581 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
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);
31589 return HANDLER_WAIT_FOR_FD;
31592 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
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);
31600 scgi_connection_cleanup(srv, hctx);
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 @@
31608 /* response might have been already started, kill the connection */
31609 scgi_connection_cleanup(srv, hctx);
31611 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
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);
31619 connection_set_state(srv, con, CON_STATE_ERROR);
31627 joblist_append(srv, con);
31628 return HANDLER_FINISHED;
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
31639 * 1. in a unfinished connect() call
31640 * 2. in a unfinished write() call (long POST request)
31642 return mod_scgi_handle_subrequest(srv, con, p);
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:",
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 ?)
31658 - * if we are in connect we might get a EINPROGRESS
31659 - * in the first call and a FDEVENT_HUP in the
31661 + * if we are in connect we might get a EINPROGRESS
31662 + * in the first call and a FDEVENT_HUP in the
31666 * FIXME: as it is a bit ugly.
31670 return mod_scgi_handle_subrequest(srv, con, p);
31671 } else if (hctx->state == FCGI_STATE_READ &&
31672 hctx->proc->port == 0) {
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
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",
31685 - "(no scgi process on host: ",
31686 + "(no scgi process on host: ",
31695 connection_set_state(srv, con, CON_STATE_ERROR);
31696 scgi_connection_close(srv, hctx);
31697 joblist_append(srv, con);
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 */
31705 @@ -2628,42 +2628,39 @@
31706 scgi_connection_close(srv, hctx);
31707 joblist_append(srv, con);
31711 return HANDLER_FINISHED;
31713 -#define PATCH(x) \
31714 - p->conf.x = s->x;
31716 static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
31718 plugin_config *s = p->config_storage[0];
31724 + PATCH_OPTION(exts);
31725 + PATCH_OPTION(debug);
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];
31733 /* condition didn't match */
31734 if (!config_check_cond(srv, con, dc)) continue;
31738 for (j = 0; j < dc->value->used; j++) {
31739 data_unset *du = dc->value->data[j];
31742 if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
31744 + PATCH_OPTION(exts);
31745 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
31747 + PATCH_OPTION(debug);
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 @@
31763 scgi_extension *extension = NULL;
31766 /* Possibly, we processed already this request */
31767 if (con->file_started == 1) return HANDLER_GO_ON;
31770 fn = uri_path_handler ? con->uri.path : con->physical.path;
31772 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
31774 s_len = fn->used - 1;
31777 scgi_patch_connection(srv, con, p);
31779 /* check if extension matches */
31780 for (k = 0; k < p->conf.exts->used; k++) {
31784 extension = p->conf.exts->exts[k];
31787 if (extension->key->used == 0) continue;
31790 ct_len = extension->key->used - 1;
31793 if (s_len < ct_len) continue;
31796 /* check extension in the form "/scgi_pattern" */
31797 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
31799 @@ -2710,17 +2707,17 @@
31800 if (k == p->conf.exts->used) {
31801 return HANDLER_GO_ON;
31805 /* get best server */
31806 for (k = 0, ndx = -1; k < extension->used; k++) {
31807 scgi_extension_host *host = extension->hosts[k];
31810 /* we should have at least one proc that can do somthing */
31811 if (host->active_procs == 0) continue;
31813 if (used == -1 || host->load < used) {
31820 @@ -2728,12 +2725,12 @@
31821 /* found a server */
31823 scgi_extension_host *host = extension->hosts[ndx];
31826 - * if check-local is disabled, use the uri.path handler
31830 + * if check-local is disabled, use the uri.path handler
31835 /* init handler-context */
31836 if (uri_path_handler) {
31837 if (host->check_local == 0) {
31838 @@ -2741,7 +2738,7 @@
31841 hctx = handler_ctx_init();
31844 hctx->remote_conn = con;
31845 hctx->plugin_data = p;
31847 @@ -2749,45 +2746,45 @@
31849 hctx->conf.exts = p->conf.exts;
31850 hctx->conf.debug = p->conf.debug;
31853 con->plugin_ctx[p->id] = hctx;
31861 if (con->conf.log_request_handling) {
31862 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
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"
31871 * if prefix = /admin.fcgi
31874 * /admin.fcgi/foo/bar
31877 * SCRIPT_NAME = /admin.fcgi
31878 * PATH_INFO = /foo/bar
31881 * if prefix = /fcgi-bin/
31884 * /fcgi-bin/foo/bar
31887 * SCRIPT_NAME = /fcgi-bin/foo
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 */
31900 + /* rewrite uri.path and pathinfo */
31902 buffer_copy_string(con->request.pathinfo, pathinfo);
31905 con->uri.path->used -= con->request.pathinfo->used - 1;
31906 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
31908 @@ -2796,21 +2793,21 @@
31911 hctx = handler_ctx_init();
31914 hctx->remote_conn = con;
31915 hctx->plugin_data = p;
31920 hctx->conf.exts = p->conf.exts;
31921 hctx->conf.debug = p->conf.debug;
31924 con->plugin_ctx[p->id] = hctx;
31933 if (con->conf.log_request_handling) {
31934 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
31936 @@ -2821,11 +2818,11 @@
31937 /* no handler found */
31938 buffer_reset(con->physical.path);
31939 con->http_status = 500;
31941 - log_error_write(srv, __FILE__, __LINE__, "sb",
31942 - "no fcgi-handler found for:",
31944 + log_error_write(srv, __FILE__, __LINE__, "sb",
31945 + "no fcgi-handler found for:",
31949 return HANDLER_FINISHED;
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];
31958 if (hctx == NULL) return HANDLER_GO_ON;
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);
31967 case FCGI_STATE_CONNECT:
31968 case FCGI_STATE_WRITE:
31969 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31973 case FCGI_STATE_INIT:
31975 @@ -2873,21 +2870,21 @@
31977 static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
31978 plugin_data *p = p_d;
31981 return scgi_connection_close(srv, con->plugin_ctx[p->id]);
31984 TRIGGER_FUNC(mod_scgi_handle_trigger) {
31985 plugin_data *p = p_d;
31991 /* perhaps we should kill a connect attempt after 10-15 seconds
31994 * currently we wait for the TCP timeout which is on Linux 180 seconds
32003 /* check all childs if they are still up */
32004 @@ -2904,47 +2901,47 @@
32005 scgi_extension *ex;
32007 ex = exts->exts[j];
32010 for (n = 0; n < ex->used; n++) {
32014 unsigned long sum_load = 0;
32015 scgi_extension_host *host;
32018 host = ex->hosts[n];
32021 scgi_restart_dead_procs(srv, p, host);
32024 for (proc = host->first; proc; proc = proc->next) {
32025 sum_load += proc->load;
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;
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");
32043 for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
32047 if (fp == host->unused_procs) host->unused_procs = fp->next;
32050 if (fp->next) fp->next->prev = NULL;
32055 fp = scgi_process_init();
32056 fp->id = host->max_id++;
32063 if (buffer_is_empty(host->unixsocket)) {
32064 fp->port = host->port + fp->id;
32066 @@ -2952,13 +2949,13 @@
32067 buffer_append_string(fp->socket, "-");
32068 buffer_append_long(fp->socket, fp->id);
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;
32080 fp->next = host->first;
32082 @@ -2966,56 +2963,57 @@
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;
32094 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
32095 /* a proc is idling for a long time now,
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,
32112 if (proc->next) proc->next->prev = proc->prev;
32113 if (proc->prev) proc->prev->next = proc->next;
32116 if (proc->prev == NULL) host->first = proc->next;
32120 proc->next = host->unused_procs;
32123 if (host->unused_procs) host->unused_procs->prev = proc;
32124 host->unused_procs = proc;
32127 kill(proc->pid, SIGTERM);
32130 proc->state = PROC_STATE_KILLED;
32132 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32134 - "socket:", proc->socket,
32136 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32138 + "socket:", proc->socket,
32145 /* proc is now in unused, let the next second handle the next process */
32153 for (proc = host->unused_procs; proc; proc = proc->next) {
32157 if (proc->pid == 0) continue;
32160 switch (waitpid(proc->pid, &status, WNOHANG)) {
32162 /* child still running after timeout, good */
32163 @@ -3023,10 +3021,10 @@
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));
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",
32182 + log_error_write(srv, __FILE__, __LINE__, "sdb",
32184 WEXITSTATUS(status), proc->socket);
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:",
32195 - log_error_write(srv, __FILE__, __LINE__, "sd",
32196 - "child died somehow:",
32197 + log_error_write(srv, __FILE__, __LINE__, "sd",
32198 + "child died somehow:",
32202 proc->state = PROC_STATE_UNSET;
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;
32220 --- ../lighttpd-1.4.11/src/mod_secure_download.c 2005-12-14 14:37:29.000000000 +0200
32221 +++ lighttpd-1.4.12/src/mod_secure_download.c 2006-07-11 22:07:51.000000000 +0300
32231 @@ -36,28 +36,28 @@
32234 buffer *uri_prefix;
32237 unsigned short timeout;
32247 plugin_config **config_storage;
32249 - plugin_config conf;
32251 + plugin_config conf;
32254 /* init the plugin data */
32255 INIT_FUNC(mod_secdownload_init) {
32259 p = calloc(1, sizeof(*p));
32262 p->md5 = buffer_init();
32268 @@ -65,27 +65,27 @@
32269 FREE_FUNC(mod_secdownload_free) {
32270 plugin_data *p = p_d;
32274 if (!p) return HANDLER_GO_ON;
32277 if (p->config_storage) {
32279 for (i = 0; i < srv->config_context->used; i++) {
32280 plugin_config *s = p->config_storage[i];
32283 buffer_free(s->secret);
32284 buffer_free(s->doc_root);
32285 buffer_free(s->uri_prefix);
32290 free(p->config_storage);
32294 buffer_free(p->md5);
32300 return HANDLER_GO_ON;
32303 @@ -94,107 +94,103 @@
32304 SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
32305 plugin_data *p = p_d;
32308 - config_values_t cv[] = {
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 }
32319 if (!p) return HANDLER_ERROR;
32322 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32325 for (i = 0; i < srv->config_context->used; i++) {
32329 s = calloc(1, sizeof(plugin_config));
32330 s->secret = buffer_init();
32331 s->doc_root = buffer_init();
32332 s->uri_prefix = buffer_init();
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);
32342 p->config_storage[i] = s;
32345 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32346 return HANDLER_ERROR;
32351 return HANDLER_GO_ON;
32355 * checks if the supplied string is a MD5 string
32358 * @param str a possible MD5 string
32359 * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
32362 int is_hex_len(const char *str, size_t len) {
32366 if (NULL == str) return 0;
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'))
32384 -#define PATCH(x) \
32385 - p->conf.x = s->x;
32386 static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
32388 plugin_config *s = p->config_storage[0];
32392 - PATCH(uri_prefix);
32396 + PATCH_OPTION(secret);
32397 + PATCH_OPTION(doc_root);
32398 + PATCH_OPTION(uri_prefix);
32399 + PATCH_OPTION(timeout);
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];
32407 /* condition didn't match */
32408 if (!config_check_cond(srv, con, dc)) continue;
32412 for (j = 0; j < dc->value->used; j++) {
32413 data_unset *du = dc->value->data[j];
32416 if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
32418 + PATCH_OPTION(secret);
32419 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-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"))) {
32427 + PATCH_OPTION(timeout);
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;
32446 if (con->uri.path->used == 0) return HANDLER_GO_ON;
32449 mod_secdownload_patch_connection(srv, con, p);
32451 if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
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;
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;
32470 * /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
32474 if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
32477 md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
32480 if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
32481 if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
32484 ts_str = md5_str + 32 + 1;
32487 if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
32488 if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
32491 for (i = 0; i < 8; i++) {
32492 ts = (ts << 4) + hex2int(*(ts_str + i));
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;
32503 return HANDLER_FINISHED;
32507 rel_uri = ts_str + 8;
32514 * <secret><rel-path><timestamp-hex>
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);
32524 MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
32525 MD5_Final(HA1, &Md5Ctx);
32528 buffer_copy_string_hex(p->md5, (char *)HA1, 16);
32531 if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
32532 con->http_status = 403;
32534 - log_error_write(srv, __FILE__, __LINE__, "sss",
32536 + log_error_write(srv, __FILE__, __LINE__, "sss",
32538 md5_str, p->md5->ptr);
32541 return HANDLER_FINISHED;
32545 /* starting with the last / we should have relative-path to the docroot
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);
32555 return HANDLER_GO_ON;
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");
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;
32575 --- ../lighttpd-1.4.11/src/mod_setenv.c 2006-01-14 20:33:12.000000000 +0200
32576 +++ lighttpd-1.4.12/src/mod_setenv.c 2006-07-11 22:07:53.000000000 +0300
32577 @@ -18,25 +18,25 @@
32579 array *request_header;
32580 array *response_header;
32583 array *environment;
32590 plugin_config **config_storage;
32592 - plugin_config conf;
32594 + plugin_config conf;
32597 static handler_ctx * handler_ctx_init() {
32598 handler_ctx * hctx;
32601 hctx = calloc(1, sizeof(*hctx));
32610 @@ -48,36 +48,36 @@
32611 /* init the plugin data */
32612 INIT_FUNC(mod_setenv_init) {
32616 p = calloc(1, sizeof(*p));
32622 /* detroy the plugin data */
32623 FREE_FUNC(mod_setenv_free) {
32624 plugin_data *p = p_d;
32629 if (!p) return HANDLER_GO_ON;
32632 if (p->config_storage) {
32634 for (i = 0; i < srv->config_context->used; i++) {
32635 plugin_config *s = p->config_storage[i];
32638 array_free(s->request_header);
32639 array_free(s->response_header);
32640 array_free(s->environment);
32645 free(p->config_storage);
32652 return HANDLER_GO_ON;
32655 @@ -86,86 +86,83 @@
32656 SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
32657 plugin_data *p = p_d;
32660 - config_values_t cv[] = {
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 }
32670 if (!p) return HANDLER_ERROR;
32673 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32676 for (i = 0; i < srv->config_context->used; i++) {
32680 s = calloc(1, sizeof(plugin_config));
32681 s->request_header = array_init();
32682 s->response_header = array_init();
32683 s->environment = array_init();
32686 cv[0].destination = s->request_header;
32687 cv[1].destination = s->response_header;
32688 cv[2].destination = s->environment;
32691 p->config_storage[i] = s;
32694 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32695 return HANDLER_ERROR;
32700 return HANDLER_GO_ON;
32703 -#define PATCH(x) \
32704 - p->conf.x = s->x;
32705 static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
32707 plugin_config *s = p->config_storage[0];
32709 - PATCH(request_header);
32710 - PATCH(response_header);
32711 - PATCH(environment);
32714 + PATCH_OPTION(request_header);
32715 + PATCH_OPTION(response_header);
32716 + PATCH_OPTION(environment);
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];
32724 /* condition didn't match */
32725 if (!config_check_cond(srv, con, dc)) continue;
32729 for (j = 0; j < dc->value->used; j++) {
32730 data_unset *du = dc->value->data[j];
32733 if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
32734 - PATCH(request_header);
32735 + PATCH_OPTION(request_header);
32736 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
32737 - PATCH(response_header);
32738 + PATCH_OPTION(response_header);
32739 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
32740 - PATCH(environment);
32741 + PATCH_OPTION(environment);
32751 URIHANDLER_FUNC(mod_setenv_uri_handler) {
32752 plugin_data *p = p_d;
32757 if (con->plugin_ctx[p->id]) {
32758 hctx = con->plugin_ctx[p->id];
32760 hctx = handler_ctx_init();
32763 con->plugin_ctx[p->id] = hctx;
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;
32772 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
32773 ds_dst = data_string_init();
32777 buffer_copy_string_buffer(ds_dst->key, ds->key);
32778 buffer_copy_string_buffer(ds_dst->value, ds->value);
32781 array_insert_unique(con->request.headers, (data_unset *)ds_dst);
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;
32790 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
32791 ds_dst = data_string_init();
32795 buffer_copy_string_buffer(ds_dst->key, ds->key);
32796 buffer_copy_string_buffer(ds_dst->value, ds->value);
32799 array_insert_unique(con->environment, (data_unset *)ds_dst);
32803 for (k = 0; k < p->conf.response_header->used; k++) {
32804 data_string *ds = (data_string *)p->conf.response_header->data[k];
32807 response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
32812 return HANDLER_GO_ON;
32815 REQUESTDONE_FUNC(mod_setenv_reset) {
32816 plugin_data *p = p_d;
32822 if (con->plugin_ctx[p->id]) {
32823 handler_ctx_free(con->plugin_ctx[p->id]);
32824 con->plugin_ctx[p->id] = NULL;
32827 - return HANDLER_GO_ON;
32828 + return HANDLER_GO_ON;
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");
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;
32844 p->handle_request_done = mod_setenv_reset;
32851 --- ../lighttpd-1.4.11/src/mod_simple_vhost.c 2005-11-18 15:16:13.000000000 +0200
32852 +++ lighttpd-1.4.12/src/mod_simple_vhost.c 2006-07-11 22:07:52.000000000 +0300
32855 #include "plugin.h"
32857 +#include "sys-files.h"
32859 #ifdef HAVE_CONFIG_H
32860 #include "config.h"
32863 buffer *server_root;
32864 buffer *default_host;
32865 buffer *document_root;
32868 buffer *docroot_cache_key;
32869 buffer *docroot_cache_value;
32870 buffer *docroot_cache_servername;
32871 @@ -28,138 +30,138 @@
32880 plugin_config **config_storage;
32881 - plugin_config conf;
32882 + plugin_config conf;
32885 INIT_FUNC(mod_simple_vhost_init) {
32889 p = calloc(1, sizeof(*p));
32892 p->doc_root = buffer_init();
32898 FREE_FUNC(mod_simple_vhost_free) {
32899 plugin_data *p = p_d;
32904 if (!p) return HANDLER_GO_ON;
32907 if (p->config_storage) {
32909 for (i = 0; i < srv->config_context->used; i++) {
32910 plugin_config *s = p->config_storage[i];
32913 buffer_free(s->document_root);
32914 buffer_free(s->default_host);
32915 buffer_free(s->server_root);
32918 buffer_free(s->docroot_cache_key);
32919 buffer_free(s->docroot_cache_value);
32920 buffer_free(s->docroot_cache_servername);
32927 free(p->config_storage);
32931 buffer_free(p->doc_root);
32937 return HANDLER_GO_ON;
32940 SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
32941 plugin_data *p = p_d;
32944 - config_values_t cv[] = {
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 }
32955 if (!p) return HANDLER_ERROR;
32958 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32961 for (i = 0; i < srv->config_context->used; i++) {
32965 s = calloc(1, sizeof(plugin_config));
32968 s->server_root = buffer_init();
32969 s->default_host = buffer_init();
32970 s->document_root = buffer_init();
32973 s->docroot_cache_key = buffer_init();
32974 s->docroot_cache_value = buffer_init();
32975 s->docroot_cache_servername = buffer_init();
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);
32988 p->config_storage[i] = s;
32991 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32992 return HANDLER_ERROR;
32997 return HANDLER_GO_ON;
33000 static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
33001 stat_cache_entry *sce = NULL;
33004 buffer_prepare_copy(out, 128);
33006 if (p->conf.server_root->used) {
33007 buffer_copy_string_buffer(out, p->conf.server_root);
33011 /* a hostname has to start with a alpha-numerical character
33012 * and must not contain a slash "/"
33016 - BUFFER_APPEND_SLASH(out);
33019 + PATHNAME_APPEND_SLASH(out);
33021 if (NULL == (dp = strchr(host->ptr, ':'))) {
33022 buffer_append_string_buffer(out, host);
33024 buffer_append_string_len(out, host->ptr, dp - host->ptr);
33027 - BUFFER_APPEND_SLASH(out);
33029 + PATHNAME_APPEND_SLASH(out);
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);
33034 buffer_append_string_buffer(out, p->conf.document_root);
33035 - BUFFER_APPEND_SLASH(out);
33036 + PATHNAME_APPEND_SLASH(out);
33039 buffer_copy_string_buffer(out, con->conf.document_root);
33040 - BUFFER_APPEND_SLASH(out);
33041 + PATHNAME_APPEND_SLASH(out);
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)) {
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) {
33062 plugin_config *s = p->config_storage[0];
33064 - PATCH(server_root);
33065 - PATCH(default_host);
33066 - PATCH(document_root);
33068 - PATCH(docroot_cache_key);
33069 - PATCH(docroot_cache_value);
33070 - PATCH(docroot_cache_servername);
33074 + PATCH_OPTION(server_root);
33075 + PATCH_OPTION(default_host);
33076 + PATCH_OPTION(document_root);
33078 + PATCH_OPTION(docroot_cache_key);
33079 + PATCH_OPTION(docroot_cache_value);
33080 + PATCH_OPTION(docroot_cache_servername);
33082 + PATCH_OPTION(debug);
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];
33090 /* condition didn't match */
33091 if (!config_check_cond(srv, con, dc)) continue;
33095 for (j = 0; j < dc->value->used; j++) {
33096 data_unset *du = dc->value->data[j];
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"))) {
33116 + PATCH_OPTION(debug);
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 @@
33130 * cache the last successfull translation from hostname (authority) to docroot
33131 * - this saves us a stat() call
33137 mod_simple_vhost_patch_connection(srv, con, p);
33139 - if (p->conf.docroot_cache_key->used &&
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)) {
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,
33151 + if (build_doc_root(srv, con, p,
33153 p->conf.default_host)) {
33154 return HANDLER_GO_ON;
33156 @@ -253,15 +251,15 @@
33158 buffer_copy_string_buffer(con->server_name, con->uri.authority);
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);
33168 buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
33172 return HANDLER_GO_ON;
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");
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;
33192 --- ../lighttpd-1.4.11/src/mod_skeleton.c 2005-10-02 18:30:51.000000000 +0300
33193 +++ lighttpd-1.4.12/src/mod_skeleton.c 2006-07-11 22:07:51.000000000 +0300
33194 @@ -14,13 +14,13 @@
33197 * this is a skeleton for a lighttpd plugin
33200 * just replaces every occurance of 'skeleton' by your plugin name
33206 * :%s/skeleton/myhandler/
33212 @@ -33,12 +33,12 @@
33221 plugin_config **config_storage;
33223 - plugin_config conf;
33225 + plugin_config conf;
33229 @@ -47,36 +47,36 @@
33231 static handler_ctx * handler_ctx_init() {
33232 handler_ctx * hctx;
33235 hctx = calloc(1, sizeof(*hctx));
33241 static void handler_ctx_free(handler_ctx *hctx) {
33247 /* init the plugin data */
33248 INIT_FUNC(mod_skeleton_init) {
33252 p = calloc(1, sizeof(*p));
33255 p->match_buf = buffer_init();
33261 /* detroy the plugin data */
33262 FREE_FUNC(mod_skeleton_free) {
33263 plugin_data *p = p_d;
33268 if (!p) return HANDLER_GO_ON;
33271 if (p->config_storage) {
33274 @@ -84,18 +84,18 @@
33275 plugin_config *s = p->config_storage[i];
33280 array_free(s->match);
33285 free(p->config_storage);
33289 buffer_free(p->match_buf);
33295 return HANDLER_GO_ON;
33298 @@ -104,91 +104,88 @@
33299 SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
33300 plugin_data *p = p_d;
33303 - config_values_t cv[] = {
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 }
33311 if (!p) return HANDLER_ERROR;
33314 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33317 for (i = 0; i < srv->config_context->used; i++) {
33321 s = calloc(1, sizeof(plugin_config));
33322 s->match = array_init();
33325 cv[0].destination = s->match;
33328 p->config_storage[i] = s;
33331 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33332 return HANDLER_ERROR;
33337 return HANDLER_GO_ON;
33340 -#define PATCH(x) \
33341 - p->conf.x = s->x;
33342 static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
33344 plugin_config *s = p->config_storage[0];
33349 + PATCH_OPTION(match);
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];
33357 /* condition didn't match */
33358 if (!config_check_cond(srv, con, dc)) continue;
33362 for (j = 0; j < dc->value->used; j++) {
33363 data_unset *du = dc->value->data[j];
33366 if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
33368 + PATCH_OPTION(match);
33378 URIHANDLER_FUNC(mod_skeleton_uri_handler) {
33379 plugin_data *p = p_d;
33386 if (con->uri.path->used == 0) return HANDLER_GO_ON;
33389 mod_skeleton_patch_connection(srv, con, p);
33391 s_len = con->uri.path->used - 1;
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;
33399 if (ct_len > s_len) continue;
33400 if (ds->value->used == 0) continue;
33403 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
33404 con->http_status = 403;
33407 return HANDLER_FINISHED;
33413 return HANDLER_GO_ON;
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");
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;
33432 --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.c 1970-01-01 03:00:00.000000000 +0300
33433 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.c 2006-07-11 22:07:53.000000000 +0300
33435 +#include <stdio.h>
33436 +#include <errno.h>
33437 +#include <fcntl.h>
33438 +#include <string.h>
33440 +#ifdef HAVE_CONFIG_H
33441 +#include "config.h"
33444 +#include "plugin.h"
33447 +#include "stat_cache.h"
33449 +#include "mod_sql_vhost_core.h"
33451 +#define plugin_data mod_sql_vhost_core_plugin_data
33452 +#define plugin_config mod_sql_vhost_core_plugin_config
33454 +/* init the plugin data */
33455 +INIT_FUNC(mod_sql_vhost_core_init) {
33458 + p = calloc(1, sizeof(*p));
33460 + p->docroot = buffer_init();
33461 + p->host = buffer_init();
33466 +/* cleanup the plugin data */
33467 +SERVER_FUNC(mod_sql_vhost_core_cleanup) {
33468 + plugin_data *p = p_d;
33472 + if (!p) return HANDLER_GO_ON;
33474 + if (p->config_storage) {
33476 + for (i = 0; i < srv->config_context->used; i++) {
33477 + plugin_config *s = p->config_storage[i];
33479 + if (!s) continue;
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);
33489 + free(p->config_storage);
33491 + buffer_free(p->docroot);
33492 + buffer_free(p->host);
33496 + return HANDLER_GO_ON;
33499 +/* set configuration values */
33500 +SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
33501 + plugin_data *p = p_d;
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 */
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 */
33524 + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33527 + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33529 + for (i = 0; i < srv->config_context->used; i++) {
33530 + plugin_config *s;
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;
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;
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;
33561 + p->config_storage[i] = s;
33563 + if (config_insert_values_global(srv,
33564 + ((data_config *)srv->config_context->data[i])->value,
33565 + cv)) return HANDLER_ERROR;
33567 + /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
33570 + return HANDLER_GO_ON;
33573 +static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
33575 + plugin_config *s = p->config_storage[0];
33577 + PATCH_OPTION(backend_data);
33578 + PATCH_OPTION(get_vhost);
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];
33585 + /* condition didn't match */
33586 + if (!config_check_cond(srv, con, dc)) continue;
33588 + if (s->backend_data) {
33589 + PATCH_OPTION(backend_data);
33590 + PATCH_OPTION(get_vhost);
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;
33602 + /* no host specified? */
33603 + if (!con->uri.authority->used) return HANDLER_GO_ON;
33605 + mod_sql_vhost_core_patch_connection(srv, con, p);
33607 + /* do we have backend ? */
33608 + if (!p->conf.get_vhost) return HANDLER_GO_ON;
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;
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;
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;
33624 + buffer_copy_string_buffer(con->server_name, p->host);
33625 + buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
33627 + return HANDLER_GO_ON;
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");
33635 + p->init = mod_sql_vhost_core_init;
33636 + p->cleanup = mod_sql_vhost_core_cleanup;
33638 + p->set_defaults = mod_sql_vhost_core_set_defaults;
33639 + p->handle_docroot = mod_sql_vhost_core_handle_docroot;
33644 --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.h 1970-01-01 03:00:00.000000000 +0300
33645 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.h 2006-07-11 22:07:53.000000000 +0300
33647 +#ifndef _MOD_SQL_VHOST_CORE_H_
33648 +#define _MOD_SQL_VHOST_CORE_H_
33650 +#include "buffer.h"
33651 +#include "plugin.h"
33653 +#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
33654 + (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
33656 +#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
33658 +#define SQLVHOST_BACKEND_GETVHOST(name) \
33659 + SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
33661 +#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
33662 + SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
33670 + buffer *hostname;
33671 + unsigned short port;
33674 + void *backend_data;
33676 + buffer *select_vhost;
33678 + SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
33679 +} mod_sql_vhost_core_plugin_config;
33681 +/* global plugin data */
33688 + mod_sql_vhost_core_plugin_config **config_storage;
33690 + mod_sql_vhost_core_plugin_config conf;
33691 +} mod_sql_vhost_core_plugin_data;
33696 --- ../lighttpd-1.4.11/src/mod_ssi.c 2006-03-04 17:09:48.000000000 +0200
33697 +++ lighttpd-1.4.12/src/mod_ssi.c 2006-07-11 22:07:53.000000000 +0300
33699 #include <string.h>
33702 -#include <unistd.h>
33707 #include "inet_ntop_cache.h"
33709 #include "sys-socket.h"
33710 +#include "sys-strings.h"
33711 +#include "sys-files.h"
33715 @@ -39,15 +40,15 @@
33716 /* init the plugin data */
33717 INIT_FUNC(mod_ssi_init) {
33721 p = calloc(1, sizeof(*p));
33724 p->timefmt = buffer_init();
33725 p->stat_fn = buffer_init();
33728 p->ssi_vars = array_init();
33729 p->ssi_cgi_env = array_init();
33735 @@ -55,21 +56,21 @@
33736 FREE_FUNC(mod_ssi_free) {
33737 plugin_data *p = p_d;
33741 if (!p) return HANDLER_GO_ON;
33744 if (p->config_storage) {
33746 for (i = 0; i < srv->config_context->used; i++) {
33747 plugin_config *s = p->config_storage[i];
33750 array_free(s->ssi_extension);
33755 free(p->config_storage);
33759 array_free(p->ssi_vars);
33760 array_free(p->ssi_cgi_env);
33764 buffer_free(p->timefmt);
33765 buffer_free(p->stat_fn);
33771 return HANDLER_GO_ON;
33774 @@ -92,36 +93,36 @@
33775 const char *errptr;
33779 - config_values_t cv[] = {
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 }
33787 if (!p) return HANDLER_ERROR;
33790 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33793 for (i = 0; i < srv->config_context->used; i++) {
33797 s = calloc(1, sizeof(plugin_config));
33798 s->ssi_extension = array_init();
33801 cv[0].destination = s->ssi_extension;
33804 p->config_storage[i] = s;
33807 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33808 return HANDLER_ERROR;
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",
33820 return HANDLER_ERROR;
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;
33828 return HANDLER_GO_ON;
33831 int ssi_env_add(array *env, const char *key, const char *val) {
33835 if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
33836 ds = data_string_init();
33838 buffer_copy_string(ds->key, key);
33839 buffer_copy_string(ds->value, val);
33842 array_insert_unique(env, (data_unset *)ds);
33850 * the next two functions are take from fcgi.c
33855 static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
33859 for (i = 0; i < con->request.headers->used; i++) {
33863 ds = (data_string *)con->request.headers->data[i];
33866 if (ds->value->used && ds->key->used) {
33868 buffer_reset(srv->tmp_buf);
33871 /* don't forward the Authorization: Header */
33872 if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
33877 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
33878 buffer_copy_string(srv->tmp_buf, "HTTP_");
33879 srv->tmp_buf->used--;
33883 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
33884 for (j = 0; j < ds->key->used - 1; j++) {
33886 @@ -189,33 +190,33 @@
33887 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
33889 srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
33892 ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
33900 static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
33904 server_socket *srv_sock = con->srv_socket;
33908 char b2[INET6_ADDRSTRLEN + 1];
33911 #define CONST_STRING(x) \
33915 array_reset(p->ssi_cgi_env);
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"),
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),
33928 @@ -224,28 +225,28 @@
33931 ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
33937 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
33939 ntohs(srv_sock->addr.ipv4.sin_port)
33944 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
33947 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
33948 inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
33951 if (con->authed_user->used) {
33952 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
33953 con->authed_user->ptr);
33957 if (con->request.content_length > 0) {
33958 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
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);
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);
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));
33981 ssi_env_add_request_headers(srv, con, p);
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;
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;
34003 @@ -310,27 +311,27 @@
34004 { "endif", SSI_ENDIF },
34005 { "else", SSI_ELSE },
34006 { "exec", SSI_EXEC },
34009 { NULL, SSI_UNSET }
34013 for (i = 0; ssicmds[i].var; i++) {
34014 if (0 == strcmp(l[1], ssicmds[i].var)) {
34015 ssicmd = ssicmds[i].type;
34024 int var = 0, enc = 0;
34025 const char *var_val = NULL;
34026 stat_cache_entry *sce = NULL;
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;
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 },
34043 { NULL, SSI_ECHO_UNSET }
34050 enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
34052 { "url", SSI_ENC_URL },
34053 { "none", SSI_ENC_NONE },
34054 { "entity", SSI_ENC_ENTITY },
34057 { NULL, SSI_ENC_UNSET }
34061 for (i = 2; i < n; i += 2) {
34062 if (0 == strcmp(l[i], "var")) {
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 @@
34074 } else if (0 == strcmp(l[i], "encoding")) {
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 @@
34084 log_error_write(srv, __FILE__, __LINE__, "sss",
34085 - "ssi: unknow attribute for ",
34086 + "ssi: unknow attribute for ",
34092 if (p->if_is_false) break;
34096 log_error_write(srv, __FILE__, __LINE__, "sss",
34099 l[1], "var is missing");
34103 stat_cache_get_entry(srv, con, con->physical.path, &sce);
34107 case SSI_ECHO_USER_NAME: {
34111 b = chunkqueue_get_append_buffer(con->write_queue);
34113 if (NULL == (pw = getpwuid(sce->st.st_uid))) {
34114 @@ -411,7 +412,7 @@
34116 case SSI_ECHO_LAST_MODIFIED: {
34117 time_t t = sce->st.st_mtime;
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 @@
34125 case SSI_ECHO_DATE_LOCAL: {
34126 time_t t = time(NULL);
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 @@
34134 case SSI_ECHO_DATE_GMT: {
34135 time_t t = time(NULL);
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 @@
34143 case SSI_ECHO_DOCUMENT_NAME: {
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 @@
34153 /* check if it is a cgi-var */
34156 b = chunkqueue_get_append_buffer(con->write_queue);
34159 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
34160 buffer_copy_string_buffer(b, ds->value);
34162 buffer_copy_string(b, "(none)");
34169 @@ -481,7 +482,7 @@
34170 const char * file_path = NULL, *virt_path = NULL;
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];
34181 log_error_write(srv, __FILE__, __LINE__, "sss",
34182 - "ssi: unknow attribute for ",
34183 + "ssi: unknow attribute for ",
34189 if (!file_path && !virt_path) {
34190 log_error_write(srv, __FILE__, __LINE__, "sss",
34193 l[1], "file or virtual are missing");
34198 if (file_path && virt_path) {
34199 log_error_write(srv, __FILE__, __LINE__, "sss",
34202 l[1], "only one of file and virtual is allowed here");
34209 if (p->if_is_false) break;
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);
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);
34230 if (virt_path[0] == '/') {
34231 buffer_copy_string(p->stat_fn, virt_path);
34233 /* there is always a / */
34234 sl = strrchr(con->uri.path->ptr, '/');
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);
34242 buffer_urldecode_path(p->stat_fn);
34243 buffer_path_simplify(srv->tmp_buf, p->stat_fn);
34246 /* we have an uri */
34249 buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
34250 buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34254 if (0 == stat(p->stat_fn->ptr, &st)) {
34255 time_t t = st.st_mtime;
34260 b = chunkqueue_get_append_buffer(con->write_queue);
34263 const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
34266 off_t s = st.st_size;
34269 for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
34272 buffer_copy_off_t(b, s);
34273 buffer_append_string(b, abr[j]);
34275 @@ -579,7 +580,7 @@
34278 log_error_write(srv, __FILE__, __LINE__, "sbs",
34279 - "ssi: stating failed ",
34280 + "ssi: stating failed ",
34281 p->stat_fn, strerror(errno));
34284 @@ -593,33 +594,33 @@
34287 log_error_write(srv, __FILE__, __LINE__, "sss",
34288 - "ssi: unknow attribute for ",
34289 + "ssi: unknow attribute for ",
34295 if (p->if_is_false) break;
34302 if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
34303 ds = data_string_init();
34305 buffer_copy_string(ds->key, key);
34306 buffer_copy_string(ds->value, val);
34309 array_insert_unique(p->ssi_vars, (data_unset *)ds);
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",
34320 if (p->if_is_false) break;
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 '",
34335 log_error_write(srv, __FILE__, __LINE__, "sss",
34336 - "ssi: unknow attribute for ",
34337 + "ssi: unknow attribute for ",
34343 if (p->if_is_false) break;
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]];
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 />");
34359 buffer_append_string(b, "</pre>");
34366 const char *cmd = NULL;
34368 int from_exec_fds[2];
34371 for (i = 2; i < n; i += 2) {
34372 if (0 == strcmp(l[i], "cmd")) {
34375 log_error_write(srv, __FILE__, __LINE__, "sss",
34376 - "ssi: unknow attribute for ",
34377 + "ssi: unknow attribute for ",
34383 if (p->if_is_false) break;
34386 /* create a return pipe and send output to the html-page
34388 - * as exec is assumed evil it is implemented synchronously
34390 + * as exec is assumed evil it is implemented synchronously
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));
34406 switch (pid = fork()) {
34408 @@ -698,14 +701,14 @@
34409 close(from_exec_fds[1]);
34411 close(from_exec_fds[0]);
34415 close(STDIN_FILENO);
34418 execl("/bin/sh", "sh", "-c", cmd, NULL);
34421 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
34427 @@ -718,9 +721,9 @@
34433 close(from_exec_fds[1]);
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 @@
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)");
34448 @@ -738,10 +741,10 @@
34450 b = chunkqueue_get_append_buffer(con->write_queue);
34452 - buffer_prepare_copy(b, toread + 1);
34453 + buffer_prepare_copy(b, toread + 1);
34455 if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
34456 - /* read failed */
34457 + /* read failed */
34461 @@ -755,59 +758,58 @@
34462 log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
34464 close(from_exec_fds[0]);
34479 const char *expr = NULL;
34482 for (i = 2; i < n; i += 2) {
34483 if (0 == strcmp(l[i], "expr")) {
34486 log_error_write(srv, __FILE__, __LINE__, "sss",
34487 - "ssi: unknow attribute for ",
34488 + "ssi: unknow attribute for ",
34495 log_error_write(srv, __FILE__, __LINE__, "sss",
34498 l[1], "expr missing");
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)) {
34510 - p->if_is_false = 1;
34512 + p->if_is_false = 1;
34513 p->if_is_false_level = p->if_level;
34516 - p->if_is_false = 0;
34518 + p->if_is_false = 0;
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 @@
34539 p->if_is_false = 1;
34542 p->if_is_false_level = p->if_level;
34549 const char *expr = NULL;
34550 @@ -828,52 +830,52 @@
34553 log_error_write(srv, __FILE__, __LINE__, "sss",
34554 - "ssi: unknow attribute for ",
34555 + "ssi: unknow attribute for ",
34562 log_error_write(srv, __FILE__, __LINE__, "sss",
34565 l[1], "expr missing");
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)) {
34579 - p->if_is_false = 1;
34581 + p->if_is_false = 1;
34582 p->if_is_false_level = p->if_level;
34585 - p->if_is_false = 0;
34587 + p->if_is_false = 0;
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;
34608 if (p->if_level == p->if_is_false_level) {
34609 p->if_is_false = 0;
34610 p->if_is_false_endif = 0;
34616 log_error_write(srv, __FILE__, __LINE__, "ss",
34617 @@ -881,41 +883,41 @@
34628 static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
34639 /* get a stream to the file */
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");
34646 build_ssi_cgi_vars(srv, con, p);
34647 p->if_is_false = 0;
34650 if (-1 == stream_open(&s, con->physical.path)) {
34651 log_error_write(srv, __FILE__, __LINE__, "sb",
34652 "stream-open: ", con->physical.path);
34660 - * <!--#element attribute=value attribute=value ... -->
34662 + * <!--#element attribute=value attribute=value ... -->
34665 - * errmsg -- missing
34666 + * errmsg -- missing
34670 @@ -937,13 +939,13 @@
34687 @@ -951,118 +953,115 @@
34699 - * The current date in Greenwich Mean Time.
34701 - * The current date in the local time zone.
34703 - * The filename (excluding directories) of the document requested by the user.
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.
34707 - * The last modification date of the document requested by the user.
34710 + * The current date in Greenwich Mean Time.
34712 + * The current date in the local time zone.
34714 + * The filename (excluding directories) of the document requested by the user.
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.
34718 + * The last modification date of the document requested by the user.
34720 * Contains the owner of the file which included it.
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]) {
34728 /* take everything from last offset to current match pos */
34731 if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
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);
34741 case PCRE_ERROR_NOMATCH:
34742 /* copy everything/the rest */
34743 chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
34748 log_error_write(srv, __FILE__, __LINE__, "sd",
34749 "execution error while matching: ", n);
34761 con->file_started = 1;
34762 con->file_finished = 1;
34765 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
34768 /* reset physical.path */
34769 buffer_reset(con->physical.path);
34775 -#define PATCH(x) \
34776 - p->conf.x = s->x;
34777 static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
34779 plugin_config *s = p->config_storage[0];
34781 - PATCH(ssi_extension);
34784 + PATCH_OPTION(ssi_extension);
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];
34792 /* condition didn't match */
34793 if (!config_check_cond(srv, con, dc)) continue;
34797 for (j = 0; j < dc->value->used; j++) {
34798 data_unset *du = dc->value->data[j];
34801 if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
34802 - PATCH(ssi_extension);
34803 + PATCH_OPTION(ssi_extension);
34813 URIHANDLER_FUNC(mod_ssi_physical_path) {
34814 plugin_data *p = p_d;
34818 if (con->physical.path->used == 0) return HANDLER_GO_ON;
34821 mod_ssi_patch_connection(srv, con, p);
34824 for (k = 0; k < p->conf.ssi_extension->used; k++) {
34825 data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
34828 if (ds->value->used == 0) continue;
34831 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
34832 /* handle ssi-request */
34835 if (mod_ssi_handle_request(srv, con, p)) {
34837 con->http_status = 500;
34841 return HANDLER_FINISHED;
34847 return HANDLER_GO_ON;
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");
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;
34866 --- ../lighttpd-1.4.11/src/mod_ssi.h 2005-08-11 01:26:39.000000000 +0300
34867 +++ lighttpd-1.4.12/src/mod_ssi.h 2006-07-11 22:07:53.000000000 +0300
34868 @@ -19,23 +19,23 @@
34873 -#ifdef HAVE_PCRE_H
34875 +#ifdef HAVE_PCRE_H
34887 array *ssi_cgi_env;
34890 int if_level, if_is_false_level, if_is_false, if_is_false_endif;
34893 plugin_config **config_storage;
34895 - plugin_config conf;
34897 + plugin_config conf;
34900 int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
34901 --- ../lighttpd-1.4.11/src/mod_ssi_expr.c 2005-08-11 01:26:48.000000000 +0300
34902 +++ lighttpd-1.4.12/src/mod_ssi_expr.c 2006-07-11 22:07:52.000000000 +0300
34915 @@ -21,15 +21,15 @@
34917 ssi_val_t *ssi_val_init() {
34921 s = calloc(1, sizeof(*s));
34927 void ssi_val_free(ssi_val_t *s) {
34928 if (s->str) buffer_free(s->str);
34934 @@ -45,175 +45,175 @@
34935 ssi_tokenizer_t *t, int *token_id, buffer *token) {
34942 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
34943 char c = t->input[t->offset];
34957 buffer_copy_string(token, "(=)");
34962 if (t->input[t->offset + 1] == '=') {
34970 buffer_copy_string(token, "(>=)");
34979 buffer_copy_string(token, "(>)");
34985 if (t->input[t->offset + 1] == '=') {
34993 buffer_copy_string(token, "(<=)");
35002 buffer_copy_string(token, "(<)");
35010 if (t->input[t->offset + 1] == '=') {
35018 buffer_copy_string(token, "(!=)");
35027 buffer_copy_string(token, "(!)");
35033 if (t->input[t->offset + 1] == '&') {
35041 buffer_copy_string(token, "(&&)");
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 &");
35054 if (t->input[t->offset + 1] == '|') {
35062 buffer_copy_string(token, "(||)");
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 |");
35082 /* search for the terminating " */
35083 for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
35086 if (t->input[t->offset + i]) {
35090 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35093 t->offset += i + 1;
35094 t->line_pos += i + 1;
35098 - log_error_write(srv, __FILE__, __LINE__, "sds",
35099 - "pos:", t->line_pos,
35101 + log_error_write(srv, __FILE__, __LINE__, "sds",
35102 + "pos:", t->line_pos,
35103 "missing closing quote");
35119 buffer_copy_string(token, "(");
35129 buffer_copy_string(token, ")");
35132 if (t->input[t->offset + 1] == '{') {
35133 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
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");
35148 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
35150 for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_'; i++);
35153 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
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 @@
35165 buffer_copy_string(token, "");
35175 for (i = 0; isgraph(t->input[t->offset + i]); i++) {
35176 char d = t->input[t->offset + i];
35183 @@ -244,25 +244,25 @@
35192 buffer_copy_string_len(token, t->input + t->offset, i);
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,
35217 @@ -275,50 +275,50 @@
35225 t.size = strlen(expr);
35238 /* default context */
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);
35247 token = buffer_init();
35249 ssiexprparser(pParser, 0, token, &context);
35250 ssiexprparserFree(pParser, free );
35253 buffer_free(token);
35257 - log_error_write(srv, __FILE__, __LINE__, "s",
35258 + log_error_write(srv, __FILE__, __LINE__, "s",
35259 "expr parser failed");
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");
35273 - log_error_write(srv, __FILE__, __LINE__, "ssd",
35274 + log_error_write(srv, __FILE__, __LINE__, "ssd",
35280 return context.val.bo;
35282 --- ../lighttpd-1.4.11/src/mod_ssi_expr.h 2005-08-11 01:26:48.000000000 +0300
35283 +++ lighttpd-1.4.12/src/mod_ssi_expr.h 2006-07-11 22:07:52.000000000 +0300
35287 enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
35304 --- ../lighttpd-1.4.11/src/mod_ssi_exprparser.c 2005-10-03 00:40:25.000000000 +0300
35305 +++ lighttpd-1.4.12/src/mod_ssi_exprparser.c 2006-07-11 22:08:02.000000000 +0300
35306 @@ -18,10 +18,10 @@
35307 /* Next is all token values, in a form suitable for use by makeheaders.
35308 ** This section will be null unless lemon is run with the -m switch.
35312 ** These constants (all generated automatically by the parser generator)
35313 ** specify the various kinds of tokens (terminals) that the parser
35317 ** Each symbol here is a terminal symbol in the grammar.
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
35326 ** YYFALLBACK If defined, this indicates that one or more tokens
35327 ** have fall-back values which should be used if the
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
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.
35344 ** Suppose the action integer is N. Then the action is determined as
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.
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 @@
35357 /* The next table maps tokens into fallback tokens. If a construct
35358 ** like the following:
35361 ** %fallback ID X Y Z.
35363 ** appears in the grammer, then ID becomes a fallback token for X, Y,
35364 @@ -219,10 +219,10 @@
35365 #endif /* NDEBUG */
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
35377 @@ -247,7 +247,7 @@
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 @@
35392 ** This function allocates a new parser.
35393 ** The only argument is a pointer to a function which works like
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.
35403 ** Note: during a reduce, the only symbols destroyed are those
35404 @@ -379,7 +379,7 @@
35410 ** Deallocate and destroy a parser. Destructors are all called for
35411 ** all stack elements before shutting the parser down.
35413 @@ -415,7 +415,7 @@
35416 int stateno = pParser->yystack[pParser->yyidx].stateno;
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 @@
35425 int stateno = pParser->yystack[pParser->yyidx].stateno;
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];
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".
35447 ** This is what we do if the grammar does define ERROR:
35449 --- ../lighttpd-1.4.11/src/mod_staticfile.c 2006-02-15 14:31:14.000000000 +0200
35450 +++ lighttpd-1.4.12/src/mod_staticfile.c 2006-07-11 22:07:51.000000000 +0300
35452 #include "http_chunk.h"
35453 #include "response.h"
35455 +#include "sys-files.h"
35456 +#include "sys-strings.h"
35458 * this is a staticfile for a lighttpd plugin
35464 @@ -29,48 +31,48 @@
35473 plugin_config **config_storage;
35475 - plugin_config conf;
35477 + plugin_config conf;
35480 /* init the plugin data */
35481 INIT_FUNC(mod_staticfile_init) {
35485 p = calloc(1, sizeof(*p));
35488 p->range_buf = buffer_init();
35494 -/* detroy the plugin data */
35495 +/* destroy the plugin data */
35496 FREE_FUNC(mod_staticfile_free) {
35497 plugin_data *p = p_d;
35502 if (!p) return HANDLER_GO_ON;
35505 if (p->config_storage) {
35507 for (i = 0; i < srv->config_context->used; i++) {
35508 plugin_config *s = p->config_storage[i];
35511 array_free(s->exclude_ext);
35516 free(p->config_storage);
35518 buffer_free(p->range_buf);
35524 return HANDLER_GO_ON;
35527 @@ -79,63 +81,60 @@
35528 SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
35529 plugin_data *p = p_d;
35532 - config_values_t cv[] = {
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 }
35540 if (!p) return HANDLER_ERROR;
35543 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
35546 for (i = 0; i < srv->config_context->used; i++) {
35550 s = calloc(1, sizeof(plugin_config));
35551 s->exclude_ext = array_init();
35554 cv[0].destination = s->exclude_ext;
35557 p->config_storage[i] = s;
35560 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
35561 return HANDLER_ERROR;
35566 return HANDLER_GO_ON;
35569 -#define PATCH(x) \
35570 - p->conf.x = s->x;
35571 static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
35573 plugin_config *s = p->config_storage[0];
35575 - PATCH(exclude_ext);
35578 + PATCH_OPTION(exclude_ext);
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];
35586 /* condition didn't match */
35587 if (!config_check_cond(srv, con, dc)) continue;
35591 for (j = 0; j < dc->value->used; j++) {
35592 data_unset *du = dc->value->data[j];
35595 if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
35596 - PATCH(exclude_ext);
35597 + PATCH_OPTION(exclude_ext);
35607 static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
35609 @@ -146,69 +145,69 @@
35611 stat_cache_entry *sce = NULL;
35612 buffer *content_type = NULL;
35615 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35621 end = sce->st.st_size - 1;
35624 con->response.content_length = 0;
35627 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
35628 content_type = ds->value;
35632 for (s = con->request.http_range, error = 0;
35633 !error && *s && NULL != (minus = strchr(s, '-')); ) {
35642 le = strtoll(s, &err, 10);
35646 /* RFC 2616 - 14.35.1 */
35649 con->http_status = 416;
35651 } else if (*err == '\0') {
35656 end = sce->st.st_size - 1;
35657 start = sce->st.st_size + le;
35658 } else if (*err == ',') {
35663 end = sce->st.st_size - 1;
35664 start = sce->st.st_size + le;
35670 } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
35674 la = strtoll(s, &err, 10);
35677 if (err == minus) {
35681 if (*(err + 1) == '\0') {
35685 end = sce->st.st_size - 1;
35689 } else if (*(err + 1) == ',') {
35694 end = sce->st.st_size - 1;
35697 @@ -220,64 +219,64 @@
35700 /* <start>-<stop> */
35703 la = strtoll(s, &err, 10);
35706 if (err == minus) {
35707 le = strtoll(minus+1, &err, 10);
35710 /* RFC 2616 - 14.35.1 */
35716 if (*err == '\0') {
35723 } else if (*err == ',') {
35746 if (start < 0) start = 0;
35749 /* RFC 2616 - 14.35.1 */
35750 if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
35753 if (start > sce->st.st_size - 1) {
35757 con->http_status = 416;
35764 /* write boundary-header */
35768 b = chunkqueue_get_append_buffer(con->write_queue);
35771 buffer_copy_string(b, "\r\n--");
35772 buffer_append_string(b, boundary);
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);
35784 buffer_append_string(b, "\r\nContent-Type: ");
35785 buffer_append_string_buffer(b, content_type);
35788 /* write END-OF-HEADER */
35789 buffer_append_string(b, "\r\n\r\n");
35792 con->response.content_length += b->used - 1;
35798 chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
35799 con->response.content_length += end - start + 1;
35804 /* something went wrong */
35805 if (error) return -1;
35809 /* add boundary end */
35813 b = chunkqueue_get_append_buffer(con->write_queue);
35816 buffer_copy_string_len(b, "\r\n--", 4);
35817 buffer_append_string(b, boundary);
35818 buffer_append_string_len(b, "--\r\n", 4);
35821 con->response.content_length += b->used - 1;
35824 /* set header-fields */
35827 buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
35828 buffer_append_string(p->range_buf, boundary);
35831 /* overwrite content-type */
35832 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
35834 /* add Content-Range-header */
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);
35845 response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
35848 @@ -347,12 +346,12 @@
35849 stat_cache_entry *sce = NULL;
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;
35860 /* someone else has handled this request */
35861 if (con->mode != DIRECT) return HANDLER_GO_ON;
35863 @@ -365,52 +364,52 @@
35865 return HANDLER_GO_ON;
35869 mod_staticfile_patch_connection(srv, con, p);
35872 s_len = con->uri.path->used - 1;
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];
35879 + ds = (data_string *)p->conf.exclude_ext->data[k];
35881 if (ds->value->used == 0) continue;
35883 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
35884 return HANDLER_GO_ON;
35890 if (con->conf.log_request_handling) {
35891 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling file as static file");
35895 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35896 con->http_status = 403;
35899 log_error_write(srv, __FILE__, __LINE__, "sbsb",
35900 "not a regular file:", con->uri.path,
35901 "->", con->physical.path);
35904 return HANDLER_FINISHED;
35907 - /* we only handline regular files */
35909 + /* we only handle regular files */
35910 if (!S_ISREG(sce->st.st_mode)) {
35911 con->http_status = 404;
35914 if (con->conf.log_file_not_found) {
35915 log_error_write(srv, __FILE__, __LINE__, "sbsb",
35916 "not a regular file:", con->uri.path,
35921 return HANDLER_FINISHED;
35924 - /* mod_compress might set several data directly, don't overwrite them */
35926 + /* mod_compress might set several parameters directly; don't overwrite them */
35928 /* set response content-type, if not set already */
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));
35937 if (NULL == array_get_element(con->response.headers, "ETag")) {
35938 /* generate e-tag */
35939 etag_mutate(con->physical.etag, sce->etag);
35942 response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
35944 response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
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 */
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 */
35958 if (!buffer_is_equal(ds->value, con->physical.etag)) {
35959 do_range_request = 0;
35964 if (do_range_request) {
35965 /* content prepared, I'm done */
35966 con->file_finished = 1;
35969 if (0 == http_response_parse_range(srv, con, p)) {
35970 con->http_status = 206;
35972 return HANDLER_FINISHED;
35977 /* if we are still here, prepare body */
35979 - /* we add it here for all requests
35980 - * the HEAD request will drop it afterwards again
35982 + /* we add it here for all requests
35983 + * the HEAD request will drop it afterwards again
35985 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
35988 con->file_finished = 1;
35991 return HANDLER_FINISHED;
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");
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;
36011 --- ../lighttpd-1.4.11/src/mod_status.c 2006-01-10 21:45:32.000000000 +0200
36012 +++ lighttpd-1.4.12/src/mod_status.c 2006-07-11 22:07:53.000000000 +0300
36015 #include <stdlib.h>
36016 #include <string.h>
36017 -#include <unistd.h>
36021 @@ -29,114 +28,114 @@
36027 double traffic_out;
36031 double mod_5s_traffic_out[5];
36032 double mod_5s_requests[5];
36036 double rel_traffic_out;
36037 double rel_requests;
36040 double abs_traffic_out;
36041 double abs_requests;
36044 double bytes_written;
36047 buffer *module_list;
36050 plugin_config **config_storage;
36052 - plugin_config conf;
36054 + plugin_config conf;
36057 INIT_FUNC(mod_status_init) {
36062 p = calloc(1, sizeof(*p));
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();
36072 for (i = 0; i < 5; i++) {
36073 p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
36080 FREE_FUNC(mod_status_free) {
36081 plugin_data *p = p_d;
36086 if (!p) return HANDLER_GO_ON;
36089 buffer_free(p->module_list);
36092 if (p->config_storage) {
36094 for (i = 0; i < srv->config_context->used; i++) {
36095 plugin_config *s = p->config_storage[i];
36098 buffer_free(s->status_url);
36099 buffer_free(s->statistics_url);
36100 buffer_free(s->config_url);
36105 free(p->config_storage);
36114 return HANDLER_GO_ON;
36117 SETDEFAULTS_FUNC(mod_status_set_defaults) {
36118 plugin_data *p = p_d;
36121 - config_values_t cv[] = {
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 }
36132 if (!p) return HANDLER_ERROR;
36135 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36138 for (i = 0; i < srv->config_context->used; i++) {
36142 s = calloc(1, sizeof(plugin_config));
36143 s->config_url = buffer_init();
36144 s->status_url = buffer_init();
36146 s->statistics_url = buffer_init();
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;
36155 p->config_storage[i] = s;
36158 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36159 return HANDLER_ERROR;
36164 return HANDLER_GO_ON;
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");
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");
36185 static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
36186 plugin_data *p = p_d;
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");
36201 static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
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 @@
36211 char multiplier = '\0';
36217 int days, hours, mins, seconds;
36220 b = chunkqueue_get_append_buffer(con->write_queue);
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"
36229 " <title>Status</title>\n");
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"
36241 if (p->conf.sort) {
36242 BUFFER_APPEND_STRING_CONST(b,
36243 "<script type=\"text/javascript\">\n"
36245 "var sort_column;\n"
36246 "var prev_span = null;\n");
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 @@
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"
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");
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 @@
36284 - BUFFER_APPEND_STRING_CONST(b,
36286 + BUFFER_APPEND_STRING_CONST(b,
36295 /* connection listing */
36296 BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
36298 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
36299 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
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\">");
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\">");
36313 ts = srv->cur_ts - srv->startup_ts;
36316 days = ts / (60 * 60 * 24);
36317 ts %= (60 * 60 * 24);
36320 hours = ts / (60 * 60);
36332 buffer_append_long(b, days);
36333 BUFFER_APPEND_STRING_CONST(b, " days ");
36338 buffer_append_long(b, hours);
36339 BUFFER_APPEND_STRING_CONST(b, " hours ");
36344 buffer_append_long(b, mins);
36345 BUFFER_APPEND_STRING_CONST(b, " min ");
36349 buffer_append_long(b, seconds);
36350 BUFFER_APPEND_STRING_CONST(b, " s");
36353 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36354 BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
36357 ts = srv->startup_ts;
36359 - strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
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");
36368 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
36370 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36372 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
36373 avg = p->abs_requests;
36375 mod_status_get_multiplier(&avg, &multiplier, 1000);
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");
36384 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36385 + BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
36387 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
36388 avg = p->abs_traffic_out;
36390 mod_status_get_multiplier(&avg, &multiplier, 1024);
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");
36402 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
36404 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
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);
36409 mod_status_get_multiplier(&avg, &multiplier, 1000);
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");
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");
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);
36423 mod_status_get_multiplier(&avg, &multiplier, 1024);
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");
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];
36445 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36447 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
36449 mod_status_get_multiplier(&avg, &multiplier, 1000);
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);
36456 - BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36459 + BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36461 for (j = 0, avg = 0; j < 5; j++) {
36462 avg += p->mod_5s_traffic_out[j];
36468 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36470 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
36472 mod_status_get_multiplier(&avg, &multiplier, 1024);
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");
36481 + BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36483 BUFFER_APPEND_STRING_CONST(b, "</table>\n");
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");
36494 - BUFFER_APPEND_STRING_CONST(b, "<b>");
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");
36500 + BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
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);
36507 buffer_append_string_len(b, state, 1);
36510 if (((j + 1) % 50) == 0) {
36511 BUFFER_APPEND_STRING_CONST(b, "\n");
36516 BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
36518 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
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");
36530 for (j = 0; j < srv->conns->used; j++) {
36531 connection *c = srv->conns->ptr[j];
36533 - BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
36536 + BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
36538 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
36540 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36543 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
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 @@
36550 BUFFER_APPEND_STRING_CONST(b, "0/0");
36553 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36556 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
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));
36562 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36565 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
36567 buffer_append_string(b, connection_get_state(c->state));
36569 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36572 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
36574 buffer_append_long(b, srv->cur_ts - c->request_start);
36576 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36579 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
36581 if (buffer_is_empty(c->server_name)) {
36582 buffer_append_string_buffer(b, c->uri.authority);
36585 buffer_append_string_buffer(b, c->server_name);
36588 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36591 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
36593 if (!buffer_is_empty(c->uri.path)) {
36594 buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
36597 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36600 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
36602 buffer_append_string_buffer(b, c->physical.path);
36605 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36609 - BUFFER_APPEND_STRING_CONST(b,
36612 + BUFFER_APPEND_STRING_CONST(b,
36616 - BUFFER_APPEND_STRING_CONST(b,
36619 + BUFFER_APPEND_STRING_CONST(b,
36625 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36631 @@ -548,7 +547,7 @@
36637 b = chunkqueue_get_append_buffer(con->write_queue);
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");
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");
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");
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 */
36666 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36672 @@ -591,10 +590,10 @@
36673 /* we have nothing to send */
36674 con->http_status = 204;
36675 con->file_finished = 1;
36678 return HANDLER_FINISHED;
36682 b = chunkqueue_get_append_buffer(con->write_queue);
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");
36691 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36694 con->http_status = 200;
36695 con->file_finished = 1;
36698 return HANDLER_FINISHED;
36702 static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
36705 if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
36706 mod_status_handle_server_status_text(srv, con, p_d);
36708 mod_status_handle_server_status_html(srv, con, p_d);
36712 con->http_status = 200;
36713 con->file_finished = 1;
36716 return HANDLER_FINISHED;
36719 @@ -634,9 +633,9 @@
36720 plugin_data *p = p_d;
36721 buffer *b, *m = p->module_list;
36724 - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36727 + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36729 /* - poll is most reliable
36730 * - select works everywhere
36731 * - linux-* are experimental
36732 @@ -661,10 +660,10 @@
36734 { FDEVENT_HANDLER_UNSET, NULL }
36738 b = chunkqueue_get_append_buffer(con->write_queue);
36740 - BUFFER_COPY_STRING_CONST(b,
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 @@
36748 " <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
36749 " <table border=\"1\">\n");
36752 mod_status_header_append(b, "Server-Features");
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");
36758 mod_status_header_append(b, "Network Engine");
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);
36769 mod_status_header_append(b, "Config-File-Settings");
36772 for (i = 0; i < srv->plugins.used; i++) {
36773 plugin **ps = srv->plugins.ptr;
36776 plugin *pl = ps[i];
36780 buffer_copy_string_buffer(m, pl->name);
36782 @@ -705,137 +704,135 @@
36783 buffer_append_string_buffer(m, pl->name);
36788 mod_status_row_append(b, "Loaded Modules", m->ptr);
36791 BUFFER_APPEND_STRING_CONST(b, " </table>\n");
36793 - BUFFER_APPEND_STRING_CONST(b,
36795 + BUFFER_APPEND_STRING_CONST(b,
36801 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36804 con->http_status = 200;
36805 con->file_finished = 1;
36808 return HANDLER_FINISHED;
36811 -#define PATCH(x) \
36812 - p->conf.x = s->x;
36813 static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
36815 plugin_config *s = p->config_storage[0];
36817 - PATCH(status_url);
36818 - PATCH(config_url);
36820 - PATCH(statistics_url);
36823 + PATCH_OPTION(status_url);
36824 + PATCH_OPTION(config_url);
36825 + PATCH_OPTION(sort);
36826 + PATCH_OPTION(statistics_url);
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];
36834 /* condition didn't match */
36835 if (!config_check_cond(srv, con, dc)) continue;
36839 for (j = 0; j < dc->value->used; j++) {
36840 data_unset *du = dc->value->data[j];
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"))) {
36851 + PATCH_OPTION(sort);
36852 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
36853 - PATCH(statistics_url);
36855 + PATCH_OPTION(statistics_url);
36864 static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
36865 plugin_data *p = p_d;
36868 mod_status_patch_connection(srv, con, p);
36870 - if (!buffer_is_empty(p->conf.status_url) &&
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);
36886 return HANDLER_GO_ON;
36889 TRIGGER_FUNC(mod_status_trigger) {
36890 plugin_data *p = p_d;
36894 /* check all connections */
36895 for (i = 0; i < srv->conns->used; i++) {
36896 connection *c = srv->conns->ptr[i];
36899 p->bytes_written += c->bytes_written_cur_second;
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;
36908 p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
36911 p->abs_traffic_out += p->bytes_written;
36912 p->rel_traffic_out += p->bytes_written;
36915 p->bytes_written = 0;
36918 /* reset storage - second */
36919 p->traffic_out = 0;
36923 return HANDLER_GO_ON;
36926 REQUESTDONE_FUNC(mod_status_account) {
36927 plugin_data *p = p_d;
36937 p->bytes_written += con->bytes_written_cur_second;
36940 return HANDLER_GO_ON;
36943 int mod_status_plugin_init(plugin *p) {
36944 p->version = LIGHTTPD_VERSION_ID;
36945 p->name = buffer_init_string("status");
36948 p->init = mod_status_init;
36949 p->cleanup = mod_status_free;
36950 p->set_defaults= mod_status_set_defaults;
36953 p->handle_uri_clean = mod_status_handler;
36954 p->handle_trigger = mod_status_trigger;
36955 p->handle_request_done = mod_status_account;
36963 --- ../lighttpd-1.4.11/src/mod_trigger_b4_dl.c 2005-09-23 22:53:55.000000000 +0300
36964 +++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c 2006-07-11 22:07:51.000000000 +0300
36965 @@ -24,18 +24,18 @@
36968 * this is a trigger_b4_dl for a lighttpd plugin
36973 /* plugin config for all request/connections */
36976 buffer *db_filename;
36979 buffer *trigger_url;
36980 buffer *download_url;
36985 buffer *mc_namespace;
36986 #if defined(HAVE_PCRE_H)
36987 @@ -46,58 +46,58 @@
36991 -#if defined(HAVE_MEMCACHE_H)
36992 +#if defined(HAVE_MEMCACHE_H)
36993 struct memcache *mc;
36997 unsigned short trigger_timeout;
36998 unsigned short debug;
37008 plugin_config **config_storage;
37010 - plugin_config conf;
37012 + plugin_config conf;
37015 /* init the plugin data */
37016 INIT_FUNC(mod_trigger_b4_dl_init) {
37020 p = calloc(1, sizeof(*p));
37023 p->tmp_buf = buffer_init();
37029 /* detroy the plugin data */
37030 FREE_FUNC(mod_trigger_b4_dl_free) {
37031 plugin_data *p = p_d;
37036 if (!p) return HANDLER_GO_ON;
37039 if (p->config_storage) {
37041 for (i = 0; i < srv->config_context->used; i++) {
37042 plugin_config *s = p->config_storage[i];
37047 buffer_free(s->db_filename);
37048 buffer_free(s->download_url);
37049 buffer_free(s->trigger_url);
37050 buffer_free(s->deny_url);
37053 buffer_free(s->mc_namespace);
37054 array_free(s->mc_hosts);
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);
37068 free(p->config_storage);
37072 buffer_free(p->tmp_buf);
37078 return HANDLER_GO_ON;
37081 @@ -126,9 +126,9 @@
37082 SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
37083 plugin_data *p = p_d;
37087 - config_values_t cv[] = {
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 }
37100 if (!p) return HANDLER_ERROR;
37103 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37106 for (i = 0; i < srv->config_context->used; i++) {
37108 #if defined(HAVE_PCRE_H)
37109 const char *errptr;
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();
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);
37132 p->config_storage[i] = s;
37135 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37136 return HANDLER_ERROR;
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;
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))) {
37154 - log_error_write(srv, __FILE__, __LINE__, "sbss",
37155 - "compiling regex for download-url failed:",
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;
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))) {
37169 - log_error_write(srv, __FILE__, __LINE__, "sbss",
37170 - "compiling regex for trigger-url failed:",
37172 + log_error_write(srv, __FILE__, __LINE__, "sbss",
37173 + "compiling regex for trigger-url failed:",
37174 s->trigger_url, "pos:", erroff);
37177 return HANDLER_ERROR;
37180 @@ -211,100 +211,97 @@
37181 #if defined(HAVE_MEMCACHE_H)
37186 for (k = 0; k < s->mc_hosts->used; k++) {
37187 data_string *ds = (data_string *)s->mc_hosts->data[k];
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:",
37198 return HANDLER_ERROR;
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;
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;
37220 return HANDLER_GO_ON;
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) {
37227 plugin_config *s = p->config_storage[0];
37230 #if defined(HAVE_GDBM)
37233 + PATCH_OPTION(db);
37235 #if defined(HAVE_PCRE_H)
37236 - PATCH(download_regex);
37237 - PATCH(trigger_regex);
37239 - PATCH(trigger_timeout);
37241 - PATCH(mc_namespace);
37243 + PATCH_OPTION(download_regex);
37244 + PATCH_OPTION(trigger_regex);
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)
37252 + PATCH_OPTION(mc);
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];
37262 /* condition didn't match */
37263 if (!config_check_cond(srv, con, dc)) continue;
37267 for (j = 0; j < dc->value->used; j++) {
37268 data_unset *du = dc->value->data[j];
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);
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);
37280 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
37281 #if defined(HAVE_GDBM_H)
37283 + PATCH_OPTION(db);
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"))) {
37290 + PATCH_OPTION(debug);
37291 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.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)
37300 + PATCH_OPTION(mc);
37311 URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
37312 plugin_data *p = p_d;
37313 @@ -315,20 +312,20 @@
37319 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37322 mod_trigger_b4_dl_patch_connection(srv, con, p);
37325 if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
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 */
37336 return HANDLER_GO_ON;
37338 # elif defined(HAVE_GDBM_H)
37339 @@ -336,12 +333,12 @@
37341 if (!p->conf.mc) return HANDLER_GO_ON;
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 */
37349 remote_ip = ds->value->ptr;
37352 /* memcache can't handle spaces */
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);
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);
37368 return HANDLER_ERROR;
37371 @@ -364,34 +361,34 @@
37373 /* the trigger matched */
37377 key.dptr = (char *)remote_ip;
37378 key.dsize = strlen(remote_ip);
37381 val.dptr = (char *)&(srv->cur_ts);
37382 val.dsize = sizeof(srv->cur_ts);
37385 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37386 log_error_write(srv, __FILE__, __LINE__, "s",
37391 -# if defined(HAVE_MEMCACHE_H)
37392 +# if defined(HAVE_MEMCACHE_H)
37395 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37396 buffer_append_string(p->tmp_buf, remote_ip);
37399 for (i = 0; i < p->tmp_buf->used - 1; i++) {
37400 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37404 if (p->conf.debug) {
37405 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
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 @@
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 @@
37425 /* the download uri matched */
37426 -# if defined(HAVE_GDBM_H)
37427 +# if defined(HAVE_GDBM_H)
37433 key.dptr = (char *)remote_ip;
37434 key.dsize = strlen(remote_ip);
37437 val = gdbm_fetch(p->conf.db, key);
37440 if (val.dptr == NULL) {
37441 /* not found, redirect */
37444 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37447 con->http_status = 307;
37450 return HANDLER_FINISHED;
37454 last_hit = *(time_t *)(val.dptr);
37460 if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
37461 /* found, but timeout, redirect */
37464 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37465 con->http_status = 307;
37469 if (0 != gdbm_delete(p->conf.db, key)) {
37470 log_error_write(srv, __FILE__, __LINE__, "s",
37476 return HANDLER_FINISHED;
37480 val.dptr = (char *)&(srv->cur_ts);
37481 val.dsize = sizeof(srv->cur_ts);
37484 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37485 log_error_write(srv, __FILE__, __LINE__, "s",
37491 -# if defined(HAVE_MEMCACHE_H)
37493 +# if defined(HAVE_MEMCACHE_H)
37499 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37500 buffer_append_string(p->tmp_buf, remote_ip);
37503 for (i = 0; i < p->tmp_buf->used - 1; i++) {
37504 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37508 if (p->conf.debug) {
37509 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
37515 * memcached is do expiration for us, as long as we can fetch it every thing is ok
37516 - * and the timestamp is updated
37518 + * and the timestamp is updated
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)
37527 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37530 con->http_status = 307;
37533 return HANDLER_FINISHED;
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 @@
37559 return HANDLER_GO_ON;
37562 @@ -521,21 +518,21 @@
37563 TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
37564 plugin_data *p = p_d;
37568 /* check DB each minute */
37569 if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
37573 for (i = 0; i < srv->config_context->used; i++) {
37574 plugin_config *s = p->config_storage[i];
37575 datum key, val, okey;
37578 if (!s->db) continue;
37583 - /* according to the manual this loop + delete does delete all entries on its way
37586 + /* according to the manual this loop + delete does delete all entries on its way
37588 * we don't care as the next round will remove them. We don't have to perfect here.
37590 for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
37591 @@ -544,21 +541,21 @@
37597 val = gdbm_fetch(s->db, key);
37600 last_hit = *(time_t *)(val.dptr);
37606 if (srv->cur_ts - last_hit > s->trigger_timeout) {
37607 gdbm_delete(s->db, key);
37613 if (okey.dptr) free(okey.dptr);
37616 /* reorg once a day */
37617 if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
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");
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;
37631 p->cleanup = mod_trigger_b4_dl_free;
37639 --- ../lighttpd-1.4.11/src/mod_userdir.c 2005-10-28 16:48:28.000000000 +0300
37640 +++ lighttpd-1.4.12/src/mod_userdir.c 2006-07-11 22:07:52.000000000 +0300
37642 #include "response.h"
37644 #include "plugin.h"
37645 +#include "sys-files.h"
37649 @@ -25,54 +26,54 @@
37659 plugin_config **config_storage;
37661 - plugin_config conf;
37663 + plugin_config conf;
37666 /* init the plugin data */
37667 INIT_FUNC(mod_userdir_init) {
37671 p = calloc(1, sizeof(*p));
37674 p->username = buffer_init();
37675 p->temp_path = buffer_init();
37681 /* detroy the plugin data */
37682 FREE_FUNC(mod_userdir_free) {
37683 plugin_data *p = p_d;
37686 if (!p) return HANDLER_GO_ON;
37689 if (p->config_storage) {
37693 for (i = 0; i < srv->config_context->used; i++) {
37694 plugin_config *s = p->config_storage[i];
37697 array_free(s->include_user);
37698 array_free(s->exclude_user);
37699 buffer_free(s->path);
37700 buffer_free(s->basepath);
37705 free(p->config_storage);
37709 buffer_free(p->username);
37710 buffer_free(p->temp_path);
37716 return HANDLER_GO_ON;
37719 @@ -81,81 +82,78 @@
37720 SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
37721 plugin_data *p = p_d;
37724 - config_values_t cv[] = {
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 }
37735 if (!p) return HANDLER_ERROR;
37738 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37741 for (i = 0; i < srv->config_context->used; i++) {
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();
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;
37758 p->config_storage[i] = s;
37761 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37762 return HANDLER_ERROR;
37767 return HANDLER_GO_ON;
37770 -#define PATCH(x) \
37771 - p->conf.x = s->x;
37772 static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
37774 plugin_config *s = p->config_storage[0];
37777 - PATCH(exclude_user);
37778 - PATCH(include_user);
37782 + PATCH_OPTION(path);
37783 + PATCH_OPTION(exclude_user);
37784 + PATCH_OPTION(include_user);
37785 + PATCH_OPTION(basepath);
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];
37793 /* condition didn't match */
37794 if (!config_check_cond(srv, con, dc)) continue;
37798 for (j = 0; j < dc->value->used; j++) {
37799 data_unset *du = dc->value->data[j];
37802 if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.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"))) {
37813 + PATCH_OPTION(basepath);
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;
37828 mod_userdir_patch_connection(srv, con, p);
37831 uri_len = con->uri.path->used - 1;
37834 /* /~user/foo.html -> /home/user/public_html/foo.html */
37837 if (con->uri.path->ptr[0] != '/' ||
37838 con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
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);
37846 return HANDLER_FINISHED;
37849 @@ -188,10 +186,10 @@
37850 if (0 == rel_url - (con->uri.path->ptr + 2)) {
37851 return HANDLER_GO_ON;
37855 buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
37857 - if (buffer_is_empty(p->conf.basepath)
37859 + if (buffer_is_empty(p->conf.basepath)
37861 && NULL == (pwd = getpwnam(p->username->ptr))
37863 @@ -200,31 +198,31 @@
37864 return HANDLER_GO_ON;
37869 for (k = 0; k < p->conf.exclude_user->used; k++) {
37870 data_string *ds = (data_string *)p->conf.exclude_user->data[k];
37873 if (buffer_is_equal(ds->value, p->username)) {
37874 /* user in exclude list */
37875 return HANDLER_GO_ON;
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];
37886 if (buffer_is_equal(ds->value, p->username)) {
37887 /* user in include list */
37894 if (!found_user) return HANDLER_GO_ON;
37898 /* we build the physical path */
37900 if (buffer_is_empty(p->conf.basepath)) {
37901 @@ -252,23 +250,23 @@
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);
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);
37914 if (buffer_is_empty(p->conf.basepath)) {
37919 ret = stat(p->temp_path->ptr, &st);
37920 if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
37921 return HANDLER_GO_ON;
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);
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");
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;
37948 --- ../lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200
37949 +++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-11 22:07:53.000000000 +0300
37950 @@ -24,44 +24,44 @@
37956 plugin_config **config_storage;
37958 - plugin_config conf;
37960 + plugin_config conf;
37963 /* init the plugin data */
37964 INIT_FUNC(mod_usertrack_init) {
37968 p = calloc(1, sizeof(*p));
37974 /* detroy the plugin data */
37975 FREE_FUNC(mod_usertrack_free) {
37976 plugin_data *p = p_d;
37982 if (!p) return HANDLER_GO_ON;
37985 if (p->config_storage) {
37987 for (i = 0; i < srv->config_context->used; i++) {
37988 plugin_config *s = p->config_storage[i];
37991 buffer_free(s->cookie_name);
37992 buffer_free(s->cookie_domain);
37997 free(p->config_storage);
38004 return HANDLER_GO_ON;
38007 @@ -70,38 +70,38 @@
38008 SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
38009 plugin_data *p = p_d;
38012 - config_values_t cv[] = {
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 */
38019 - { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38021 + { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38022 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38026 if (!p) return HANDLER_ERROR;
38029 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38032 for (i = 0; i < srv->config_context->used; i++) {
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;
38042 cv[0].destination = s->cookie_name;
38043 cv[1].destination = &(s->cookie_max_age);
38044 cv[2].destination = s->cookie_domain;
38047 p->config_storage[i] = s;
38050 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38051 return HANDLER_ERROR;
38055 if (buffer_is_empty(s->cookie_name)) {
38056 buffer_copy_string(s->cookie_name, "TRACKID");
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:",
38069 return HANDLER_ERROR;
38075 if (!buffer_is_empty(s->cookie_domain)) {
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:",
38087 return HANDLER_ERROR;
38094 return HANDLER_GO_ON;
38097 -#define PATCH(x) \
38098 - p->conf.x = s->x;
38099 static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
38101 plugin_config *s = p->config_storage[0];
38103 - PATCH(cookie_name);
38104 - PATCH(cookie_domain);
38105 - PATCH(cookie_max_age);
38108 + PATCH_OPTION(cookie_name);
38109 + PATCH_OPTION(cookie_domain);
38110 + PATCH_OPTION(cookie_max_age);
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];
38118 /* condition didn't match */
38119 if (!config_check_cond(srv, con, dc)) continue;
38123 for (j = 0; j < dc->value->used; j++) {
38124 data_unset *du = dc->value->data[j];
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);
38145 URIHANDLER_FUNC(mod_usertrack_uri_handler) {
38146 plugin_data *p = p_d;
38147 @@ -178,38 +175,38 @@
38148 unsigned char h[16];
38153 if (con->uri.path->used == 0) return HANDLER_GO_ON;
38156 mod_usertrack_patch_connection(srv, con, p);
38159 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
38161 /* we have a cookie, does it contain a valid name ? */
38163 - /* parse the cookie
38166 + /* parse the cookie
38168 * check for cookiename + (WS | '=')
38174 if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
38179 for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
38183 /* ok, found the key of our own cookie */
38186 if (strlen(nc) > 32) {
38188 return HANDLER_GO_ON;
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, "=");
38206 /* taken from mod_auth.c */
38209 /* generate shared-secret */
38211 MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
38212 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
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));
38222 MD5_Final(h, &Md5Ctx);
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");
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);
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);
38242 array_insert_unique(con->response.headers, (data_unset *)ds);
38245 return HANDLER_GO_ON;
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");
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;
38265 --- ../lighttpd-1.4.11/src/mod_webdav.c 2006-03-03 01:28:58.000000000 +0200
38266 +++ lighttpd-1.4.12/src/mod_webdav.c 2006-07-11 22:07:53.000000000 +0300
38269 #include <stdlib.h>
38270 #include <string.h>
38271 -#include <dirent.h>
38273 -#include <unistd.h>
38276 #include <assert.h>
38277 -#include <sys/mman.h>
38279 #ifdef HAVE_CONFIG_H
38280 #include "config.h"
38282 #include <sqlite3.h>
38285 +#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
38287 +#include <uuid/uuid.h>
38292 #include "buffer.h"
38293 @@ -33,13 +35,16 @@
38294 #include "stream.h"
38295 #include "stat_cache.h"
38297 +#include "sys-files.h"
38298 +#include "sys-mmap.h"
38299 +#include "sys-strings.h"
38302 * this is a webdav for a lighttpd plugin
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
38312 @@ -58,64 +63,70 @@
38313 sqlite3_stmt *stmt_delete_prop;
38314 sqlite3_stmt *stmt_select_prop;
38315 sqlite3_stmt *stmt_select_propnames;
38318 sqlite3_stmt *stmt_delete_uri;
38319 sqlite3_stmt *stmt_move_uri;
38320 sqlite3_stmt *stmt_copy_uri;
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;
38338 plugin_config **config_storage;
38340 - plugin_config conf;
38342 + plugin_config conf;
38345 /* init the plugin data */
38346 INIT_FUNC(mod_webdav_init) {
38350 p = calloc(1, sizeof(*p));
38353 p->tmp_buf = buffer_init();
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();
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();
38370 /* detroy the plugin data */
38371 FREE_FUNC(mod_webdav_free) {
38372 plugin_data *p = p_d;
38377 if (!p) return HANDLER_GO_ON;
38380 if (p->config_storage) {
38382 for (i = 0; i < srv->config_context->used; i++) {
38383 plugin_config *s = p->config_storage[i];
38388 buffer_free(s->sqlite_db_name);
38389 #ifdef USE_PROPPATCH
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);
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);
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);
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);
38424 buffer_free(p->tmp_buf);
38430 return HANDLER_GO_ON;
38433 @@ -153,32 +170,32 @@
38434 SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
38435 plugin_data *p = p_d;
38438 - config_values_t cv[] = {
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 }
38449 if (!p) return HANDLER_ERROR;
38452 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38455 for (i = 0; i < srv->config_context->used; i++) {
38459 s = calloc(1, sizeof(plugin_config));
38460 s->sqlite_db_name = buffer_init();
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);
38469 p->config_storage[i] = s;
38472 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38473 return HANDLER_ERROR;
38475 @@ -193,8 +210,26 @@
38476 return HANDLER_ERROR;
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)) {
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);
38494 + return HANDLER_ERROR;
38496 + sqlite3_free(err);
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 */
38504 @@ -202,8 +237,8 @@
38505 return HANDLER_ERROR;
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 */
38515 @@ -211,16 +246,67 @@
38516 return HANDLER_ERROR;
38519 - if (SQLITE_OK != sqlite3_exec(s->sql,
38520 - "CREATE TABLE properties ("
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 */
38527 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38528 + return HANDLER_ERROR;
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));
38537 + return HANDLER_ERROR;
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));
38546 + return HANDLER_ERROR;
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));
38555 + return HANDLER_ERROR;
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));
38564 + return HANDLER_ERROR;
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)) {
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);
38590 @@ -228,127 +314,138 @@
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)) {
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));
38605 - log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38606 return HANDLER_ERROR;
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));
38618 return HANDLER_ERROR;
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));
38630 return HANDLER_ERROR;
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));
38642 return HANDLER_ERROR;
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));
38654 return HANDLER_ERROR;
38659 log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
38660 return HANDLER_ERROR;
38666 return HANDLER_GO_ON;
38669 -#define PATCH(x) \
38670 - p->conf.x = s->x;
38671 static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
38673 plugin_config *s = p->config_storage[0];
38676 - PATCH(is_readonly);
38680 + PATCH_OPTION(enabled);
38681 + PATCH_OPTION(is_readonly);
38682 + PATCH_OPTION(log_xml);
38684 #ifdef USE_PROPPATCH
38686 - PATCH(stmt_update_prop);
38687 - PATCH(stmt_delete_prop);
38688 - PATCH(stmt_select_prop);
38689 - PATCH(stmt_select_propnames);
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);
38700 + PATCH_OPTION(stmt_delete_uri);
38701 + PATCH_OPTION(stmt_move_uri);
38702 + PATCH_OPTION(stmt_copy_uri);
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);
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];
38716 /* condition didn't match */
38717 if (!config_check_cond(srv, con, dc)) continue;
38721 for (j = 0; j < dc->value->used; j++) {
38722 data_unset *du = dc->value->data[j];
38725 if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
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"))) {
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
38737 - PATCH(stmt_update_prop);
38738 - PATCH(stmt_delete_prop);
38739 - PATCH(stmt_select_prop);
38740 - PATCH(stmt_select_propnames);
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);
38751 + PATCH_OPTION(stmt_delete_uri);
38752 + PATCH_OPTION(stmt_move_uri);
38753 + PATCH_OPTION(stmt_copy_uri);
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);
38770 URIHANDLER_FUNC(mod_webdav_uri_handler) {
38771 plugin_data *p = p_d;
38776 if (con->uri.path->used == 0) return HANDLER_GO_ON;
38779 mod_webdav_patch_connection(srv, con, p);
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"));
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"));
38796 return HANDLER_GO_ON;
38798 -static int webdav_gen_prop_tag(server *srv, connection *con,
38802 +static int webdav_gen_prop_tag(server *srv, connection *con,
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");
38815 if (con->request.http_version == HTTP_VERSION_1_1) {
38816 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
38818 @@ -458,11 +555,11 @@
38820 /* bind the values to the insert */
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,
38830 if (SQLITE_DONE != sqlite3_step(stmt)) {
38833 @@ -493,14 +590,14 @@
38834 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38836 /* ignore the parent dir */
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);
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);
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);
38858 /* try to unlink it */
38859 if (-1 == rmdir(d.path->ptr)) {
38861 @@ -535,11 +632,11 @@
38863 /* bind the values to the insert */
38865 - sqlite3_bind_text(stmt, 1,
38867 + sqlite3_bind_text(stmt, 1,
38869 d.rel_path->used - 1,
38873 if (SQLITE_DONE != sqlite3_step(stmt)) {
38876 @@ -569,7 +666,7 @@
38877 if (stream_open(&s, src->path)) {
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 */
38885 @@ -601,7 +698,7 @@
38894 @@ -614,16 +711,16 @@
38895 sqlite3_reset(stmt);
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,
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,
38913 if (SQLITE_DONE != sqlite3_step(stmt)) {
38916 @@ -655,21 +752,21 @@
38917 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
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);
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);
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);
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);
38942 if (-1 == stat(s.path->ptr, &st)) {
38943 @@ -692,16 +789,16 @@
38944 sqlite3_reset(stmt);
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,
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,
38962 if (SQLITE_DONE != sqlite3_step(stmt)) {
38965 @@ -721,7 +818,7 @@
38966 buffer_free(s.rel_path);
38967 buffer_free(d.path);
38968 buffer_free(d.rel_path);
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>");
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];
38984 if (ds->key->used == 0) continue;
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 @@
38992 /* bind the values to the insert */
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,
39000 - sqlite3_bind_text(stmt, 2,
39001 + sqlite3_bind_text(stmt, 2,
39005 - sqlite3_bind_text(stmt, 3,
39006 + sqlite3_bind_text(stmt, 3,
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);
39020 @@ -840,7 +937,7 @@
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;
39032 prop = props->ptr[i];
39034 - if (0 != webdav_get_property(srv, con, p,
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);
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));
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);
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);
39062 c->offset += weHave;
39063 cq->bytes_out += weHave;
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);
39071 c->offset += weHave;
39072 cq->bytes_out += weHave;
39074 @@ -991,6 +1088,113 @@
39078 +int webdav_lockdiscovery(server *srv, connection *con,
39079 + buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
39083 + response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
39085 + response_header_overwrite(srv, con,
39086 + CONST_STR_LEN("Content-Type"),
39087 + CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39089 + b = chunkqueue_get_append_buffer(con->write_queue);
39091 + buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
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");
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");
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");
39109 + buffer_append_string(b,"<D:depth>");
39110 + buffer_append_string(b, depth == 0 ? "0" : "infinity");
39111 + buffer_append_string(b,"</D:depth>\n");
39113 + buffer_append_string(b,"<D:timeout>");
39114 + buffer_append_string(b, "Second-600");
39115 + buffer_append_string(b,"</D:timeout>\n");
39117 + buffer_append_string(b,"<D:owner>");
39118 + buffer_append_string(b,"</D:owner>\n");
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");
39126 + buffer_append_string(b,"</D:activelock>\n");
39127 + buffer_append_string(b,"</D:lockdiscovery>\n");
39128 + buffer_append_string(b,"</D:prop>\n");
39133 + * check if resource is having the right locks to access to resource
39138 +int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
39139 + int has_lock = 1;
39149 + * there is NOT, AND and OR
39150 + * and a list can be tagged
39152 + * (<lock-token>) is untagged
39153 + * <tag> (<lock-token>) is tagged
39155 + * as long as we don't handle collections it is simple. :)
39157 + * X-Litmus: locks: 11 (owner_modify)
39158 + * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
39160 + * X-Litmus: locks: 16 (fail_cond_put)
39161 + * If: (<DAV:no-lock> ["-1622396671"])
39163 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39165 + /* we didn't provided a lock-token -> */
39166 + /* if the resource is locked -> 423 */
39168 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39170 + sqlite3_reset(stmt);
39172 + sqlite3_bind_text(stmt, 1,
39173 + CONST_BUF_LEN(uri),
39174 + SQLITE_TRANSIENT);
39176 + while (SQLITE_ROW == sqlite3_step(stmt)) {
39185 URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
39186 plugin_data *p = p_d;
39188 @@ -1001,7 +1205,8 @@
39191 webdav_properties *req_props;
39193 + stat_cache_entry *sce = NULL;
39197 if (!p->conf.enabled) return HANDLER_GO_ON;
39198 @@ -1019,7 +1224,19 @@
39201 /* is there a content-body ? */
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;
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 */
39224 - sqlite3_bind_text(stmt, 1,
39225 - con->uri.path->ptr,
39227 + sqlite3_bind_text(stmt, 1,
39228 + con->uri.path->ptr,
39229 con->uri.path->used - 1,
39233 if (SQLITE_DONE != sqlite3_step(stmt)) {
39236 @@ -1115,13 +1332,13 @@
39237 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39239 b = chunkqueue_get_append_buffer(con->write_queue);
39242 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39244 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39249 prop_200 = buffer_init();
39250 prop_404 = buffer_init();
39252 @@ -1129,7 +1346,7 @@
39255 webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
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);
39264 buffer_append_string(b,"</D:prop>\n");
39267 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39270 buffer_append_string(b,"</D:propstat>\n");
39272 if (!buffer_is_empty(prop_404)) {
39273 @@ -1157,16 +1374,16 @@
39274 buffer_append_string_buffer(b, prop_404);
39276 buffer_append_string(b,"</D:prop>\n");
39279 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39282 buffer_append_string(b,"</D:propstat>\n");
39285 buffer_append_string(b,"</D:response>\n");
39290 if (NULL != (dir = opendir(con->physical.path->ptr))) {
39293 @@ -1179,16 +1396,16 @@
39294 if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
39296 /* ignore the parent dir */
39300 buffer_copy_string_buffer(d.path, dst->path);
39301 - BUFFER_APPEND_SLASH(d.path);
39302 + PATHNAME_APPEND_SLASH(d.path);
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);
39308 if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
39309 - /* don't append the . */
39310 + /* don't append the . */
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);
39317 webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
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);
39326 buffer_append_string(b,"</D:prop>\n");
39329 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39332 buffer_append_string(b,"</D:propstat>\n");
39334 if (!buffer_is_empty(prop_404)) {
39335 @@ -1226,9 +1443,9 @@
39336 buffer_append_string_buffer(b, prop_404);
39338 buffer_append_string(b,"</D:prop>\n");
39341 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39344 buffer_append_string(b,"</D:propstat>\n");
39347 @@ -1275,7 +1492,7 @@
39349 return HANDLER_FINISHED;
39353 /* let's create the directory */
39355 if (-1 == mkdir(con->physical.path->ptr, 0700)) {
39356 @@ -1303,7 +1520,13 @@
39357 con->http_status = 403;
39358 return HANDLER_FINISHED;
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;
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\""));
39374 b = chunkqueue_get_append_buffer(con->write_queue);
39377 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
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);
39383 buffer_append_string(b,"</D:multistatus>\n");
39386 if (p->conf.log_xml) {
39387 log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
39389 @@ -1340,7 +1563,7 @@
39390 con->file_finished = 1;
39392 /* everything went fine, remove the directory */
39395 if (-1 == rmdir(con->physical.path->ptr)) {
39398 @@ -1375,97 +1598,174 @@
39399 case HTTP_METHOD_PUT: {
39401 chunkqueue *cq = con->request_content_queue;
39403 + data_string *ds_range;
39405 if (p->conf.is_readonly) {
39406 con->http_status = 403;
39407 return HANDLER_FINISHED;
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;
39417 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
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;
39425 + /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
39426 + * - most important Content-Range
39429 + * Example: Content-Range: bytes 100-1037/1038 */
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;
39436 + char *err = NULL;
39438 - for (c = cq->first; c; c = cq->first) {
39440 + if (0 != strncmp(num, "bytes ", 6)) {
39441 + con->http_status = 501; /* not implemented */
39443 - /* copy all chunks */
39444 - switch(c->type) {
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));
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;
39463 + /* we only support <num>- ... */
39465 - c->file.mmap.length = c->file.length;
39468 - close(c->file.fd);
39471 - /* chunk_reset() or chunk_free() will cleanup for us */
39474 - if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39477 - con->http_status = 507;
39481 - con->http_status = 403;
39487 - if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39490 - con->http_status = 507;
39494 - con->http_status = 403;
39499 + while (*num == ' ' || *num == '\t') num++;
39501 + if (*num == '\0') {
39502 + con->http_status = 501; /* not implemented */
39504 + return HANDLER_FINISHED;
39507 + offset = strtoll(num, &err, 10);
39509 + if (*err != '-' || offset < 0) {
39510 + con->http_status = 501; /* not implemented */
39512 + return HANDLER_FINISHED;
39515 + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
39518 + con->http_status = 404; /* not found */
39520 - case UNUSED_CHUNK:
39522 + con->http_status = 403; /* not found */
39525 + return HANDLER_FINISHED;
39528 + if (-1 == lseek(fd, offset, SEEK_SET)) {
39529 + con->http_status = 501; /* not implemented */
39533 + return HANDLER_FINISHED;
39535 + con->http_status = 200; /* modified */
39537 + /* take what we have in the request-body and write it to a file */
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;
39548 - cq->bytes_out += r;
39549 + return HANDLER_FINISHED;
39552 + con->http_status = 201; /* created */
39555 + con->http_status = 200; /* modified */
39559 + con->file_finished = 1;
39561 + for (c = cq->first; c; c = cq->first) {
39564 + /* copy all chunks */
39565 + switch(c->type) {
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));
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);
39583 + c->file.mmap.length = c->file.length;
39585 + close(c->file.fd);
39588 + /* chunk_reset() or chunk_free() will cleanup for us */
39591 + if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39594 + con->http_status = 507;
39598 + con->http_status = 403;
39602 - chunkqueue_remove_finished_chunks(cq);
39605 + if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39608 + con->http_status = 507;
39612 + con->http_status = 403;
39617 + case UNUSED_CHUNK:
39624 + cq->bytes_out += r;
39628 + chunkqueue_remove_finished_chunks(cq);
39632 return HANDLER_FINISHED;
39634 - case HTTP_METHOD_MOVE:
39635 + case HTTP_METHOD_MOVE:
39636 case HTTP_METHOD_COPY: {
39637 buffer *destination = NULL;
39639 @@ -1475,7 +1775,15 @@
39640 con->http_status = 403;
39641 return HANDLER_FINISHED;
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;
39653 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
39654 destination = ds->value;
39656 @@ -1549,10 +1857,10 @@
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);
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);
39669 @@ -1613,6 +1921,12 @@
39670 /* it is just a file, good */
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;
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;
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;
39691 @@ -1655,16 +1969,16 @@
39692 sqlite3_reset(stmt);
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,
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,
39710 if (SQLITE_DONE != sqlite3_step(stmt)) {
39711 log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
39713 @@ -1691,12 +2005,17 @@
39715 return HANDLER_FINISHED;
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;
39724 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39725 + con->http_status = 423;
39726 + return HANDLER_FINISHED;
39729 /* check if destination exists */
39730 if (-1 == stat(con->physical.path->ptr, &st)) {
39732 @@ -1737,7 +2056,7 @@
39734 sqlite3_stmt *stmt;
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;
39740 for (props = cmd->children; props; props = props->next) {
39741 @@ -1762,34 +2081,35 @@
39743 /* bind the values to the insert */
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,
39751 - sqlite3_bind_text(stmt, 2,
39752 + sqlite3_bind_text(stmt, 2,
39753 (char *)prop->name,
39754 strlen((char *)prop->name),
39757 - sqlite3_bind_text(stmt, 3,
39758 + sqlite3_bind_text(stmt, 3,
39759 (char *)prop->ns->href,
39760 strlen((char *)prop->ns->href),
39763 - sqlite3_bind_text(stmt, 3,
39764 + sqlite3_bind_text(stmt, 3,
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)),
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));
39785 @@ -1804,7 +2124,7 @@
39787 goto propmatch_cleanup;
39791 con->http_status = 400;
39793 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
39794 @@ -1821,6 +2141,7 @@
39801 con->http_status = 400;
39802 @@ -1830,11 +2151,307 @@
39804 con->http_status = 501;
39805 return HANDLER_FINISHED;
39807 + case HTTP_METHOD_LOCK:
39809 + * a mac wants to write
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
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
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
39826 + * <D:href>http://www.apple.com/webdav_fs/</D:href>\n
39828 + * </D:lockinfo>\n
39831 + if (depth != 0 && depth != -1) {
39832 + con->http_status = 400;
39834 + return HANDLER_FINISHED;
39838 + if (con->request.content_length) {
39840 + buffer *hdr_if = NULL;
39842 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39843 + hdr_if = ds->value;
39846 + /* we don't support Depth: Infinity on locks */
39847 + if (hdr_if == NULL && depth == -1) {
39848 + con->http_status = 409; /* Conflict */
39850 + return HANDLER_FINISHED;
39853 + if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
39854 + xmlNode *rootnode = xmlDocGetRootElement(xml);
39856 + assert(rootnode);
39858 + if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
39859 + xmlNode *lockinfo;
39860 + const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
39862 + for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
39863 + if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
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;
39870 + con->http_status = 400;
39873 + return HANDLER_FINISHED;
39876 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
39878 + for (value = lockinfo->children; value; value = value->next) {
39879 + if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
39880 + locktype = value->name;
39882 + con->http_status = 400;
39885 + return HANDLER_FINISHED;
39889 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
39893 + if (lockscope && locktype) {
39894 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39896 + /* is this resourse already locked ? */
39898 + /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
39900 + * WHERE resource = ? */
39904 + sqlite3_reset(stmt);
39906 + sqlite3_bind_text(stmt, 1,
39907 + p->uri.path->ptr,
39908 + p->uri.path->used - 1,
39909 + SQLITE_TRANSIENT);
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);
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;
39926 + if (con->http_status == 423) {
39928 + return HANDLER_FINISHED;
39932 + stmt = p->conf.stmt_create_lock;
39934 + /* create a lock-token */
39936 + char uuid[37] /* 36 + \0 */;
39938 + uuid_generate(id);
39939 + uuid_unparse(id, uuid);
39941 + buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
39942 + buffer_append_string(p->tmp_buf, uuid);
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,"
39953 + sqlite3_reset(stmt);
39955 + sqlite3_bind_text(stmt, 1,
39956 + CONST_BUF_LEN(p->tmp_buf),
39957 + SQLITE_TRANSIENT);
39959 + sqlite3_bind_text(stmt, 2,
39960 + CONST_BUF_LEN(con->uri.path),
39961 + SQLITE_TRANSIENT);
39963 + sqlite3_bind_text(stmt, 3,
39965 + xmlStrlen(lockscope),
39966 + SQLITE_TRANSIENT);
39968 + sqlite3_bind_text(stmt, 4,
39970 + xmlStrlen(locktype),
39971 + SQLITE_TRANSIENT);
39974 + sqlite3_bind_text(stmt, 5,
39977 + SQLITE_TRANSIENT);
39980 + sqlite3_bind_int(stmt, 6,
39984 + if (SQLITE_DONE != sqlite3_step(stmt)) {
39985 + log_error_write(srv, __FILE__, __LINE__, "ss",
39986 + "create lock:", sqlite3_errmsg(p->conf.sql));
39989 + /* looks like we survived */
39990 + webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
39992 + con->http_status = 201;
39993 + con->file_finished = 1;
39999 + return HANDLER_FINISHED;
40001 + con->http_status = 400;
40002 + return HANDLER_FINISHED;
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;
40010 + /* remove the < > around the token */
40011 + if (locktoken->used < 6) {
40012 + con->http_status = 400;
40014 + return HANDLER_FINISHED;
40017 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
40019 + sqlite3_reset(stmt);
40021 + sqlite3_bind_text(stmt, 1,
40022 + CONST_BUF_LEN(p->tmp_buf),
40023 + SQLITE_TRANSIENT);
40025 + if (SQLITE_DONE != sqlite3_step(stmt)) {
40026 + log_error_write(srv, __FILE__, __LINE__, "ss",
40027 + "refresh lock:", sqlite3_errmsg(p->conf.sql));
40030 + webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
40032 + con->http_status = 200;
40033 + con->file_finished = 1;
40034 + return HANDLER_FINISHED;
40036 + /* we need a lock-token to refresh */
40037 + con->http_status = 400;
40039 + return HANDLER_FINISHED;
40044 + con->http_status = 501;
40045 + return HANDLER_FINISHED;
40047 + case HTTP_METHOD_UNLOCK:
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;
40053 + /* remove the < > around the token */
40054 + if (locktoken->used < 4) {
40055 + con->http_status = 400;
40057 + return HANDLER_FINISHED;
40063 + * if the resourse is locked:
40064 + * - by us: unlock
40065 + * - by someone else: 401
40066 + * if the resource is not locked:
40070 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
40072 + sqlite3_reset(stmt);
40074 + sqlite3_bind_text(stmt, 1,
40075 + CONST_BUF_LEN(p->tmp_buf),
40076 + SQLITE_TRANSIENT);
40078 + sqlite3_bind_text(stmt, 2,
40079 + CONST_BUF_LEN(con->uri.path),
40080 + SQLITE_TRANSIENT);
40082 + if (SQLITE_DONE != sqlite3_step(stmt)) {
40083 + log_error_write(srv, __FILE__, __LINE__, "ss",
40084 + "remove lock:", sqlite3_errmsg(p->conf.sql));
40087 + if (0 == sqlite3_changes(p->conf.sql)) {
40088 + con->http_status = 401;
40090 + con->http_status = 204;
40092 + return HANDLER_FINISHED;
40094 + /* we need a lock-token to unlock */
40095 + con->http_status = 400;
40097 + return HANDLER_FINISHED;
40101 + con->http_status = 501;
40102 + return HANDLER_FINISHED;
40110 return HANDLER_GO_ON;
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");
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;
40130 --- ../lighttpd-1.4.11/src/network.c 2006-03-04 16:45:46.000000000 +0200
40131 +++ lighttpd-1.4.12/src/network.c 2006-07-11 22:07:51.000000000 +0300
40133 #include <sys/types.h>
40134 #include <sys/stat.h>
40135 -#include <sys/time.h>
40139 -#include <unistd.h>
40140 #include <string.h>
40141 #include <stdlib.h>
40142 #include <assert.h>
40144 +#include <stdio.h>
40146 #include "network.h"
40147 #include "fdevent.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"
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>
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;
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",
40180 @@ -44,12 +45,12 @@
40182 /* accept()s at most 100 connections directly
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++) {
40190 connection_state_machine(srv, con);
40193 switch(r = plugins_call_handle_joblist(srv, con)) {
40194 case HANDLER_FINISHED:
40195 case HANDLER_GO_ON:
40196 @@ -72,18 +73,18 @@
40198 int is_unix_domain_socket = 0;
40202 #ifdef SO_ACCEPTFILTER
40203 struct accept_filter_arg afa;
40208 WORD wVersionRequested;
40213 wVersionRequested = MAKEWORD( 2, 2 );
40216 err = WSAStartup( wVersionRequested, &wsaData );
40218 /* Tell the user that we could not find a usable */
40219 @@ -91,37 +92,37 @@
40225 srv_socket = calloc(1, sizeof(*srv_socket));
40226 srv_socket->fd = -1;
40229 srv_socket->srv_token = buffer_init();
40230 buffer_copy_string_buffer(srv_socket->srv_token, host_token);
40234 buffer_copy_string_buffer(b, host_token);
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);
40252 /* check for [ and ] */
40253 if (b->ptr[0] == '[' && *(sp-1) == ']') {
40265 port = strtol(sp, NULL, 10);
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);
40278 if (*host == '\0') host = NULL;
40280 if (is_unix_domain_socket) {
40281 #ifdef HAVE_SYS_UN_H
40283 srv_socket->addr.plain.sa_family = AF_UNIX;
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));
40289 @@ -154,7 +155,7 @@
40292 srv_socket->addr.plain.sa_family = AF_INET6;
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));
40298 @@ -162,7 +163,7 @@
40299 srv_socket->use_ipv6 = 1;
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 @@
40314 srv->cur_fds = srv_socket->fd;
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));
40324 switch(srv_socket->addr.plain.sa_family) {
40327 @@ -190,23 +191,23 @@
40329 struct addrinfo hints, *res;
40333 memset(&hints, 0, sizeof(hints));
40336 hints.ai_family = AF_INET6;
40337 hints.ai_socktype = SOCK_STREAM;
40338 hints.ai_protocol = IPPROTO_TCP;
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, "'");
40353 memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
40358 srv_socket->addr.ipv6.sin6_port = htons(port);
40359 @@ -221,33 +222,34 @@
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: ",
40372 if (he->h_addrtype != AF_INET) {
40373 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
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);
40384 memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
40386 srv_socket->addr.ipv4.sin_port = htons(port);
40389 addr_len = sizeof(struct sockaddr_in);
40395 srv_socket->addr.un.sun_family = AF_UNIX;
40396 strcpy(srv_socket->addr.un.sun_path, host);
40400 addr_len = SUN_LEN(&srv_socket->addr.un);
40402 @@ -259,8 +261,8 @@
40403 if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
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:",
40413 @@ -275,88 +277,89 @@
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));
40436 if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
40437 switch(srv_socket->addr.plain.sa_family) {
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));
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));
40457 if (-1 == listen(srv_socket->fd, 128 * 8)) {
40458 log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
40465 if (srv->ssl_is_init == 0) {
40466 SSL_load_error_strings();
40467 SSL_library_init();
40468 srv->ssl_is_init = 1;
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");
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));
40488 if (buffer_is_empty(s->ssl_pemfile)) {
40489 log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
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);
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);
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);
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),
40526 @@ -364,15 +367,15 @@
40528 srv_socket->ssl_ctx = s->ssl_ctx;
40532 buffer_free(srv_socket->srv_token);
40538 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40540 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40541 "ssl requested but openssl support is not compiled in");
40547 @@ -390,10 +393,10 @@
40553 srv_socket->is_ssl = s->is_ssl;
40554 srv_socket->fde_ndx = -1;
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));
40566 srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
40574 @@ -414,45 +416,58 @@
40576 for (i = 0; i < srv->srv_sockets.used; i++) {
40577 server_socket *srv_socket = srv->srv_sockets.ptr[i];
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);
40588 close(srv_socket->fd);
40592 + if (srv_socket->is_ssl) {
40593 +#ifdef USE_OPENSSL
40594 + SSL_CTX_free(srv_socket->ssl_ctx);
40598 buffer_free(srv_socket->srv_token);
40605 +#ifdef USE_OPENSSL
40606 + ERR_free_strings();
40608 free(srv->srv_sockets.ptr);
40615 NETWORK_BACKEND_UNSET,
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,
40624 + NETWORK_BACKEND_WIN32_SEND,
40625 + NETWORK_BACKEND_WIN32_TRANSMITFILE,
40626 } network_backend_t;
40628 int network_init(server *srv) {
40631 network_backend_t backend;
40634 - network_backend_t nb;
40635 - const char *name;
40636 - } network_backends[] = {
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" },
40649 +#if defined USE_WRITE
40650 { NETWORK_BACKEND_WRITE, "write" },
40652 +#if defined USE_WIN32_TRANSMITFILE
40653 + { NETWORK_BACKEND_WIN32_TRANSMITFILE, "win32-transmitfile" },
40655 +#if defined USE_WIN32_SEND
40656 + { NETWORK_BACKEND_WIN32_SEND, "win32-send" },
40659 { NETWORK_BACKEND_UNSET, NULL }
40666 buffer_copy_string_buffer(b, srv->srvconf.bindhost);
40667 buffer_append_string(b, ":");
40668 buffer_append_long(b, srv->srvconf.port);
40671 if (0 != network_server_init(srv, b, srv->config_storage[0])) {
40678 srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
40680 @@ -500,54 +524,80 @@
40681 if (NULL == network_backends[i].name) {
40682 /* we don't know it */
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);
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
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
40704 +#ifdef USE_WIN32_SEND
40705 + case NETWORK_BACKEND_WIN32_SEND:
40706 + SET_NETWORK_BACKEND(win32recv, win32send);
40708 +#ifdef USE_WIN32_TRANSMITFILE
40709 + case NETWORK_BACKEND_WIN32_TRANSMITFILE:
40710 + SET_NETWORK_BACKEND(win32recv, win32transmitfile);
40716 case NETWORK_BACKEND_WRITE:
40717 - srv->network_backend_write = network_write_chunkqueue_write;
40718 + SET_NETWORK_BACKEND(read, write);
40722 case NETWORK_BACKEND_WRITEV:
40723 - srv->network_backend_write = network_write_chunkqueue_writev;
40724 + SET_NETWORK_BACKEND(read, writev);
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);
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);
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);
40749 +#ifdef USE_OPENSSL
40750 + SET_NETWORK_BACKEND_SSL(openssl, openssl);
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];
40760 /* not our stage */
40761 if (COMP_SERVER_SOCKET != dc->comp) continue;
40764 if (dc->cond != CONFIG_COND_EQ) {
40765 log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
40771 @@ -558,36 +608,47 @@
40777 if (j == srv->srv_sockets.used) {
40778 if (0 != network_server_init(srv, dc->string, s)) return -1;
40786 int network_register_fdevents(server *srv) {
40789 if (-1 == fdevent_reset(srv->ev)) {
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];
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);
40803 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40805 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40806 + server_socket *srv_socket = con->srv_socket;
40808 + if (srv_socket->is_ssl) {
40809 +#ifdef USE_OPENSSL
40810 + return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
40812 + return NETWORK_STATUS_FATAL_ERROR;
40815 + return srv->network_backend_read(srv, con, con->fd, cq);
40819 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40820 + network_status_t ret = NETWORK_STATUS_UNSET;
40826 server_socket *srv_socket = con->srv_socket;
40827 @@ -600,11 +661,11 @@
40828 joblist_append(srv, con);
40834 written = cq->bytes_out;
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
40841 @@ -613,7 +674,7 @@
40842 setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
40847 if (srv_socket->is_ssl) {
40849 ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
40850 @@ -621,12 +682,17 @@
40852 ret = srv->network_backend_write(srv, con, con->fd, cq);
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;
40872 @@ -639,13 +705,13 @@
40873 con->bytes_written_cur_second += written;
40875 *(con->conf.global_bytes_per_second_cnt_ptr) += written;
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 */
40882 con->traffic_limit_reached = 1;
40883 joblist_append(srv, con);
40888 --- ../lighttpd-1.4.11/src/network.h 2005-08-11 01:26:42.000000000 +0300
40889 +++ lighttpd-1.4.12/src/network.h 2006-07-11 22:07:51.000000000 +0300
40892 #include "server.h"
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);
40898 int network_init(server *srv);
40899 int network_close(server *srv);
40900 --- ../lighttpd-1.4.11/src/network_backends.h 2005-10-24 15:13:51.000000000 +0300
40901 +++ lighttpd-1.4.12/src/network_backends.h 2006-07-11 22:07:52.000000000 +0300
40902 @@ -43,16 +43,52 @@
40903 # define USE_AIX_SENDFILE
40907 +* unix can use read/write or recv/send on sockets
40908 +* win32 only recv/send
40911 +# define USE_WIN32_SEND
40912 +/* wait for async-io support
40913 +# define USE_WIN32_TRANSMITFILE
40916 +# define USE_WRITE
40920 +#include "network.h"
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)
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)
40930 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
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);
40938 +NETWORK_BACKEND_WRITE(win32transmitfile);
40939 +NETWORK_BACKEND_WRITE(win32send);
40941 +NETWORK_BACKEND_READ(read);
40942 +NETWORK_BACKEND_READ(win32recv);
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);
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)
40956 +NETWORK_BACKEND_WRITE_SSL(openssl);
40957 +NETWORK_BACKEND_READ_SSL(openssl);
40961 --- ../lighttpd-1.4.11/src/network_freebsd_sendfile.c 2005-10-22 12:28:18.000000000 +0300
40962 +++ lighttpd-1.4.12/src/network_freebsd_sendfile.c 2006-07-11 22:07:52.000000000 +0300
40963 @@ -26,142 +26,61 @@
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
40973 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
40974 +NETWORK_BACKEND_WRITE(freebsdsendfile) {
40976 size_t chunks_written = 0;
40979 for(c = cq->first; c; c = c->next, chunks_written++) {
40980 int chunk_finished = 0;
40982 + network_status_t ret;
40985 - case MEM_CHUNK: {
40990 - size_t num_chunks, i;
40991 - struct iovec chunks[UIO_MAXIOV];
40993 - size_t num_bytes = 0;
40995 - /* we can't send more then SSIZE_MAX bytes in one chunk */
40997 - /* build writev list
40999 - * 1. limit: num_chunks < UIO_MAXIOV
41000 - * 2. limit: num_bytes < SSIZE_MAX
41002 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
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;
41009 - offset = tc->mem->ptr + tc->offset;
41010 - toSend = tc->mem->used - 1 - tc->offset;
41012 - chunks[i].iov_base = offset;
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;
41019 - num_chunks = i + 1;
41022 - chunks[i].iov_len = toSend;
41025 - num_bytes += toSend;
41029 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
41039 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41040 - "writev failed:", strerror(errno), fd);
41045 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41050 - /* check which chunks have been written */
41051 - cq->bytes_out += r;
41053 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41054 - if (r >= (ssize_t)chunks[i].iov_len) {
41056 - r -= chunks[i].iov_len;
41057 - tc->offset += chunks[i].iov_len;
41059 - if (chunk_finished) {
41060 - /* skip the chunks from further touches */
41061 - chunks_written++;
41064 - /* chunks_written + c = c->next is done in the for()*/
41065 - chunk_finished++;
41068 - /* partially written */
41071 - chunk_finished = 0;
41075 + if (ret != NETWORK_STATUS_SUCCESS) {
41080 + chunk_finished = 1;
41087 stat_cache_entry *sce = NULL;
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);
41095 + return NETWORK_STATUS_FATAL_ERROR;
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;
41106 if (offset > sce->st.st_size) {
41107 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41111 + return NETWORK_STATUS_FATAL_ERROR;
41115 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41116 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41120 + return NETWORK_STATUS_FATAL_ERROR;
41127 /* FreeBSD sendfile() */
41128 if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
41130 @@ -169,39 +88,39 @@
41135 + return NETWORK_STATUS_CONNECTION_CLOSE;
41137 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41140 + return NETWORK_STATUS_FATAL_ERROR;
41147 cq->bytes_out += r;
41150 if (c->offset == c->file.length) {
41151 chunk_finished = 1;
41160 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41167 if (!chunk_finished) {
41168 /* not finished yet */
41175 - return chunks_written;
41176 + return NETWORK_STATUS_SUCCESS;
41180 --- ../lighttpd-1.4.11/src/network_linux_sendfile.c 2006-02-15 20:02:36.000000000 +0200
41181 +++ lighttpd-1.4.12/src/network_linux_sendfile.c 2006-07-15 22:43:21.000000000 +0300
41182 @@ -26,122 +26,54 @@
41183 /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
41184 #undef HAVE_POSIX_FADVISE
41186 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41188 +NETWORK_BACKEND_WRITE(linuxsendfile) {
41190 size_t chunks_written = 0;
41193 for(c = cq->first; c; c = c->next, chunks_written++) {
41194 int chunk_finished = 0;
41196 + network_status_t ret;
41199 - case MEM_CHUNK: {
41204 - size_t num_chunks, i;
41205 - struct iovec chunks[UIO_MAXIOV];
41207 - size_t num_bytes = 0;
41209 - /* we can't send more then SSIZE_MAX bytes in one chunk */
41211 - /* build writev list
41213 - * 1. limit: num_chunks < UIO_MAXIOV
41214 - * 2. limit: num_bytes < SSIZE_MAX
41216 - for (num_chunks = 0, tc = c;
41217 - tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
41218 - tc = tc->next, num_chunks++);
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;
41225 - offset = tc->mem->ptr + tc->offset;
41226 - toSend = tc->mem->used - 1 - tc->offset;
41228 - chunks[i].iov_base = offset;
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;
41235 - num_chunks = i + 1;
41238 - chunks[i].iov_len = toSend;
41241 - num_bytes += toSend;
41245 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
41255 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41256 - "writev failed:", strerror(errno), fd);
41262 - /* check which chunks have been written */
41263 - cq->bytes_out += r;
41265 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
41267 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41268 - if (r >= (ssize_t)chunks[i].iov_len) {
41270 - r -= chunks[i].iov_len;
41271 - tc->offset += chunks[i].iov_len;
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++;
41283 - /* chunks_written + c = c->next is done in the for()*/
41284 - chunk_finished++;
41285 + chunk_finished = 1;
41288 - /* partially written */
41291 - chunk_finished = 0;
41298 + if (ret != NETWORK_STATUS_SUCCESS) {
41308 stat_cache_entry *sce = NULL;
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;
41317 - /* open file if not already opened */
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));
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);
41337 @@ -168,7 +100,7 @@
41341 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41342 + log_error_write(srv, __FILE__, __LINE__, "ssd",
41343 "sendfile failed:", strerror(errno), fd);
41346 @@ -179,7 +111,7 @@
41348 * - the file shrinked -> error
41349 * - the remote side closed inbetween -> remote-close */
41352 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41353 /* file is gone ? */
41355 @@ -196,22 +128,22 @@
41356 #ifdef HAVE_POSIX_FADVISE
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);
41376 cq->bytes_out += r;
41379 if (c->offset == c->file.length) {
41380 chunk_finished = 1;
41382 @@ -222,24 +154,24 @@
41393 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41400 if (!chunk_finished) {
41401 /* not finished yet */
41408 - return chunks_written;
41409 + return NETWORK_STATUS_SUCCESS;
41413 --- ../lighttpd-1.4.11/src/network_openssl.c 2005-11-17 14:53:29.000000000 +0200
41414 +++ lighttpd-1.4.12/src/network_openssl.c 2006-07-11 22:07:52.000000000 +0300
41415 @@ -23,17 +23,87 @@
41417 #include "stat_cache.h"
41419 -# include <openssl/ssl.h>
41420 -# include <openssl/err.h>
41421 +# include <openssl/ssl.h>
41422 +# include <openssl/err.h>
41424 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
41425 +NETWORK_BACKEND_READ_SSL(openssl) {
41429 + b = chunkqueue_get_append_buffer(cq);
41430 + buffer_prepare_copy(b, 8192);
41431 + len = SSL_read(ssl, b->ptr, b->size - 1);
41433 + log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
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:
41443 + * man SSL_get_error()
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).
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));
41462 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41464 + strerror(errno));
41469 + case SSL_ERROR_ZERO_RETURN:
41470 + /* clean shutdown on the remote side */
41473 + /* FIXME: later */
41476 + /* fall thourgh */
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));
41489 + b->ptr[b->used - 1] = '\0';
41491 + return NETWORK_STATUS_SUCCESS;
41495 +NETWORK_BACKEND_WRITE_SSL(openssl) {
41498 size_t chunks_written = 0;
41500 /* this is a 64k sendbuffer
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
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
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
41516 #define LOCAL_SEND_BUFSIZE (64 * 1024)
41517 static char *local_send_buffer = NULL;
41519 /* the remote side closed the connection before without shutdown request
41523 * if keep-alive is disabled */
41525 @@ -60,32 +130,34 @@
41527 for(c = cq->first; c; c = c->next) {
41528 int chunk_finished = 0;
41539 if (c->mem->used == 0) {
41540 chunk_finished = 1;
41545 offset = c->mem->ptr + c->offset;
41546 toSend = c->mem->used - 1 - c->offset;
41550 * SSL_write man-page
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.
41559 + * SSL_write(..., 0) return 0 which is handle as an error (Success)
41560 + * checking toSend and not calling SSL_write() is simpler
41563 - if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
41565 + if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
41568 switch ((ssl_r = SSL_get_error(ssl, r))) {
41570 /* perhaps we have error waiting in our error-queue */
41571 if (0 != (err = ERR_get_error())) {
41573 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41574 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41576 ERR_error_string(err, NULL));
41577 } while((err = ERR_get_error()));
41578 @@ -105,43 +177,43 @@
41582 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41583 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
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):",
41598 case SSL_ERROR_ZERO_RETURN:
41599 /* clean shutdown on the remote side */
41602 if (r == 0) return -2;
41607 while((err = ERR_get_error())) {
41608 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41609 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41611 ERR_error_string(err, NULL));
41619 cq->bytes_out += r;
41623 if (c->offset == (off_t)c->mem->used - 1) {
41624 chunk_finished = 1;
41631 @@ -150,7 +222,7 @@
41632 stat_cache_entry *sce = NULL;
41634 int write_wait = 0;
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 @@
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;
41647 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
41650 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41651 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
41657 @@ -183,9 +255,9 @@
41660 s = local_send_buffer;
41666 if ((r = SSL_write(ssl, s, toSend)) <= 0) {
41669 @@ -197,7 +269,7 @@
41670 /* perhaps we have error waiting in our error-queue */
41671 if (0 != (err = ERR_get_error())) {
41673 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41674 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41676 ERR_error_string(err, NULL));
41677 } while((err = ERR_get_error()));
41678 @@ -207,58 +279,58 @@
41682 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41683 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
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):",
41698 case SSL_ERROR_ZERO_RETURN:
41699 /* clean shutdown on the remote side */
41702 if (r == 0) return -2;
41707 while((err = ERR_get_error())) {
41708 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41709 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41711 ERR_error_string(err, NULL));
41719 cq->bytes_out += r;
41723 if (c->offset == c->file.length) {
41724 chunk_finished = 1;
41726 } while(!chunk_finished && !write_wait);
41732 log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
41739 if (!chunk_finished) {
41740 /* not finished yet */
41750 --- ../lighttpd-1.4.11/src/network_solaris_sendfilev.c 2005-10-22 12:28:27.000000000 +0300
41751 +++ lighttpd-1.4.12/src/network_solaris_sendfilev.c 2006-07-11 22:07:53.000000000 +0300
41752 @@ -29,114 +29,34 @@
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()'
41760 - * If you want such an interface and need the performance, just give me an account on
41763 + * If you want such an interface and need the performance, just give me an account on
41765 * - jan@kneschke.de
41769 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
41770 +NETWORK_BACKEND_WRITE(solarissendfilev) {
41772 size_t chunks_written = 0;
41775 for(c = cq->first; c; c = c->next, chunks_written++) {
41776 int chunk_finished = 0;
41778 + network_status_t ret;
41781 - case MEM_CHUNK: {
41786 - size_t num_chunks, i;
41787 - struct iovec chunks[UIO_MAXIOV];
41790 - size_t num_bytes = 0;
41792 - /* we can't send more then SSIZE_MAX bytes in one chunk */
41794 - /* build writev list
41796 - * 1. limit: num_chunks < UIO_MAXIOV
41797 - * 2. limit: num_bytes < SSIZE_MAX
41799 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
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;
41806 - offset = tc->mem->ptr + tc->offset;
41807 - toSend = tc->mem->used - 1 - tc->offset;
41809 - chunks[i].iov_base = offset;
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;
41816 - num_chunks = i + 1;
41819 - chunks[i].iov_len = toSend;
41822 - num_bytes += toSend;
41826 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
41836 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41837 - "writev failed:", strerror(errno), fd);
41843 - /* check which chunks have been written */
41844 - cq->bytes_out += r;
41846 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41847 - if (r >= (ssize_t)chunks[i].iov_len) {
41849 - r -= chunks[i].iov_len;
41850 - tc->offset += chunks[i].iov_len;
41852 - if (chunk_finished) {
41853 - /* skip the chunks from further touches */
41854 - chunks_written++;
41857 - /* chunks_written + c = c->next is done in the for()*/
41858 - chunk_finished++;
41861 - /* partially written */
41864 - chunk_finished = 0;
41869 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41871 + if (ret != NETWORK_STATUS_SUCCESS) {
41876 + chunk_finished = 1;
41883 @@ -144,25 +64,25 @@
41884 sendfilevec_t fvec;
41885 stat_cache_entry *sce = NULL;
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);
41896 offset = c->file.start + c->offset;
41897 toSend = c->file.length - c->offset;
41900 if (offset > sce->st.st_size) {
41901 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41907 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41908 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41914 @@ -170,44 +90,43 @@
41916 fvec.sfv_off = offset;
41917 fvec.sfv_len = toSend;
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);
41928 + return NETWORK_STATUS_FATAL_ERROR;
41937 c->offset += written;
41938 cq->bytes_out += written;
41941 if (c->offset == c->file.length) {
41942 chunk_finished = 1;
41950 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41954 + return NETWORK_STATUS_FATAL_ERROR;
41958 if (!chunk_finished) {
41959 /* not finished yet */
41966 - return chunks_written;
41967 + return NETWORK_STATUS_SUCCESS;
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
41974 #include <sys/types.h>
41975 #include <sys/stat.h>
41976 -#include <sys/time.h>
41980 -#include <unistd.h>
41981 #include <string.h>
41982 #include <stdlib.h>
41983 +#include <assert.h>
41985 #include "network.h"
41986 #include "fdevent.h"
41988 #include "stat_cache.h"
41990 #include "sys-socket.h"
41991 +#include "sys-files.h"
41993 #include "network_backends.h"
41997 #ifdef HAVE_SYS_FILIO_H
41998 # include <sys/filio.h>
42000 @@ -24,47 +27,84 @@
42001 #include <sys/resource.h>
42004 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
42006 +* fill the chunkqueue will all the data that we can get
42008 +* this might be optimized into a readv() which uses the chunks
42011 +NETWORK_BACKEND_READ(read) {
42016 + /* use a chunk-size of 8k */
42020 + b = chunkqueue_get_append_buffer(cq);
42022 + buffer_prepare_copy(b, toread);
42024 + if (-1 == (r = read(fd, b->ptr, toread))) {
42027 + return NETWORK_STATUS_WAIT_FOR_EVENT;
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;
42037 + return NETWORK_STATUS_CONNECTION_CLOSE;
42040 + /* this should be catched by the b > 0 above */
42042 + b->used += r + 1;
42043 + b->ptr[b->used - 1] = '\0';
42044 + } while (r == toread);
42046 + return NETWORK_STATUS_SUCCESS;
42049 +NETWORK_BACKEND_WRITE(write) {
42051 size_t chunks_written = 0;
42054 for(c = cq->first; c; c = c->next) {
42055 int chunk_finished = 0;
42065 if (c->mem->used == 0) {
42066 chunk_finished = 1;
42071 offset = c->mem->ptr + c->offset;
42072 toSend = c->mem->used - 1 - c->offset;
42074 - if ((r = send(fd, offset, toSend, 0)) < 0) {
42075 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42081 if ((r = write(fd, offset, toSend)) < 0) {
42082 log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42086 + return NETWORK_STATUS_FATAL_ERROR;
42092 cq->bytes_out += r;
42095 if (c->offset == (off_t)c->mem->used - 1) {
42096 chunk_finished = 1;
42103 @@ -76,93 +116,89 @@
42105 stat_cache_entry *sce = NULL;
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);
42113 + return NETWORK_STATUS_FATAL_ERROR;
42117 offset = c->file.start + c->offset;
42118 toSend = c->file.length - c->offset;
42121 if (offset > sce->st.st_size) {
42122 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42126 + return NETWORK_STATUS_FATAL_ERROR;
42129 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42130 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42134 + return NETWORK_STATUS_FATAL_ERROR;
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));
42146 + return NETWORK_STATUS_FATAL_ERROR;
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);
42154 + return NETWORK_STATUS_FATAL_ERROR;
42158 munmap(p, sce->st.st_size);
42160 buffer_prepare_copy(srv->tmp_buf, toSend);
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));
42170 + return NETWORK_STATUS_FATAL_ERROR;
42174 if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
42175 log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
42179 + return NETWORK_STATUS_FATAL_ERROR;
42183 cq->bytes_out += r;
42186 if (c->offset == c->file.length) {
42187 chunk_finished = 1;
42196 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42200 + return NETWORK_STATUS_FATAL_ERROR;
42204 if (!chunk_finished) {
42205 /* not finished yet */
42215 - return chunks_written;
42216 + return NETWORK_STATUS_SUCCESS;
42220 -network_write_init(void) {
42221 - p->write = network_write_write_chunkset;
42224 --- ../lighttpd-1.4.11/src/network_writev.c 2006-02-15 01:02:36.000000000 +0200
42225 +++ lighttpd-1.4.12/src/network_writev.c 2006-07-15 22:43:21.000000000 +0300
42226 @@ -28,10 +28,10 @@
42229 # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
42230 -/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42231 +/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42232 # define UIO_MAXIOV 1024
42233 # elif defined(__sgi)
42234 -/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42235 +/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42236 # define UIO_MAXIOV 512
42237 # elif defined(__sun)
42238 /* Solaris (and SunOS?) defines IOV_MAX instead */
42239 @@ -51,105 +51,121 @@
42240 #define LOCAL_BUFFERING 1
42243 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
42245 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
42250 + size_t num_chunks, i;
42251 + struct iovec chunks[UIO_MAXIOV];
42252 + chunk *tc; /* transfer chunks */
42253 + size_t num_bytes = 0;
42255 + /* we can't send more then SSIZE_MAX bytes in one chunk */
42257 + /* build writev list
42259 + * 1. limit: num_chunks < UIO_MAXIOV
42260 + * 2. limit: num_bytes < SSIZE_MAX
42262 + for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
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;
42269 + offset = tc->mem->ptr + tc->offset;
42270 + toSend = tc->mem->used - 1 - tc->offset;
42272 + chunks[i].iov_base = offset;
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;
42279 + num_chunks = i + 1;
42282 + chunks[i].iov_len = toSend;
42285 + num_bytes += toSend;
42289 + if ((r = writev(fd, chunks, num_chunks)) < 0) {
42292 + return NETWORK_STATUS_WAIT_FOR_EVENT;
42294 + return NETWORK_STATUS_INTERRUPTED;
42297 + return NETWORK_STATUS_CONNECTION_CLOSE;
42299 + log_error_write(srv, __FILE__, __LINE__, "ssd",
42300 + "writev failed:", strerror(errno), fd);
42302 + return NETWORK_STATUS_FATAL_ERROR;
42306 + cq->bytes_out += r;
42308 + /* check which chunks have been written */
42310 + for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42311 + if (r >= (ssize_t)chunks[i].iov_len) {
42313 + r -= chunks[i].iov_len;
42314 + tc->offset += chunks[i].iov_len;
42316 + /* partially written */
42320 + return NETWORK_STATUS_WAIT_FOR_EVENT;
42324 + /* all chunks have been pushed out */
42325 + return NETWORK_STATUS_SUCCESS;
42328 +NETWORK_BACKEND_WRITE(writev) {
42330 size_t chunks_written = 0;
42333 for(c = cq->first; c; c = c->next) {
42334 int chunk_finished = 0;
42336 + network_status_t ret;
42339 - case MEM_CHUNK: {
42344 - size_t num_chunks, i;
42345 - struct iovec chunks[UIO_MAXIOV];
42347 - size_t num_bytes = 0;
42349 - /* we can't send more then SSIZE_MAX bytes in one chunk */
42351 - /* build writev list
42353 - * 1. limit: num_chunks < UIO_MAXIOV
42354 - * 2. limit: num_bytes < SSIZE_MAX
42356 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
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;
42363 - offset = tc->mem->ptr + tc->offset;
42364 - toSend = tc->mem->used - 1 - tc->offset;
42366 - chunks[i].iov_base = offset;
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;
42373 - num_chunks = i + 1;
42376 - chunks[i].iov_len = toSend;
42379 - num_bytes += toSend;
42383 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
42393 - log_error_write(srv, __FILE__, __LINE__, "ssd",
42394 - "writev failed:", strerror(errno), fd);
42400 - cq->bytes_out += r;
42402 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
42404 - /* check which chunks have been written */
42406 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42407 - if (r >= (ssize_t)chunks[i].iov_len) {
42409 - r -= chunks[i].iov_len;
42410 - tc->offset += chunks[i].iov_len;
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++;
42422 - /* chunks_written + c = c->next is done in the for()*/
42423 - chunk_finished++;
42424 + chunk_finished = 1;
42427 - /* partially written */
42430 - chunk_finished = 0;
42437 + if (ret != NETWORK_STATUS_SUCCESS) {
42446 @@ -159,26 +175,26 @@
42447 #define KByte * 1024
42448 #define MByte * 1024 KByte
42449 #define GByte * 1024 MByte
42450 - const off_t we_want_to_mmap = 512 KByte;
42451 + const off_t we_want_to_mmap = 512 KByte;
42452 char *start = NULL;
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);
42458 + return NETWORK_STATUS_FATAL_ERROR;
42461 abs_offset = c->file.start + c->offset;
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);
42471 + return NETWORK_STATUS_FATAL_ERROR;
42474 - /* mmap the buffer
42476 + /* mmap the buffer
42478 * - new mmap as the we are at the end of the last one */
42479 if (c->file.mmap.start == MAP_FAILED ||
42480 abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
42481 @@ -188,7 +204,7 @@
42482 * adaptive mem-mapping
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
42489 * only mmap 16M in one chunk and move the window as soon as we have finished
42490 @@ -234,8 +250,8 @@
42491 if (-1 == c->file.fd) { /* open the file if not already open */
42492 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
42493 log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
42497 + return NETWORK_STATUS_FATAL_ERROR;
42500 fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
42501 @@ -245,10 +261,10 @@
42502 if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
42503 /* close it here, otherwise we'd have to set FD_CLOEXEC */
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);
42510 + return NETWORK_STATUS_FATAL_ERROR;
42513 c->file.mmap.length = to_mmap;
42514 @@ -258,7 +274,7 @@
42515 #ifdef HAVE_MADVISE
42516 /* don't advise files < 64Kb */
42517 if (c->file.mmap.length > (64 KByte)) {
42518 - /* darwin 7 is returning EINVAL all the time and I don't know how to
42519 + /* darwin 7 is returning EINVAL all the time and I don't know how to
42520 * detect this at runtime.i
42522 * ignore the return value for now */
42523 @@ -274,12 +290,12 @@
42524 toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
42527 - log_error_write(srv, __FILE__, __LINE__, "soooo",
42528 + log_error_write(srv, __FILE__, __LINE__, "soooo",
42529 "toSend is negative:",
42531 c->file.mmap.length,
42533 - c->file.mmap.offset);
42534 + c->file.mmap.offset);
42535 assert(toSend < 0);
42538 @@ -297,18 +313,18 @@
42543 + return NETWORK_STATUS_CONNECTION_CLOSE;
42545 - log_error_write(srv, __FILE__, __LINE__, "ssd",
42546 + log_error_write(srv, __FILE__, __LINE__, "ssd",
42547 "write failed:", strerror(errno), fd);
42551 + return NETWORK_STATUS_FATAL_ERROR;
42557 cq->bytes_out += r;
42560 if (c->offset == c->file.length) {
42561 chunk_finished = 1;
42563 @@ -318,26 +334,26 @@
42564 c->file.mmap.start = MAP_FAILED;
42574 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42578 + return NETWORK_STATUS_FATAL_ERROR;
42582 if (!chunk_finished) {
42583 /* not finished yet */
42593 - return chunks_written;
42594 + return NETWORK_STATUS_SUCCESS;
42598 --- ../lighttpd-1.4.11/src/plugin.c 2006-02-08 14:00:54.000000000 +0200
42599 +++ lighttpd-1.4.12/src/plugin.c 2006-07-11 22:07:52.000000000 +0300
42600 @@ -13,27 +13,27 @@
42601 #include <valgrind/valgrind.h>
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()
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,
42648 static plugin *plugin_init(void) {
42652 p = calloc(1, sizeof(*p));
42655 + p->required_plugins = array_init();
42660 static void plugin_free(plugin *p) {
42661 int use_dlclose = 1;
42662 if (p->name) buffer_free(p->name);
42664 + array_free(p->required_plugins);
42665 #ifdef HAVE_VALGRIND_VALGRIND_H
42666 /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
42669 #ifndef LIGHTTPD_STATIC
42670 - if (use_dlclose && p->lib) {
42672 + if (use_dlclose && p->lib) {
42674 FreeLibrary(p->lib);
42685 @@ -89,17 +93,17 @@
42686 srv->plugins.size += 4;
42687 srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
42691 ps = srv->plugins.ptr;
42692 ps[srv->plugins.used++] = p;
42707 #ifdef LIGHTTPD_STATIC
42708 @@ -121,30 +125,35 @@
42710 int plugins_load(server *srv) {
42715 int (*init)(plugin *pl);
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;
42728 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
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");
42736 buffer_append_string(srv->tmp_buf, ".so");
42743 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
42746 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
42747 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
42748 FORMAT_MESSAGE_FROM_SYSTEM,
42751 @@ -152,36 +161,36 @@
42752 (LPTSTR) &lpMsgBuf,
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);
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());
42782 buffer_reset(srv->tmp_buf);
42783 buffer_copy_string(srv->tmp_buf, modules);
42784 buffer_append_string(srv->tmp_buf, "_plugin_init");
42788 init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
42790 if (init == NULL) {
42793 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
42794 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
42795 FORMAT_MESSAGE_FROM_SYSTEM,
42798 @@ -190,7 +199,7 @@
42801 log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
42807 @@ -203,24 +212,43 @@
42809 if ((error = dlerror()) != NULL) {
42810 log_error_write(srv, __FILE__, __LINE__, "s", error);
42820 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
42827 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
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];
42833 + for (j = 0; j < i; j++) {
42834 + data_string *mod = (data_string *)srv->srvconf.modules->data[j];
42836 + if (buffer_is_equal(req->value, mod->value)) break;
42841 + log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
42848 plugins_register(srv, p);
42855 @@ -253,8 +281,8 @@
42859 - * plugins that use
42861 + * plugins that use
42864 * - connection *con
42865 * - void *p_d (plugin_data *)
42866 @@ -301,12 +329,12 @@
42870 - * plugins that use
42872 + * plugins that use
42875 * - void *p_d (plugin_data *)
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 @@
42884 #undef PLUGIN_TO_SLOT
42895 handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
42900 ps = srv->plugins.ptr;
42903 for (i = 0; i < srv->plugins.used; i++) {
42905 if (p->handle_fdevent) {
42906 @@ -344,34 +372,34 @@
42912 return HANDLER_GO_ON;
42918 * - call init function of all plugins to init the plugin-internals
42919 * - added each plugin that supports has callback to the corresponding slot
42922 * - is only called once.
42925 handler_t plugins_call_init(server *srv) {
42930 ps = srv->plugins.ptr;
42936 srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
42939 for (i = 0; i < srv->plugins.used; i++) {
42941 /* check which calls are supported */
42947 #define PLUGIN_TO_SLOT(x, y) \
42949 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
42950 @@ -384,11 +412,11 @@
42957 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
42958 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
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
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;
42982 /* used for con->mode, DIRECT == 0, plugins above that */
42983 ((plugin_data *)(p->data))->id = i + 1;
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;
42992 @@ -422,29 +450,46 @@
42998 return HANDLER_GO_ON;
43002 + * get the config-storage of the named plugin
43004 +void *plugin_get_config(server *srv, const char *name) {
43007 + for (i = 0; i < srv->plugins.used; i++) {
43008 + plugin *p = ((plugin **)srv->plugins.ptr)[i];
43010 + if (buffer_is_equal_string(p->name, name, strlen(name))) {
43018 void plugins_free(server *srv) {
43020 plugins_call_cleanup(srv);
43023 for (i = 0; i < srv->plugins.used; i++) {
43024 plugin *p = ((plugin **)srv->plugins.ptr)[i];
43031 for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
43032 plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
43035 if (slot) free(slot);
43039 free(srv->plugin_slots);
43040 srv->plugin_slots = NULL;
43043 free(srv->plugins.ptr);
43044 srv->plugins.ptr = NULL;
43045 srv->plugins.used = 0;
43046 --- ../lighttpd-1.4.11/src/plugin.h 2005-08-15 12:28:56.000000000 +0300
43047 +++ lighttpd-1.4.12/src/plugin.h 2006-07-11 22:07:52.000000000 +0300
43050 #define INIT_FUNC(x) \
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.
43056 +#define PATCH_OPTION(x) \
43059 #define FREE_FUNC SERVER_FUNC
43060 #define TRIGGER_FUNC SERVER_FUNC
43061 @@ -25,19 +31,19 @@
43062 #define URIHANDLER_FUNC CONNECTION_FUNC
43064 #define PLUGIN_DATA size_t id
43071 buffer *name; /* name of the plugin */
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 */
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 */
43092 - handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43094 - /* when a handler for the request
43098 + handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43100 + /* when a handler for the request
43103 handler_t (* handle_subrequest) (server *srv, connection *con, void *p_d); /* */
43104 handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* */
43108 /* dlopen handle */
43111 + array *required_plugins;
43114 int plugins_load(server *srv);
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);
43121 +void *plugin_get_config(server *srv, const char *name);
43124 --- ../lighttpd-1.4.11/src/proc_open.c 2005-08-11 01:26:39.000000000 +0300
43125 +++ lighttpd-1.4.12/src/proc_open.c 2006-07-11 22:07:53.000000000 +0300
43126 @@ -13,13 +13,13 @@
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)
43140 HANDLE copy, self = GetCurrentProcess();
43142 @@ -148,11 +148,14 @@
43145 SECURITY_ATTRIBUTES security;
43146 - const char *shell;
43147 + const char *shell = NULL;
43148 + const char *windir = NULL;
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);
43160 @@ -177,17 +180,23 @@
43161 memset(&pi, 0, sizeof(pi));
43163 cmdline = buffer_init();
43164 - buffer_append_string(cmdline, shell);
43166 + buffer_append_string(cmdline, shell);
43168 + buffer_append_string(cmdline, windir);
43169 + buffer_append_string(cmdline, "\\system32\\cmd.exe");
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);
43177 if (FALSE == procok) {
43178 - fprintf(stderr, "failed to CreateProcess");
43179 + fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
43180 + buffer_free(cmdline);
43183 + buffer_free(cmdline);
43185 proc->child = pi.hProcess;
43186 CloseHandle(pi.hThread);
43187 @@ -226,8 +235,7 @@
43190 if (NULL == (shell = getenv(SHELLENV))) {
43191 - fprintf(stderr, "env %s is required", SHELLENV);
43193 + shell = "/bin/sh";
43196 if (proc_open_pipes(proc) != 0) {
43197 @@ -262,11 +270,11 @@
43201 -#endif /* WIN32 */
43202 +#endif /* _WIN32 */
43204 /* {{{ proc_read_fd_to_buffer */
43205 static void proc_read_fd_to_buffer(int fd, buffer *b) {
43207 + int s; /* win32 has not ssize_t */
43210 buffer_prepare_append(b, 512);
43211 --- ../lighttpd-1.4.11/src/proc_open.h 2005-08-11 01:26:39.000000000 +0300
43212 +++ lighttpd-1.4.12/src/proc_open.h 2006-07-11 22:07:53.000000000 +0300
43215 #include "buffer.h"
43219 #include <windows.h>
43220 typedef HANDLE descriptor_t;
43221 typedef HANDLE proc_pid_t;
43222 --- ../lighttpd-1.4.11/src/request.c 2006-03-05 11:58:09.000000000 +0200
43223 +++ lighttpd-1.4.12/src/request.c 2006-07-11 22:07:52.000000000 +0300
43224 @@ -10,15 +10,17 @@
43225 #include "keyvalue.h"
43228 +#include "sys-strings.h"
43230 static int request_check_hostname(server *srv, connection *con, buffer *host) {
43231 enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
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 */
43244 @@ -32,17 +34,17 @@
43245 * IPv6address = "[" ... "]"
43251 if (!host || host->used == 0) return 0;
43254 host_len = host->used - 1;
43258 if (host->ptr[0] == '[') {
43259 char *c = host->ptr + 1;
43263 /* check portnumber */
43264 for (; *c && *c != ']'; c++) {
43266 @@ -53,12 +55,12 @@
43279 if (*(c+1) == ':') {
43280 for (c += 2; *c; c++) {
43281 @@ -69,39 +71,39 @@
43287 if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
43288 char *c = colon + 1;
43291 /* check portnumber */
43293 if (!light_isdigit(*c)) return -1;
43297 /* remove the port from the host-len */
43298 host_len = colon - host->ptr;
43302 /* Host is empty */
43303 if (host_len == 0) return -1;
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];
43314 /* only switch stage, if this is not the last character */
43315 if (i != host_len - 1) {
43316 if (label_len == 0) {
43321 /* check the first character at right of the dot */
43323 if (!light_isalpha(host->ptr[i+1])) {
43327 } else if (!light_isdigit(host->ptr[i+1])) {
43329 @@ -111,9 +113,9 @@
43335 stage = DOMAINLABEL;
43340 } else if (i == 0) {
43341 @@ -135,7 +137,7 @@
43350 @@ -143,7 +145,7 @@
43351 if (label_len == 0) {
43358 } else if (!light_isdigit(c)) {
43359 @@ -156,12 +158,12 @@
43360 if (label_len == 0) {
43365 /* c is either - or alphanum here */
43366 if ('-' == host->ptr[i+1]) {
43373 } else if (i == 0) {
43374 @@ -176,20 +178,20 @@
43385 /* a IP has to consist of 4 parts */
43386 if (is_ip == 1 && level != 3) {
43391 if (label_len == 0) {
43399 @@ -201,53 +203,53 @@
43409 * val1, val2, val3, val4
43412 * into a array (more or less a explode() incl. striping of whitespaces
43416 if (b->used == 0) return 0;
43422 for (i =0; i < b->used - 1; ) {
43423 char *start = NULL, *end = NULL;
43432 for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
43439 case 1: /* value */
43443 for (; *s != ',' && i < b->used - 1; i++, s++);
43447 for (; (*end == ' ' || *end == '\t') && end > start; end--);
43450 if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
43451 ds = data_string_init();
43454 buffer_copy_string_len(ds->value, start, end-start+1);
43455 array_insert_unique(vals, (data_unset *)ds);
43463 /* end of string */
43469 @@ -263,7 +265,7 @@
43470 if (c <= 32) return 0;
43471 if (c == 127) return 0;
43472 if (c == 255) return 0;
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;
43484 enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
43490 int request_line_stage = 0;
43497 data_string *ds = NULL;
43500 - * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43501 - * Option : "^([-a-zA-Z]+): (.+)$"
43504 + * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43505 + * Option : "^([-a-zA-Z]+): (.+)$"
43509 if (con->conf.log_request_header) {
43510 - log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43512 - "request-len:", con->request.request->used,
43513 + log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43515 + "request-len:", con->request.request->used,
43516 "\n", con->request.request);
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.*/
43525 buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
43527 /* fill the local request buffer */
43528 buffer_copy_string_buffer(con->parse_request, con->request.request);
43532 keep_alive_set = 0;
43533 con_length_set = 0;
43535 @@ -318,25 +320,25 @@
43537 for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
43538 char *cur = con->parse_request->ptr + i;
43544 if (con->parse_request->ptr[i+1] == '\n') {
43551 con->parse_request->ptr[i] = '\0';
43552 con->parse_request->ptr[i+1] = '\0';
43555 buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
43558 if (request_line_stage != 2) {
43559 con->http_status = 400;
43560 con->response.keep_alive = 0;
43561 con->keep_alive = 0;
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 @@
43573 proto = con->parse_request->ptr + first;
43577 *(proto - 1) = '\0';
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;
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);
43599 con->request.http_method = r;
43606 * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
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 @@
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;
43623 con->http_status = 505;
43625 if (srv->srvconf.log_request_header_on_error) {
43626 @@ -439,30 +441,30 @@
43632 if (0 == strncmp(uri, "http://", 7) &&
43633 NULL != (nuri = strchr(uri + 7, '/'))) {
43634 /* ignore the host-part */
43637 buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
43639 /* everything looks good so far */
43640 buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
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;
43652 if (srv->srvconf.log_request_header_on_error) {
43653 buf[0] = con->request.uri->ptr[j];
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]);
43669 log_error_write(srv, __FILE__, __LINE__, "Sb",
43670 "request-header:\n",
43671 con->request.request);
43680 buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
43683 con->http_status = 0;
43689 @@ -494,14 +496,14 @@
43692 switch(request_line_stage) {
43696 - method = con->parse_request->ptr + first;
43697 + method = con->parse_request->ptr + first;
43702 - uri = con->parse_request->ptr + first;
43703 + uri = con->parse_request->ptr + first;
43707 @@ -509,7 +511,7 @@
43708 con->http_status = 400;
43709 con->response.keep_alive = 0;
43710 con->keep_alive = 0;
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 @@
43722 request_line_stage++;
43730 if (con->request.uri->used == 1) {
43731 @@ -540,30 +542,30 @@
43737 for (; i < con->parse_request->used && !done; i++) {
43738 char *cur = con->parse_request->ptr + i;
43747 * 1*<any CHAR except CTLs or separators>
43748 * CTLs == 0-31 + 127
43760 if (is_ws_after_key == 0) {
43761 key_len = i - first;
43763 is_ws_after_key = 0;
43769 @@ -584,8 +586,8 @@
43770 con->http_status = 400;
43771 con->keep_alive = 0;
43772 con->response.keep_alive = 0;
43774 - log_error_write(srv, __FILE__, __LINE__, "sbsds",
43776 + log_error_write(srv, __FILE__, __LINE__, "sbsds",
43777 "invalid character in key", con->request.request, cur, *cur, "-> 400");
43780 @@ -594,13 +596,13 @@
43792 key_len = i - first;
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 @@
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);
43821 con->http_status = 400;
43822 con->response.keep_alive = 0;
43823 con->keep_alive = 0;
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';
43847 if (srv->srvconf.log_request_header_on_error) {
43848 @@ -652,7 +654,7 @@
43849 "request-header:\n",
43850 con->request.request);
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;
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");
43868 log_error_write(srv, __FILE__, __LINE__, "Sb",
43869 "request-header:\n",
43870 con->request.request);
43877 @@ -710,25 +712,25 @@
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';
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");
43898 log_error_write(srv, __FILE__, __LINE__, "Sb",
43899 "request-header:\n",
43900 con->request.request);
43905 con->http_status = 400;
43906 con->keep_alive = 0;
43907 con->response.keep_alive = 0;
43908 @@ -738,9 +740,9 @@
43911 key = con->parse_request->ptr + first;
43914 s_len = cur - value;
43919 if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
43920 @@ -748,86 +750,87 @@
43922 buffer_copy_string_len(ds->key, key, key_len);
43923 buffer_copy_string_len(ds->value, value, s_len);
43925 - /* retreive values
43929 + /* retreive values
43932 * the list of options is sorted to simplify the search
43936 if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
43944 vals = srv->split_vals;
43949 http_request_split_value(vals, ds->value);
43952 for (vi = 0; vi < vals->used; vi++) {
43953 data_string *dsv = (data_string *)vals->data[vi];
43956 if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
43957 keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
43961 } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
43962 keep_alive_set = HTTP_CONNECTION_CLOSE;
43970 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
43972 unsigned long int r;
43976 if (con_length_set) {
43977 con->http_status = 400;
43978 con->keep_alive = 0;
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);
43989 + ds->free((data_unset *) ds);
43994 if (ds->value->used == 0) SEGFAULT();
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");
44005 con->http_status = 400;
44006 con->keep_alive = 0;
44009 array_insert_unique(con->request.headers, (data_unset *)ds);
44015 r = strtoul(ds->value->ptr, &err, 10);
44018 if (*err == '\0') {
44019 con_length_set = 1;
44020 con->request.content_length = r;
44022 - log_error_write(srv, __FILE__, __LINE__, "sbs",
44023 + log_error_write(srv, __FILE__, __LINE__, "sbs",
44024 "content-length broken:", ds->value, "-> 400");
44027 con->http_status = 400;
44028 con->keep_alive = 0;
44031 array_insert_unique(con->request.headers, (data_unset *)ds);
44034 @@ -838,23 +841,24 @@
44036 con->http_status = 400;
44037 con->keep_alive = 0;
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);
44048 + ds->free((data_unset *) ds);
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
44057 * -> (10.1.1) 100 (read content, process request, send final status-code)
44058 * -> (10.4.18) 417 (close)
44061 * (not handled at all yet, we always send 417 here)
44063 * What has to be added ?
44064 @@ -863,10 +867,10 @@
44070 con->http_status = 417;
44071 con->keep_alive = 0;
44074 array_insert_unique(con->request.headers, (data_unset *)ds);
44076 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
44077 @@ -875,14 +879,15 @@
44079 con->http_status = 400;
44080 con->keep_alive = 0;
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);
44091 + ds->free((data_unset *) ds);
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 @@
44097 con->http_status = 400;
44098 con->keep_alive = 0;
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);
44109 + ds->free((data_unset *) ds);
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 @@
44115 con->http_status = 400;
44116 con->keep_alive = 0;
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);
44127 + ds->free((data_unset *) ds);
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) {
44135 if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
44136 NULL != strchr(ds->value->ptr+6, '-')) {
44139 /* if dup, only the first one will survive */
44140 con->request.http_range = ds->value->ptr + 6;
44143 con->http_status = 400;
44144 con->keep_alive = 0;
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);
44155 + ds->free((data_unset *) ds);
44161 array_insert_unique(con->request.headers, (data_unset *)ds);
44163 /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
44171 @@ -963,10 +971,10 @@
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");
44181 con->http_status = 400;
44182 con->keep_alive = 0;
44183 con->response.keep_alive = 0;
44184 @@ -982,28 +990,28 @@
44190 con->header_len = i;
44193 /* do some post-processing */
44195 if (con->request.http_version == HTTP_VERSION_1_1) {
44196 if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
44197 /* no Connection-Header sent */
44200 /* HTTP/1.1 -> keep-alive default TRUE */
44201 con->keep_alive = 1;
44203 con->keep_alive = 0;
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;
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 @@
44220 if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
44221 /* no Connection-Header sent */
44224 /* HTTP/1.0 -> keep-alive default FALSE */
44225 con->keep_alive = 1;
44227 con->keep_alive = 0;
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)) {
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;
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");
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");
44266 con->keep_alive = 0;
44267 @@ -1073,16 +1081,16 @@
44268 /* the may have a content-length */
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;
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");
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
44298 con->http_status = 413;
44299 con->keep_alive = 0;
44301 - log_error_write(srv, __FILE__, __LINE__, "sds",
44303 + log_error_write(srv, __FILE__, __LINE__, "sds",
44304 "request-size too long:", con->request.content_length, "-> 413");
44311 /* we have content */
44312 if (con->request.content_length != 0) {
44321 @@ -1116,9 +1124,9 @@
44324 if (con->request.request->used < 5) return 0;
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;
44333 --- ../lighttpd-1.4.11/src/response.c 2006-03-04 16:41:39.000000000 +0200
44334 +++ lighttpd-1.4.12/src/response.c 2006-07-11 22:07:52.000000000 +0300
44336 #include <stdlib.h>
44337 #include <string.h>
44339 -#include <unistd.h>
44341 #include <assert.h>
44343 @@ -24,15 +23,17 @@
44344 #include "plugin.h"
44346 #include "sys-socket.h"
44347 +#include "sys-files.h"
44348 +#include "sys-strings.h"
44350 int http_response_write_header(server *srv, connection *con) {
44354 int have_server = 0;
44357 b = chunkqueue_get_prepend_buffer(con->write_queue);
44360 if (con->request.http_version == HTTP_VERSION_1_1) {
44361 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
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));
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");
44375 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
44376 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
44382 /* add all headers */
44383 for (i = 0; i < con->response.headers->used; i++) {
44387 ds = (data_string *)con->response.headers->data[i];
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;
44397 @@ -68,28 +70,28 @@
44398 BUFFER_APPEND_STRING_CONST(b, ": ");
44399 buffer_append_string_buffer(b, ds->value);
44401 - log_error_write(srv, __FILE__, __LINE__, "bb",
44402 + log_error_write(srv, __FILE__, __LINE__, "bb",
44403 ds->key, ds->value);
44410 /* HTTP/1.1 requires a Date: header */
44411 BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
44414 /* cache the generated timestamp */
44415 if (srv->cur_ts != srv->last_generated_date_ts) {
44416 buffer_prepare_copy(srv->ts_date_str, 255);
44418 - strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
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)));
44424 srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
44427 srv->last_generated_date_ts = srv->cur_ts;
44431 buffer_append_string_buffer(b, srv->ts_date_str);
44434 @@ -101,16 +103,16 @@
44435 buffer_append_string_buffer(b, con->conf.server_tag);
44440 BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
44445 con->bytes_header = b->used - 1;
44448 if (con->conf.log_response_header) {
44449 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
44456 @@ -118,71 +120,71 @@
44458 handler_t http_response_prepare(server *srv, connection *con) {
44461 - /* looks like someone has already done a decision */
44462 - if (con->mode == DIRECT &&
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);
44473 return HANDLER_FINISHED;
44477 /* no decision yet, build conf->filename */
44478 if (con->mode == DIRECT && con->physical.path->used == 0) {
44481 - /* we only come here when we have the parse the full request again
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
44486 + * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44487 * problem here as mod_setenv might get called multiple times
44489 * fastcgi-auth might lead to a COMEBACK too
44490 * fastcgi again dead server too
44492 * mod_compress might add headers twice too
44498 if (con->conf.log_condition_handling) {
44499 log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
44501 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
44510 * - uri.path (secure)
44519 * Name according to RFC 2396
44528 * (scheme)://(authority)(path)?(query)
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);
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: */
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);
44557 /* disable keep-alive if requested */
44560 if (con->request_count > con->conf.max_keep_alive_requests) {
44561 con->keep_alive = 0;
44574 * - based on the raw URL
44580 switch(r = plugins_call_handle_uri_raw(srv, con)) {
44581 case HANDLER_GO_ON:
44583 @@ -229,14 +231,14 @@
44587 - /* build filename
44588 + /* build filename
44590 * - decode url-encodings (e.g. %20 -> ' ')
44591 * - remove path-modifiers (e.g. /../)
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 @@
44612 * - based on the clean URL
44618 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
44621 + /* do we have to downgrade to 1.0 ? */
44622 + if (!con->conf.allow_http11) {
44623 + con->request.http_version = HTTP_VERSION_1_0;
44626 switch(r = plugins_call_handle_uri_clean(srv, con)) {
44627 case HANDLER_GO_ON:
44629 @@ -274,11 +281,11 @@
44630 log_error_write(srv, __FILE__, __LINE__, "");
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 */
44639 + /* option requests are handled directly without checking the path */
44641 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
44643 con->http_status = 200;
44644 @@ -288,46 +295,47 @@
44654 * logical filename (URI) becomes a physical filename here
44671 * ... ISREG() -> ok, go on
44672 * ... ISDIR() -> index-file -> redirect
44687 * SEARCH DOCUMENT ROOT
44691 /* set a default */
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);
44697 -#if defined(__WIN32) || defined(__CYGWIN__)
44698 - /* strip dots from the end and spaces
44700 + filename_unix2local(con->physical.rel_path);
44701 +#if defined(_WIN32) || defined(__CYGWIN__)
44702 + /* strip dots and spaces from the end
44704 * windows/dos handle those filenames as the same file
44706 * foo == foo. == foo..... == "foo... " == "foo.. ./"
44708 - * This will affect in some cases PATHINFO
44709 + * This will affect PATHINFO in some cases
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__, "");
44718 - /* MacOS X and Windows can't distiguish between upper and lower-case
44720 - * convert to lower-case
44722 + /* The default Mac OS X and Windows filesystems can't distiguish between
44723 + * upper- and lowercase, so convert to lowercase
44725 if (con->conf.force_lowercase_filenames) {
44726 buffer_to_lower(con->physical.rel_path);
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);
44736 - * create physical filename
44739 + * create physical filename
44740 * -> physical.path = docroot + rel_path
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);
44755 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
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--;
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__, "");
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);
44782 - * Noone catched away the file from normal path of execution yet (like mod_access)
44786 + * No one took the file away from the normal path of execution yet (like mod_access)
44788 * Go on and check of the file exists at all
44792 if (con->mode == DIRECT) {
44793 char *slash = NULL;
44794 char *pathinfo = NULL;
44796 stat_cache_entry *sce = NULL;
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);
44805 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
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);
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 .../ */
44821 http_response_redirect_to_directory(srv, con);
44824 return HANDLER_FINISHED;
44826 } else if (!S_ISREG(sce->st.st_mode)) {
44827 @@ -477,12 +490,12 @@
44830 con->http_status = 403;
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);
44839 buffer_reset(con->physical.path);
44840 return HANDLER_FINISHED;
44842 @@ -499,77 +512,77 @@
44843 /* PATH_INFO ! :) */
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);
44852 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
44853 "file not found ... or so: ", strerror(errno),
44855 "->", con->physical.path);
44858 return HANDLER_FINISHED;
44862 /* not found, perhaps PATHINFO */
44865 buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
44873 buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
44875 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
44879 if (0 == stat(con->physical.path->ptr, &(st)) &&
44880 S_ISREG(st.st_mode)) {
44886 if (pathinfo != NULL) {
44889 slash = strrchr(srv->tmp_buf->ptr, '/');
44892 if (pathinfo != NULL) {
44898 if (slash) pathinfo = slash;
44899 } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
44903 - /* no it really doesn't exists */
44904 + /* no, it really doesn't exists */
44905 con->http_status = 404;
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);
44915 buffer_reset(con->physical.path);
44918 return HANDLER_FINISHED;
44922 /* we have a PATHINFO */
44924 buffer_copy_string(con->request.pathinfo, pathinfo);
44932 con->uri.path->used -= strlen(pathinfo);
44933 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
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);
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);
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");
44960 - /* something strange happend */
44962 + /* something strange happened */
44966 - /* if we are still here, no one wanted the file, status 403 is ok I think */
44969 + /* if we are still here, no one wanted the file; status 403 is ok I think */
44971 if (con->mode == DIRECT) {
44972 con->http_status = 403;
44975 return HANDLER_FINISHED;
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 */
44990 - /* something strange happend */
44991 + /* something strange happened */
44997 return HANDLER_COMEBACK;
44999 --- ../lighttpd-1.4.11/src/server.c 2006-03-04 19:12:17.000000000 +0200
45000 +++ lighttpd-1.4.12/src/server.c 2006-07-11 22:07:53.000000000 +0300
45002 #include <sys/types.h>
45003 -#include <sys/time.h>
45004 #include <sys/stat.h>
45006 #include <string.h>
45009 -#include <unistd.h>
45010 #include <stdlib.h>
45012 #include <signal.h>
45014 #include "plugin.h"
45015 #include "joblist.h"
45016 #include "network_backends.h"
45019 +/* use local getopt implementation */
45020 +# undef HAVE_GETOPT_H
45022 #ifdef HAVE_GETOPT_H
45023 #include <getopt.h>
45025 +#include "getopt.h"
45028 #ifdef HAVE_VALGRIND_VALGRIND_H
45030 /* #define USE_ALARM */
45034 +#undef HAVE_SIGNAL
45037 +#include "sys-files.h"
45038 +#include "sys-process.h"
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;
45049 case SIGTERM: srv_shutdown = 1; break;
45052 if (graceful_shutdown) srv_shutdown = 1;
45053 - else graceful_shutdown = 1;
45054 + else graceful_shutdown = 1;
45057 case SIGALRM: handle_sig_alarm = 1; break;
45059 static void signal_handler(int sig) {
45061 case SIGTERM: srv_shutdown = 1; break;
45064 if (graceful_shutdown) srv_shutdown = 1;
45065 - else graceful_shutdown = 1;
45066 + else graceful_shutdown = 1;
45069 case SIGALRM: handle_sig_alarm = 1; break;
45070 @@ -110,25 +121,26 @@
45071 signal(SIGTSTP, SIG_IGN);
45073 if (0 != fork()) exit(0);
45076 if (-1 == setsid()) exit(0);
45078 signal(SIGHUP, SIG_IGN);
45080 if (0 != fork()) exit(0);
45083 if (0 != chdir("/")) exit(0);
45087 static server *server_init(void) {
45091 server *srv = calloc(1, sizeof(*srv));
45093 + srv->max_fds = 1024;
45095 srv->x = buffer_init();
45098 CLEAN(response_header);
45099 CLEAN(parse_full_path);
45100 CLEAN(ts_debug_str);
45101 @@ -138,7 +150,7 @@
45103 srv->empty_string = buffer_init_string("");
45104 CLEAN(cond_check_buf);
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);
45116 CLEAN(tmp_chunk_len);
45121 srv->x = array_init();
45124 CLEAN(config_context);
45125 CLEAN(config_touched);
45130 for (i = 0; i < FILE_CACHE_MAX; i++) {
45131 srv->mtime_cache[i].str = buffer_init();
45135 srv->cur_ts = time(NULL);
45136 srv->startup_ts = srv->cur_ts;
45139 srv->conns = calloc(1, sizeof(*srv->conns));
45140 assert(srv->conns);
45143 srv->joblist = calloc(1, sizeof(*srv->joblist));
45144 assert(srv->joblist);
45147 srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
45148 assert(srv->fdwaitqueue);
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();
45158 srv->errorlog_fd = -1;
45159 srv->errorlog_mode = ERRORLOG_STDERR;
45161 srv->split_vals = array_init();
45167 static void server_free(server *srv) {
45171 for (i = 0; i < FILE_CACHE_MAX; i++) {
45172 buffer_free(srv->mtime_cache[i].str);
45177 buffer_free(srv->x);
45180 CLEAN(response_header);
45181 CLEAN(parse_full_path);
45182 CLEAN(ts_debug_str);
45183 @@ -207,7 +219,7 @@
45185 CLEAN(empty_string);
45186 CLEAN(cond_check_buf);
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);
45198 CLEAN(tmp_chunk_len);
45201 @@ -225,15 +237,15 @@
45202 fdevent_unregister(srv->ev, srv->fd);
45204 fdevent_free(srv->ev);
45210 if (srv->config_storage) {
45211 for (i = 0; i < srv->config_context->used; i++) {
45212 specific_config *s = srv->config_storage[i];
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);
45228 free(srv->config_storage);
45229 srv->config_storage = NULL;
45234 array_free(srv->x);
45237 CLEAN(config_context);
45238 CLEAN(config_touched);
45240 CLEAN(srvconf.upload_tempdirs);
45244 joblist_free(srv, srv->joblist);
45245 fdwaitqueue_free(srv, srv->fdwaitqueue);
45248 if (srv->stat_cache) {
45249 stat_cache_free(srv->stat_cache);
45252 array_free(srv->srvconf.modules);
45253 array_free(srv->split_vals);
45259 @@ -281,14 +293,12 @@
45260 " - a light and fast webserver\n" \
45261 "Build-Date: " __DATE__ " " __TIME__ "\n";
45265 write(STDOUT_FILENO, b, strlen(b));
45268 static void show_features (void) {
45270 - printf("\nEvent Handlers:\n\n%s",
45272 + const char *s = ""
45274 "\t+ select (generic)\n"
45276 @@ -355,11 +365,6 @@
45278 "\t- crypt support\n"
45281 - "\t+ PAM support\n"
45283 - "\t- PAM support\n"
45286 "\t+ SSL Support\n"
45288 @@ -371,9 +376,9 @@
45289 "\t- PCRE support\n"
45292 - "\t+ mySQL support\n"
45293 + "\t+ MySQL support\n"
45295 - "\t- mySQL support\n"
45296 + "\t- MySQL support\n"
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 @@
45302 "\t- GDBM support\n"
45310 + printf("\nEvent Handlers:\n\n%s", s);
45313 static void show_help (void) {
45314 @@ -433,12 +441,12 @@
45315 " -h show this help\n" \
45321 write(STDOUT_FILENO, b, strlen(b));
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;
45334 + char *optarg = NULL;
45337 #ifdef HAVE_SIGACTION
45338 struct sigaction act;
45340 #ifdef HAVE_GETRLIMIT
45341 struct rlimit rlim;
45346 struct itimerval interval;
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;
45358 /* for nice %b handling in strfime() */
45359 setlocale(LC_TIME, "C");
45362 if (NULL == (srv = server_init())) {
45363 fprintf(stderr, "did this really happen?\n");
45368 /* init structs done */
45371 srv->srvconf.port = 0;
45373 i_am_root = (getuid() == 0);
45374 @@ -481,14 +493,19 @@
45377 srv->srvconf.dont_daemonize = 0;
45380 while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
45383 - if (config_read(srv, optarg)) {
45386 + /* evil HACK for windows, optarg is not set */
45387 + optarg = argv[optind-1];
45389 + if (config_read(srv, optarg)) {
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;
45413 if (!srv->config_storage) {
45414 log_error_write(srv, __FILE__, __LINE__, "s",
45415 "No configuration available. Try using -f option.");
45423 if (print_config) {
45424 data_unset *dc = srv->config_context->data[0];
45426 @@ -533,7 +550,7 @@
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);
45441 /* move stdout to /dev/null */
45442 if (-1 != (fd = open("/dev/null", O_WRONLY))) {
45443 close(STDOUT_FILENO);
45444 dup2(fd, STDOUT_FILENO);
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");
45460 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
45461 /* we are setuid-root */
45463 - log_error_write(srv, __FILE__, __LINE__, "s",
45465 + log_error_write(srv, __FILE__, __LINE__, "s",
45466 "Are you nuts ? Don't apply a SUID bit to this binary");
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");
45489 if (plugins_load(srv)) {
45490 log_error_write(srv, __FILE__, __LINE__, "s",
45491 "loading plugins finally failed");
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));
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));
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);
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 @@
45534 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45535 /* select limits itself
45537 * as it is a hard limit and will lead to a segfault we add some safety
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;
45543 srv->max_fds = 4096;
45545 @@ -636,7 +655,7 @@
45546 #ifdef HAVE_VALGRIND_VALGRIND_H
45547 if (RUNNING_ON_VALGRIND) use_rlimit = 0;
45551 #ifdef HAVE_GETRLIMIT
45552 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
45553 log_error_write(srv, __FILE__, __LINE__,
45554 @@ -644,13 +663,13 @@
45560 if (use_rlimit && srv->srvconf.max_fds) {
45564 rlim.rlim_cur = srv->srvconf.max_fds;
45565 rlim.rlim_max = srv->srvconf.max_fds;
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 @@
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;
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.");
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);
45605 if (pwd->pw_uid == 0) {
45606 log_error_write(srv, __FILE__, __LINE__, "s",
45607 "I will not set uid to 0\n");
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);
45620 @@ -713,15 +732,15 @@
45626 /* we need root-perms for port < 1024 */
45627 if (0 != network_init(srv)) {
45634 -#ifdef HAVE_CHROOT
45635 +#ifdef HAVE_CHROOT
45636 if (srv->srvconf.changeroot->used) {
45639 @@ -761,7 +780,7 @@
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;
45646 srv->max_fds = rlim.rlim_cur;
45648 @@ -775,18 +794,18 @@
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.");
45664 if (0 != network_init(srv)) {
45672 @@ -802,25 +821,27 @@
45673 /* or use the default */
45674 srv->max_conns = srv->max_fds;
45678 if (HANDLER_GO_ON != plugins_call_init(srv)) {
45679 log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
45683 network_close(srv);
45692 /* network is up, let's deamonize ourself */
45693 if (srv->srvconf.dont_daemonize == 0) daemonize();
45697 srv->gid = getgid();
45698 srv->uid = getuid();
45702 /* write pid file */
45703 if (pid_fd != -1) {
45704 buffer_copy_long(srv->tmp_buf, getpid());
45705 @@ -829,17 +850,17 @@
45711 if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
45712 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
45716 network_close(srv);
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 @@
45729 for (j = 0; config && j < config->used; j++) {
45730 data_unset *du = config->data[j];
45733 /* all var.* is known as user defined variable */
45734 if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
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:",
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.");
45756 network_close(srv);
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");
45771 network_close(srv);
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);
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);
45797 signal(SIGALRM, signal_handler);
45800 /* setup periodic timer (1 second) */
45801 if (setitimer(ITIMER_REAL, &interval, NULL)) {
45802 log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
45807 getitimer(ITIMER_REAL, &interval);
45812 /* start watcher and workers */
45813 num_childs = srv->srvconf.max_worker;
45814 if (num_childs > 0) {
45815 @@ -957,13 +977,13 @@
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");
45826 - * kqueue() is called here, select resets its internals,
45828 + * kqueue() is called here, select resets its internals,
45829 * all server sockets get their handlers
45832 @@ -971,7 +991,7 @@
45834 network_close(srv);
45841 @@ -986,7 +1006,7 @@
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.");
45850 @@ -1018,16 +1038,40 @@
45856 if (handle_sig_hup) {
45860 /* reset notification */
45861 handle_sig_hup = 0;
45868 + /* send the old process into a graceful-shutdown and start a
45869 + * new process right away
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
45877 + if (0 == (pid = fork())) {
45878 + execve(argv[0], argv, envp);
45881 + } else if (pid == -1) {
45886 + graceful_shutdown = 1; /* shutdown without killing running connections */
45887 + graceful_restart = 1; /* don't delete pid file */
45890 /* cycle logfiles */
45893 switch(r = plugins_call_handle_sighup(srv)) {
45894 case HANDLER_GO_ON:
45896 @@ -1035,30 +1079,31 @@
45897 log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
45902 if (-1 == log_error_cycle(srv)) {
45903 log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
45912 if (handle_sig_alarm) {
45917 /* reset notification */
45918 handle_sig_alarm = 0;
45922 /* get current time */
45923 min_ts = time(NULL);
45926 if (min_ts != srv->cur_ts) {
45928 connections *conns = srv->conns;
45932 switch(r = plugins_call_handle_trigger(srv)) {
45933 case HANDLER_GO_ON:
45935 @@ -1069,21 +1114,21 @@
45936 log_error_write(srv, __FILE__, __LINE__, "d", r);
45941 /* trigger waitpid */
45942 srv->cur_ts = min_ts;
45944 - /* cleanup stat-cache */
45946 + /* cleanup stat-cache */
45947 stat_cache_trigger_cleanup(srv);
45949 - * check all connections for timeouts
45951 + * check all connections for timeouts
45954 for (ndx = 0; ndx < conns->used; ndx++) {
45960 con = conns->ptr[ndx];
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) {
45967 - log_error_write(srv, __FILE__, __LINE__, "sd",
45968 + log_error_write(srv, __FILE__, __LINE__, "sd",
45969 "connection closed - read-timeout:", con->fd);
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) {
45976 - log_error_write(srv, __FILE__, __LINE__, "sd",
45977 + log_error_write(srv, __FILE__, __LINE__, "sd",
45978 "connection closed - read-timeout:", con->fd);
45980 connection_set_state(srv, con, CON_STATE_ERROR);
45981 @@ -1110,20 +1155,20 @@
45987 if ((con->state == CON_STATE_WRITE) &&
45988 - (con->write_request_ts != 0)) {
45989 + (con->write_request_ts != 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);
45999 if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
46002 - log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46003 + log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46004 "NOTE: a request for",
46006 "timed out after writing",
46007 @@ -1138,35 +1183,35 @@
46009 /* we don't like div by zero */
46010 if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
46012 - if (con->traffic_limit_reached &&
46013 - (con->conf.kbytes_per_second == 0 ||
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;
46027 connection_state_machine(srv, con);
46029 con->bytes_written_cur_second = 0;
46030 *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
46035 fprintf(stderr, "connection-state: ");
46040 fprintf(stderr, "c[%d,%d]: %s ",
46043 connection_get_state(con->state));
46048 if (cs == 1) fprintf(stderr, "\n");
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);
46057 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
46060 srv->sockets_disabled = 0;
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 */
46068 /* disable server-fds */
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 */
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 @@
46085 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
46089 srv->sockets_disabled = 1;
46092 @@ -1229,16 +1274,16 @@
46093 * we are ready to terminate without harming anyone */
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;
46106 for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
46107 connection_state_machine(srv, con);
46113 @@ -1249,27 +1294,27 @@
46117 - log_error_write(srv, __FILE__, __LINE__, "sd",
46118 + log_error_write(srv, __FILE__, __LINE__, "sd",
46125 fdevent_handler handler;
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);
46137 /* connection_handle_fdevent needs a joblist_append */
46139 - log_error_write(srv, __FILE__, __LINE__, "sdd",
46140 + log_error_write(srv, __FILE__, __LINE__, "sdd",
46141 "event for", fd, revents);
46144 switch (r = (*handler)(srv, context, revents)) {
46145 case HANDLER_FINISHED:
46146 case HANDLER_GO_ON:
46147 @@ -1286,17 +1331,17 @@
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:",
46159 for (ndx = 0; ndx < srv->joblist->used; ndx++) {
46160 connection *con = srv->joblist->ptr[ndx];
46164 connection_state_machine(srv, con);
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);
46176 con->in_joblist = 0;
46180 srv->joblist->used = 0;
46183 - if (srv->srvconf.pid_file->used &&
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,
46203 log_error_close(srv);
46204 network_close(srv);
46205 connections_free(srv);
46212 --- ../lighttpd-1.4.11/src/settings.h 2005-08-11 01:26:41.000000000 +0300
46213 +++ lighttpd-1.4.12/src/settings.h 2006-07-11 22:07:53.000000000 +0300
46216 * max size of a buffer which will just be reset
46217 * to ->used = 0 instead of really freeing the buffer
46220 * 64kB (no real reason, just a guess)
46222 #define BUFFER_MAX_REUSE_SIZE (4 * 1024)
46225 * max size of the HTTP request header
46228 * 32k should be enough for everything (just a guess)
46232 #define MAX_HTTP_REQUEST_HEADER (32 * 1024)
46234 -typedef enum { HANDLER_UNSET,
46236 +typedef enum { HANDLER_UNSET,
46239 - HANDLER_COMEBACK,
46240 - HANDLER_WAIT_FOR_EVENT,
46241 + HANDLER_COMEBACK,
46242 + HANDLER_WAIT_FOR_EVENT,
46244 HANDLER_WAIT_FOR_FD
46246 --- ../lighttpd-1.4.11/src/spawn-fcgi.c 2006-03-07 14:18:10.000000000 +0200
46247 +++ lighttpd-1.4.12/src/spawn-fcgi.c 2006-07-11 22:07:53.000000000 +0300
46249 #include <sys/types.h>
46250 -#include <sys/time.h>
46251 #include <sys/stat.h>
46253 #include <stdlib.h>
46254 #include <string.h>
46257 -#include <unistd.h>
46261 #ifdef HAVE_CONFIG_H
46262 #include "config.h"
46272 #include "sys-socket.h"
46273 +#include "sys-files.h"
46275 #ifdef HAVE_SYS_WAIT_H
46276 #include <sys/wait.h>
46277 @@ -45,28 +43,28 @@
46279 int socket_type, status;
46280 struct timeval tv = { 0, 100 * 1000 };
46283 struct sockaddr_un fcgi_addr_un;
46284 struct sockaddr_in fcgi_addr_in;
46285 struct sockaddr *fcgi_addr;
46291 if (child_count < 2) {
46296 if (child_count > 256) {
46304 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
46307 fcgi_addr_un.sun_family = AF_UNIX;
46308 strcpy(fcgi_addr_un.sun_path, unixsocket);
46312 servlen = SUN_LEN(&fcgi_addr_un);
46314 @@ -84,50 +82,50 @@
46316 fcgi_addr_in.sin_port = htons(port);
46317 servlen = sizeof(fcgi_addr_in);
46320 socket_type = AF_INET;
46321 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
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__);
46333 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
46334 /* server is not up, spawn in */
46339 if (unixsocket) unlink(unixsocket);
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__);
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__);
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__,
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__);
46377 @@ -137,42 +135,45 @@
46385 char cgi_childs[64];
46392 + /* loose control terminal */
46395 /* is save as we limit to 256 childs */
46396 sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
46399 if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
46400 close(FCGI_LISTENSOCK_FILENO);
46401 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
46406 /* we don't need the client socket */
46407 for (i = 3; i < 256; i++) {
46412 /* create environment */
46415 putenv(cgi_childs);
46418 /* fork and replace shell */
46419 b = malloc(strlen("exec ") + strlen(appPath) + 1);
46420 strcpy(b, "exec ");
46421 strcat(b, appPath);
46425 execl("/bin/sh", "sh", "-c", b, NULL);
46434 @@ -180,47 +181,47 @@
46441 select(0, NULL, NULL, NULL, &tv);
46444 switch (waitpid(child, &status, WNOHANG)) {
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__,
46452 /* write pid file */
46453 if (pid_fd != -1) {
46454 /* assume a 32bit pid_t */
46458 snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
46461 write(pid_fd, pidbuf, strlen(pidbuf));
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__,
46482 - fprintf(stderr, "%s.%d: child died somehow: %d\n",
46483 + fprintf(stderr, "%s.%d: child died somehow: %d\n",
46484 __FILE__, __LINE__,
46493 @@ -228,16 +229,16 @@
46494 __FILE__, __LINE__);
46506 void show_version () {
46507 char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
46508 -" - spawns fastcgi processes\n"
46509 +" - spawns fastcgi processes\n"
46511 write(1, b, strlen(b));
46513 @@ -265,7 +266,7 @@
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,
46521 unsigned short port = 0;
46522 @@ -273,9 +274,9 @@
46528 i_am_root = (getuid() == 0);
46531 while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
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;
46546 if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
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");
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");
46574 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
46575 /* we are setuid-root */
46577 - fprintf(stderr, "%s.%d: %s\n",
46579 + fprintf(stderr, "%s.%d: %s\n",
46580 __FILE__, __LINE__,
46581 "Are you nuts ? Don't apply a SUID bit to this binary\n");
46590 (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
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));
46603 /* ok, file exists */
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));
46617 /* is it a regular file ? */
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__,
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));
46644 struct group *grp = NULL;
46645 struct passwd *pwd = NULL;
46648 /* set user and group */
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);
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");
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",
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");
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));
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));
46709 /* drop root privs */
46711 setgid(grp->gr_gid);
46712 @@ -428,7 +429,7 @@
46714 if (username) setuid(pwd->pw_uid);
46718 return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
46721 --- ../lighttpd-1.4.11/src/splaytree.c 2005-09-12 21:51:28.000000000 +0300
46722 +++ lighttpd-1.4.12/src/splaytree.c 2006-07-11 22:07:51.000000000 +0300
46723 @@ -56,19 +56,19 @@
46725 #define node_size splaytree_size
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;
46737 if (t == NULL) return t;
46738 N.left = N.right = NULL;
46740 root_size = node_size(t);
46741 l_size = r_size = 0;
46745 comp = compare(i, t->key);
46747 @@ -120,7 +120,7 @@
46749 r_size -= 1+node_size(y->right);
46753 l->right = t->left; /* assemble */
46754 r->left = t->right;
46756 --- ../lighttpd-1.4.11/src/splaytree.h 2005-09-12 21:51:13.000000000 +0300
46757 +++ lighttpd-1.4.12/src/splaytree.h 2006-07-11 22:07:51.000000000 +0300
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. */
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
46769 #include <stdlib.h>
46770 #include <string.h>
46772 -#include <unistd.h>
46775 #include <assert.h>
46779 #include "sys-mmap.h"
46781 -/* NetBSD 1.3.x needs it */
46782 -#ifndef MAP_FAILED
46783 -# define MAP_FAILED -1
46786 -#ifndef O_LARGEFILE
46787 -# define O_LARGEFILE 0
46790 -#ifndef HAVE_LSTAT
46791 -#define lstat stat
46793 +#include "sys-files.h"
46794 +#include "sys-strings.h"
46797 /* enables debug code for testing if all nodes in the stat-cache as accessable */
46800 * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
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.
46809 @@ -62,17 +50,17 @@
46810 * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
46812 * stat <<-> directory <-> FAMRequest
46814 - * if file is deleted, directory is dirty, file is rechecked ...
46816 + * if file is deleted, directory is dirty, file is rechecked ...
46817 * if directory is deleted, directory mapping is removed
46831 @@ -83,16 +71,16 @@
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
46838 /* we want to cleanup the stat-cache every few seconds, let's say 10
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
46846 -#ifdef DEBUG_STAT_CACHE
46847 +#ifdef DEBUG_STAT_CACHE
46851 @@ -105,15 +93,15 @@
46853 stat_cache *stat_cache_init(void) {
46854 stat_cache *fc = NULL;
46857 fc = calloc(1, sizeof(*fc));
46860 fc->dir_name = buffer_init();
46862 fc->fam = calloc(1, sizeof(*fc->fam));
46865 -#ifdef DEBUG_STAT_CACHE
46866 +#ifdef DEBUG_STAT_CACHE
46870 @@ -122,24 +110,24 @@
46872 static stat_cache_entry * stat_cache_entry_init(void) {
46873 stat_cache_entry *sce = NULL;
46876 sce = calloc(1, sizeof(*sce));
46879 sce->name = buffer_init();
46880 sce->etag = buffer_init();
46881 sce->content_type = buffer_init();
46887 static void stat_cache_entry_free(void *data) {
46888 stat_cache_entry *sce = data;
46892 buffer_free(sce->etag);
46893 buffer_free(sce->name);
46894 buffer_free(sce->content_type);
46900 @@ -148,22 +136,22 @@
46901 fam_dir_entry *fam_dir = NULL;
46903 fam_dir = calloc(1, sizeof(*fam_dir));
46906 fam_dir->name = buffer_init();
46912 static void fam_dir_entry_free(void *data) {
46913 fam_dir_entry *fam_dir = data;
46916 if (!fam_dir) return;
46919 FAMCancelMonitor(fam_dir->fc, fam_dir->req);
46922 buffer_free(fam_dir->name);
46923 free(fam_dir->req);
46929 @@ -174,7 +162,7 @@
46930 splay_tree *node = sc->files;
46932 osize = sc->files->size;
46935 stat_cache_entry_free(node->data);
46936 sc->files = splaytree_delete(sc->files, node->key);
46938 @@ -187,12 +175,12 @@
46941 splay_tree *node = sc->dirs;
46944 osize = sc->dirs->size;
46946 fam_dir_entry_free(node->data);
46947 sc->dirs = splaytree_delete(sc->dirs, node->key);
46951 assert(NULL == sc->dirs);
46953 @@ -212,7 +200,7 @@
46954 static int stat_cache_attr_get(buffer *buf, char *name) {
46960 buffer_prepare_copy(buf, attrlen);
46962 @@ -251,15 +239,15 @@
46965 events = FAMPending(sc->fam);
46968 for (i = 0; i < events; i++) {
46970 fam_dir_entry *fam_dir;
46975 FAMNextEvent(sc->fam, &fe);
46981 @@ -280,7 +268,7 @@
46983 sc->dirs = splaytree_splay(sc->dirs, ndx);
46987 if (node && (node->key == ndx)) {
46988 int osize = splaytree_size(sc->dirs);
46990 @@ -308,7 +296,7 @@
46996 return HANDLER_GO_ON;
46999 @@ -332,7 +320,7 @@
47005 * - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
47006 * - HANDLER_ERROR on stat() failed -> see errno for problem
47008 @@ -348,16 +336,16 @@
47012 -#ifdef DEBUG_STAT_CACHE
47013 +#ifdef DEBUG_STAT_CACHE
47018 splay_tree *file_node = NULL;
47025 * check if the directory for this file has changed
47028 @@ -366,23 +354,23 @@
47029 file_ndx = hashme(name);
47030 sc->files = splaytree_splay(sc->files, file_ndx);
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;
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);
47046 - /* we have seen this file already and
47048 + /* we have seen this file already and
47049 * don't stat() it again in the same second */
47051 file_node = sc->files;
47054 sce = file_node->data;
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) {
47063 return HANDLER_GO_ON;
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().
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.
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);
47085 @@ -424,23 +412,23 @@
47088 dir_ndx = hashme(sc->dir_name);
47091 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
47094 if (sc->dirs && (sc->dirs->key == dir_ndx)) {
47095 dir_node = sc->dirs;
47099 if (dir_node && file_node) {
47100 /* we found a file */
47103 sce = file_node->data;
47104 fam_dir = dir_node->data;
47107 if (fam_dir->version == sce->dir_version) {
47108 /* the stat()-cache entry is still ok */
47113 return HANDLER_GO_ON;
47116 @@ -448,7 +436,7 @@
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
47125 @@ -469,16 +457,16 @@
47132 osize = sc->files->size;
47135 sce = stat_cache_entry_init();
47136 buffer_copy_string_buffer(sce->name, name);
47138 - sc->files = splaytree_insert(sc->files, file_ndx, sce);
47139 -#ifdef DEBUG_STAT_CACHE
47141 + sc->files = splaytree_insert(sc->files, file_ndx, sce);
47142 +#ifdef DEBUG_STAT_CACHE
47143 if (ctrl.size == 0) {
47146 @@ -499,29 +487,29 @@
47148 sce->stat_ts = srv->cur_ts;
47150 - /* catch the obvious symlinks
47151 + /* catch the obvious symlinks
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
47159 * and keeping the file open for the rest of the time. But this can
47160 * only be done at network level.
47164 if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
47165 return HANDLER_ERROR;
47168 - if (S_ISREG(st.st_mode)) {
47169 + if (S_ISREG(st.st_mode)) {
47170 /* determine mimetype */
47171 buffer_reset(sce->content_type);
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;
47179 if (type->used == 0) continue;
47181 /* check if the right side is the same */
47182 @@ -538,8 +526,10 @@
47183 stat_cache_attr_get(sce->content_type, name->ptr);
47186 + } else if (S_ISDIR(st.st_mode)) {
47187 + etag_create(sce->etag, &(sce->st));
47193 (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
47194 @@ -549,19 +539,19 @@
47195 fam_dir->fc = sc->fam;
47197 buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
47200 fam_dir->version = 1;
47203 fam_dir->req = calloc(1, sizeof(FAMRequest));
47205 - if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47207 + if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47208 fam_dir->req, fam_dir)) {
47210 - log_error_write(srv, __FILE__, __LINE__, "sbs",
47211 - "monitoring dir failed:",
47214 + log_error_write(srv, __FILE__, __LINE__, "sbs",
47215 + "monitoring dir failed:",
47217 FamErrlist[FAMErrno]);
47220 fam_dir_entry_free(fam_dir);
47223 @@ -570,7 +560,7 @@
47224 osize = sc->dirs->size;
47227 - sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47228 + sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47230 assert(sc->dirs->data == fam_dir);
47231 assert(osize == (sc->dirs->size - 1));
47232 @@ -578,9 +568,9 @@
47234 fam_dir = dir_node->data;
47238 /* bind the fam_fc to the stat() cache entry */
47242 sce->dir_version = fam_dir->version;
47243 sce->dir_ndx = dir_ndx;
47244 @@ -594,11 +584,11 @@
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
47253 - * walk though the stat-cache, collect the ids which are too old
47255 + * walk though the stat-cache, collect the ids which are too old
47256 * and remove them in a second loop
47259 @@ -639,9 +629,9 @@
47260 sc->files = splaytree_splay(sc->files, ndx);
47265 if (node && (node->key == ndx)) {
47266 -#ifdef DEBUG_STAT_CACHE
47267 +#ifdef DEBUG_STAT_CACHE
47269 int osize = splaytree_size(sc->files);
47270 stat_cache_entry *sce = node->data;
47271 @@ -649,7 +639,7 @@
47272 stat_cache_entry_free(node->data);
47273 sc->files = splaytree_delete(sc->files, ndx);
47275 -#ifdef DEBUG_STAT_CACHE
47276 +#ifdef DEBUG_STAT_CACHE
47277 for (j = 0; j < ctrl.used; j++) {
47278 if (ctrl.ptr[j] == ndx) {
47279 ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
47280 --- ../lighttpd-1.4.11/src/stream.c 2005-09-23 21:50:15.000000000 +0300
47281 +++ lighttpd-1.4.12/src/stream.c 2006-07-11 22:07:53.000000000 +0300
47283 #include <sys/types.h>
47284 #include <sys/stat.h>
47286 -#include <unistd.h>
47289 #include "stream.h"
47293 #include "sys-mmap.h"
47294 +#include "sys-files.h"
47297 # define O_BINARY 0
47298 @@ -19,39 +19,39 @@
47302 -#elif defined __WIN32
47303 +#elif defined _WIN32
47311 if (-1 == stat(fn->ptr, &st)) {
47316 f->size = st.st_size;
47319 if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
47324 f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
47330 if (MAP_FAILED == f->start) {
47334 -#elif defined __WIN32
47335 - fh = CreateFile(fn->ptr,
47340 - FILE_ATTRIBUTE_READONLY,
47341 +#elif defined _WIN32
47342 + fh = CreateFile(fn->ptr,
47347 + FILE_ATTRIBUTE_READONLY,
47350 if (!fh) return -1;
47355 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
47356 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
47357 FORMAT_MESSAGE_FROM_SYSTEM,
47366 p = MapViewOfFile(mh,
47373 -# error no mmap found
47374 +# error no mmap found
47381 --- ../lighttpd-1.4.11/src/sys-files.h 1970-01-01 03:00:00.000000000 +0300
47382 +++ lighttpd-1.4.12/src/sys-files.h 2006-07-11 22:07:53.000000000 +0300
47384 +#ifndef _SYS_FILES_H_
47385 +#define _SYS_FILES_H_
47387 +#define DIR_SEPERATOR_UNIX '/'
47388 +#define DIR_SEPERATOR_WIN '\\'
47391 +#include <windows.h>
47392 +#include <io.h> /* open */
47393 +#include <direct.h> /* chdir */
47395 +#include "buffer.h"
47397 +#define DIR_SEPERATOR DIR_SEPERATOR_WIN
47399 +#define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
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
47408 +#define lstat stat
47409 +#define mkstemp mktemp
47410 +#define mkdir(x, y) mkdir(x)
47413 + const char *d_name;
47418 + WIN32_FIND_DATA finddata;
47419 + struct dirent dent;
47422 +DIR *opendir(const char *dn);
47423 +struct dirent *readdir(DIR *d);
47424 +void closedir(DIR *d);
47426 +buffer *filename_unix2local(buffer *b);
47427 +buffer *pathname_unix2local(buffer *b);
47430 +#include <unistd.h>
47431 +#include <dirent.h>
47433 +#define DIR_SEPERATOR DIR_SEPERATOR_UNIX
47435 +#define filename_unix2local(x) (x)
47436 +#define pathname_unix2local(x) (x)
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); \
47445 +#ifndef O_LARGEFILE
47446 +# define O_LARGEFILE 0
47451 --- ../lighttpd-1.4.11/src/sys-mmap.h 2005-08-11 01:26:34.000000000 +0300
47452 +++ lighttpd-1.4.12/src/sys-mmap.h 2006-07-11 22:07:52.000000000 +0300
47454 #ifndef WIN32_MMAP_H
47455 #define WIN32_MMAP_H
47460 #define MAP_FAILED -1
47461 #define PROT_SHARED 0
47462 --- ../lighttpd-1.4.11/src/sys-process.h 1970-01-01 03:00:00.000000000 +0300
47463 +++ lighttpd-1.4.12/src/sys-process.h 2006-07-15 22:43:21.000000000 +0300
47465 +#ifndef _SYS_PROCESS_H_
47466 +#define _SYS_PROCESS_H_
47469 +#include <process.h>
47471 +/* win32 has no fork() */
47472 +#define kill(x, y)
47473 +#define getpid() 0
47476 +#include <sys/wait.h>
47477 +#include <unistd.h>
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
47485 #ifndef WIN32_SOCKET_H
47486 #define WIN32_SOCKET_H
47491 #include <winsock2.h>
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
47505 +int inet_aton(const char *cp, struct in_addr *inp);
47506 +#define HAVE_INET_ADDR
47507 +#undef HAVE_INET_ATON
47510 #include <sys/socket.h>
47511 #include <sys/ioctl.h>
47513 #include <sys/un.h>
47514 #include <arpa/inet.h>
47517 +#define SUN_LEN(su) \
47518 + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
47526 + struct sockaddr_in6 ipv6;
47528 + struct sockaddr_in ipv4;
47529 +#ifdef HAVE_SYS_UN_H
47530 + struct sockaddr_un un;
47532 + struct sockaddr plain;
47536 --- ../lighttpd-1.4.11/src/sys-strings.h 1970-01-01 03:00:00.000000000 +0300
47537 +++ lighttpd-1.4.12/src/sys-strings.h 2006-07-11 22:07:51.000000000 +0300
47539 +#ifndef _SYS_STRINGS_H_
47540 +#define _SYS_STRINGS_H_
47543 +#define strcasecmp stricmp
47544 +#define strncasecmp strnicmp
47545 +#define strtoll(p, e, b) _strtoi64(p, e, b)
47550 --- ../lighttpd-1.4.11/tests/LightyTest.pm 2006-01-14 20:32:31.000000000 +0200
47551 +++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-11 22:07:53.000000000 +0300
47552 @@ -87,14 +87,14 @@
47553 # pre-process configfile if necessary
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};
47561 unlink($self->{LIGHTTPD_PIDFILE});
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});
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}." &");
47570 select(undef, undef, undef, 0.1);
47571 @@ -184,7 +184,7 @@
47572 (my $h = $1) =~ tr/[A-Z]/[a-z]/;
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));
47579 $resp_hdr{$h} = $2;
47580 @@ -196,6 +196,9 @@
47584 + $t->{etag} = $resp_hdr{'etag'};
47585 + $t->{date} = $resp_hdr{'date'};
47588 if (defined $resp_hdr{"content-length"}) {
47589 $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
47590 --- ../lighttpd-1.4.11/tests/Makefile.am 2005-09-16 15:48:40.000000000 +0300
47591 +++ lighttpd-1.4.12/tests/Makefile.am 2006-07-15 22:43:22.000000000 +0300
47592 @@ -39,10 +39,18 @@
47607 + proxy-backend-1.conf \
47608 + proxy-backend-2.conf
47611 TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
47612 --- ../lighttpd-1.4.11/tests/bug-06.conf 2005-08-27 17:44:19.000000000 +0300
47613 +++ lighttpd-1.4.12/tests/bug-06.conf 2006-07-11 22:07:53.000000000 +0300
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"
47620 ## bind to port (default: 80)
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"
47632 ######################## MODULE CONFIG ############################
47635 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47636 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47638 mimetype.assign = ( ".png" => "image/png",
47639 ".jpg" => "image/jpeg",
47641 ".c" => "text/plain",
47642 ".conf" => "text/plain" )
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")
47648 setenv.add-environment = ( "TRAC_ENV" => "foo")
47650 "host" => "127.0.0.1",
47652 # "mode" => "authorizer",
47653 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47654 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47658 @@ -106,7 +106,7 @@
47659 ssl.pemfile = "server.pem"
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"
47666 auth.backend.ldap.hostname = "localhost"
47667 @@ -149,15 +149,15 @@
47668 status.config-url = "/server-config"
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"
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/"
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"
47686 --- ../lighttpd-1.4.11/tests/bug-12.conf 2005-08-27 17:44:19.000000000 +0300
47687 +++ lighttpd-1.4.12/tests/bug-12.conf 2006-07-11 22:07:53.000000000 +0300
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"
47694 ## bind to port (default: 80)
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"
47706 ######################## MODULE CONFIG ############################
47709 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47710 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47712 mimetype.assign = ( ".png" => "image/png",
47713 ".jpg" => "image/jpeg",
47715 ".c" => "text/plain",
47716 ".conf" => "text/plain" )
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")
47722 setenv.add-environment = ( "TRAC_ENV" => "foo")
47724 "host" => "127.0.0.1",
47726 # "mode" => "authorizer",
47727 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47728 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47732 @@ -108,7 +108,7 @@
47733 ssl.pemfile = "server.pem"
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"
47740 auth.backend.ldap.hostname = "localhost"
47741 @@ -151,15 +151,15 @@
47742 status.config-url = "/server-config"
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"
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/"
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"
47760 --- ../lighttpd-1.4.11/tests/cachable.t 1970-01-01 03:00:00.000000000 +0300
47761 +++ lighttpd-1.4.12/tests/cachable.t 2006-07-11 22:07:53.000000000 +0300
47763 +#!/usr/bin/env perl
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;
47773 +use Test::More tests => 12;
47776 +my $tf = LightyTest->new();
47779 +$tf->{CONFIGFILE} = 'lighttpd.conf';
47781 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
47783 +## check if If-Modified-Since, If-None-Match works
47785 +$t->{REQUEST} = ( <<EOF
47787 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
47790 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47791 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
47793 +$t->{REQUEST} = ( <<EOF
47795 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
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');
47801 +my $now = $t->{date};
47803 +$t->{REQUEST} = ( <<EOF
47805 +If-Modified-Since: $now
47808 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47809 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
47811 +$t->{REQUEST} = ( <<EOF
47813 +If-Modified-Since: $now; foo
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');
47819 +$t->{REQUEST} = ( <<EOF
47821 +If-None-Match: foo
47824 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47825 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47827 +my $etag = $t->{etag};
47829 +$t->{REQUEST} = ( <<EOF
47831 +If-None-Match: $etag
47834 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47835 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47837 +$t->{REQUEST} = ( <<EOF
47839 +If-None-Match: $etag
47840 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47843 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47844 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
47846 +$t->{REQUEST} = ( <<EOF
47848 +If-None-Match: $etag
47849 +If-Modified-Since: $now; foo
47852 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47853 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
47855 +$t->{REQUEST} = ( <<EOF
47857 +If-None-Match: Foo
47858 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
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');
47864 +$t->{REQUEST} = ( <<EOF
47866 +If-None-Match: $etag
47867 +If-Modified-Since: $now foo
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');
47873 +ok($tf->stop_proc == 0, "Stopping lighttpd");
47875 --- ../lighttpd-1.4.11/tests/condition.conf 2005-08-27 17:44:19.000000000 +0300
47876 +++ lighttpd-1.4.12/tests/condition.conf 2006-07-11 22:07:53.000000000 +0300
47878 debug.log-request-handling = "enable"
47879 debug.log-condition-handling = "enable"
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"
47886 ## bind to port (default: 80)
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"
47896 @@ -22,25 +22,25 @@
47897 ######################## MODULE CONFIG ############################
47900 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47901 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47903 mimetype.assign = ( ".html" => "text/html" )
47905 url.redirect = ("^" => "/default")
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")
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")
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")
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")
47935 --- ../lighttpd-1.4.11/tests/core-keepalive.t 2005-11-17 15:54:19.000000000 +0200
47936 +++ lighttpd-1.4.12/tests/core-keepalive.t 2006-07-11 22:07:53.000000000 +0300
47939 GET /12345.txt HTTP/1.0
47940 Host: 123.example.org
47941 -Connection: keep-alive
47945 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47946 --- ../lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries 2006-03-09 19:21:49.000000000 +0200
47947 +++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries 2006-07-15 22:43:22.000000000 +0300
47951 uuid="152afb58-edef-0310-8abb-c4023f1b3aa9"
47952 - revision="1040"/>
47953 + repos="svn://svn.lighttpd.net/lighttpd"
47954 + revision="1173"/>
47956 --- ../lighttpd-1.4.11/tests/fastcgi-10.conf 2005-08-31 23:36:34.000000000 +0300
47957 +++ lighttpd-1.4.12/tests/fastcgi-10.conf 2006-07-11 22:07:53.000000000 +0300
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"
47964 ## bind to port (default: 80)
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"
47975 ######################## MODULE CONFIG ############################
47978 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47979 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47981 mimetype.assign = ( ".png" => "image/png",
47982 ".jpg" => "image/jpeg",
47984 ".c" => "text/plain",
47985 ".conf" => "text/plain" )
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")
47993 ssl.pemfile = "server.pem"
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"
48000 auth.backend.ldap.hostname = "localhost"
48001 @@ -128,11 +128,11 @@
48002 status.config-url = "/server-config"
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/"
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"
48015 --- ../lighttpd-1.4.11/tests/fastcgi-13.conf 2006-01-03 12:38:17.000000000 +0200
48016 +++ lighttpd-1.4.12/tests/fastcgi-13.conf 2006-07-11 22:07:53.000000000 +0300
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"
48023 debug.log-request-header = "enable"
48024 debug.log-response-header = "enable"
48027 ## bind to localhost (default: all interfaces)
48028 server.bind = "localhost"
48029 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48030 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48031 server.name = "www.example.org"
48032 server.tag = "Apache 1.3.29"
48035 ######################## MODULE CONFIG ############################
48038 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48039 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48041 mimetype.assign = ( ".png" => "image/png",
48042 ".jpg" => "image/jpeg",
48044 ".c" => "text/plain",
48045 ".conf" => "text/plain" )
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")
48052 @@ -102,7 +102,7 @@
48053 ssl.pemfile = "server.pem"
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"
48060 auth.backend.ldap.hostname = "localhost"
48061 @@ -145,11 +145,11 @@
48062 status.config-url = "/server-config"
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/"
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"
48075 --- ../lighttpd-1.4.11/tests/fastcgi-auth.conf 2005-08-27 17:44:19.000000000 +0300
48076 +++ lighttpd-1.4.12/tests/fastcgi-auth.conf 2006-07-11 22:07:53.000000000 +0300
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"
48083 debug.log-request-header = "enable"
48084 debug.log-response-header = "enable"
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"
48095 ######################## MODULE CONFIG ############################
48098 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48099 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48101 mimetype.assign = ( ".png" => "image/png",
48102 ".jpg" => "image/jpeg",
48104 ".c" => "text/plain",
48105 ".conf" => "text/plain" )
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")
48114 "host" => "127.0.0.1",
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/",
48124 @@ -106,7 +106,7 @@
48125 ssl.pemfile = "server.pem"
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"
48132 auth.backend.ldap.hostname = "localhost"
48133 @@ -149,11 +149,11 @@
48134 status.config-url = "/server-config"
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/"
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"
48147 --- ../lighttpd-1.4.11/tests/fastcgi-responder.conf 2005-08-27 17:44:19.000000000 +0300
48148 +++ lighttpd-1.4.12/tests/fastcgi-responder.conf 2006-07-11 22:07:53.000000000 +0300
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"
48155 #debug.log-request-header = "enable"
48156 #debug.log-response-header = "enable"
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"
48167 ######################## MODULE CONFIG ############################
48170 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48171 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48173 mimetype.assign = ( ".png" => "image/png",
48174 ".jpg" => "image/jpeg",
48176 ".c" => "text/plain",
48177 ".conf" => "text/plain" )
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")
48184 @@ -90,10 +90,11 @@
48186 "host" => "127.0.0.1",
48188 - "bin-path" => "@SRCDIR@/fcgi-responder",
48189 + "bin-path" => env.SRCDIR + "/fcgi-responder",
48190 "check-local" => "disable",
48193 + "min-procs" => 1,
48194 + "allow-x-send-file" => "enable",
48198 @@ -109,7 +110,7 @@
48199 ssl.pemfile = "server.pem"
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"
48206 auth.backend.ldap.hostname = "localhost"
48207 @@ -152,11 +153,11 @@
48208 status.config-url = "/server-config"
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/"
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"
48221 --- ../lighttpd-1.4.11/tests/fcgi-responder.c 2005-08-11 01:26:55.000000000 +0300
48222 +++ lighttpd-1.4.12/tests/fcgi-responder.c 2006-07-11 22:07:53.000000000 +0300
48225 int num_requests = 2;
48227 - while (num_requests > 0 &&
48228 - FCGI_Accept() >= 0) {
48231 - if (NULL != (p = getenv("QUERY_STRING"))) {
48232 + while (num_requests > 0 && FCGI_Accept() >= 0) {
48234 + char* doc_root = NULL;
48235 + char fname[4096];
48236 + char* pfname = (char *)fname;
48238 + doc_root = getenv("DOCUMENT_ROOT");
48239 + p = getenv("QUERY_STRING");
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")) {
48247 printf("Status: 200 OK\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);
48254 + } else if (0 == strcmp(p,"xsendfile")) {
48255 + printf("Status: 200 OK\r\n");
48256 + printf("X-Sendfile: %s\r\n", pfname);
48258 + } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
48259 + printf("Status: 200 OK\r\n");
48260 + printf("X-SeNdFiLe: %s\r\n", pfname);
48262 } else if (0 == strcmp(p, "die-at-end")) {
48263 printf("Status: 200 OK\r\n\r\n");
48265 --- ../lighttpd-1.4.11/tests/lighttpd.conf 2006-03-09 15:26:58.000000000 +0200
48266 +++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-11 22:07:53.000000000 +0300
48268 -debug.log-request-handling = "enable"
48269 -debug.log-condition-handling = "enable"
48270 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48271 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48272 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48273 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48274 +server.tag = "Apache 1.3.29"
48276 ## 64 Mbyte ... nice limit
48277 server.max-request-size = 65000
48279 -## bind to port (default: 80)
48280 -server.port = 2048
48281 +include "default.conf"
48283 -## bind to localhost (default: all interfaces)
48284 -server.bind = "localhost"
48285 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48286 -server.name = "www.example.org"
48287 -server.tag = "Apache 1.3.29"
48289 -server.dir-listing = "enable"
48291 -#server.event-handler = "linux-sysepoll"
48292 -#server.event-handler = "linux-rtsig"
48294 -#server.modules.path = ""
48295 -server.modules = (
48298 - "mod_secdownload",
48304 - "mod_simple_vhost",
48307 -# "mod_localizer",
48313 - "mod_accesslog" )
48315 -server.indexfiles = ( "index.php", "index.html",
48316 - "index.htm", "default.htm" )
48319 -######################## MODULE CONFIG ############################
48321 -ssi.extension = ( ".shtml" )
48323 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48325 -mimetype.assign = ( ".png" => "image/png",
48326 - ".jpg" => "image/jpeg",
48327 - ".jpeg" => "image/jpeg",
48328 - ".gif" => "image/gif",
48329 - ".html" => "text/html",
48330 - ".htm" => "text/html",
48331 - ".pdf" => "application/pdf",
48332 - ".swf" => "application/x-shockwave-flash",
48333 - ".spl" => "application/futuresplash",
48334 - ".txt" => "text/plain",
48335 - ".tar.gz" => "application/x-tgz",
48336 - ".tgz" => "application/x-tgz",
48337 - ".gz" => "application/x-gzip",
48338 - ".c" => "text/plain",
48339 - ".conf" => "text/plain" )
48340 +setenv.add-request-header = ( "FOO" => "foo")
48341 +setenv.add-response-header = ( "BAR" => "foo")
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/"
48347 -compress.filetype = ("text/plain", "text/html")
48349 -setenv.add-environment = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
48350 -setenv.add-request-header = ( "FOO" => "foo")
48351 -setenv.add-response-header = ( "BAR" => "foo")
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" ) )
48360 -cgi.assign = ( ".pl" => "/usr/bin/perl",
48361 - ".cgi" => "/usr/bin/perl",
48362 - ".py" => "/usr/bin/python" )
48364 -userdir.include-user = ( "jan" )
48365 -userdir.path = "/"
48367 -ssl.engine = "disable"
48368 -ssl.pemfile = "server.pem"
48370 $HTTP["host"] == "auth-htpasswd.example.org" {
48371 auth.backend = "htpasswd"
48374 -auth.backend = "plain"
48375 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48377 -auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
48380 -auth.require = ( "/server-status" =>
48382 - "method" => "digest",
48383 - "realm" => "download archiv",
48384 - "require" => "group=www|user=jan|host=192.168.2.10"
48386 - "/server-config" =>
48388 - "method" => "basic",
48389 - "realm" => "download archiv",
48390 - "require" => "valid-user"
48394 -url.access-deny = ( "~", ".inc")
48396 -url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
48397 - "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48399 -expire.url = ( "/expire/access" => "access 2 hours",
48400 - "/expire/modification" => "access plus 1 seconds 2 minutes")
48402 -#cache.cache-dir = "/home/weigon/wwwroot/cache/"
48404 -#### status module
48405 -status.status-url = "/server-status"
48406 -status.config-url = "/server-config"
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
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"
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"
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"
48437 --- ../lighttpd-1.4.11/tests/lowercase.conf 1970-01-01 03:00:00.000000000 +0300
48438 +++ lighttpd-1.4.12/tests/lowercase.conf 2006-07-11 22:07:53.000000000 +0300
48440 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48441 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48443 +## bind to port (default: 80)
48444 +server.port = 2048
48446 +## bind to localhost (default: all interfaces)
48447 +server.bind = "localhost"
48448 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48450 +server.force-lowercase-filenames = "enable"
48452 +server.dir-listing = "enable"
48454 +server.modules = (
48457 + "mod_secdownload",
48466 +server.indexfiles = ( "index.php", "index.html",
48467 + "index.htm", "default.htm" )
48470 +######################## MODULE CONFIG ############################
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" )
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" ) )
48494 +cgi.assign = ( ".pl" => "/usr/bin/perl",
48495 + ".cgi" => "/usr/bin/perl",
48496 + ".py" => "/usr/bin/python" )
48498 +auth.backend = "plain"
48499 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48501 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
48503 +$HTTP["host"] == "lowercase-auth" {
48504 + auth.require = ( "/image.jpg" =>
48506 + "method" => "digest",
48507 + "realm" => "download archiv",
48508 + "require" => "valid-user"
48513 +$HTTP["host"] == "lowercase-deny" {
48514 + url.access-deny = ( ".jpg")
48517 +$HTTP["host"] == "lowercase-exclude" {
48518 + static-file.exclude-extensions = ( ".jpg" )
48520 --- ../lighttpd-1.4.11/tests/lowercase.t 1970-01-01 03:00:00.000000000 +0300
48521 +++ lighttpd-1.4.12/tests/lowercase.t 2006-07-11 22:07:53.000000000 +0300
48523 +#!/usr/bin/env perl
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;
48533 +use Test::More tests => 10;
48536 +my $tf = LightyTest->new();
48539 +$tf->{CONFIGFILE} = 'lowercase.conf';
48541 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
48543 +## check if lower-casing works
48545 +$t->{REQUEST} = ( <<EOF
48546 +GET /image.JPG HTTP/1.0
48549 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48550 +ok($tf->handle_http($t) == 0, 'uppercase access');
48552 +$t->{REQUEST} = ( <<EOF
48553 +GET /image.jpg HTTP/1.0
48556 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48557 +ok($tf->handle_http($t) == 0, 'lowercase access');
48559 +## check that mod-auth works
48561 +$t->{REQUEST} = ( <<EOF
48562 +GET /image.JPG HTTP/1.0
48563 +Host: lowercase-auth
48566 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48567 +ok($tf->handle_http($t) == 0, 'uppercase access');
48569 +$t->{REQUEST} = ( <<EOF
48570 +GET /image.jpg HTTP/1.0
48571 +Host: lowercase-auth
48574 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48575 +ok($tf->handle_http($t) == 0, 'lowercase access');
48578 +## check that mod-staticfile exclude works
48579 +$t->{REQUEST} = ( <<EOF
48580 +GET /image.JPG HTTP/1.0
48581 +Host: lowercase-exclude
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');
48587 +$t->{REQUEST} = ( <<EOF
48588 +GET /image.jpg HTTP/1.0
48589 +Host: lowercase-exclude
48592 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48593 +ok($tf->handle_http($t) == 0, 'lowercase access');
48596 +## check that mod-access exclude works
48597 +$t->{REQUEST} = ( <<EOF
48598 +GET /image.JPG HTTP/1.0
48599 +Host: lowercase-deny
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');
48605 +$t->{REQUEST} = ( <<EOF
48606 +GET /image.jpg HTTP/1.0
48607 +Host: lowercase-deny
48610 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48611 +ok($tf->handle_http($t) == 0, 'lowercase access');
48615 +ok($tf->stop_proc == 0, "Stopping lighttpd");
48617 --- ../lighttpd-1.4.11/tests/mod-fastcgi.t 2006-03-09 15:30:45.000000000 +0200
48618 +++ lighttpd-1.4.12/tests/mod-fastcgi.t 2006-07-11 22:07:53.000000000 +0300
48623 -use Test::More tests => 47;
48624 +use Test::More tests => 49;
48627 my $tf = LightyTest->new();
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);
48635 ok($tf->start_proc == 0, "Starting lighttpd") or die();
48637 @@ -223,7 +223,7 @@
48641 - skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48642 + skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48643 $tf->{CONFIGFILE} = 'fastcgi-13.conf';
48644 ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
48645 $t->{REQUEST} = ( <<EOF
48646 @@ -285,6 +285,34 @@
48647 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
48648 ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
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
48656 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48658 + ok($tf->handle_http($t) == 0, 'X-LIGHTTPD-send-file');
48660 + $t->{REQUEST} = ( <<EOF
48661 +GET /index.fcgi?xsendfile HTTP/1.0
48662 +Host: www.example.org
48665 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48667 + ok($tf->handle_http($t) == 0, 'X-Sendfile');
48669 + $t->{REQUEST} = ( <<EOF
48670 +GET /index.fcgi?xsendfile-mixed-case HTTP/1.0
48671 +Host: www.example.org
48674 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48676 + ok($tf->handle_http($t) == 0, 'X-SeNdFiLe in mixed case');
48678 $t->{REQUEST} = ( <<EOF
48679 GET /index.fcgi?die-at-end HTTP/1.0
48680 Host: www.example.org
48681 --- ../lighttpd-1.4.11/tests/mod-proxy.t 1970-01-01 03:00:00.000000000 +0300
48682 +++ lighttpd-1.4.12/tests/mod-proxy.t 2006-07-11 22:07:53.000000000 +0300
48684 +#!/usr/bin/env perl
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;
48694 +use Test::More tests => 21;
48697 +my $tf_proxy = LightyTest->new();
48698 +my $tf_backend1 = LightyTest->new();
48699 +my $tf_backend2 = LightyTest->new();
48703 +## we need two procs
48704 +## 1. the real webserver
48705 +## 2. the proxy server
48707 +$tf_proxy->{PORT} = 2048;
48708 +$tf_proxy->{CONFIGFILE} = 'proxy.conf';
48709 +$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
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';
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';
48720 +ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
48722 +ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
48726 +$t->{REQUEST} = ( <<EOF
48727 +GET /index.html HTTP/1.0
48728 +Host: www.example.org
48731 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48732 +ok($tf_proxy->handle_http($t) == 0, 'valid request');
48734 +$t->{REQUEST} = ( <<EOF
48735 +GET /index.html HTTP/1.0
48736 +Host: www.example.org
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');
48742 +$t->{REQUEST} = ( <<EOF
48743 +GET /balance-rr/foo HTTP/1.0
48744 +Host: www.example.org
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');
48750 +$t->{REQUEST} = ( <<EOF
48751 +GET /balance-rr/foo HTTP/1.0
48752 +Host: www.example.org
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');
48758 +$t->{REQUEST} = ( <<EOF
48759 +GET /balance-fair/foo HTTP/1.0
48760 +Host: www.example.org
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');
48766 +## backend 2 starting
48767 +ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
48769 +$t->{REQUEST} = ( <<EOF
48770 +GET /balance-rr/foo HTTP/1.0
48771 +Host: www.example.org
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');
48777 +$t->{REQUEST} = ( <<EOF
48778 +GET /balance-rr/foo HTTP/1.0
48779 +Host: www.example.org
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');
48785 +$t->{REQUEST} = ( <<EOF
48786 +GET /balance-hash/foo HTTP/1.0
48787 +Host: www.example.org
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');
48793 +$t->{REQUEST} = ( <<EOF
48794 +GET /balance-hash/foo HTTP/1.0
48795 +Host: www.example.org
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');
48801 +$t->{REQUEST} = ( <<EOF
48802 +GET /balance-hash/bar HTTP/1.0
48803 +Host: www.example.org
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');
48809 +$t->{REQUEST} = ( <<EOF
48810 +GET /balance-hash/bar HTTP/1.0
48811 +Host: www.example.org
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');
48817 +## backend 1 stopping, failover
48818 +ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
48820 +$t->{REQUEST} = ( <<EOF
48821 +GET /balance-hash/foo HTTP/1.0
48822 +Host: www.example.org
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');
48828 +$t->{REQUEST} = ( <<EOF
48829 +GET /balance-hash/bar HTTP/1.0
48830 +Host: www.example.org
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');
48836 +$t->{REQUEST} = ( <<EOF
48837 +GET /balance-rr/foo HTTP/1.0
48838 +Host: www.example.org
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');
48844 +$t->{REQUEST} = ( <<EOF
48845 +GET /balance-fair/foo HTTP/1.0
48846 +Host: www.example.org
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');
48853 +ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
48855 +ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
48857 --- ../lighttpd-1.4.11/tests/proxy.conf 1970-01-01 03:00:00.000000000 +0300
48858 +++ lighttpd-1.4.12/tests/proxy.conf 2006-07-11 22:07:53.000000000 +0300
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"
48864 +include "default.conf"
48866 +## 127.0.0.1 and 127.0.0.2 are the same host
48868 + "" => (( "host" => "127.0.0.1",
48869 + "port" => 2050 ),
48870 + ( "host" => "127.0.0.2",
48874 +$HTTP["url"] =~ "^/balance-rr/" {
48875 + proxy.balance = "round-robin"
48878 +$HTTP["url"] =~ "^/balance-hash/" {
48879 + proxy.balance = "hash"
48882 +$HTTP["url"] =~ "^/balance-fair/" {
48883 + proxy.balance = "fair"
48886 --- ../lighttpd-1.4.11/tests/var-include.conf 2005-08-27 17:44:19.000000000 +0300
48887 +++ lighttpd-1.4.12/tests/var-include.conf 2006-07-11 22:07:53.000000000 +0300
48889 debug.log-request-handling = "enable"
48890 debug.log-condition-handling = "enable"
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"
48897 ## bind to port (default: 80)
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"
48907 @@ -21,19 +21,19 @@
48908 ######################## MODULE CONFIG ############################
48911 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48912 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48914 mimetype.assign = ( ".html" => "text/html" )
48916 url.redirect = ("^" => "/default")
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")
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"