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 23:38:00.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/http_resp_parser.h 1970-01-01 03:00:00.000000000 +0300
12397 +++ lighttpd-1.4.12/src/http_resp_parser.h 2006-07-15 22:44:07.000000000 +0300
12400 +#define TK_STRING 2
12401 +#define TK_COLON 3
12402 --- ../lighttpd-1.4.11/src/http_resp_parser.y 1970-01-01 03:00:00.000000000 +0300
12403 +++ lighttpd-1.4.12/src/http_resp_parser.y 2006-07-15 22:43:21.000000000 +0300
12406 +%token_type {buffer *}
12407 +%extra_argument {http_resp_ctx_t *ctx}
12408 +%name http_resp_parser
12411 +#include <assert.h>
12412 +#include <string.h>
12413 +#include "http_resp.h"
12414 +#include "keyvalue.h"
12415 +#include "array.h"
12422 +%type protocol { int }
12423 +%type response_hdr { http_resp * }
12424 +%type number { int }
12425 +%type headers { array * }
12426 +%type header { data_string * }
12427 +%token_destructor { buffer_free($$); }
12429 +/* just headers + Status: ... */
12430 +response_hdr ::= headers(HDR) CRLF . {
12431 + http_resp *resp = ctx->resp;
12434 + resp->protocol = HTTP_VERSION_UNSET;
12436 + buffer_copy_string(resp->reason, ""); /* no reason */
12437 + array_free(resp->headers);
12438 + resp->headers = HDR;
12440 + if (NULL == (ds = (data_string *)array_get_element(HDR, "Status"))) {
12441 + resp->status = 0;
12444 + resp->status = strtol(ds->value->ptr, &err, 10);
12446 + if (*err != '\0' && *err != ' ') {
12447 + buffer_copy_string(ctx->errmsg, "expected a number: ");
12448 + buffer_append_string_buffer(ctx->errmsg, ds->value);
12449 + buffer_append_string(ctx->errmsg, err);
12457 +/* HTTP/1.0 <status> ... */
12458 +response_hdr ::= protocol(B) number(C) reason(D) CRLF headers(HDR) CRLF . {
12459 + http_resp *resp = ctx->resp;
12461 + resp->status = C;
12462 + resp->protocol = B;
12463 + buffer_copy_string_buffer(resp->reason, D);
12465 + array_free(resp->headers);
12467 + resp->headers = HDR;
12472 +protocol(A) ::= STRING(B). {
12473 + if (buffer_is_equal_string(B, CONST_STR_LEN("HTTP/1.0"))) {
12474 + A = HTTP_VERSION_1_0;
12475 + } else if (buffer_is_equal_string(B, CONST_STR_LEN("HTTP/1.1"))) {
12476 + A = HTTP_VERSION_1_1;
12478 + buffer_copy_string(ctx->errmsg, "unknown protocol: ");
12479 + buffer_append_string_buffer(ctx->errmsg, B);
12485 +number(A) ::= STRING(B). {
12487 + A = strtol(B->ptr, &err, 10);
12489 + if (*err != '\0') {
12490 + buffer_copy_string(ctx->errmsg, "expected a number: ");
12491 + buffer_append_string_buffer(ctx->errmsg, B);
12497 +reason(A) ::= STRING(B). {
12502 +reason(A) ::= reason(C) STRING(B). {
12505 + buffer_append_string(A, " ");
12506 + buffer_append_string_buffer(A, B);
12511 +headers(HDRS) ::= headers(SRC) header(HDR). {
12514 + array_insert_unique(HDRS, (data_unset *)HDR);
12519 +headers(HDRS) ::= header(HDR). {
12520 + HDRS = array_init();
12522 + array_insert_unique(HDRS, (data_unset *)HDR);
12524 +header(HDR) ::= STRING(A) COLON STRING(B) CRLF. {
12525 + HDR = data_string_init();
12527 + buffer_copy_string_buffer(HDR->key, A);
12528 + buffer_copy_string_buffer(HDR->value, B);
12530 --- ../lighttpd-1.4.11/src/inet_ntop_cache.c 2005-08-11 01:26:38.000000000 +0300
12531 +++ lighttpd-1.4.12/src/inet_ntop_cache.c 2006-07-11 22:07:52.000000000 +0300
12533 #include "sys-socket.h"
12535 const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
12539 for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
12540 if (srv->inet_ntop_cache[i].ts != 0) {
12541 @@ -20,31 +20,31 @@
12542 srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
12543 /* IPv4 found in cache */
12552 if (i == INET_NTOP_CACHE_MAX) {
12553 /* not found in cache */
12557 - inet_ntop(addr->plain.sa_family,
12558 - addr->plain.sa_family == AF_INET6 ?
12559 + inet_ntop(addr->plain.sa_family,
12560 + addr->plain.sa_family == AF_INET6 ?
12561 (const void *) &(addr->ipv6.sin6_addr) :
12562 (const void *) &(addr->ipv4.sin_addr),
12563 srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
12566 srv->inet_ntop_cache[i].ts = srv->cur_ts;
12567 srv->inet_ntop_cache[i].family = addr->plain.sa_family;
12570 if (srv->inet_ntop_cache[i].family == AF_INET) {
12571 srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
12572 } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
12573 memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
12578 return srv->inet_ntop_cache[i].b2;
12581 --- ../lighttpd-1.4.11/src/joblist.c 2005-08-11 01:26:41.000000000 +0300
12582 +++ lighttpd-1.4.12/src/joblist.c 2006-07-11 22:07:51.000000000 +0300
12585 int joblist_append(server *srv, connection *con) {
12586 if (con->in_joblist) return 0;
12589 if (srv->joblist->size == 0) {
12590 srv->joblist->size = 16;
12591 srv->joblist->ptr = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
12592 @@ -15,15 +15,15 @@
12593 srv->joblist->size += 16;
12594 srv->joblist->ptr = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
12598 srv->joblist->ptr[srv->joblist->used++] = con;
12604 void joblist_free(server *srv, connections *joblist) {
12608 free(joblist->ptr);
12611 @@ -31,14 +31,14 @@
12612 connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
12619 if (fdwaitqueue->used == 0) return NULL;
12622 con = fdwaitqueue->ptr[0];
12625 memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
12632 srv->fdwaitqueue->size += 16;
12633 srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
12637 srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
12643 --- ../lighttpd-1.4.11/src/keyvalue.c 2006-03-02 16:08:06.000000000 +0200
12644 +++ lighttpd-1.4.12/src/keyvalue.c 2006-07-11 22:07:51.000000000 +0300
12646 { 504, "Gateway Timeout" },
12647 { 505, "HTTP Version Not Supported" },
12648 { 507, "Insufficient Storage" }, /* WebDAV */
12650 + { 509, "Bandwidth Limit exceeded" },
12655 @@ -102,12 +103,12 @@
12656 { 501, "501.html" },
12657 { 503, "503.html" },
12658 { 505, "505.html" },
12665 -const char *keyvalue_get_value(keyvalue *kv, int k) {
12666 +const char *keyvalue_get_value(keyvalue *kv, int k) {
12668 for (i = 0; kv[i].value; i++) {
12669 if (kv[i].key == k) return kv[i].value;
12670 @@ -115,7 +116,7 @@
12674 -int keyvalue_get_key(keyvalue *kv, const char *s) {
12675 +int keyvalue_get_key(keyvalue *kv, const char *s) {
12677 for (i = 0; kv[i].value; i++) {
12678 if (0 == strcmp(kv[i].value, s)) return kv[i].key;
12679 @@ -125,9 +126,9 @@
12681 keyvalue_buffer *keyvalue_buffer_init(void) {
12682 keyvalue_buffer *kvb;
12685 kvb = calloc(1, sizeof(*kvb));
12691 @@ -135,49 +136,49 @@
12693 if (kvb->size == 0) {
12697 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12700 for(i = 0; i < kvb->size; i++) {
12701 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12703 } else if (kvb->used == kvb->size) {
12707 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12710 for(i = kvb->used; i < kvb->size; i++) {
12711 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12716 kvb->kv[kvb->used]->key = key;
12717 kvb->kv[kvb->used]->value = strdup(value);
12726 void keyvalue_buffer_free(keyvalue_buffer *kvb) {
12730 for (i = 0; i < kvb->size; i++) {
12731 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12736 if (kvb->kv) free(kvb->kv);
12743 s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
12744 s_keyvalue_buffer *kvb;
12747 kvb = calloc(1, sizeof(*kvb));
12753 @@ -186,50 +187,50 @@
12754 if (kvb->size == 0) {
12759 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12762 for(i = 0; i < kvb->size; i++) {
12763 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12765 } else if (kvb->used == kvb->size) {
12769 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12772 for(i = kvb->used; i < kvb->size; i++) {
12773 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12778 kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
12779 kvb->kv[kvb->used]->value = strdup(value);
12788 void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
12792 for (i = 0; i < kvb->size; i++) {
12793 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12794 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12799 if (kvb->kv) free(kvb->kv);
12806 httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
12807 httpauth_keyvalue_buffer *kvb;
12810 kvb = calloc(1, sizeof(*kvb));
12816 @@ -237,42 +238,42 @@
12818 if (kvb->size == 0) {
12822 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12825 for(i = 0; i < kvb->size; i++) {
12826 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12828 } else if (kvb->used == kvb->size) {
12832 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12835 for(i = kvb->used; i < kvb->size; i++) {
12836 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12841 kvb->kv[kvb->used]->key = strdup(key);
12842 kvb->kv[kvb->used]->realm = strdup(realm);
12843 kvb->kv[kvb->used]->type = type;
12852 void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
12856 for (i = 0; i < kvb->size; i++) {
12857 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12858 if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
12863 if (kvb->kv) free(kvb->kv);
12869 @@ -306,9 +307,9 @@
12871 pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
12872 pcre_keyvalue_buffer *kvb;
12875 kvb = calloc(1, sizeof(*kvb));
12881 @@ -319,46 +320,46 @@
12887 if (!key) return -1;
12890 if (kvb->size == 0) {
12895 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12898 for(i = 0; i < kvb->size; i++) {
12899 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12901 } else if (kvb->used == kvb->size) {
12905 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12908 for(i = kvb->used; i < kvb->size; i++) {
12909 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12914 kv = kvb->kv[kvb->used];
12915 if (NULL == (kv->key = pcre_compile(key,
12916 0, &errptr, &erroff, NULL))) {
12919 fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
12923 - if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
12924 + if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
12930 kv->value = buffer_init_string(value);
12939 @@ -380,9 +381,9 @@
12940 if (kv->value) buffer_free(kv->value);
12945 if (kvb->kv) free(kvb->kv);
12951 --- ../lighttpd-1.4.11/src/keyvalue.h 2006-03-02 16:08:06.000000000 +0200
12952 +++ lighttpd-1.4.12/src/keyvalue.h 2006-07-11 22:07:52.000000000 +0300
12958 - HTTP_METHOD_UNSET = -1,
12960 - HTTP_METHOD_POST,
12961 - HTTP_METHOD_HEAD,
12962 - HTTP_METHOD_OPTIONS,
12964 + HTTP_METHOD_UNSET = -1,
12966 + HTTP_METHOD_POST,
12967 + HTTP_METHOD_HEAD,
12968 + HTTP_METHOD_OPTIONS,
12969 HTTP_METHOD_PROPFIND, /* WebDAV */
12970 - HTTP_METHOD_MKCOL,
12972 - HTTP_METHOD_DELETE,
12973 - HTTP_METHOD_COPY,
12974 - HTTP_METHOD_MOVE,
12975 - HTTP_METHOD_PROPPATCH,
12976 + HTTP_METHOD_MKCOL,
12978 + HTTP_METHOD_DELETE,
12979 + HTTP_METHOD_COPY,
12980 + HTTP_METHOD_MOVE,
12981 + HTTP_METHOD_PROPPATCH,
12982 HTTP_METHOD_REPORT, /* DeltaV */
12983 HTTP_METHOD_CHECKOUT,
12984 HTTP_METHOD_CHECKIN,
12985 @@ -39,13 +39,13 @@
13003 pcre_extra *key_extra;
13017 httpauth_type type;
13018 } httpauth_keyvalue;
13019 --- ../lighttpd-1.4.11/src/lemon.c 2005-09-01 00:21:34.000000000 +0300
13020 +++ lighttpd-1.4.12/src/lemon.c 2006-07-11 22:07:51.000000000 +0300
13021 @@ -579,7 +579,7 @@
13024 /* Find a precedence symbol of every rule in the grammar.
13027 ** Those rules which have a precedence symbol coded in the input
13028 ** grammar using the "[symbol]" construct will already have the
13029 ** rp->precsym field filled. Other rules take as their precedence
13030 @@ -869,7 +869,7 @@
13031 cfp->status = INCOMPLETE;
13038 for(i=0; i<lemp->nstate; i++){
13039 @@ -900,7 +900,7 @@
13043 - /* Add all of the reduce actions
13044 + /* Add all of the reduce actions
13045 ** A reduce action is added for each element of the followset of
13046 ** a configuration which has its dot at the extreme right.
13048 @@ -1017,7 +1017,7 @@
13049 apx->type = RD_RESOLVED;
13054 apx->type==SH_RESOLVED ||
13055 apx->type==RD_RESOLVED ||
13056 apx->type==CONFLICT ||
13057 @@ -1350,7 +1350,7 @@
13058 OptInit(argv,options,stderr);
13060 printf("Lemon version 1.0\n");
13064 if( OptNArgs() < 1 ){
13065 fprintf(stderr,"Exactly one filename argument is required.\n");
13066 @@ -2031,7 +2031,7 @@
13070 - rp = (struct rule *)malloc( sizeof(struct rule) +
13071 + rp = (struct rule *)malloc( sizeof(struct rule) +
13072 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
13074 ErrorMsg(psp->filename,psp->tokenlineno,
13075 @@ -2546,7 +2546,7 @@
13079 -/* Duplicate the input file without comments and without actions
13080 +/* Duplicate the input file without comments and without actions
13083 struct lemon *lemp;
13084 @@ -2822,7 +2822,7 @@
13085 PRIVATE FILE *tplt_open(lemp)
13086 struct lemon *lemp;
13093 @@ -2930,7 +2930,7 @@
13099 ** Generate code which executes when the rule "rp" is reduced. Write
13100 ** the code to "out". Make sure lineno stays up-to-date.
13102 @@ -3384,7 +3384,7 @@
13104 /* Output the yy_shift_ofst[] table */
13105 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
13106 - fprintf(out, "static %s yy_shift_ofst[] = {\n",
13107 + fprintf(out, "static %s yy_shift_ofst[] = {\n",
13108 minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
13110 for(i=j=0; i<n; i++){
13111 @@ -3405,7 +3405,7 @@
13113 /* Output the yy_reduce_ofst[] table */
13114 fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
13115 - fprintf(out, "static %s yy_reduce_ofst[] = {\n",
13116 + fprintf(out, "static %s yy_reduce_ofst[] = {\n",
13117 minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
13119 for(i=j=0; i<n; i++){
13120 @@ -3480,7 +3480,7 @@
13121 tplt_xfer(lemp->name,in,out,&lineno);
13123 /* Generate code which executes every time a symbol is popped from
13124 - ** the stack while processing errors or while destroying the parser.
13125 + ** the stack while processing errors or while destroying the parser.
13126 ** (In other words, generate the %destructor actions)
13128 if( lemp->tokendest ){
13129 @@ -3522,7 +3522,7 @@
13130 tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
13131 tplt_xfer(lemp->name,in,out,&lineno);
13133 - /* Generate the table of rule information
13134 + /* Generate the table of rule information
13136 ** Note: This code depends on the fact that rules are number
13137 ** sequentually beginning with 0.
13138 @@ -3589,7 +3589,7 @@
13139 for(i=1; i<lemp->nterminal; i++){
13140 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
13147 @@ -3630,7 +3630,7 @@
13153 /* Do not make a default if the number of rules to default
13154 ** is not at least 2 */
13155 if( nbest<2 ) continue;
13156 @@ -3781,7 +3781,7 @@
13160 - x1a->tbl = (x1node*)malloc(
13161 + x1a->tbl = (x1node*)malloc(
13162 (sizeof(x1node) + sizeof(x1node*))*1024 );
13165 @@ -3943,7 +3943,7 @@
13169 - x2a->tbl = (x2node*)malloc(
13170 + x2a->tbl = (x2node*)malloc(
13171 (sizeof(x2node) + sizeof(x2node*))*128 );
13174 @@ -4149,7 +4149,7 @@
13178 - x3a->tbl = (x3node*)malloc(
13179 + x3a->tbl = (x3node*)malloc(
13180 (sizeof(x3node) + sizeof(x3node*))*128 );
13183 @@ -4295,7 +4295,7 @@
13187 - x4a->tbl = (x4node*)malloc(
13188 + x4a->tbl = (x4node*)malloc(
13189 (sizeof(x4node) + sizeof(x4node*))*64 );
13192 --- ../lighttpd-1.4.11/src/lempar.c 2005-08-11 01:26:40.000000000 +0300
13193 +++ lighttpd-1.4.12/src/lempar.c 2006-07-11 22:07:51.000000000 +0300
13195 /* Next is all token values, in a form suitable for use by makeheaders.
13196 ** This section will be null unless lemon is run with the -m switch.
13200 ** These constants (all generated automatically by the parser generator)
13201 ** specify the various kinds of tokens (terminals) that the parser
13205 ** Each symbol here is a terminal symbol in the grammar.
13208 ** and nonterminals. "int" is used otherwise.
13209 ** YYNOCODE is a number of type YYCODETYPE which corresponds
13210 ** to no legal terminal or nonterminal number. This
13211 -** number is used to fill in empty slots of the hash
13212 +** number is used to fill in empty slots of the hash
13214 ** YYFALLBACK If defined, this indicates that one or more tokens
13215 ** have fall-back values which should be used if the
13217 ** and nonterminal numbers. "unsigned char" is
13218 ** used if there are fewer than 250 rules and
13219 ** states combined. "int" is used otherwise.
13220 -** ParseTOKENTYPE is the data type used for minor tokens given
13221 +** ParseTOKENTYPE is the data type used for minor tokens given
13222 ** directly to the parser from the tokenizer.
13223 ** YYMINORTYPE is the data type used for all minor tokens.
13224 ** This is typically a union of many types, one of
13226 /* Next are that tables used to determine what action to take based on the
13227 ** current state and lookahead token. These tables are used to implement
13228 ** functions that take a state number and lookahead value and return an
13229 -** action integer.
13230 +** action integer.
13232 ** Suppose the action integer is N. Then the action is determined as
13235 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
13236 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
13237 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
13238 -** and that yy_default[S] should be used instead.
13239 +** and that yy_default[S] should be used instead.
13241 ** The formula above is for computing the action when the lookahead is
13242 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
13243 @@ -111,7 +111,7 @@
13245 /* The next table maps tokens into fallback tokens. If a construct
13246 ** like the following:
13249 ** %fallback ID X Y Z.
13251 ** appears in the grammer, then ID becomes a fallback token for X, Y,
13252 @@ -163,10 +163,10 @@
13253 #endif /* NDEBUG */
13258 ** Turn parser tracing on by giving a stream to which to write the trace
13259 ** and a prompt to preface each trace message. Tracing is turned off
13260 -** by making either argument NULL
13261 +** by making either argument NULL
13265 @@ -191,7 +191,7 @@
13267 /* For tracing shifts, the names of all terminals and nonterminals
13268 ** are required. The following table supplies these names */
13269 -static const char *yyTokenName[] = {
13270 +static const char *yyTokenName[] = {
13273 #endif /* NDEBUG */
13274 @@ -220,7 +220,7 @@
13280 ** This function allocates a new parser.
13281 ** The only argument is a pointer to a function which works like
13283 @@ -251,7 +251,7 @@
13284 /* Here is inserted the actions which take place when a
13285 ** terminal or non-terminal is destroyed. This can happen
13286 ** when the symbol is popped from the stack during a
13287 - ** reduce or during error processing or when a parser is
13288 + ** reduce or during error processing or when a parser is
13289 ** being destroyed before it is finished parsing.
13291 ** Note: during a reduce, the only symbols destroyed are those
13292 @@ -289,7 +289,7 @@
13298 ** Deallocate and destroy a parser. Destructors are all called for
13299 ** all stack elements before shutting the parser down.
13301 @@ -325,7 +325,7 @@
13304 int stateno = pParser->yystack[pParser->yyidx].stateno;
13307 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
13308 i = yy_shift_ofst[stateno];
13309 if( i==YY_SHIFT_USE_DFLT ){
13310 @@ -369,7 +369,7 @@
13313 int stateno = pParser->yystack[pParser->yyidx].stateno;
13316 i = yy_reduce_ofst[stateno];
13317 if( i==YY_REDUCE_USE_DFLT ){
13318 return yy_default[stateno];
13319 @@ -455,7 +455,7 @@
13321 yymsp = &yypParser->yystack[yypParser->yyidx];
13323 - if( yyTraceFILE && yyruleno>=0
13324 + if( yyTraceFILE && yyruleno>=0
13325 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
13326 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
13327 yyRuleName[yyruleno]);
13328 @@ -608,7 +608,7 @@
13329 #ifdef YYERRORSYMBOL
13330 /* A syntax error has occurred.
13331 ** The response to an error depends upon whether or not the
13332 - ** grammar defines an error token "ERROR".
13333 + ** grammar defines an error token "ERROR".
13335 ** This is what we do if the grammar does define ERROR:
13337 --- ../lighttpd-1.4.11/src/log.c 2005-11-07 15:01:35.000000000 +0200
13338 +++ lighttpd-1.4.12/src/log.c 2006-07-15 22:43:21.000000000 +0300
13343 -#include <unistd.h>
13344 #include <string.h>
13345 #include <stdlib.h>
13348 #include "config.h"
13352 +#undef HAVE_SYSLOG_H
13355 #ifdef HAVE_SYSLOG_H
13356 #include <syslog.h>
13362 +#include "sys-files.h"
13364 #ifdef HAVE_VALGRIND_VALGRIND_H
13365 #include <valgrind/valgrind.h>
13367 @@ -31,38 +36,38 @@
13368 # define O_LARGEFILE 0
13373 * open the errorlog
13376 * we have 3 possibilities:
13377 * - stderr (default)
13383 * if the open failed, report to the user and die
13388 int log_error_open(server *srv) {
13390 int close_stderr = 1;
13393 #ifdef HAVE_SYSLOG_H
13394 /* perhaps someone wants to use syslog() */
13395 openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
13397 srv->errorlog_mode = ERRORLOG_STDERR;
13400 if (srv->srvconf.errorlog_use_syslog) {
13401 srv->errorlog_mode = ERRORLOG_SYSLOG;
13402 } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
13403 const char *logfile = srv->srvconf.errorlog_file->ptr;
13406 if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13407 - log_error_write(srv, __FILE__, __LINE__, "SSSS",
13408 + log_error_write(srv, __FILE__, __LINE__, "SSSS",
13409 "opening errorlog '", logfile,
13410 "' failed: ", strerror(errno));
13416 @@ -71,15 +76,15 @@
13418 srv->errorlog_mode = ERRORLOG_FILE;
13422 log_error_write(srv, __FILE__, __LINE__, "s", "server started");
13425 #ifdef HAVE_VALGRIND_VALGRIND_H
13426 /* don't close stderr for debugging purposes if run in valgrind */
13427 if (RUNNING_ON_VALGRIND) close_stderr = 0;
13429 if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
13432 /* move stderr to /dev/null */
13433 if (close_stderr &&
13434 -1 != (fd = open("/dev/null", O_WRONLY))) {
13435 @@ -90,33 +95,33 @@
13441 * open the errorlog
13444 * if the open failed, report to the user and die
13445 * if no filename is given, use syslog instead
13450 int log_error_cycle(server *srv) {
13451 /* only cycle if we are not in syslog-mode */
13454 if (srv->errorlog_mode == ERRORLOG_FILE) {
13455 const char *logfile = srv->srvconf.errorlog_file->ptr;
13456 /* already check of opening time */
13462 if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13463 /* write to old log */
13464 - log_error_write(srv, __FILE__, __LINE__, "SSSSS",
13465 + log_error_write(srv, __FILE__, __LINE__, "SSSSS",
13466 "cycling errorlog '", logfile,
13467 "' failed: ", strerror(errno),
13468 ", falling back to syslog()");
13471 close(srv->errorlog_fd);
13472 srv->errorlog_fd = -1;
13473 -#ifdef HAVE_SYSLOG_H
13474 +#ifdef HAVE_SYSLOG_H
13475 srv->errorlog_mode = ERRORLOG_SYSLOG;
13478 @@ -125,15 +130,15 @@
13479 srv->errorlog_fd = new_fd;
13484 log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
13490 int log_error_close(server *srv) {
13491 log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
13494 switch(srv->errorlog_mode) {
13495 case ERRORLOG_FILE:
13496 close(srv->errorlog_fd);
13497 @@ -146,13 +151,13 @@
13498 case ERRORLOG_STDERR:
13506 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
13510 switch(srv->errorlog_mode) {
13511 case ERRORLOG_FILE:
13512 case ERRORLOG_STDERR:
13513 @@ -161,7 +166,7 @@
13514 buffer_prepare_copy(srv->ts_debug_str, 255);
13515 strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
13516 srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
13519 srv->last_generated_debug_ts = srv->cur_ts;
13522 @@ -173,19 +178,19 @@
13523 BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
13528 buffer_append_string(srv->errorlog_buf, filename);
13529 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ".");
13530 buffer_append_long(srv->errorlog_buf, line);
13531 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") ");
13536 for(va_start(ap, fmt); *fmt; fmt++) {
13544 case 's': /* string */
13545 s = va_arg(ap, char *);
13546 @@ -227,7 +232,7 @@
13555 @@ -236,7 +241,7 @@
13561 switch(srv->errorlog_mode) {
13562 case ERRORLOG_FILE:
13563 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13564 @@ -246,11 +251,13 @@
13565 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13566 write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
13568 +#ifdef HAVE_SYSLOG_H
13569 case ERRORLOG_SYSLOG:
13570 syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
13579 --- ../lighttpd-1.4.11/src/log.h 2005-08-11 01:26:36.000000000 +0300
13580 +++ lighttpd-1.4.12/src/log.h 2006-07-11 22:07:53.000000000 +0300
13582 int log_error_close(server *srv);
13583 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
13584 int log_error_cycle(server *srv);
13588 --- ../lighttpd-1.4.11/src/md5.h 2005-11-17 16:20:40.000000000 +0200
13589 +++ lighttpd-1.4.12/src/md5.h 2006-07-11 22:07:53.000000000 +0300
13591 # include <inttypes.h>
13595 +#define UINT4 unsigned __int32
13596 +#define UINT2 unsigned __int16
13597 +#define POINTER unsigned char *
13599 #define UINT4 uint32_t
13600 #define UINT2 uint16_t
13601 #define POINTER unsigned char *
13606 --- ../lighttpd-1.4.11/src/mod_access.c 2006-01-14 19:44:54.000000000 +0200
13607 +++ lighttpd-1.4.12/src/mod_access.c 2006-07-11 22:07:53.000000000 +0300
13608 @@ -8,126 +8,125 @@
13610 #include "plugin.h"
13612 +#include "sys-strings.h"
13615 array *access_deny;
13622 plugin_config **config_storage;
13624 - plugin_config conf;
13626 + plugin_config conf;
13629 INIT_FUNC(mod_access_init) {
13633 p = calloc(1, sizeof(*p));
13639 FREE_FUNC(mod_access_free) {
13640 plugin_data *p = p_d;
13645 if (!p) return HANDLER_GO_ON;
13648 if (p->config_storage) {
13650 for (i = 0; i < srv->config_context->used; i++) {
13651 plugin_config *s = p->config_storage[i];
13654 array_free(s->access_deny);
13659 free(p->config_storage);
13666 return HANDLER_GO_ON;
13669 SETDEFAULTS_FUNC(mod_access_set_defaults) {
13670 plugin_data *p = p_d;
13673 - config_values_t cv[] = {
13675 + config_values_t cv[] = {
13676 { "url.access-deny", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
13677 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
13681 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
13684 for (i = 0; i < srv->config_context->used; i++) {
13688 s = calloc(1, sizeof(plugin_config));
13689 s->access_deny = array_init();
13692 cv[0].destination = s->access_deny;
13695 p->config_storage[i] = s;
13698 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
13699 return HANDLER_ERROR;
13704 return HANDLER_GO_ON;
13707 -#define PATCH(x) \
13708 - p->conf.x = s->x;
13709 static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
13711 plugin_config *s = p->config_storage[0];
13713 - PATCH(access_deny);
13715 + PATCH_OPTION(access_deny);
13717 /* skip the first, the global context */
13718 for (i = 1; i < srv->config_context->used; i++) {
13719 data_config *dc = (data_config *)srv->config_context->data[i];
13720 s = p->config_storage[i];
13723 /* condition didn't match */
13724 if (!config_check_cond(srv, con, dc)) continue;
13728 for (j = 0; j < dc->value->used; j++) {
13729 data_unset *du = dc->value->data[j];
13732 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
13733 - PATCH(access_deny);
13734 + PATCH_OPTION(access_deny);
13744 URIHANDLER_FUNC(mod_access_uri_handler) {
13745 plugin_data *p = p_d;
13750 if (con->uri.path->used == 0) return HANDLER_GO_ON;
13753 mod_access_patch_connection(srv, con, p);
13756 s_len = con->uri.path->used - 1;
13759 for (k = 0; k < p->conf.access_deny->used; k++) {
13760 data_string *ds = (data_string *)p->conf.access_deny->data[k];
13761 int ct_len = ds->value->used - 1;
13764 if (ct_len > s_len) continue;
13767 if (ds->value->used == 0) continue;
13769 /* if we have a case-insensitive FS we have to lower-case the URI here too */
13770 @@ -135,18 +134,18 @@
13771 if (con->conf.force_lowercase_filenames) {
13772 if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13773 con->http_status = 403;
13776 return HANDLER_FINISHED;
13779 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13780 con->http_status = 403;
13783 return HANDLER_FINISHED;
13790 return HANDLER_GO_ON;
13792 @@ -155,13 +154,13 @@
13793 int mod_access_plugin_init(plugin *p) {
13794 p->version = LIGHTTPD_VERSION_ID;
13795 p->name = buffer_init_string("access");
13798 p->init = mod_access_init;
13799 p->set_defaults = mod_access_set_defaults;
13800 p->handle_uri_clean = mod_access_uri_handler;
13801 p->cleanup = mod_access_free;
13809 --- ../lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200
13810 +++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-11 22:07:53.000000000 +0300
13813 #include <stdlib.h>
13814 #include <string.h>
13815 -#include <fcntl.h>
13816 -#include <unistd.h>
13817 +#include <fcntl.h> /* only the defines on windows */
13822 #include "inet_ntop_cache.h"
13824 #include "sys-socket.h"
13825 +#include "sys-files.h"
13827 #ifdef HAVE_SYSLOG_H
13828 # include <syslog.h>
13836 FORMAT_UNSUPPORTED,
13840 FORMAT_BYTES_OUT_NO_HEADER,
13844 FORMAT_REMOTE_ADDR,
13847 @@ -59,20 +59,20 @@
13848 FORMAT_CONNECTION_STATUS,
13853 FORMAT_RESPONSE_HEADER
13862 * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
13867 -const format_mapping fmap[] =
13869 +const format_mapping fmap[] =
13871 { '%', FORMAT_PERCENT },
13872 { 'h', FORMAT_REMOTE_HOST },
13873 { 'l', FORMAT_REMOTE_IDENT },
13875 { 's', FORMAT_STATUS },
13876 { 'b', FORMAT_BYTES_OUT_NO_HEADER },
13877 { 'i', FORMAT_HEADER },
13880 { 'a', FORMAT_REMOTE_ADDR },
13881 { 'A', FORMAT_LOCAL_ADDR },
13882 { 'B', FORMAT_BYTES_OUT_NO_HEADER },
13883 @@ -103,23 +103,23 @@
13884 { 'X', FORMAT_CONNECTION_STATUS },
13885 { 'I', FORMAT_BYTES_IN },
13886 { 'O', FORMAT_BYTES_OUT },
13889 { 'o', FORMAT_RESPONSE_HEADER },
13892 { '\0', FORMAT_UNSET }
13897 enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
13905 format_field **ptr;
13911 @@ -128,39 +128,39 @@
13912 buffer *access_logfile;
13914 unsigned short use_syslog;
13920 time_t last_generated_accesslog_ts;
13921 time_t *last_generated_accesslog_ts_ptr;
13926 buffer *access_logbuffer;
13927 buffer *ts_accesslog_str;
13930 format_fields *parsed_format;
13937 plugin_config **config_storage;
13938 - plugin_config conf;
13939 + plugin_config conf;
13942 INIT_FUNC(mod_accesslog_init) {
13946 p = calloc(1, sizeof(*p));
13952 int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
13953 size_t i, j, k = 0, start = 0;
13956 for (i = 0; i < format->used - 1; i++) {
13959 switch(format->ptr[i]) {
13962 @@ -173,19 +173,19 @@
13963 fields->size += 16;
13964 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
13968 fields->ptr[fields->used] = malloc(sizeof(format_fields));
13969 fields->ptr[fields->used]->type = FIELD_STRING;
13970 fields->ptr[fields->used]->string = buffer_init();
13973 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
13982 /* we need a new field */
13985 if (fields->size == 0) {
13988 @@ -194,43 +194,43 @@
13989 fields->size += 16;
13990 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
13994 /* search for the terminating command */
13995 switch (format->ptr[i+1]) {
14001 for (j = 0; fmap[j].key != '\0'; j++) {
14002 if (fmap[j].key != format->ptr[i+2]) continue;
14008 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14009 fields->ptr[fields->used]->type = FIELD_FORMAT;
14010 fields->ptr[fields->used]->field = fmap[j].type;
14011 fields->ptr[fields->used]->string = NULL;
14021 if (fmap[j].key == '\0') {
14022 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14032 /* go forward to } */
14035 for (k = i+2; k < format->used - 1; k++) {
14036 if (format->ptr[k] == '}') break;
14040 if (k == format->used - 1) {
14041 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14043 @@ -239,62 +239,62 @@
14044 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14049 for (j = 0; fmap[j].key != '\0'; j++) {
14050 if (fmap[j].key != format->ptr[k+1]) continue;
14056 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14057 fields->ptr[fields->used]->type = FIELD_FORMAT;
14058 fields->ptr[fields->used]->field = fmap[j].type;
14059 fields->ptr[fields->used]->string = buffer_init();
14062 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
14072 if (fmap[j].key == '\0') {
14073 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14083 for (j = 0; fmap[j].key != '\0'; j++) {
14084 if (fmap[j].key != format->ptr[i+1]) continue;
14090 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14091 fields->ptr[fields->used]->type = FIELD_FORMAT;
14092 fields->ptr[fields->used]->field = fmap[j].type;
14093 fields->ptr[fields->used]->string = NULL;
14103 if (fmap[j].key == '\0') {
14104 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14122 /* copy the string */
14123 if (fields->size == 0) {
14124 @@ -305,32 +305,32 @@
14125 fields->size += 16;
14126 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14130 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14131 fields->ptr[fields->used]->type = FIELD_STRING;
14132 fields->ptr[fields->used]->string = buffer_init();
14135 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14145 FREE_FUNC(mod_accesslog_free) {
14146 plugin_data *p = p_d;
14150 if (!p) return HANDLER_GO_ON;
14153 if (p->config_storage) {
14156 for (i = 0; i < srv->config_context->used; i++) {
14157 plugin_config *s = p->config_storage[i];
14162 if (s->access_logbuffer->used) {
14163 if (s->use_syslog) {
14164 # ifdef HAVE_SYSLOG_H
14165 @@ -342,14 +342,14 @@
14166 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14171 if (s->log_access_fd != -1) close(s->log_access_fd);
14174 buffer_free(s->ts_accesslog_str);
14175 buffer_free(s->access_logbuffer);
14176 buffer_free(s->format);
14177 buffer_free(s->access_logfile);
14180 if (s->parsed_format) {
14182 for (j = 0; j < s->parsed_format->used; j++) {
14183 @@ -359,36 +359,36 @@
14184 free(s->parsed_format->ptr);
14185 free(s->parsed_format);
14193 free(p->config_storage);
14200 return HANDLER_GO_ON;
14203 SETDEFAULTS_FUNC(log_access_open) {
14204 plugin_data *p = p_d;
14207 - config_values_t cv[] = {
14209 + config_values_t cv[] = {
14210 { "accesslog.filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14211 { "accesslog.use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
14212 { "accesslog.format", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14213 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14217 if (!p) return HANDLER_ERROR;
14220 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14223 for (i = 0; i < srv->config_context->used; i++) {
14227 s = calloc(1, sizeof(plugin_config));
14228 s->access_logfile = buffer_init();
14229 s->format = buffer_init();
14230 @@ -397,44 +397,44 @@
14231 s->log_access_fd = -1;
14232 s->last_generated_accesslog_ts = 0;
14233 s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
14238 cv[0].destination = s->access_logfile;
14239 cv[1].destination = &(s->use_syslog);
14240 cv[2].destination = s->format;
14243 p->config_storage[i] = s;
14246 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14247 return HANDLER_ERROR;
14251 if (i == 0 && buffer_is_empty(s->format)) {
14252 /* set a default logfile string */
14255 buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
14262 if (s->format->used) {
14263 s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
14266 if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
14268 - log_error_write(srv, __FILE__, __LINE__, "sb",
14269 + log_error_write(srv, __FILE__, __LINE__, "sb",
14270 "parsing accesslog-definition failed:", s->format);
14272 return HANDLER_ERROR;
14277 for (j = 0; j < s->parsed_format->used; j++) {
14278 switch (s->parsed_format->ptr[j]->type) {
14280 - log_error_write(srv, __FILE__, __LINE__, "ssds",
14281 + log_error_write(srv, __FILE__, __LINE__, "ssds",
14282 "config:", "format", s->parsed_format->ptr[j]->field,
14283 - s->parsed_format->ptr[j]->string ?
14284 + s->parsed_format->ptr[j]->string ?
14285 s->parsed_format->ptr[j]->string->ptr : "" );
14288 @@ -446,52 +446,52 @@
14294 if (s->use_syslog) {
14295 /* ignore the next checks */
14300 if (buffer_is_empty(s->access_logfile)) continue;
14303 if (s->access_logfile->ptr[0] == '|') {
14305 /* create write pipe and spawn process */
14312 if (pipe(to_log_fds)) {
14313 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
14314 return HANDLER_ERROR;
14319 switch (pid = fork()) {
14325 close(STDIN_FILENO);
14326 dup2(to_log_fds[0], STDIN_FILENO);
14327 close(to_log_fds[0]);
14329 close(to_log_fds[1]);
14332 /* we don't need the client socket */
14333 for (i = 3; i < 256; i++) {
14337 - /* exec the log-process (skip the | )
14340 + /* exec the log-process (skip the | )
14345 execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
14347 - log_error_write(srv, __FILE__, __LINE__, "sss",
14348 - "spawning log-process failed: ", strerror(errno),
14349 + log_error_write(srv, __FILE__, __LINE__, "sss",
14350 + "spawning log-process failed: ", strerror(errno),
14351 s->access_logfile->ptr + 1);
14357 @@ -500,27 +500,28 @@
14360 close(to_log_fds[0]);
14363 s->log_access_fd = to_log_fds[1];
14371 - } else if (-1 == (s->log_access_fd =
14372 + } else if (-1 == (s->log_access_fd =
14373 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14375 - log_error_write(srv, __FILE__, __LINE__, "ssb",
14376 - "opening access-log failed:",
14378 + log_error_write(srv, __FILE__, __LINE__, "ssb",
14379 + "opening access-log failed:",
14380 strerror(errno), s->access_logfile);
14383 return HANDLER_ERROR;
14386 fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
14392 return HANDLER_GO_ON;
14395 @@ -529,7 +530,7 @@
14398 if (!p->config_storage) return HANDLER_GO_ON;
14401 for (i = 0; i < srv->config_context->used; i++) {
14402 plugin_config *s = p->config_storage[i];
14404 @@ -544,90 +545,87 @@
14405 } else if (s->log_access_fd != -1) {
14406 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14410 buffer_reset(s->access_logbuffer);
14414 if (s->use_syslog == 0 &&
14415 !buffer_is_empty(s->access_logfile) &&
14416 s->access_logfile->ptr[0] != '|') {
14419 close(s->log_access_fd);
14421 - if (-1 == (s->log_access_fd =
14423 + if (-1 == (s->log_access_fd =
14424 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14427 log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
14430 return HANDLER_ERROR;
14436 return HANDLER_GO_ON;
14439 -#define PATCH(x) \
14440 - p->conf.x = s->x;
14441 static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
14443 plugin_config *s = p->config_storage[0];
14445 - PATCH(access_logfile);
14447 - PATCH(log_access_fd);
14448 - PATCH(last_generated_accesslog_ts_ptr);
14449 - PATCH(access_logbuffer);
14450 - PATCH(ts_accesslog_str);
14451 - PATCH(parsed_format);
14452 - PATCH(use_syslog);
14455 + PATCH_OPTION(access_logfile);
14456 + PATCH_OPTION(format);
14457 + PATCH_OPTION(log_access_fd);
14458 + PATCH_OPTION(last_generated_accesslog_ts_ptr);
14459 + PATCH_OPTION(access_logbuffer);
14460 + PATCH_OPTION(ts_accesslog_str);
14461 + PATCH_OPTION(parsed_format);
14462 + PATCH_OPTION(use_syslog);
14464 /* skip the first, the global context */
14465 for (i = 1; i < srv->config_context->used; i++) {
14466 data_config *dc = (data_config *)srv->config_context->data[i];
14467 s = p->config_storage[i];
14470 /* condition didn't match */
14471 if (!config_check_cond(srv, con, dc)) continue;
14475 for (j = 0; j < dc->value->used; j++) {
14476 data_unset *du = dc->value->data[j];
14479 if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
14480 - PATCH(access_logfile);
14481 - PATCH(log_access_fd);
14482 - PATCH(last_generated_accesslog_ts_ptr);
14483 - PATCH(access_logbuffer);
14484 - PATCH(ts_accesslog_str);
14485 + PATCH_OPTION(access_logfile);
14486 + PATCH_OPTION(log_access_fd);
14487 + PATCH_OPTION(last_generated_accesslog_ts_ptr);
14488 + PATCH_OPTION(access_logbuffer);
14489 + PATCH_OPTION(ts_accesslog_str);
14490 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
14492 - PATCH(parsed_format);
14493 + PATCH_OPTION(format);
14494 + PATCH_OPTION(parsed_format);
14495 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
14496 - PATCH(use_syslog);
14497 + PATCH_OPTION(use_syslog);
14507 REQUESTDONE_FUNC(log_access_write) {
14508 plugin_data *p = p_d;
14517 mod_accesslog_patch_connection(srv, con, p);
14520 b = p->conf.access_logbuffer;
14521 if (b->used == 0) {
14522 buffer_copy_string(b, "");
14526 for (j = 0; j < p->conf.parsed_format->used; j++) {
14527 switch(p->conf.parsed_format->ptr[j]->type) {
14529 @@ -636,14 +634,14 @@
14531 switch(p->conf.parsed_format->ptr[j]->field) {
14532 case FORMAT_TIMESTAMP:
14535 /* cache the generated timestamp */
14536 if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
14538 #if defined(HAVE_STRUCT_TM_GMTOFF)
14539 long scd, hrs, min;
14543 buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
14544 #if defined(HAVE_STRUCT_TM_GMTOFF)
14545 # ifdef HAVE_LOCALTIME_R
14546 @@ -653,17 +651,17 @@
14547 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)));
14549 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14552 buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
14555 scd = abs(tm.tm_gmtoff);
14557 min = (scd % 3600) / 60;
14561 if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14562 buffer_append_long(p->conf.ts_accesslog_str, hrs);
14565 if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14566 buffer_append_long(p->conf.ts_accesslog_str, min);
14567 BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]");
14568 @@ -676,20 +674,20 @@
14570 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14574 *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
14579 buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
14583 case FORMAT_REMOTE_HOST:
14586 /* handle inet_ntop cache */
14589 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
14593 case FORMAT_REMOTE_IDENT:
14595 @@ -710,10 +708,10 @@
14596 case FORMAT_STATUS:
14597 buffer_append_long(b, con->http_status);
14601 case FORMAT_BYTES_OUT_NO_HEADER:
14602 if (con->bytes_written > 0) {
14603 - buffer_append_off_t(b,
14604 + buffer_append_off_t(b,
14605 con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
14607 BUFFER_APPEND_STRING_CONST(b, "-");
14608 @@ -772,7 +770,7 @@
14611 case FORMAT_REQUEST_PROTOCOL:
14612 - buffer_append_string(b,
14613 + buffer_append_string(b,
14614 con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
14616 case FORMAT_REQUEST_METHOD:
14617 @@ -801,7 +799,7 @@
14618 { 'D', FORMAT_TIME_USED_MS },
14619 { 'e', FORMAT_ENV },
14626 @@ -809,7 +807,7 @@
14632 BUFFER_APPEND_STRING_CONST(b, "\n");
14634 if (p->conf.use_syslog || /* syslog doesn't cache */
14635 @@ -828,7 +826,7 @@
14641 return HANDLER_GO_ON;
14644 @@ -836,15 +834,15 @@
14645 int mod_accesslog_plugin_init(plugin *p) {
14646 p->version = LIGHTTPD_VERSION_ID;
14647 p->name = buffer_init_string("accesslog");
14650 p->init = mod_accesslog_init;
14651 p->set_defaults= log_access_open;
14652 p->cleanup = mod_accesslog_free;
14655 p->handle_request_done = log_access_write;
14656 p->handle_sighup = log_access_cycle;
14664 --- ../lighttpd-1.4.11/src/mod_alias.c 2006-03-01 23:18:51.000000000 +0200
14665 +++ lighttpd-1.4.12/src/mod_alias.c 2006-07-11 22:07:51.000000000 +0300
14667 #include "buffer.h"
14669 #include "plugin.h"
14670 +#include "sys-strings.h"
14672 /* plugin config for all request/connections */
14674 @@ -16,44 +17,44 @@
14680 plugin_config **config_storage;
14682 - plugin_config conf;
14684 + plugin_config conf;
14687 /* init the plugin data */
14688 INIT_FUNC(mod_alias_init) {
14692 p = calloc(1, sizeof(*p));
14702 /* detroy the plugin data */
14703 FREE_FUNC(mod_alias_free) {
14704 plugin_data *p = p_d;
14707 if (!p) return HANDLER_GO_ON;
14710 if (p->config_storage) {
14714 for (i = 0; i < srv->config_context->used; i++) {
14715 plugin_config *s = p->config_storage[i];
14718 array_free(s->alias);
14723 free(p->config_storage);
14730 return HANDLER_GO_ON;
14733 @@ -62,25 +63,25 @@
14734 SETDEFAULTS_FUNC(mod_alias_set_defaults) {
14735 plugin_data *p = p_d;
14738 - config_values_t cv[] = {
14740 + config_values_t cv[] = {
14741 { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
14742 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14746 if (!p) return HANDLER_ERROR;
14749 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14752 for (i = 0; i < srv->config_context->used; i++) {
14756 s = calloc(1, sizeof(plugin_config));
14757 - s->alias = array_init();
14758 + s->alias = array_init();
14759 cv[0].destination = s->alias;
14762 p->config_storage[i] = s;
14765 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14766 return HANDLER_ERROR;
14768 @@ -110,76 +111,73 @@
14774 return HANDLER_GO_ON;
14777 -#define PATCH(x) \
14778 - p->conf.x = s->x;
14779 static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
14781 plugin_config *s = p->config_storage[0];
14786 + PATCH_OPTION(alias);
14788 /* skip the first, the global context */
14789 for (i = 1; i < srv->config_context->used; i++) {
14790 data_config *dc = (data_config *)srv->config_context->data[i];
14791 s = p->config_storage[i];
14794 /* condition didn't match */
14795 if (!config_check_cond(srv, con, dc)) continue;
14799 for (j = 0; j < dc->value->used; j++) {
14800 data_unset *du = dc->value->data[j];
14803 if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
14805 + PATCH_OPTION(alias);
14815 PHYSICALPATH_FUNC(mod_alias_physical_handler) {
14816 plugin_data *p = p_d;
14817 int uri_len, basedir_len;
14822 if (con->physical.path->used == 0) return HANDLER_GO_ON;
14825 mod_alias_patch_connection(srv, con, p);
14828 /* not to include the tailing slash */
14829 basedir_len = (con->physical.basedir->used - 1) - 1;
14830 uri_len = con->physical.path->used - 1 - basedir_len;
14831 uri_ptr = con->physical.path->ptr + basedir_len;
14834 for (k = 0; k < p->conf.alias->used; k++) {
14835 data_string *ds = (data_string *)p->conf.alias->data[k];
14836 int alias_len = ds->key->used - 1;
14839 if (alias_len > uri_len) continue;
14840 if (ds->key->used == 0) continue;
14843 if (0 == (con->conf.force_lowercase_filenames ?
14844 strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
14845 strncmp(uri_ptr, ds->key->ptr, alias_len))) {
14849 buffer_copy_string_buffer(con->physical.basedir, ds->value);
14850 buffer_copy_string_buffer(srv->tmp_buf, ds->value);
14851 buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
14852 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
14855 return HANDLER_GO_ON;
14861 return HANDLER_GO_ON;
14863 @@ -189,13 +187,13 @@
14864 int mod_alias_plugin_init(plugin *p) {
14865 p->version = LIGHTTPD_VERSION_ID;
14866 p->name = buffer_init_string("alias");
14869 p->init = mod_alias_init;
14870 p->handle_physical= mod_alias_physical_handler;
14871 p->set_defaults = mod_alias_set_defaults;
14872 p->cleanup = mod_alias_free;
14880 --- ../lighttpd-1.4.11/src/mod_auth.c 2006-02-15 20:01:31.000000000 +0200
14881 +++ lighttpd-1.4.12/src/mod_auth.c 2006-07-11 22:07:53.000000000 +0300
14882 @@ -5,168 +5,167 @@
14883 #include <string.h>
14886 -#include <unistd.h>
14888 #include "plugin.h"
14889 #include "http_auth.h"
14891 #include "response.h"
14893 +#include "sys-strings.h"
14894 +#include "sys-files.h"
14896 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
14900 * the basic and digest auth framework
14903 * - config handling
14904 * - protocol handling
14907 - * http_auth_digest.c
14911 + * http_auth_digest.c
14916 INIT_FUNC(mod_auth_init) {
14917 mod_auth_plugin_data *p;
14920 p = calloc(1, sizeof(*p));
14923 p->tmp_buf = buffer_init();
14926 p->auth_user = buffer_init();
14928 p->ldap_filter = buffer_init();
14935 FREE_FUNC(mod_auth_free) {
14936 mod_auth_plugin_data *p = p_d;
14941 if (!p) return HANDLER_GO_ON;
14944 buffer_free(p->tmp_buf);
14945 buffer_free(p->auth_user);
14947 buffer_free(p->ldap_filter);
14951 if (p->config_storage) {
14953 for (i = 0; i < srv->config_context->used; i++) {
14954 mod_auth_plugin_config *s = p->config_storage[i];
14960 array_free(s->auth_require);
14961 buffer_free(s->auth_plain_groupfile);
14962 buffer_free(s->auth_plain_userfile);
14963 buffer_free(s->auth_htdigest_userfile);
14964 buffer_free(s->auth_htpasswd_userfile);
14965 buffer_free(s->auth_backend_conf);
14968 buffer_free(s->auth_ldap_hostname);
14969 buffer_free(s->auth_ldap_basedn);
14970 buffer_free(s->auth_ldap_binddn);
14971 buffer_free(s->auth_ldap_bindpw);
14972 buffer_free(s->auth_ldap_filter);
14973 buffer_free(s->auth_ldap_cafile);
14977 buffer_free(s->ldap_filter_pre);
14978 buffer_free(s->ldap_filter_post);
14981 if (s->ldap) ldap_unbind_s(s->ldap);
14987 free(p->config_storage);
14994 return HANDLER_GO_ON;
14997 -#define PATCH(x) \
14998 - p->conf.x = s->x;
14999 static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
15001 mod_auth_plugin_config *s = p->config_storage[0];
15003 - PATCH(auth_backend);
15004 - PATCH(auth_plain_groupfile);
15005 - PATCH(auth_plain_userfile);
15006 - PATCH(auth_htdigest_userfile);
15007 - PATCH(auth_htpasswd_userfile);
15008 - PATCH(auth_require);
15009 - PATCH(auth_debug);
15010 - PATCH(auth_ldap_hostname);
15011 - PATCH(auth_ldap_basedn);
15012 - PATCH(auth_ldap_binddn);
15013 - PATCH(auth_ldap_bindpw);
15014 - PATCH(auth_ldap_filter);
15015 - PATCH(auth_ldap_cafile);
15016 - PATCH(auth_ldap_starttls);
15017 + PATCH_OPTION(auth_backend);
15018 + PATCH_OPTION(auth_plain_groupfile);
15019 + PATCH_OPTION(auth_plain_userfile);
15020 + PATCH_OPTION(auth_htdigest_userfile);
15021 + PATCH_OPTION(auth_htpasswd_userfile);
15022 + PATCH_OPTION(auth_require);
15023 + PATCH_OPTION(auth_debug);
15024 + PATCH_OPTION(auth_ldap_hostname);
15025 + PATCH_OPTION(auth_ldap_basedn);
15026 + PATCH_OPTION(auth_ldap_binddn);
15027 + PATCH_OPTION(auth_ldap_bindpw);
15028 + PATCH_OPTION(auth_ldap_filter);
15029 + PATCH_OPTION(auth_ldap_cafile);
15030 + PATCH_OPTION(auth_ldap_starttls);
15033 - PATCH(ldap_filter_pre);
15034 - PATCH(ldap_filter_post);
15035 + PATCH_OPTION(ldap);
15036 + PATCH_OPTION(ldap_filter_pre);
15037 + PATCH_OPTION(ldap_filter_post);
15041 /* skip the first, the global context */
15042 for (i = 1; i < srv->config_context->used; i++) {
15043 data_config *dc = (data_config *)srv->config_context->data[i];
15044 s = p->config_storage[i];
15047 /* condition didn't match */
15048 if (!config_check_cond(srv, con, dc)) continue;
15052 for (j = 0; j < dc->value->used; j++) {
15053 data_unset *du = dc->value->data[j];
15056 if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
15057 - PATCH(auth_backend);
15058 + PATCH_OPTION(auth_backend);
15059 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
15060 - PATCH(auth_plain_groupfile);
15061 + PATCH_OPTION(auth_plain_groupfile);
15062 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
15063 - PATCH(auth_plain_userfile);
15064 + PATCH_OPTION(auth_plain_userfile);
15065 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
15066 - PATCH(auth_htdigest_userfile);
15067 + PATCH_OPTION(auth_htdigest_userfile);
15068 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
15069 - PATCH(auth_htpasswd_userfile);
15070 + PATCH_OPTION(auth_htpasswd_userfile);
15071 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
15072 - PATCH(auth_require);
15073 + PATCH_OPTION(auth_require);
15074 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
15075 - PATCH(auth_debug);
15076 + PATCH_OPTION(auth_debug);
15077 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
15078 - PATCH(auth_ldap_hostname);
15079 + PATCH_OPTION(auth_ldap_hostname);
15082 - PATCH(ldap_filter_pre);
15083 - PATCH(ldap_filter_post);
15084 + PATCH_OPTION(ldap);
15085 + PATCH_OPTION(ldap_filter_pre);
15086 + PATCH_OPTION(ldap_filter_post);
15088 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
15089 - PATCH(auth_ldap_basedn);
15090 + PATCH_OPTION(auth_ldap_basedn);
15091 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
15092 - PATCH(auth_ldap_filter);
15093 + PATCH_OPTION(auth_ldap_filter);
15094 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
15095 - PATCH(auth_ldap_cafile);
15096 + PATCH_OPTION(auth_ldap_cafile);
15097 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
15098 - PATCH(auth_ldap_starttls);
15099 + PATCH_OPTION(auth_ldap_starttls);
15109 static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
15111 @@ -175,22 +174,22 @@
15113 mod_auth_plugin_data *p = p_d;
15117 /* select the right config */
15118 mod_auth_patch_connection(srv, con, p);
15121 if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
15131 /* do we have to ask for auth ? */
15135 auth_satisfied = 0;
15138 /* search auth-directives for path */
15139 for (k = 0; k < p->conf.auth_require->used; k++) {
15140 buffer *req = p->conf.auth_require->data[k]->key;
15141 @@ -212,31 +211,31 @@
15147 /* nothing to do for us */
15148 if (auth_required == 0) return HANDLER_GO_ON;
15151 req = ((data_array *)(p->conf.auth_require->data[k]))->value;
15154 /* try to get Authorization-header */
15157 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
15158 http_authorization = ds->value->ptr;
15162 if (ds && ds->value && ds->value->used) {
15164 data_string *method;
15167 method = (data_string *)array_get_element(req, "method");
15170 /* parse auth-header */
15171 if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
15172 int auth_type_len = auth_realm - http_authorization;
15175 if ((auth_type_len == 5) &&
15176 (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
15179 if (0 == strcmp(method->value->ptr, "basic")) {
15180 auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
15182 @@ -245,43 +244,43 @@
15183 if (0 == strcmp(method->value->ptr, "digest")) {
15184 if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
15185 con->http_status = 400;
15188 /* a field was missing */
15191 return HANDLER_FINISHED;
15195 - log_error_write(srv, __FILE__, __LINE__, "ss",
15196 + log_error_write(srv, __FILE__, __LINE__, "ss",
15197 "unknown authentification type:",
15198 http_authorization);
15204 if (!auth_satisfied) {
15205 data_string *method, *realm;
15206 method = (data_string *)array_get_element(req, "method");
15207 realm = (data_string *)array_get_element(req, "realm");
15210 con->http_status = 401;
15213 if (0 == strcmp(method->value->ptr, "basic")) {
15214 buffer_copy_string(p->tmp_buf, "Basic realm=\"");
15215 buffer_append_string_buffer(p->tmp_buf, realm->value);
15216 buffer_append_string(p->tmp_buf, "\"");
15219 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15220 } else if (0 == strcmp(method->value->ptr, "digest")) {
15222 http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
15225 buffer_copy_string(p->tmp_buf, "Digest realm=\"");
15226 buffer_append_string_buffer(p->tmp_buf, realm->value);
15227 buffer_append_string(p->tmp_buf, "\", nonce=\"");
15228 buffer_append_string(p->tmp_buf, hh);
15229 buffer_append_string(p->tmp_buf, "\", qop=\"auth\"");
15232 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15235 @@ -289,18 +288,18 @@
15236 return HANDLER_FINISHED;
15238 /* the REMOTE_USER header */
15241 buffer_copy_string_buffer(con->authed_user, p->auth_user);
15245 return HANDLER_GO_ON;
15248 SETDEFAULTS_FUNC(mod_auth_set_defaults) {
15249 mod_auth_plugin_data *p = p_d;
15252 - config_values_t cv[] = {
15254 + config_values_t cv[] = {
15255 { "auth.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15256 { "auth.backend.plain.groupfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15257 { "auth.backend.plain.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15258 @@ -317,7 +316,7 @@
15259 { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
15260 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
15264 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15266 for (i = 0; i < srv->config_context->used; i++) {
15267 @@ -325,14 +324,14 @@
15273 s = calloc(1, sizeof(mod_auth_plugin_config));
15274 s->auth_plain_groupfile = buffer_init();
15275 s->auth_plain_userfile = buffer_init();
15276 s->auth_htdigest_userfile = buffer_init();
15277 s->auth_htpasswd_userfile = buffer_init();
15278 s->auth_backend_conf = buffer_init();
15281 s->auth_ldap_hostname = buffer_init();
15282 s->auth_ldap_basedn = buffer_init();
15283 s->auth_ldap_binddn = buffer_init();
15284 @@ -341,15 +340,15 @@
15285 s->auth_ldap_cafile = buffer_init();
15286 s->auth_ldap_starttls = 0;
15290 s->auth_require = array_init();
15294 s->ldap_filter_pre = buffer_init();
15295 s->ldap_filter_post = buffer_init();
15300 cv[0].destination = s->auth_backend_conf;
15301 cv[1].destination = s->auth_plain_groupfile;
15302 cv[2].destination = s->auth_plain_userfile;
15303 @@ -364,14 +363,14 @@
15304 cv[11].destination = s->auth_htdigest_userfile;
15305 cv[12].destination = s->auth_htpasswd_userfile;
15306 cv[13].destination = &(s->auth_debug);
15309 p->config_storage[i] = s;
15310 ca = ((data_config *)srv->config_context->data[i])->value;
15313 if (0 != config_insert_values_global(srv, ca, cv)) {
15314 return HANDLER_ERROR;
15318 if (s->auth_backend_conf->used) {
15319 if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
15320 s->auth_backend = AUTH_BACKEND_HTPASSWD;
15321 @@ -383,31 +382,31 @@
15322 s->auth_backend = AUTH_BACKEND_LDAP;
15324 log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
15327 return HANDLER_ERROR;
15331 /* no auth.require for this section */
15332 if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
15335 if (da->type != TYPE_ARRAY) continue;
15338 for (n = 0; n < da->value->used; n++) {
15340 data_array *da_file = (data_array *)da->value->data[n];
15341 const char *method, *realm, *require;
15344 if (da->value->data[n]->type != TYPE_ARRAY) {
15345 - log_error_write(srv, __FILE__, __LINE__, "ss",
15346 - "auth.require should contain an array as in:",
15347 + log_error_write(srv, __FILE__, __LINE__, "ss",
15348 + "auth.require should contain an array as in:",
15349 "auth.require = ( \"...\" => ( ..., ...) )");
15351 return HANDLER_ERROR;
15355 method = realm = require = NULL;
15358 for (m = 0; m < da_file->value->used; m++) {
15359 if (da_file->value->data[m]->type == TYPE_STRING) {
15360 if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
15361 @@ -417,8 +416,8 @@
15362 } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
15363 require = ((data_string *)(da_file->value->data[m]))->value->ptr;
15365 - log_error_write(srv, __FILE__, __LINE__, "ssbs",
15366 - "the field is unknown in:",
15367 + log_error_write(srv, __FILE__, __LINE__, "ssbs",
15368 + "the field is unknown in:",
15369 "auth.require = ( \"...\" => ( ..., -> \"",
15370 da_file->value->data[m]->key,
15371 "\" <- => \"...\" ) )");
15372 @@ -426,19 +425,19 @@
15373 return HANDLER_ERROR;
15376 - log_error_write(srv, __FILE__, __LINE__, "ssbs",
15377 - "a string was expected for:",
15378 + log_error_write(srv, __FILE__, __LINE__, "ssbs",
15379 + "a string was expected for:",
15380 "auth.require = ( \"...\" => ( ..., -> \"",
15381 da_file->value->data[m]->key,
15382 "\" <- => \"...\" ) )");
15385 return HANDLER_ERROR;
15390 if (method == NULL) {
15391 - log_error_write(srv, __FILE__, __LINE__, "ss",
15392 - "the require field is missing in:",
15393 + log_error_write(srv, __FILE__, __LINE__, "ss",
15394 + "the require field is missing in:",
15395 "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
15396 return HANDLER_ERROR;
15398 @@ -450,60 +449,60 @@
15399 return HANDLER_ERROR;
15404 if (realm == NULL) {
15405 - log_error_write(srv, __FILE__, __LINE__, "ss",
15406 - "the require field is missing in:",
15407 + log_error_write(srv, __FILE__, __LINE__, "ss",
15408 + "the require field is missing in:",
15409 "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
15410 return HANDLER_ERROR;
15414 if (require == NULL) {
15415 - log_error_write(srv, __FILE__, __LINE__, "ss",
15416 - "the require field is missing in:",
15417 + log_error_write(srv, __FILE__, __LINE__, "ss",
15418 + "the require field is missing in:",
15419 "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
15420 return HANDLER_ERROR;
15424 if (method && realm && require) {
15429 a = data_array_init();
15430 buffer_copy_string_buffer(a->key, da_file->key);
15433 ds = data_string_init();
15436 buffer_copy_string(ds->key, "method");
15437 buffer_copy_string(ds->value, method);
15440 array_insert_unique(a->value, (data_unset *)ds);
15443 ds = data_string_init();
15446 buffer_copy_string(ds->key, "realm");
15447 buffer_copy_string(ds->value, realm);
15450 array_insert_unique(a->value, (data_unset *)ds);
15453 ds = data_string_init();
15456 buffer_copy_string(ds->key, "require");
15457 buffer_copy_string(ds->value, require);
15460 array_insert_unique(a->value, (data_unset *)ds);
15463 array_insert_unique(s->auth_require, (data_unset *)a);
15468 switch(s->auth_backend) {
15469 case AUTH_BACKEND_PLAIN:
15470 if (s->auth_plain_userfile->used) {
15473 if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) {
15474 - log_error_write(srv, __FILE__, __LINE__, "sbss",
15475 + log_error_write(srv, __FILE__, __LINE__, "sbss",
15476 "opening auth.backend.plain.userfile:", s->auth_plain_userfile,
15477 "failed:", strerror(errno));
15478 return HANDLER_ERROR;
15479 @@ -516,7 +515,7 @@
15482 if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) {
15483 - log_error_write(srv, __FILE__, __LINE__, "sbss",
15484 + log_error_write(srv, __FILE__, __LINE__, "sbss",
15485 "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile,
15486 "failed:", strerror(errno));
15487 return HANDLER_ERROR;
15488 @@ -529,7 +528,7 @@
15491 if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) {
15492 - log_error_write(srv, __FILE__, __LINE__, "sbss",
15493 + log_error_write(srv, __FILE__, __LINE__, "sbss",
15494 "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile,
15495 "failed:", strerror(errno));
15496 return HANDLER_ERROR;
15497 @@ -554,75 +553,75 @@
15498 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
15503 if (s->auth_ldap_basedn->used == 0) {
15504 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
15507 return HANDLER_ERROR;
15512 if (s->auth_ldap_filter->used) {
15519 if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
15520 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
15523 return HANDLER_ERROR;
15527 buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
15528 buffer_copy_string(s->ldap_filter_post, dollar+1);
15532 if (s->auth_ldap_hostname->used) {
15533 if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
15534 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
15537 return HANDLER_ERROR;
15541 ret = LDAP_VERSION3;
15542 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
15543 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15546 return HANDLER_ERROR;
15549 if (s->auth_ldap_starttls) {
15550 - /* if no CA file is given, it is ok, as we will use encryption
15551 + /* if no CA file is given, it is ok, as we will use encryption
15552 * if the server requires a CAfile it will tell us */
15553 if (!buffer_is_empty(s->auth_ldap_cafile)) {
15554 - if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
15555 + if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
15556 s->auth_ldap_cafile->ptr))) {
15557 - log_error_write(srv, __FILE__, __LINE__, "ss",
15558 + log_error_write(srv, __FILE__, __LINE__, "ss",
15559 "Loading CA certificate failed:", ldap_err2string(ret));
15562 return HANDLER_ERROR;
15567 if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL, NULL))) {
15568 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
15571 return HANDLER_ERROR;
15579 if (s->auth_ldap_binddn->used) {
15580 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
15581 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15584 return HANDLER_ERROR;
15587 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
15588 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15591 return HANDLER_ERROR;
15594 @@ -641,8 +640,8 @@
15595 p->set_defaults = mod_auth_set_defaults;
15596 p->handle_uri_clean = mod_auth_uri_handler;
15597 p->cleanup = mod_auth_free;
15605 --- ../lighttpd-1.4.11/src/mod_cgi.c 2006-02-22 15:15:10.000000000 +0200
15606 +++ lighttpd-1.4.12/src/mod_cgi.c 2006-07-11 22:07:51.000000000 +0300
15608 #include <sys/types.h>
15610 -#include <winsock2.h>
15612 -#include <sys/socket.h>
15613 -#include <sys/wait.h>
15614 -#include <sys/mman.h>
15616 -#include <netinet/in.h>
15618 -#include <arpa/inet.h>
15621 -#include <unistd.h>
15623 #include <stdlib.h>
15624 #include <string.h>
15625 -#include <fdevent.h>
15626 #include <signal.h>
15628 #include <assert.h>
15630 #include "connections.h"
15631 #include "joblist.h"
15632 #include "http_chunk.h"
15633 +#include "fdevent.h"
15635 #include "plugin.h"
15637 +#include "sys-files.h"
15638 +#include "sys-mmap.h"
15639 +#include "sys-socket.h"
15640 +#include "sys-strings.h"
15641 +#include "sys-process.h"
15643 #ifdef HAVE_SYS_FILIO_H
15644 # include <sys/filio.h>
15646 @@ -40,11 +34,12 @@
15660 @@ -58,23 +53,23 @@
15663 buffer_pid_t cgi_pid;
15667 buffer *parse_response;
15670 plugin_config **config_storage;
15672 - plugin_config conf;
15674 + plugin_config conf;
15680 int fde_ndx; /* index into the fd-event buffer */
15683 connection *remote_conn; /* dumb pointer */
15684 plugin_data *plugin_data; /* dumb pointer */
15688 buffer *response_header;
15690 @@ -83,17 +78,17 @@
15691 handler_ctx *hctx = calloc(1, sizeof(*hctx));
15696 hctx->response = buffer_init();
15697 hctx->response_header = buffer_init();
15703 static void cgi_handler_ctx_free(handler_ctx *hctx) {
15704 buffer_free(hctx->response);
15705 buffer_free(hctx->response_header);
15711 @@ -101,14 +96,14 @@
15713 INIT_FUNC(mod_cgi_init) {
15717 p = calloc(1, sizeof(*p));
15722 p->tmp_buf = buffer_init();
15723 p->parse_response = buffer_init();
15729 @@ -116,62 +111,62 @@
15730 FREE_FUNC(mod_cgi_free) {
15731 plugin_data *p = p_d;
15732 buffer_pid_t *r = &(p->cgi_pid);
15738 if (p->config_storage) {
15740 for (i = 0; i < srv->config_context->used; i++) {
15741 plugin_config *s = p->config_storage[i];
15744 array_free(s->cgi);
15749 free(p->config_storage);
15754 if (r->ptr) free(r->ptr);
15757 buffer_free(p->tmp_buf);
15758 buffer_free(p->parse_response);
15764 return HANDLER_GO_ON;
15767 SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
15768 plugin_data *p = p_d;
15771 - config_values_t cv[] = {
15773 + config_values_t cv[] = {
15774 { "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15775 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
15778 if (!p) return HANDLER_ERROR;
15781 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15784 for (i = 0; i < srv->config_context->used; i++) {
15788 s = calloc(1, sizeof(plugin_config));
15792 s->cgi = array_init();
15795 cv[0].destination = s->cgi;
15798 p->config_storage[i] = s;
15801 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
15802 return HANDLER_ERROR;
15807 return HANDLER_GO_ON;
15810 @@ -180,13 +175,13 @@
15813 buffer_pid_t *r = &(p->cgi_pid);
15818 for (i = 0; i < r->used; i++) {
15819 if (r->ptr[i] > m) m = r->ptr[i];
15823 if (r->size == 0) {
15825 r->ptr = malloc(sizeof(*r->ptr) * r->size);
15826 @@ -194,31 +189,31 @@
15828 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
15832 r->ptr[r->used++] = pid;
15838 static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
15840 buffer_pid_t *r = &(p->cgi_pid);
15845 for (i = 0; i < r->used; i++) {
15846 if (r->ptr[i] == pid) break;
15850 if (i != r->used) {
15854 if (i != r->used - 1) {
15855 r->ptr[i] = r->ptr[r->used - 1];
15864 @@ -226,32 +221,32 @@
15873 buffer_copy_string_buffer(p->parse_response, in);
15875 - for (s = p->parse_response->ptr;
15876 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
15878 + for (s = p->parse_response->ptr;
15879 + NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
15880 s = ns + (eol == EOL_RN ? 2 : 1), line++) {
15881 const char *key, *value;
15891 0 == strncmp(s, "HTTP/1.", 7)) {
15892 /* non-parsed header ... we parse them anyway */
15895 if ((s[7] == '1' ||
15899 /* after the space should be a status code for us */
15902 status = strtol(s+9, NULL, 10);
15905 if (con->http_status >= 100 &&
15906 con->http_status < 1000) {
15907 /* we expected 3 digits and didn't got them */
15908 @@ -260,27 +255,27 @@
15915 if (NULL == (value = strchr(s, ':'))) {
15916 /* we expect: "<key>: <value>\r\n" */
15921 key_len = value - key;
15926 while (*value == ' ' || *value == '\t') value++;
15929 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
15930 ds = data_response_init();
15932 buffer_copy_string_len(ds->key, key, key_len);
15933 buffer_copy_string(ds->value, value);
15936 array_insert_unique(con->response.headers, (data_unset *)ds);
15941 if (0 == strncasecmp(key, "Date", key_len)) {
15942 @@ -315,13 +310,13 @@
15948 /* CGI/1.1 rev 03 - 7.2.1.2 */
15949 if ((con->parsed_response & HTTP_LOCATION) &&
15950 !(con->parsed_response & HTTP_STATUS)) {
15951 con->http_status = 302;
15958 @@ -329,10 +324,10 @@
15959 static int cgi_demux_response(server *srv, handler_ctx *hctx) {
15960 plugin_data *p = hctx->plugin_data;
15961 connection *con = hctx->remote_conn;
15968 buffer_prepare_copy(hctx->response, 1024);
15969 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
15970 if (errno == EAGAIN || errno == EINTR) {
15971 @@ -343,125 +338,125 @@
15972 log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
15973 return FDEVENT_HANDLED_ERROR;
15978 /* read finished */
15981 con->file_finished = 1;
15984 /* send final chunk */
15985 http_chunk_append_mem(srv, con, NULL, 0);
15986 joblist_append(srv, con);
15989 return FDEVENT_HANDLED_FINISHED;
15993 hctx->response->ptr[n] = '\0';
15994 hctx->response->used = n+1;
15997 /* split header from body */
16000 if (con->file_started == 0) {
16003 int header_end = 0;
16004 int cp, eol = EOL_UNSET;
16008 buffer_append_string_buffer(hctx->response_header, hctx->response);
16011 /* nph (non-parsed headers) */
16012 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
16015 /* search for the \r\n\r\n or \n\n in the string */
16016 for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
16017 if (*c == ':') in_header = 1;
16018 else if (*c == '\n') {
16019 if (in_header == 0) {
16020 /* got a response without a response header */
16029 if (eol == EOL_UNSET) eol = EOL_N;
16032 if (*(c+1) == '\n') {
16038 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
16039 if (in_header == 0) {
16040 /* got a response without a response header */
16049 if (eol == EOL_UNSET) eol = EOL_RN;
16053 - *(c+2) == '\r' &&
16054 + *(c+2) == '\r' &&
16071 /* no header, but a body */
16074 if (con->request.http_version == HTTP_VERSION_1_1) {
16075 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
16079 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16080 joblist_append(srv, con);
16082 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
16083 size_t blen = hctx->response_header->used - hlen - 1;
16086 /* a small hack: terminate after at the second \r */
16087 hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
16088 hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
16091 /* parse the response header */
16092 cgi_response_parse(srv, con, p, hctx->response_header, eol);
16095 /* enable chunked-transfer-encoding */
16096 if (con->request.http_version == HTTP_VERSION_1_1 &&
16097 !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
16098 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
16102 if ((hctx->response->used != hlen) && blen > 0) {
16103 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
16104 joblist_append(srv, con);
16109 con->file_started = 1;
16112 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
16113 joblist_append(srv, con);
16119 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
16124 return FDEVENT_HANDLED_NOT_FINISHED;
16127 @@ -470,45 +465,46 @@
16133 if (NULL == hctx) return HANDLER_GO_ON;
16136 p = hctx->plugin_data;
16137 con = hctx->remote_conn;
16140 if (con->mode != p->id) return HANDLER_GO_ON;
16146 /* the connection to the browser went away, but we still have a connection
16147 - * to the CGI script
16148 + * to the CGI script
16150 * close cgi-connection
16154 if (hctx->fd != -1) {
16155 /* close connection to the cgi-script */
16156 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16157 fdevent_unregister(srv->ev, hctx->fd);
16160 if (close(hctx->fd)) {
16161 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16166 hctx->fde_ndx = -1;
16173 con->plugin_ctx[p->id] = NULL;
16176 /* is this a good idea ? */
16177 cgi_handler_ctx_free(hctx);
16180 /* if waitpid hasn't been called by response.c yet, do it here */
16182 /* check if the CGI-script is already gone */
16184 switch(waitpid(pid, &status, WNOHANG)) {
16186 /* not finished yet */
16187 @@ -519,19 +515,19 @@
16190 if (errno == EINTR) break;
16193 - * errno == ECHILD happens if _subrequest catches the process-status before
16196 + * errno == ECHILD happens if _subrequest catches the process-status before
16197 * we have read the response of the cgi process
16201 * -> WAIT_FOR_EVENT
16203 * -> we get here with waitpid == ECHILD
16207 if (errno == ECHILD) return HANDLER_GO_ON;
16210 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16211 return HANDLER_ERROR;
16213 @@ -541,13 +537,13 @@
16214 con->http_status = 500;
16215 con->mode = DIRECT;
16219 if (WIFEXITED(status)) {
16221 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
16226 return HANDLER_GO_ON;
16228 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
16229 @@ -555,20 +551,20 @@
16230 return HANDLER_GO_ON;
16237 kill(pid, SIGTERM);
16240 /* cgi-script is still alive, queue the PID for removal */
16241 cgi_pid_add(srv, p, pid);
16245 return HANDLER_GO_ON;
16248 static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
16249 plugin_data *p = p_d;
16252 return cgi_connection_close(srv, con->plugin_ctx[p->id]);
16255 @@ -577,43 +573,43 @@
16256 server *srv = (server *)s;
16257 handler_ctx *hctx = ctx;
16258 connection *con = hctx->remote_conn;
16261 joblist_append(srv, con);
16264 if (hctx->fd == -1) {
16265 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
16268 return HANDLER_ERROR;
16272 if (revents & FDEVENT_IN) {
16273 switch (cgi_demux_response(srv, hctx)) {
16274 case FDEVENT_HANDLED_NOT_FINISHED:
16276 case FDEVENT_HANDLED_FINISHED:
16281 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
16283 cgi_connection_close(srv, hctx);
16285 - /* if we get a IN|HUP and have read everything don't exec the close twice */
16287 + /* if we get a IN|HUP and have read everything don't exec the close twice */
16288 return HANDLER_FINISHED;
16289 case FDEVENT_HANDLED_ERROR:
16290 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
16291 con->http_status = 500;
16292 con->mode = DIRECT;
16295 log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
16301 if (revents & FDEVENT_OUT) {
16302 /* nothing to do */
16306 /* perhaps this issue is already handled */
16307 if (revents & FDEVENT_HUP) {
16308 /* check if we still have a unfinished header package which is a body in reality */
16309 @@ -623,54 +619,54 @@
16310 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16311 joblist_append(srv, con);
16315 if (con->file_finished == 0) {
16316 http_chunk_append_mem(srv, con, NULL, 0);
16317 joblist_append(srv, con);
16321 con->file_finished = 1;
16324 if (chunkqueue_is_empty(con->write_queue)) {
16325 /* there is nothing left to write */
16326 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
16328 /* used the write-handler to finish the request on demand */
16335 log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
16339 /* rtsigs didn't liked the close */
16340 cgi_connection_close(srv, hctx);
16341 } else if (revents & FDEVENT_ERR) {
16342 con->file_finished = 1;
16345 /* kill all connections to the cgi process */
16346 cgi_connection_close(srv, hctx);
16348 log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
16351 return HANDLER_ERROR;
16355 return HANDLER_FINISHED;
16359 static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
16363 if (!key || !val) return -1;
16366 dst = malloc(key_len + val_len + 3);
16367 memcpy(dst, key, key_len);
16368 dst[key_len] = '=';
16369 /* add the \0 from the value */
16370 memcpy(dst + key_len + 1, val, val_len + 1);
16373 if (env->size == 0) {
16375 env->ptr = malloc(env->size * sizeof(*env->ptr));
16376 @@ -678,45 +674,45 @@
16378 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
16382 env->ptr[env->used++] = dst;
16388 static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
16393 char b2[INET6_ADDRSTRLEN + 1];
16398 int from_cgi_fds[2];
16406 if (cgi_handler->used > 1) {
16407 /* stat the exec file */
16408 if (-1 == (stat(cgi_handler->ptr, &st))) {
16409 - log_error_write(srv, __FILE__, __LINE__, "sbss",
16410 + log_error_write(srv, __FILE__, __LINE__, "sbss",
16411 "stat for cgi-handler", cgi_handler,
16412 "failed:", strerror(errno));
16418 if (pipe(to_cgi_fds)) {
16419 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16424 if (pipe(from_cgi_fds)) {
16425 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16431 switch (pid = fork()) {
16433 @@ -730,22 +726,22 @@
16436 server_socket *srv_sock = con->srv_socket;
16439 /* move stdout to from_cgi_fd[1] */
16440 close(STDOUT_FILENO);
16441 dup2(from_cgi_fds[1], STDOUT_FILENO);
16442 close(from_cgi_fds[1]);
16444 close(from_cgi_fds[0]);
16447 /* move the stdin to to_cgi_fd[0] */
16448 close(STDIN_FILENO);
16449 dup2(to_cgi_fds[0], STDIN_FILENO);
16450 close(to_cgi_fds[0]);
16452 close(to_cgi_fds[1]);
16457 * this is not nice, but it works
16459 * we feed the stderr of the CGI to our errorlog, if possible
16460 @@ -754,20 +750,20 @@
16461 close(STDERR_FILENO);
16462 dup2(srv->errorlog_fd, STDERR_FILENO);
16466 /* create environment */
16472 cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
16474 if (!buffer_is_empty(con->server_name)) {
16475 cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
16478 - s = inet_ntop(srv_sock->addr.plain.sa_family,
16479 - srv_sock->addr.plain.sa_family == AF_INET6 ?
16480 + s = inet_ntop(srv_sock->addr.plain.sa_family,
16481 + srv_sock->addr.plain.sa_family == AF_INET6 ?
16482 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16483 (const void *) &(srv_sock->addr.ipv4.sin_addr),
16485 @@ -779,10 +775,10 @@
16486 cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
16488 s = get_http_version_name(con->request.http_version);
16491 cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
16497 ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
16499 @@ -790,10 +786,10 @@
16502 cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
16506 - s = inet_ntop(srv_sock->addr.plain.sa_family,
16507 - srv_sock->addr.plain.sa_family == AF_INET6 ?
16508 + s = inet_ntop(srv_sock->addr.plain.sa_family,
16509 + srv_sock->addr.plain.sa_family == AF_INET6 ?
16510 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16511 (const void *) &(srv_sock->addr.ipv4.sin_addr),
16513 @@ -811,15 +807,18 @@
16514 cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
16515 if (!buffer_is_empty(con->uri.query)) {
16516 cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
16518 + /* set a empty QUERY_STRING */
16519 + cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
16521 if (!buffer_is_empty(con->request.orig_uri)) {
16522 cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
16529 - s = inet_ntop(con->dst_addr.plain.sa_family,
16530 - con->dst_addr.plain.sa_family == AF_INET6 ?
16531 + s = inet_ntop(con->dst_addr.plain.sa_family,
16532 + con->dst_addr.plain.sa_family == AF_INET6 ?
16533 (const void *) &(con->dst_addr.ipv6.sin6_addr) :
16534 (const void *) &(con->dst_addr.ipv4.sin_addr),
16536 @@ -828,7 +827,7 @@
16538 cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
16543 ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
16545 @@ -836,19 +835,19 @@
16548 cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
16551 if (!buffer_is_empty(con->authed_user)) {
16552 cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
16553 CONST_BUF_LEN(con->authed_user));
16557 /* request.content_length < SSIZE_MAX, see request.c */
16558 ltostr(buf, con->request.content_length);
16559 cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
16560 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
16561 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
16562 cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
16566 if (NULL != (s = getenv("LD_PRELOAD"))) {
16567 cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
16568 @@ -863,24 +862,24 @@
16569 cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
16574 for (n = 0; n < con->request.headers->used; n++) {
16578 ds = (data_string *)con->request.headers->data[n];
16581 if (ds->value->used && ds->key->used) {
16585 buffer_reset(p->tmp_buf);
16588 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
16589 buffer_copy_string(p->tmp_buf, "HTTP_");
16590 p->tmp_buf->used--; /* strip \0 after HTTP_ */
16594 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16597 for (j = 0; j < ds->key->used - 1; j++) {
16599 if (light_isalpha(ds->key->ptr[j])) {
16600 @@ -893,46 +892,46 @@
16601 p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
16603 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16606 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16611 for (n = 0; n < con->environment->used; n++) {
16615 ds = (data_string *)con->environment->data[n];
16618 if (ds->value->used && ds->key->used) {
16622 buffer_reset(p->tmp_buf);
16625 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16628 for (j = 0; j < ds->key->used - 1; j++) {
16629 - p->tmp_buf->ptr[p->tmp_buf->used++] =
16630 - isalpha((unsigned char)ds->key->ptr[j]) ?
16631 + p->tmp_buf->ptr[p->tmp_buf->used++] =
16632 + isalpha((unsigned char)ds->key->ptr[j]) ?
16633 toupper((unsigned char)ds->key->ptr[j]) : '_';
16635 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16638 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16643 if (env.size == env.used) {
16645 env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
16649 env.ptr[env.used] = NULL;
16654 args = malloc(sizeof(*args) * argc);
16658 if (cgi_handler->used > 1) {
16659 args[i++] = cgi_handler->ptr;
16661 @@ -942,7 +941,7 @@
16662 /* search for the last / */
16663 if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
16667 /* change to the physical directory */
16668 if (-1 == chdir(con->physical.path->ptr)) {
16669 log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
16670 @@ -954,12 +953,12 @@
16671 for (i = 3; i < 256; i++) {
16672 if (i != srv->errorlog_fd) close(i);
16677 execve(args[0], args, env.ptr);
16680 log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
16686 @@ -974,11 +973,11 @@
16688 close(from_cgi_fds[1]);
16689 close(to_cgi_fds[0]);
16692 if (con->request.content_length) {
16693 chunkqueue *cq = con->request_content_queue;
16697 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
16699 /* there is content to send */
16700 @@ -993,16 +992,16 @@
16701 if (-1 == c->file.fd && /* open the file if not already open */
16702 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
16703 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
16706 close(from_cgi_fds[0]);
16707 close(to_cgi_fds[1]);
16711 c->file.mmap.length = c->file.length;
16714 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
16715 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
16716 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
16717 strerror(errno), c->file.name, c->file.fd);
16719 close(from_cgi_fds[0]);
16720 @@ -1012,7 +1011,7 @@
16726 /* chunk_reset() or chunk_free() will cleanup for us */
16729 @@ -1020,7 +1019,7 @@
16732 con->http_status = 507;
16737 con->http_status = 403;
16738 @@ -1033,7 +1032,7 @@
16741 con->http_status = 507;
16746 con->http_status = 403;
16747 @@ -1056,103 +1055,100 @@
16750 close(to_cgi_fds[1]);
16753 /* register PID and wait for them asyncronously */
16755 buffer_reset(con->physical.path);
16758 hctx = cgi_handler_ctx_init();
16761 hctx->remote_conn = con;
16762 hctx->plugin_data = p;
16764 hctx->fd = from_cgi_fds[0];
16765 hctx->fde_ndx = -1;
16768 con->plugin_ctx[p->id] = hctx;
16771 fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
16772 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
16775 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
16776 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
16779 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16780 fdevent_unregister(srv->ev, hctx->fd);
16783 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
16789 cgi_handler_ctx_free(hctx);
16792 con->plugin_ctx[p->id] = NULL;
16810 -#define PATCH(x) \
16811 - p->conf.x = s->x;
16812 static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
16814 plugin_config *s = p->config_storage[0];
16819 + PATCH_OPTION(cgi);
16821 /* skip the first, the global context */
16822 for (i = 1; i < srv->config_context->used; i++) {
16823 data_config *dc = (data_config *)srv->config_context->data[i];
16824 s = p->config_storage[i];
16827 /* condition didn't match */
16828 if (!config_check_cond(srv, con, dc)) continue;
16832 for (j = 0; j < dc->value->used; j++) {
16833 data_unset *du = dc->value->data[j];
16836 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
16838 + PATCH_OPTION(cgi);
16848 URIHANDLER_FUNC(cgi_is_handled) {
16850 plugin_data *p = p_d;
16851 buffer *fn = con->physical.path;
16854 if (fn->used == 0) return HANDLER_GO_ON;
16857 mod_cgi_patch_connection(srv, con, p);
16860 s_len = fn->used - 1;
16863 for (k = 0; k < p->conf.cgi->used; k++) {
16864 data_string *ds = (data_string *)p->conf.cgi->data[k];
16865 size_t ct_len = ds->key->used - 1;
16868 if (ds->key->used == 0) continue;
16869 if (s_len < ct_len) continue;
16872 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
16873 if (cgi_create_env(srv, con, p, ds->value)) {
16874 con->http_status = 500;
16877 buffer_reset(con->physical.path);
16878 return HANDLER_FINISHED;
16880 @@ -1160,7 +1156,7 @@
16886 return HANDLER_GO_ON;
16889 @@ -1168,11 +1164,11 @@
16890 plugin_data *p = p_d;
16892 /* the trigger handle only cares about lonely PID which we have to wait for */
16896 for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
16900 switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
16902 /* not finished yet */
16903 @@ -1182,7 +1178,7 @@
16906 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16909 return HANDLER_ERROR;
16912 @@ -1193,16 +1189,16 @@
16914 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
16918 cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
16919 - /* del modified the buffer structure
16920 + /* del modified the buffer structure
16921 * and copies the last entry to the current one
16922 * -> recheck the current index
16929 return HANDLER_GO_ON;
16932 @@ -1210,15 +1206,15 @@
16934 plugin_data *p = p_d;
16935 handler_ctx *hctx = con->plugin_ctx[p->id];
16938 if (con->mode != p->id) return HANDLER_GO_ON;
16939 if (NULL == hctx) return HANDLER_GO_ON;
16943 log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
16946 if (hctx->pid == 0) return HANDLER_FINISHED;
16949 switch(waitpid(hctx->pid, &status, WNOHANG)) {
16951 /* we only have for events here if we don't have the header yet,
16952 @@ -1228,61 +1224,61 @@
16953 return HANDLER_WAIT_FOR_EVENT;
16955 if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
16958 if (errno == ECHILD && con->file_started == 0) {
16960 - * second round but still not response
16961 + * second round but still not response
16963 - return HANDLER_WAIT_FOR_EVENT;
16964 + return HANDLER_WAIT_FOR_EVENT;
16968 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16969 con->mode = DIRECT;
16970 con->http_status = 500;
16976 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16977 fdevent_unregister(srv->ev, hctx->fd);
16980 if (close(hctx->fd)) {
16981 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16985 cgi_handler_ctx_free(hctx);
16988 con->plugin_ctx[p->id] = NULL;
16991 return HANDLER_FINISHED;
16993 - /* cgi process exited cleanly
16995 - * check if we already got the response
16996 + /* cgi process exited cleanly
16998 + * check if we already got the response
17002 if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
17005 if (WIFEXITED(status)) {
17008 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
17011 con->mode = DIRECT;
17012 con->http_status = 500;
17021 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
17022 fdevent_unregister(srv->ev, hctx->fd);
17025 if (close(hctx->fd)) {
17026 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
17030 cgi_handler_ctx_free(hctx);
17033 con->plugin_ctx[p->id] = NULL;
17034 return HANDLER_FINISHED;
17036 @@ -1306,8 +1302,8 @@
17037 p->init = mod_cgi_init;
17038 p->cleanup = mod_cgi_free;
17039 p->set_defaults = mod_fastcgi_set_defaults;
17047 --- ../lighttpd-1.4.11/src/mod_cml.c 2006-01-30 13:51:48.000000000 +0200
17048 +++ lighttpd-1.4.12/src/mod_cml.c 2006-07-11 22:07:51.000000000 +0300
17050 #include <stdlib.h>
17051 #include <string.h>
17053 -#include <unistd.h>
17056 #include "buffer.h"
17057 @@ -20,50 +19,50 @@
17058 /* init the plugin data */
17059 INIT_FUNC(mod_cml_init) {
17063 p = calloc(1, sizeof(*p));
17066 p->basedir = buffer_init();
17067 p->baseurl = buffer_init();
17068 p->trigger_handler = buffer_init();
17074 /* detroy the plugin data */
17075 FREE_FUNC(mod_cml_free) {
17076 plugin_data *p = p_d;
17081 if (!p) return HANDLER_GO_ON;
17084 if (p->config_storage) {
17086 for (i = 0; i < srv->config_context->used; i++) {
17087 plugin_config *s = p->config_storage[i];
17090 buffer_free(s->ext);
17093 buffer_free(s->mc_namespace);
17094 buffer_free(s->power_magnet);
17095 array_free(s->mc_hosts);
17098 #if defined(HAVE_MEMCACHE_H)
17099 if (s->mc) mc_free(s->mc);
17105 free(p->config_storage);
17109 buffer_free(p->trigger_handler);
17110 buffer_free(p->basedir);
17111 buffer_free(p->baseurl);
17117 return HANDLER_GO_ON;
17120 @@ -72,22 +71,22 @@
17121 SETDEFAULTS_FUNC(mod_cml_set_defaults) {
17122 plugin_data *p = p_d;
17125 - config_values_t cv[] = {
17127 + config_values_t cv[] = {
17128 { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
17129 { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
17130 { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
17131 { "cml.power-magnet", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
17132 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
17136 if (!p) return HANDLER_ERROR;
17139 p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
17142 for (i = 0; i < srv->config_context->used; i++) {
17146 s = malloc(sizeof(plugin_config));
17147 s->ext = buffer_init();
17148 s->mc_hosts = array_init();
17149 @@ -96,87 +95,84 @@
17150 #if defined(HAVE_MEMCACHE_H)
17155 cv[0].destination = s->ext;
17156 cv[1].destination = s->mc_hosts;
17157 cv[2].destination = s->mc_namespace;
17158 cv[3].destination = s->power_magnet;
17161 p->config_storage[i] = s;
17164 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
17165 return HANDLER_ERROR;
17169 if (s->mc_hosts->used) {
17170 #if defined(HAVE_MEMCACHE_H)
17175 for (k = 0; k < s->mc_hosts->used; k++) {
17176 data_string *ds = (data_string *)s->mc_hosts->data[k];
17179 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
17180 - log_error_write(srv, __FILE__, __LINE__, "sb",
17181 - "connection to host failed:",
17182 + log_error_write(srv, __FILE__, __LINE__, "sb",
17183 + "connection to host failed:",
17187 return HANDLER_ERROR;
17191 - log_error_write(srv, __FILE__, __LINE__, "s",
17192 + log_error_write(srv, __FILE__, __LINE__, "s",
17193 "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
17194 return HANDLER_ERROR;
17200 return HANDLER_GO_ON;
17203 -#define PATCH(x) \
17204 - p->conf.x = s->x;
17205 static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
17207 plugin_config *s = p->config_storage[0];
17211 + PATCH_OPTION(ext);
17212 #if defined(HAVE_MEMCACHE_H)
17214 + PATCH_OPTION(mc);
17216 - PATCH(mc_namespace);
17217 - PATCH(power_magnet);
17219 + PATCH_OPTION(mc_namespace);
17220 + PATCH_OPTION(power_magnet);
17222 /* skip the first, the global context */
17223 for (i = 1; i < srv->config_context->used; i++) {
17224 data_config *dc = (data_config *)srv->config_context->data[i];
17225 s = p->config_storage[i];
17228 /* condition didn't match */
17229 if (!config_check_cond(srv, con, dc)) continue;
17233 for (j = 0; j < dc->value->used; j++) {
17234 data_unset *du = dc->value->data[j];
17237 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
17239 + PATCH_OPTION(ext);
17240 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
17241 #if defined(HAVE_MEMCACHE_H)
17243 + PATCH_OPTION(mc);
17245 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
17246 - PATCH(mc_namespace);
17247 + PATCH_OPTION(mc_namespace);
17248 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
17249 - PATCH(power_magnet);
17250 + PATCH_OPTION(power_magnet);
17260 int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
17262 @@ -187,57 +183,57 @@
17264 buffer_copy_string_buffer(b, con->uri.path);
17265 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17269 b->used = c - b->ptr + 2;
17275 buffer_copy_string_buffer(b, con->physical.path);
17276 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17280 b->used = c - b->ptr + 2;
17286 /* prepare variables
17288 * - get-param-based
17292 return cache_parse_lua(srv, con, p, cml_file);
17297 URIHANDLER_FUNC(mod_cml_power_magnet) {
17298 plugin_data *p = p_d;
17301 mod_cml_patch_connection(srv, con, p);
17304 buffer_reset(p->basedir);
17305 buffer_reset(p->baseurl);
17306 buffer_reset(p->trigger_handler);
17308 if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
17314 * cml.power-magnet = server.docroot + "/rewrite.cml"
17316 * is called on EACH request, take the original REQUEST_URI and modifies the
17317 - * request header as neccesary.
17318 + * request header as neccesary.
17321 * if file_exists("/maintainance.html") {
17322 * output_include = ( "/maintainance.html" )
17323 - * return CACHE_HIT
17324 + * return CACHE_HIT
17327 * as we only want to rewrite HTML like requests we should cover it in a conditional
17332 switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
17333 @@ -266,20 +262,20 @@
17335 URIHANDLER_FUNC(mod_cml_is_handled) {
17336 plugin_data *p = p_d;
17339 if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
17342 mod_cml_patch_connection(srv, con, p);
17345 buffer_reset(p->basedir);
17346 buffer_reset(p->baseurl);
17347 buffer_reset(p->trigger_handler);
17349 if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
17352 if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
17353 return HANDLER_GO_ON;
17357 switch(cache_call_lua(srv, con, p, con->physical.path)) {
17359 @@ -311,15 +307,15 @@
17360 int mod_cml_plugin_init(plugin *p) {
17361 p->version = LIGHTTPD_VERSION_ID;
17362 p->name = buffer_init_string("cache");
17365 p->init = mod_cml_init;
17366 p->cleanup = mod_cml_free;
17367 p->set_defaults = mod_cml_set_defaults;
17370 p->handle_subrequest_start = mod_cml_is_handled;
17371 p->handle_physical = mod_cml_power_magnet;
17379 --- ../lighttpd-1.4.11/src/mod_cml.h 2006-01-30 13:51:35.000000000 +0200
17380 +++ lighttpd-1.4.12/src/mod_cml.h 2006-07-11 22:07:51.000000000 +0300
17381 @@ -16,10 +16,10 @@
17388 buffer *mc_namespace;
17389 -#if defined(HAVE_MEMCACHE_H)
17390 +#if defined(HAVE_MEMCACHE_H)
17391 struct memcache *mc;
17393 buffer *power_magnet;
17394 @@ -27,15 +27,15 @@
17404 buffer *trigger_handler;
17407 plugin_config **config_storage;
17409 - plugin_config conf;
17411 + plugin_config conf;
17414 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
17415 --- ../lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200
17416 +++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-11 22:07:52.000000000 +0300
17418 #include <stdlib.h>
17419 #include <string.h>
17421 -#include <unistd.h>
17422 -#include <dirent.h>
17426 #include "buffer.h"
17429 #include "plugin.h"
17430 #include "response.h"
17431 +#include "sys-files.h"
17433 #include "mod_cml.h"
17434 #include "mod_cml_funcs.h"
17444 @@ -42,29 +42,29 @@
17447 int n = lua_gettop(L);
17452 b.size = sizeof(hex);
17456 lua_pushstring(L, "md5: expected one argument");
17461 if (!lua_isstring(L, 1)) {
17462 lua_pushstring(L, "md5: argument has to be a string");
17468 MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
17469 MD5_Final(HA1, &Md5Ctx);
17472 buffer_copy_string_hex(&b, (char *)HA1, 16);
17475 lua_pushstring(L, b.ptr);
17481 @@ -72,37 +72,37 @@
17482 int f_file_mtime(lua_State *L) {
17484 int n = lua_gettop(L);
17488 lua_pushstring(L, "file_mtime: expected one argument");
17493 if (!lua_isstring(L, 1)) {
17494 lua_pushstring(L, "file_mtime: argument has to be a string");
17499 if (-1 == stat(lua_tostring(L, 1), &st)) {
17505 lua_pushnumber(L, st.st_mtime);
17512 int f_dir_files_iter(lua_State *L) {
17517 d = lua_touserdata(L, lua_upvalueindex(1));
17520 if (NULL == (de = readdir(d))) {
17527 lua_pushstring(L, de->d_name);
17528 @@ -113,75 +113,75 @@
17529 int f_dir_files(lua_State *L) {
17531 int n = lua_gettop(L);
17535 lua_pushstring(L, "dir_files: expected one argument");
17540 if (!lua_isstring(L, 1)) {
17541 lua_pushstring(L, "dir_files: argument has to be a string");
17545 - /* check if there is a valid DIR handle on the stack */
17547 + /* check if there is a valid DIR handle on the stack */
17548 if (NULL == (d = opendir(lua_tostring(L, 1)))) {
17554 /* push d into registry */
17555 lua_pushlightuserdata(L, d);
17556 lua_pushcclosure(L, f_dir_files_iter, 1);
17563 int f_file_isreg(lua_State *L) {
17565 int n = lua_gettop(L);
17569 lua_pushstring(L, "file_isreg: expected one argument");
17574 if (!lua_isstring(L, 1)) {
17575 lua_pushstring(L, "file_isreg: argument has to be a string");
17580 if (-1 == stat(lua_tostring(L, 1), &st)) {
17586 lua_pushnumber(L, S_ISREG(st.st_mode));
17592 int f_file_isdir(lua_State *L) {
17594 int n = lua_gettop(L);
17598 lua_pushstring(L, "file_isreg: expected one argument");
17603 if (!lua_isstring(L, 1)) {
17604 lua_pushstring(L, "file_isreg: argument has to be a string");
17609 if (-1 == stat(lua_tostring(L, 1), &st)) {
17615 lua_pushnumber(L, S_ISDIR(st.st_mode));
17621 @@ -192,33 +192,33 @@
17623 int n = lua_gettop(L);
17624 struct memcache *mc;
17627 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17628 lua_pushstring(L, "where is my userdata ?");
17633 mc = lua_touserdata(L, lua_upvalueindex(1));
17637 lua_pushstring(L, "expected one argument");
17642 if (!lua_isstring(L, 1)) {
17643 lua_pushstring(L, "argument has to be a string");
17647 - if (NULL == (r = mc_aget(mc,
17649 + if (NULL == (r = mc_aget(mc,
17650 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17653 lua_pushboolean(L, 0);
17661 lua_pushboolean(L, 1);
17664 @@ -226,74 +226,74 @@
17665 int f_memcache_get_string(lua_State *L) {
17667 int n = lua_gettop(L);
17670 struct memcache *mc;
17673 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17674 lua_pushstring(L, "where is my userdata ?");
17679 mc = lua_touserdata(L, lua_upvalueindex(1));
17685 lua_pushstring(L, "expected one argument");
17690 if (!lua_isstring(L, 1)) {
17691 lua_pushstring(L, "argument has to be a string");
17695 - if (NULL == (r = mc_aget(mc,
17697 + if (NULL == (r = mc_aget(mc,
17698 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17704 lua_pushstring(L, r);
17713 int f_memcache_get_long(lua_State *L) {
17715 int n = lua_gettop(L);
17718 struct memcache *mc;
17721 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17722 lua_pushstring(L, "where is my userdata ?");
17727 mc = lua_touserdata(L, lua_upvalueindex(1));
17733 lua_pushstring(L, "expected one argument");
17738 if (!lua_isstring(L, 1)) {
17739 lua_pushstring(L, "argument has to be a string");
17743 - if (NULL == (r = mc_aget(mc,
17745 + if (NULL == (r = mc_aget(mc,
17746 lua_tostring(L, 1), lua_strlen(L, 1)))) {
17752 lua_pushnumber(L, strtol(r, NULL, 10));
17761 --- ../lighttpd-1.4.11/src/mod_cml_lua.c 2006-01-30 13:56:40.000000000 +0200
17762 +++ lighttpd-1.4.12/src/mod_cml_lua.c 2006-07-11 22:07:53.000000000 +0300
17775 #include <lualib.h>
17776 +#include <lauxlib.h>
17780 @@ -39,11 +40,11 @@
17782 static const char * load_file(lua_State *L, void *data, size_t *size) {
17789 if (rm->done) return 0;
17792 *size = rm->st.size;
17794 return rm->st.start;
17795 @@ -51,47 +52,47 @@
17797 static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
17801 lua_pushstring(L, varname);
17804 curelem = lua_gettop(L);
17805 lua_gettable(L, LUA_GLOBALSINDEX);
17808 /* it should be a table */
17809 if (!lua_isstring(L, curelem)) {
17810 lua_settop(L, curelem - 1);
17817 buffer_copy_string(b, lua_tostring(L, curelem));
17823 assert(curelem - 1 == lua_gettop(L));
17829 static int lua_to_c_is_table(lua_State *L, const char *varname) {
17833 lua_pushstring(L, varname);
17836 curelem = lua_gettop(L);
17837 lua_gettable(L, LUA_GLOBALSINDEX);
17840 /* it should be a table */
17841 if (!lua_istable(L, curelem)) {
17842 lua_settop(L, curelem - 1);
17849 lua_settop(L, curelem - 1);
17852 assert(curelem - 1 == lua_gettop(L));
17859 lua_pushlstring(L, key, key_len);
17860 lua_pushlstring(L, val, val_len);
17861 lua_settable(L, tbl);
17867 @@ -108,21 +109,21 @@
17870 char *key = NULL, *val = NULL;
17876 /* we need the \0 */
17877 for (i = 0; i < qrystr->used; i++) {
17878 switch(qrystr->ptr[i]) {
17881 val = qrystr->ptr + i + 1;
17884 qrystr->ptr[i] = '\0';
17893 case '\0': /* fin symbol */
17894 @@ -131,19 +132,19 @@
17896 /* terminate the value */
17897 qrystr->ptr[i] = '\0';
17899 - c_to_lua_push(L, tbl,
17901 + c_to_lua_push(L, tbl,
17907 key = qrystr->ptr + i + 1;
17918 @@ -151,21 +152,21 @@
17924 if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
17925 data_string *ds = (data_string *)d;
17926 size_t key = 0, value = 0;
17927 size_t is_key = 1, is_sid = 0;
17932 if (!DATA_IS_STRING(d)) return -1;
17933 if (ds->value->used == 0) return -1;
17936 if (ds->value->ptr[0] == '\0' ||
17937 ds->value->ptr[0] == '=' ||
17938 ds->value->ptr[0] == ';') return -1;
17941 buffer_reset(p->session_id);
17942 for (i = 0; i < ds->value->used; i++) {
17943 switch(ds->value->ptr[i]) {
17944 @@ -176,16 +177,16 @@
17957 buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
17964 @@ -204,48 +205,43 @@
17974 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
17979 buffer *b = buffer_init();
17980 int header_tbl = 0;
17984 stream_open(&rm.st, fn);
17987 /* push the lua file to the interpreter and see what happends */
17991 - luaopen_table(L);
17992 - luaopen_string(L);
17996 + L = luaL_newstate();
17997 + luaL_openlibs(L);
17999 /* register functions */
18000 lua_register(L, "md5", f_crypto_md5);
18001 lua_register(L, "file_mtime", f_file_mtime);
18002 lua_register(L, "file_isreg", f_file_isreg);
18003 lua_register(L, "file_isdir", f_file_isreg);
18004 lua_register(L, "dir_files", f_dir_files);
18007 #ifdef HAVE_MEMCACHE_H
18008 lua_pushliteral(L, "memcache_get_long");
18009 lua_pushlightuserdata(L, p->conf.mc);
18010 lua_pushcclosure(L, f_memcache_get_long, 1);
18011 lua_settable(L, LUA_GLOBALSINDEX);
18014 lua_pushliteral(L, "memcache_get_string");
18015 lua_pushlightuserdata(L, p->conf.mc);
18016 lua_pushcclosure(L, f_memcache_get_string, 1);
18017 lua_settable(L, LUA_GLOBALSINDEX);
18020 lua_pushliteral(L, "memcache_exists");
18021 lua_pushlightuserdata(L, p->conf.mc);
18022 lua_pushcclosure(L, f_memcache_exists, 1);
18023 @@ -255,11 +251,11 @@
18024 lua_pushliteral(L, "request");
18026 lua_settable(L, LUA_GLOBALSINDEX);
18029 lua_pushliteral(L, "request");
18030 header_tbl = lua_gettop(L);
18031 lua_gettable(L, LUA_GLOBALSINDEX);
18034 c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
18035 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
18036 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
18037 @@ -267,84 +263,84 @@
18038 if (!buffer_is_empty(con->request.pathinfo)) {
18039 c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
18043 c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
18044 c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
18047 /* register GET parameter */
18048 lua_pushliteral(L, "get");
18050 lua_settable(L, LUA_GLOBALSINDEX);
18053 lua_pushliteral(L, "get");
18054 header_tbl = lua_gettop(L);
18055 lua_gettable(L, LUA_GLOBALSINDEX);
18058 buffer_copy_string_buffer(b, con->uri.query);
18059 cache_export_get_params(L, header_tbl, b);
18062 - /* 2 default constants */
18063 + /* 2 default constants */
18064 lua_pushliteral(L, "CACHE_HIT");
18065 lua_pushboolean(L, 0);
18066 lua_settable(L, LUA_GLOBALSINDEX);
18069 lua_pushliteral(L, "CACHE_MISS");
18070 lua_pushboolean(L, 1);
18071 lua_settable(L, LUA_GLOBALSINDEX);
18074 /* load lua program */
18075 if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
18076 log_error_write(srv, __FILE__, __LINE__, "s",
18077 lua_tostring(L,-1));
18084 /* get return value */
18085 ret = (int)lua_tonumber(L, -1);
18088 - /* fetch the data from lua */
18090 + /* fetch the data from lua */
18091 lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
18094 if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
18095 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
18100 /* up to now it is a cache-hit, check if all files exist */
18107 if (!lua_to_c_is_table(L, "output_include")) {
18108 log_error_write(srv, __FILE__, __LINE__, "s",
18109 "output_include is missing or not a table");
18117 lua_pushstring(L, "output_include");
18120 curelem = lua_gettop(L);
18121 lua_gettable(L, LUA_GLOBALSINDEX);
18123 /* HOW-TO build a etag ?
18124 - * as we don't just have one file we have to take the stat()
18125 + * as we don't just have one file we have to take the stat()
18126 * from all base files, merge them and build the etag from
18130 * The mtime of the content is the mtime of the freshest base file
18136 lua_pushnil(L); /* first key */
18137 while (lua_next(L, curelem) != 0) {
18138 stat_cache_entry *sce = NULL;
18139 /* key' is at index -2 and value' at index -1 */
18142 if (lua_isstring(L, -1)) {
18143 const char *s = lua_tostring(L, -1);
18145 @@ -364,18 +360,18 @@
18146 /* a file is missing, call the handler to generate it */
18147 if (!buffer_is_empty(p->trigger_handler)) {
18148 ret = 1; /* cache-miss */
18151 log_error_write(srv, __FILE__, __LINE__, "s",
18152 "a file is missing, calling handler");
18157 /* handler not set -> 500 */
18161 log_error_write(srv, __FILE__, __LINE__, "s",
18162 "a file missing and no handler set");
18168 @@ -393,12 +389,12 @@
18174 lua_pop(L, 1); /* removes value'; keeps key' for next iteration */
18178 lua_settop(L, curelem - 1);
18183 char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
18184 @@ -410,9 +406,9 @@
18186 /* no Last-Modified specified */
18187 if ((mtime) && (NULL == ds)) {
18190 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
18193 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
18196 @@ -428,9 +424,9 @@
18202 if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
18203 - /* ok, the client already has our content,
18204 + /* ok, the client already has our content,
18205 * no need to send it again */
18207 chunkqueue_reset(con->write_queue);
18208 @@ -440,24 +436,24 @@
18209 chunkqueue_reset(con->write_queue);
18214 if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
18216 buffer_copy_string_buffer(con->uri.path, p->baseurl);
18217 buffer_append_string_buffer(con->uri.path, p->trigger_handler);
18220 buffer_copy_string_buffer(con->physical.path, p->basedir);
18221 buffer_append_string_buffer(con->physical.path, p->trigger_handler);
18224 chunkqueue_reset(con->write_queue);
18232 stream_close(&rm.st);
18236 return ret /* cache-error */;
18239 --- ../lighttpd-1.4.11/src/mod_compress.c 2005-11-18 13:49:14.000000000 +0200
18240 +++ lighttpd-1.4.12/src/mod_compress.c 2006-07-11 22:07:53.000000000 +0300
18242 #include <sys/stat.h>
18245 -#include <unistd.h>
18247 #include <stdlib.h>
18248 #include <string.h>
18250 #include "buffer.h"
18251 #include "response.h"
18252 #include "stat_cache.h"
18253 +#include "http_chunk.h"
18255 #include "plugin.h"
18260 #include "sys-mmap.h"
18261 +#include "sys-files.h"
18263 /* request: accept-encoding */
18264 #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
18265 @@ -55,97 +56,127 @@
18271 plugin_config **config_storage;
18272 - plugin_config conf;
18273 + plugin_config conf;
18276 INIT_FUNC(mod_compress_init) {
18280 p = calloc(1, sizeof(*p));
18283 p->ofn = buffer_init();
18284 p->b = buffer_init();
18290 FREE_FUNC(mod_compress_free) {
18291 plugin_data *p = p_d;
18296 if (!p) return HANDLER_GO_ON;
18299 buffer_free(p->ofn);
18303 if (p->config_storage) {
18305 for (i = 0; i < srv->config_context->used; i++) {
18306 plugin_config *s = p->config_storage[i];
18311 array_free(s->compress);
18312 buffer_free(s->compress_cache_dir);
18317 free(p->config_storage);
18326 return HANDLER_GO_ON;
18329 +void mkdir_recursive(const char *dir) {
18331 + char dir_copy[256];
18332 + char *p = dir_copy;
18334 + if (!dir || !dir[0])
18337 + strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
18339 + while ((p = strchr(p + 1, '/')) != NULL) {
18342 + if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
18348 + mkdir(dir, 0700);
18351 SETDEFAULTS_FUNC(mod_compress_setdefaults) {
18352 plugin_data *p = p_d;
18355 - config_values_t cv[] = {
18357 + config_values_t cv[] = {
18358 { "compress.cache-dir", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
18359 { "compress.filetype", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
18360 { "compress.max-filesize", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
18361 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
18365 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
18368 for (i = 0; i < srv->config_context->used; i++) {
18372 s = calloc(1, sizeof(plugin_config));
18373 s->compress_cache_dir = buffer_init();
18374 s->compress = array_init();
18375 s->compress_max_filesize = 0;
18378 cv[0].destination = s->compress_cache_dir;
18379 cv[1].destination = s->compress;
18380 cv[2].destination = &(s->compress_max_filesize);
18383 p->config_storage[i] = s;
18386 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18387 return HANDLER_ERROR;
18391 if (!buffer_is_empty(s->compress_cache_dir)) {
18393 if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18394 - log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
18396 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
18397 s->compress_cache_dir, strerror(errno));
18399 - return HANDLER_ERROR;
18400 + mkdir_recursive(s->compress_cache_dir->ptr);
18402 + if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18404 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
18405 + s->compress_cache_dir, strerror(errno));
18407 + return HANDLER_ERROR;
18414 return HANDLER_GO_ON;
18420 @@ -153,32 +184,32 @@
18433 - if (Z_OK != deflateInit2(&z,
18435 + if (Z_OK != deflateInit2(&z,
18436 Z_DEFAULT_COMPRESSION,
18439 -MAX_WBITS, /* supress zlib-header */
18441 Z_DEFAULT_STRATEGY)) {
18446 z.next_in = (unsigned char *)start;
18447 z.avail_in = st_size;
18453 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
18456 /* write gzip header */
18459 c = (unsigned char *)p->b->ptr;
18462 @@ -190,24 +221,24 @@
18463 c[7] = (mtime >> 24) & 0xff;
18464 c[8] = 0x00; /* extra flags */
18465 c[9] = 0x03; /* UNIX */
18469 z.next_out = (unsigned char *)p->b->ptr + p->b->used;
18470 z.avail_out = p->b->size - p->b->used - 8;
18474 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18481 p->b->used += z.total_out;
18484 crc = generate_crc32c(start, st_size);
18487 c = (unsigned char *)p->b->ptr + p->b->used;
18490 c[0] = (crc >> 0) & 0xff;
18491 c[1] = (crc >> 8) & 0xff;
18492 c[2] = (crc >> 16) & 0xff;
18493 @@ -221,51 +252,51 @@
18494 if (Z_OK != deflateEnd(&z)) {
18502 static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18513 - if (Z_OK != deflateInit2(&z,
18515 + if (Z_OK != deflateInit2(&z,
18516 Z_DEFAULT_COMPRESSION,
18519 -MAX_WBITS, /* supress zlib-header */
18521 Z_DEFAULT_STRATEGY)) {
18527 z.avail_in = st_size;
18531 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
18534 z.next_out = (unsigned char *)p->b->ptr;
18535 z.avail_out = p->b->size;
18539 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18546 p->b->used += z.total_out;
18549 if (Z_OK != deflateEnd(&z)) {
18557 @@ -274,48 +305,48 @@
18559 static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18570 - if (BZ_OK != BZ2_bzCompressInit(&bz,
18572 + if (BZ_OK != BZ2_bzCompressInit(&bz,
18573 9, /* blocksize = 900k */
18575 0)) { /* workFactor: default */
18580 bz.next_in = (char *)start;
18581 bz.avail_in = st_size;
18582 bz.total_in_lo32 = 0;
18583 bz.total_in_hi32 = 0;
18586 buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
18589 bz.next_out = p->b->ptr;
18590 bz.avail_out = p->b->size;
18591 bz.total_out_lo32 = 0;
18592 bz.total_out_hi32 = 0;
18595 if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
18596 BZ2_bzCompressEnd(&bz);
18601 /* file is too large for now */
18602 if (bz.total_out_hi32) return -1;
18606 p->b->used = bz.total_out_lo32;
18609 if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
18617 @@ -326,47 +357,50 @@
18619 const char *filename = fn->ptr;
18622 + stat_cache_entry *compressed_sce = NULL;
18624 + if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
18627 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18629 - /* don't mmap files > 128Mb
18632 + /* don't mmap files > 128Mb
18634 * we could use a sliding window, but currently there is no need for it
18638 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18641 buffer_reset(p->ofn);
18642 buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
18643 - BUFFER_APPEND_SLASH(p->ofn);
18645 + PATHNAME_APPEND_SLASH(p->ofn);
18647 if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
18648 size_t offset = p->ofn->used - 1;
18649 char *dir, *nextdir;
18652 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
18655 buffer_copy_string_buffer(p->b, p->ofn);
18659 for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
18663 if (-1 == mkdir(p->b->ptr, 0700)) {
18664 if (errno != EEXIST) {
18665 log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
18676 buffer_append_string_buffer(p->ofn, con->uri.path);
18681 case HTTP_ACCEPT_ENCODING_GZIP:
18682 buffer_append_string(p->ofn, "-gzip-");
18683 @@ -381,55 +415,64 @@
18684 log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type);
18689 buffer_append_string_buffer(p->ofn, sce->etag);
18693 + if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
18694 + /* file exists */
18696 + http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
18697 + con->file_finished = 1;
18702 if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
18703 if (errno == EEXIST) {
18704 /* cache-entry exists */
18706 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
18708 - buffer_copy_string_buffer(con->physical.path, p->ofn);
18714 - log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
18717 + log_error_write(srv, __FILE__, __LINE__, "sbss",
18718 + "creating cachefile", p->ofn,
18719 + "failed", strerror(errno));
18724 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
18727 if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
18728 - log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18730 + log_error_write(srv, __FILE__, __LINE__, "sbss",
18731 + "opening plain-file", fn,
18732 + "failed", strerror(errno));
18743 if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18744 - log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18746 + log_error_write(srv, __FILE__, __LINE__, "sbss",
18748 + "failed", strerror(errno));
18758 - case HTTP_ACCEPT_ENCODING_GZIP:
18759 + case HTTP_ACCEPT_ENCODING_GZIP:
18760 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
18762 - case HTTP_ACCEPT_ENCODING_DEFLATE:
18763 + case HTTP_ACCEPT_ENCODING_DEFLATE:
18764 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
18768 - case HTTP_ACCEPT_ENCODING_BZIP2:
18769 + case HTTP_ACCEPT_ENCODING_BZIP2:
18770 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
18773 @@ -437,26 +480,27 @@
18779 if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
18780 - munmap(start, sce->st.st_size);
18781 + munmap(start, sce->st.st_size);
18788 if ((size_t)r != p->b->used) {
18794 munmap(start, sce->st.st_size);
18799 if (ret != 0) return -1;
18801 - buffer_copy_string_buffer(con->physical.path, p->ofn);
18804 + http_chunk_append_file(srv, con, p->ofn, 0, r);
18805 + con->file_finished = 1;
18810 @@ -465,43 +509,44 @@
18817 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18820 /* don't mmap files > 128M
18823 * we could use a sliding window, but currently there is no need for it
18827 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18831 if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
18832 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18839 - if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18841 + start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
18845 + if (MAP_FAILED == start) {
18846 log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18856 - case HTTP_ACCEPT_ENCODING_GZIP:
18857 + case HTTP_ACCEPT_ENCODING_GZIP:
18858 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
18860 - case HTTP_ACCEPT_ENCODING_DEFLATE:
18861 + case HTTP_ACCEPT_ENCODING_DEFLATE:
18862 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
18866 - case HTTP_ACCEPT_ENCODING_BZIP2:
18867 + case HTTP_ACCEPT_ENCODING_BZIP2:
18868 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
18871 @@ -509,69 +554,64 @@
18877 munmap(start, sce->st.st_size);
18881 if (ret != 0) return -1;
18884 chunkqueue_reset(con->write_queue);
18885 b = chunkqueue_get_append_buffer(con->write_queue);
18886 buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
18889 buffer_reset(con->physical.path);
18892 con->file_finished = 1;
18893 con->file_started = 1;
18900 -#define PATCH(x) \
18901 - p->conf.x = s->x;
18902 static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
18904 plugin_config *s = p->config_storage[0];
18906 - PATCH(compress_cache_dir);
18908 - PATCH(compress_max_filesize);
18910 + PATCH_OPTION(compress_cache_dir);
18911 + PATCH_OPTION(compress);
18912 + PATCH_OPTION(compress_max_filesize);
18914 /* skip the first, the global context */
18915 for (i = 1; i < srv->config_context->used; i++) {
18916 data_config *dc = (data_config *)srv->config_context->data[i];
18917 s = p->config_storage[i];
18920 /* condition didn't match */
18921 if (!config_check_cond(srv, con, dc)) continue;
18925 for (j = 0; j < dc->value->used; j++) {
18926 data_unset *du = dc->value->data[j];
18929 if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
18930 - PATCH(compress_cache_dir);
18931 + PATCH_OPTION(compress_cache_dir);
18932 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
18934 + PATCH_OPTION(compress);
18935 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
18936 - PATCH(compress_max_filesize);
18937 + PATCH_OPTION(compress_max_filesize);
18947 PHYSICALPATH_FUNC(mod_compress_physical) {
18948 plugin_data *p = p_d;
18951 stat_cache_entry *sce = NULL;
18954 /* only GET and POST can get compressed */
18955 - if (con->request.http_method != HTTP_METHOD_GET &&
18956 + if (con->request.http_method != HTTP_METHOD_GET &&
18957 con->request.http_method != HTTP_METHOD_POST) {
18958 return HANDLER_GO_ON;
18960 @@ -579,46 +619,49 @@
18961 if (buffer_is_empty(con->physical.path)) {
18962 return HANDLER_GO_ON;
18966 mod_compress_patch_connection(srv, con, p);
18969 max_fsize = p->conf.compress_max_filesize;
18971 stat_cache_get_entry(srv, con, con->physical.path, &sce);
18973 /* don't compress files that are too large as we need to much time to handle them */
18974 if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
18977 + /* compressing the file might lead to larger files instead */
18978 + if (sce->st.st_size < 128) return HANDLER_GO_ON;
18980 /* check if mimetype is in compress-config */
18981 for (m = 0; m < p->conf.compress->used; m++) {
18982 data_string *compress_ds = (data_string *)p->conf.compress->data[m];
18985 if (!compress_ds) {
18986 log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
18989 return HANDLER_GO_ON;
18993 if (buffer_is_equal(compress_ds->value, sce->content_type)) {
18994 /* mimetype found */
18998 /* the response might change according to Accept-Encoding */
18999 response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
19002 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
19003 int accept_encoding = 0;
19004 char *value = ds->value->ptr;
19005 int srv_encodings = 0;
19006 int matched_encodings = 0;
19009 /* get client side support encodings */
19010 if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
19011 if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
19012 if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
19013 if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
19014 if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
19017 /* get server side supported ones */
19019 srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
19020 @@ -627,18 +670,31 @@
19021 srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
19022 srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
19026 /* find matching entries */
19027 matched_encodings = accept_encoding & srv_encodings;
19030 if (matched_encodings) {
19031 const char *dflt_gzip = "gzip";
19032 const char *dflt_deflate = "deflate";
19033 const char *dflt_bzip2 = "bzip2";
19036 const char *compression_name = NULL;
19037 int compression_type = 0;
19041 + mtime = strftime_cache_get(srv, sce->st.st_mtime);
19042 + etag_mutate(con->physical.etag, sce->etag);
19044 + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19045 + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19047 + /* perhaps we don't even have to compress the file as the browser still has the
19048 + * current version */
19049 + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
19050 + return HANDLER_FINISHED;
19053 /* select best matching encoding */
19054 if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
19055 compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
19056 @@ -650,31 +706,21 @@
19057 compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
19058 compression_name = dflt_deflate;
19062 - if (p->conf.compress_cache_dir->used) {
19063 - if (0 == deflate_file_to_file(srv, con, p,
19064 - con->physical.path, sce, compression_type)) {
19067 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
19069 - mtime = strftime_cache_get(srv, sce->st.st_mtime);
19070 - response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19072 - etag_mutate(con->physical.etag, sce->etag);
19073 - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19075 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
19077 - return HANDLER_GO_ON;
19079 - } else if (0 == deflate_file_to_buffer(srv, con, p,
19080 - con->physical.path, sce, compression_type)) {
19082 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
19083 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
19086 + /* deflate it to file (cached) or to memory */
19087 + if (0 == deflate_file_to_file(srv, con, p,
19088 + con->physical.path, sce, compression_type) ||
19089 + 0 == deflate_file_to_buffer(srv, con, p,
19090 + con->physical.path, sce, compression_type)) {
19092 + response_header_overwrite(srv, con,
19093 + CONST_STR_LEN("Content-Encoding"),
19094 + compression_name, strlen(compression_name));
19096 + response_header_overwrite(srv, con,
19097 + CONST_STR_LEN("Content-Type"),
19098 + CONST_BUF_LEN(sce->content_type));
19100 return HANDLER_FINISHED;
19103 @@ -682,20 +728,20 @@
19109 return HANDLER_GO_ON;
19112 int mod_compress_plugin_init(plugin *p) {
19113 p->version = LIGHTTPD_VERSION_ID;
19114 p->name = buffer_init_string("compress");
19117 p->init = mod_compress_init;
19118 p->set_defaults = mod_compress_setdefaults;
19119 p->handle_subrequest_start = mod_compress_physical;
19120 p->cleanup = mod_compress_free;
19128 --- ../lighttpd-1.4.11/src/mod_dirlisting.c 2006-01-13 00:00:45.000000000 +0200
19129 +++ lighttpd-1.4.12/src/mod_dirlisting.c 2006-07-15 22:43:21.000000000 +0300
19132 #include <stdlib.h>
19133 #include <string.h>
19134 -#include <dirent.h>
19135 #include <assert.h>
19138 -#include <unistd.h>
19143 #include "response.h"
19144 #include "stat_cache.h"
19145 #include "stream.h"
19148 +#include "sys-strings.h"
19151 * this is a dirlisting for a lighttpd plugin
19152 @@ -27,10 +28,13 @@
19153 #include <sys/syslimits.h>
19156 -#ifdef HAVE_ATTR_ATTRIBUTES_H
19158 #include <attr/attributes.h>
19161 +#include "sys-files.h"
19162 +#include "sys-strings.h"
19164 /* plugin config for all request/connections */
19168 unsigned short hide_readme_file;
19169 unsigned short show_header;
19170 unsigned short hide_header_file;
19173 excludes_buffer *excludes;
19175 buffer *external_css;
19176 @@ -63,13 +67,14 @@
19183 buffer *content_charset;
19187 plugin_config **config_storage;
19189 - plugin_config conf;
19191 + plugin_config conf;
19194 excludes_buffer *excludes_buffer_init(void) {
19195 @@ -146,44 +151,46 @@
19196 /* init the plugin data */
19197 INIT_FUNC(mod_dirlisting_init) {
19201 p = calloc(1, sizeof(*p));
19203 p->tmp_buf = buffer_init();
19204 p->content_charset = buffer_init();
19206 + p->path = buffer_init();
19211 /* detroy the plugin data */
19212 FREE_FUNC(mod_dirlisting_free) {
19213 plugin_data *p = p_d;
19218 if (!p) return HANDLER_GO_ON;
19221 if (p->config_storage) {
19223 for (i = 0; i < srv->config_context->used; i++) {
19224 plugin_config *s = p->config_storage[i];
19230 excludes_buffer_free(s->excludes);
19231 buffer_free(s->external_css);
19232 buffer_free(s->encoding);
19237 free(p->config_storage);
19241 buffer_free(p->tmp_buf);
19242 + buffer_free(p->path);
19243 buffer_free(p->content_charset);
19249 return HANDLER_GO_ON;
19252 @@ -215,10 +222,10 @@
19253 if (0 != excludes_buffer_append(s->excludes,
19254 ((data_string *)(da->value->data[j]))->value)) {
19256 - log_error_write(srv, __FILE__, __LINE__, "sb",
19257 + log_error_write(srv, __FILE__, __LINE__, "sb",
19258 "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
19260 - log_error_write(srv, __FILE__, __LINE__, "s",
19261 + log_error_write(srv, __FILE__, __LINE__, "s",
19262 "pcre support is missing, please install libpcre and the headers");
19265 @@ -233,8 +240,8 @@
19266 SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
19267 plugin_data *p = p_d;
19270 - config_values_t cv[] = {
19272 + config_values_t cv[] = {
19273 { "dir-listing.exclude", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
19274 { "dir-listing.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
19275 { "dir-listing.hide-dotfiles", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
19276 @@ -245,18 +252,18 @@
19277 { "dir-listing.show-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
19278 { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
19279 { "server.dir-listing", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
19282 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19286 if (!p) return HANDLER_ERROR;
19289 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19292 for (i = 0; i < srv->config_context->used; i++) {
19297 s = calloc(1, sizeof(plugin_config));
19298 s->excludes = excludes_buffer_init();
19299 s->dir_listing = 0;
19300 @@ -267,7 +274,7 @@
19301 s->show_header = 0;
19302 s->hide_header_file = 0;
19303 s->encoding = buffer_init();
19306 cv[0].destination = s->excludes;
19307 cv[1].destination = &(s->dir_listing);
19308 cv[2].destination = &(s->hide_dot_files);
19309 @@ -292,60 +299,57 @@
19310 return HANDLER_GO_ON;
19313 -#define PATCH(x) \
19314 - p->conf.x = s->x;
19315 static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
19317 plugin_config *s = p->config_storage[0];
19319 - PATCH(dir_listing);
19320 - PATCH(external_css);
19321 - PATCH(hide_dot_files);
19323 - PATCH(show_readme);
19324 - PATCH(hide_readme_file);
19325 - PATCH(show_header);
19326 - PATCH(hide_header_file);
19329 + PATCH_OPTION(dir_listing);
19330 + PATCH_OPTION(external_css);
19331 + PATCH_OPTION(hide_dot_files);
19332 + PATCH_OPTION(encoding);
19333 + PATCH_OPTION(show_readme);
19334 + PATCH_OPTION(hide_readme_file);
19335 + PATCH_OPTION(show_header);
19336 + PATCH_OPTION(hide_header_file);
19337 + PATCH_OPTION(excludes);
19339 /* skip the first, the global context */
19340 for (i = 1; i < srv->config_context->used; i++) {
19341 data_config *dc = (data_config *)srv->config_context->data[i];
19342 s = p->config_storage[i];
19345 /* condition didn't match */
19346 if (!config_check_cond(srv, con, dc)) continue;
19350 for (j = 0; j < dc->value->used; j++) {
19351 data_unset *du = dc->value->data[j];
19354 if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
19355 buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
19356 - PATCH(dir_listing);
19357 + PATCH_OPTION(dir_listing);
19358 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
19359 - PATCH(hide_dot_files);
19360 + PATCH_OPTION(hide_dot_files);
19361 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
19362 - PATCH(external_css);
19363 + PATCH_OPTION(external_css);
19364 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
19366 + PATCH_OPTION(encoding);
19367 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
19368 - PATCH(show_readme);
19369 + PATCH_OPTION(show_readme);
19370 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
19371 - PATCH(hide_readme_file);
19372 + PATCH_OPTION(hide_readme_file);
19373 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
19374 - PATCH(show_header);
19375 + PATCH_OPTION(show_header);
19376 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
19377 - PATCH(hide_header_file);
19378 + PATCH_OPTION(hide_header_file);
19379 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
19381 + PATCH_OPTION(excludes);
19393 @@ -432,7 +436,7 @@
19395 static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
19399 BUFFER_APPEND_STRING_CONST(out,
19400 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
19401 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
19402 @@ -492,11 +496,11 @@
19403 if (p->conf.show_header) {
19405 /* if we have a HEADER file, display it in <pre class="header"></pre> */
19408 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
19409 - BUFFER_APPEND_SLASH(p->tmp_buf);
19410 + PATHNAME_APPEND_SLASH(p->tmp_buf);
19411 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
19414 if (-1 != stream_open(&s, p->tmp_buf)) {
19415 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
19416 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19417 @@ -531,21 +535,21 @@
19419 static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
19423 BUFFER_APPEND_STRING_CONST(out,
19430 if (p->conf.show_readme) {
19432 /* if we have a README file, display it in <pre class="readme"></pre> */
19435 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
19436 - BUFFER_APPEND_SLASH(p->tmp_buf);
19437 + PATHNAME_APPEND_SLASH(p->tmp_buf);
19438 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
19441 if (-1 != stream_open(&s, p->tmp_buf)) {
19442 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
19443 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19444 @@ -553,7 +557,7 @@
19450 BUFFER_APPEND_STRING_CONST(out,
19451 "<div class=\"foot\">"
19453 @@ -576,7 +580,6 @@
19455 struct dirent *dent;
19457 - char *path, *path_file;
19459 int hide_dotfiles = p->conf.hide_dot_files;
19460 dirls_list_t dirs, files, *list;
19461 @@ -586,6 +589,7 @@
19463 const char *content_type;
19469 @@ -594,10 +598,10 @@
19473 - if (dir->used == 0) return -1;
19475 - i = dir->used - 1;
19476 + /* empty pathname, never ... */
19477 + if (buffer_is_empty(dir)) return -1;
19479 + /* max-length for the opendir */
19480 #ifdef HAVE_PATHCONF
19481 if (-1 == (name_max = pathconf(dir->ptr, _PC_NAME_MAX))) {
19483 @@ -606,22 +610,24 @@
19484 name_max = 256; /* stupid default */
19487 -#elif defined __WIN32
19488 +#elif defined _WIN32
19489 name_max = FILENAME_MAX;
19491 name_max = NAME_MAX;
19494 - path = malloc(dir->used + name_max);
19496 - strcpy(path, dir->ptr);
19497 - path_file = path + i;
19499 - if (NULL == (dp = opendir(path))) {
19500 - log_error_write(srv, __FILE__, __LINE__, "sbs",
19501 + buffer_copy_string_buffer(p->path, dir);
19502 + PATHNAME_APPEND_SLASH(p->path);
19505 + /* append *.* to the path */
19506 + buffer_append_string(path, "*.*");
19509 + if (NULL == (dp = opendir(p->path->ptr))) {
19510 + log_error_write(srv, __FILE__, __LINE__, "sbs",
19511 "opendir failed:", dir, strerror(errno));
19517 @@ -633,7 +639,7 @@
19519 files.size = DIRLIST_BLOB_SIZE;
19523 while ((dent = readdir(dp)) != NULL) {
19524 unsigned short exclude_match = 0;
19526 @@ -686,15 +692,21 @@
19529 i = strlen(dent->d_name);
19532 /* NOTE: the manual says, d_name is never more than NAME_MAX
19533 * so this should actually not be a buffer-overflow-risk
19535 if (i > (size_t)name_max) continue;
19537 - memcpy(path_file, dent->d_name, i + 1);
19538 - if (stat(path, &st) != 0)
19540 + /* build the dirname */
19541 + buffer_copy_string_buffer(p->path, dir);
19542 + PATHNAME_APPEND_SLASH(p->path);
19543 + buffer_append_string(p->path, dent->d_name);
19545 + if (stat(p->path->ptr, &st) != 0) {
19546 + fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, p->path->ptr, strerror(errno));
19551 if (S_ISDIR(st.st_mode))
19552 @@ -740,7 +752,7 @@
19554 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
19558 BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
19559 buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
19560 BUFFER_APPEND_STRING_CONST(out, "/\">");
19561 @@ -757,18 +769,22 @@
19562 tmp = files.ent[i];
19564 content_type = NULL;
19568 if (con->conf.use_xattr) {
19569 - memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
19570 + /* build the dirname */
19571 + buffer_copy_string_buffer(p->path, dir);
19572 + PATHNAME_APPEND_SLASH(p->path);
19573 + buffer_append_string_len(p->path, DIRLIST_ENT_NAME(tmp), tmp->namelen);
19575 attrlen = sizeof(attrval) - 1;
19576 - if (attr_get(path, "Content-Type", attrval, &attrlen, 0) == 0) {
19577 + if (attr_get(p->path->ptr, "Content-Type", attrval, &attrlen, 0) == 0) {
19578 attrval[attrlen] = '\0';
19579 content_type = attrval;
19585 if (content_type == NULL) {
19586 content_type = "application/octet-stream";
19587 for (k = 0; k < con->conf.mimetypes->used; k++) {
19588 @@ -788,7 +804,7 @@
19594 #ifdef HAVE_LOCALTIME_R
19595 localtime_r(&(tmp->mtime), &tm);
19596 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
19597 @@ -814,7 +830,6 @@
19603 http_list_directory_footer(srv, con, p, out);
19605 @@ -837,36 +852,55 @@
19606 URIHANDLER_FUNC(mod_dirlisting_subrequest) {
19607 plugin_data *p = p_d;
19608 stat_cache_entry *sce = NULL;
19612 - if (con->physical.path->used == 0) return HANDLER_GO_ON;
19613 - if (con->uri.path->used == 0) return HANDLER_GO_ON;
19617 + if (con->uri.path->used < 2) return HANDLER_GO_ON;
19618 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
19620 + if (con->physical.path->used == 0) return HANDLER_GO_ON;
19622 mod_dirlisting_patch_connection(srv, con, p);
19624 if (!p->conf.dir_listing) return HANDLER_GO_ON;
19627 + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19628 + /* just a second ago the file was still there */
19629 + return HANDLER_GO_ON;
19632 + if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
19634 if (con->conf.log_request_handling) {
19635 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Dir-Listing");
19636 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
19639 - if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19640 - fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
19643 + /* perhaps this a cachable request
19644 + * - we use the etag of the directory
19647 + etag_mutate(con->physical.etag, sce->etag);
19648 + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19650 + /* prepare header */
19651 + if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
19652 + mtime = strftime_cache_get(srv, sce->st.st_mtime);
19653 + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19655 + mtime = ds->value;
19658 - if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
19661 + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
19662 + return HANDLER_FINISHED;
19665 if (http_list_directory(srv, con, p, con->physical.path)) {
19666 /* dirlisting failed */
19667 con->http_status = 403;
19671 buffer_reset(con->physical.path);
19675 return HANDLER_FINISHED;
19677 @@ -876,13 +910,13 @@
19678 int mod_dirlisting_plugin_init(plugin *p) {
19679 p->version = LIGHTTPD_VERSION_ID;
19680 p->name = buffer_init_string("dirlisting");
19683 p->init = mod_dirlisting_init;
19684 p->handle_subrequest_start = mod_dirlisting_subrequest;
19685 p->set_defaults = mod_dirlisting_set_defaults;
19686 p->cleanup = mod_dirlisting_free;
19694 --- ../lighttpd-1.4.11/src/mod_evasive.c 2006-01-04 15:24:51.000000000 +0200
19695 +++ lighttpd-1.4.12/src/mod_evasive.c 2006-07-11 22:07:53.000000000 +0300
19696 @@ -31,100 +31,97 @@
19702 plugin_config **config_storage;
19704 - plugin_config conf;
19706 + plugin_config conf;
19709 INIT_FUNC(mod_evasive_init) {
19713 p = calloc(1, sizeof(*p));
19719 FREE_FUNC(mod_evasive_free) {
19720 plugin_data *p = p_d;
19725 if (!p) return HANDLER_GO_ON;
19728 if (p->config_storage) {
19730 for (i = 0; i < srv->config_context->used; i++) {
19731 plugin_config *s = p->config_storage[i];
19736 free(p->config_storage);
19743 return HANDLER_GO_ON;
19746 SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
19747 plugin_data *p = p_d;
19750 - config_values_t cv[] = {
19752 + config_values_t cv[] = {
19753 { "evasive.max-conns-per-ip", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
19754 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19758 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19761 for (i = 0; i < srv->config_context->used; i++) {
19765 s = calloc(1, sizeof(plugin_config));
19769 cv[0].destination = &(s->max_conns);
19772 p->config_storage[i] = s;
19775 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19776 return HANDLER_ERROR;
19781 return HANDLER_GO_ON;
19784 -#define PATCH(x) \
19785 - p->conf.x = s->x;
19786 static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
19788 plugin_config *s = p->config_storage[0];
19790 - PATCH(max_conns);
19792 + PATCH_OPTION(max_conns);
19794 /* skip the first, the global context */
19795 for (i = 1; i < srv->config_context->used; i++) {
19796 data_config *dc = (data_config *)srv->config_context->data[i];
19797 s = p->config_storage[i];
19800 /* condition didn't match */
19801 if (!config_check_cond(srv, con, dc)) continue;
19805 for (j = 0; j < dc->value->used; j++) {
19806 data_unset *du = dc->value->data[j];
19809 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
19810 - PATCH(max_conns);
19811 + PATCH_OPTION(max_conns);
19821 URIHANDLER_FUNC(mod_evasive_uri_handler) {
19822 plugin_data *p = p_d;
19823 @@ -132,10 +129,10 @@
19826 if (con->uri.path->used == 0) return HANDLER_GO_ON;
19829 mod_evasive_patch_connection(srv, con, p);
19831 - /* no limit set, nothing to block */
19833 + /* no limit set, nothing to block */
19834 if (p->conf.max_conns == 0) return HANDLER_GO_ON;
19836 for (j = 0; j < srv->conns->used; j++) {
19837 @@ -147,7 +144,7 @@
19838 if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
19839 c->state > CON_STATE_REQUEST_END) {
19843 if (conns_by_ip > p->conf.max_conns) {
19844 log_error_write(srv, __FILE__, __LINE__, "ss",
19845 inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
19846 @@ -158,7 +155,7 @@
19852 return HANDLER_GO_ON;
19855 @@ -166,13 +163,13 @@
19856 int mod_evasive_plugin_init(plugin *p) {
19857 p->version = LIGHTTPD_VERSION_ID;
19858 p->name = buffer_init_string("evasive");
19861 p->init = mod_evasive_init;
19862 p->set_defaults = mod_evasive_set_defaults;
19863 p->handle_uri_clean = mod_evasive_uri_handler;
19864 p->cleanup = mod_evasive_free;
19872 --- ../lighttpd-1.4.11/src/mod_evhost.c 2005-08-17 10:42:03.000000000 +0300
19873 +++ lighttpd-1.4.12/src/mod_evhost.c 2006-07-11 22:07:51.000000000 +0300
19875 #include "response.h"
19876 #include "stat_cache.h"
19878 +#include "sys-files.h"
19881 /* unparsed pieces */
19882 buffer *path_pieces_raw;
19885 /* pieces for path creation */
19887 buffer **path_pieces;
19888 @@ -21,14 +23,14 @@
19891 plugin_config **config_storage;
19892 - plugin_config conf;
19893 + plugin_config conf;
19896 INIT_FUNC(mod_evhost_init) {
19900 p = calloc(1, sizeof(*p));
19903 p->tmp_buf = buffer_init();
19906 @@ -36,34 +38,34 @@
19908 FREE_FUNC(mod_evhost_free) {
19909 plugin_data *p = p_d;
19914 if (!p) return HANDLER_GO_ON;
19917 if (p->config_storage) {
19919 for (i = 0; i < srv->config_context->used; i++) {
19920 plugin_config *s = p->config_storage[i];
19925 if(s->path_pieces) {
19927 for (j = 0; j < s->len; j++) {
19928 buffer_free(s->path_pieces[j]);
19932 free(s->path_pieces);
19936 buffer_free(s->path_pieces_raw);
19941 free(p->config_storage);
19945 buffer_free(p->tmp_buf);
19948 @@ -73,30 +75,30 @@
19950 static void mod_evhost_parse_pattern(plugin_config *s) {
19951 char *ptr = s->path_pieces_raw->ptr,*pos;
19954 s->path_pieces = NULL;
19957 for(pos=ptr;*ptr;ptr++) {
19959 s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
19960 s->path_pieces[s->len] = buffer_init();
19961 s->path_pieces[s->len+1] = buffer_init();
19964 buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
19968 buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
19977 s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
19978 s->path_pieces[s->len] = buffer_init();
19981 buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
19987 @@ -104,9 +106,9 @@
19988 SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
19989 plugin_data *p = p_d;
19997 * # define a pattern for the host url finding
19999 @@ -117,39 +119,39 @@
20000 * # %4 => subdomain 2 name
20002 * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
20007 - config_values_t cv[] = {
20009 + config_values_t cv[] = {
20010 { "evhost.path-pattern", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
20011 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20015 if (!p) return HANDLER_ERROR;
20018 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20021 for (i = 0; i < srv->config_context->used; i++) {
20025 s = calloc(1, sizeof(plugin_config));
20026 s->path_pieces_raw = buffer_init();
20027 s->path_pieces = NULL;
20031 cv[0].destination = s->path_pieces_raw;
20034 p->config_storage[i] = s;
20037 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
20038 return HANDLER_ERROR;
20042 if (s->path_pieces_raw->used != 0) {
20043 mod_evhost_parse_pattern(s);
20048 return HANDLER_GO_ON;
20051 @@ -158,7 +160,7 @@
20052 * - %0 - full hostname (authority w/o port)
20054 * - %2 - domain.tld
20059 static int mod_evhost_parse_host(connection *con,array *host) {
20060 @@ -168,7 +170,7 @@
20066 /* first, find the domain + tld */
20067 for(;ptr > con->uri.authority->ptr;ptr--) {
20069 @@ -179,18 +181,18 @@
20075 ds = data_string_init();
20076 buffer_copy_string(ds->key,"%0");
20079 /* if we stopped at a dot, skip the dot */
20080 if (*ptr == '.') ptr++;
20081 buffer_copy_string_len(ds->value, ptr, colon-ptr);
20084 array_insert_unique(host,(data_unset *)ds);
20087 /* if the : is not the start of the authority, go on parsing the hostname */
20090 if (colon != con->uri.authority->ptr) {
20091 for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
20093 @@ -200,59 +202,55 @@
20094 buffer_copy_string(ds->key,"%");
20095 buffer_append_long(ds->key, i++);
20096 buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
20099 array_insert_unique(host,(data_unset *)ds);
20106 /* if the . is not the first charactor of the hostname */
20107 if (colon != ptr) {
20108 ds = data_string_init();
20109 buffer_copy_string(ds->key,"%");
20110 buffer_append_long(ds->key, i++);
20111 buffer_copy_string_len(ds->value,ptr,colon-ptr);
20114 array_insert_unique(host,(data_unset *)ds);
20122 -#define PATCH(x) \
20123 - p->conf.x = s->x;
20124 static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
20126 plugin_config *s = p->config_storage[0];
20128 - PATCH(path_pieces);
20132 + PATCH_OPTION(path_pieces);
20133 + PATCH_OPTION(len);
20135 /* skip the first, the global context */
20136 for (i = 1; i < srv->config_context->used; i++) {
20137 data_config *dc = (data_config *)srv->config_context->data[i];
20138 s = p->config_storage[i];
20141 /* condition didn't match */
20142 if (!config_check_cond(srv, con, dc)) continue;
20146 for (j = 0; j < dc->value->used; j++) {
20147 data_unset *du = dc->value->data[j];
20150 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
20151 - PATCH(path_pieces);
20153 + PATCH_OPTION(path_pieces);
20154 + PATCH_OPTION(len);
20165 static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
20166 plugin_data *p = p_d;
20167 @@ -261,29 +259,29 @@
20168 register char *ptr;
20170 stat_cache_entry *sce = NULL;
20173 /* not authority set */
20174 if (con->uri.authority->used == 0) return HANDLER_GO_ON;
20177 mod_evhost_patch_connection(srv, con, p);
20180 /* missing even default(global) conf */
20181 if (0 == p->conf.len) {
20182 return HANDLER_GO_ON;
20185 parsed_host = array_init();
20188 mod_evhost_parse_host(con, parsed_host);
20191 /* build document-root */
20192 buffer_reset(p->tmp_buf);
20195 for (i = 0; i < p->conf.len; i++) {
20196 ptr = p->conf.path_pieces[i]->ptr;
20201 if (*(ptr+1) == '%') {
20203 BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
20204 @@ -298,11 +296,11 @@
20205 buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
20209 - BUFFER_APPEND_SLASH(p->tmp_buf);
20212 + PATHNAME_APPEND_SLASH(p->tmp_buf);
20214 array_free(parsed_host);
20217 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
20218 log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
20220 @@ -310,11 +308,11 @@
20221 log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
20227 buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
20231 return HANDLER_GO_ON;
20234 @@ -325,9 +323,9 @@
20235 p->set_defaults = mod_evhost_set_defaults;
20236 p->handle_docroot = mod_evhost_uri_handler;
20237 p->cleanup = mod_evhost_free;
20246 --- ../lighttpd-1.4.11/src/mod_expire.c 2005-11-03 09:52:13.000000000 +0200
20247 +++ lighttpd-1.4.12/src/mod_expire.c 2006-07-11 22:07:52.000000000 +0300
20249 #include "stat_cache.h"
20252 - * this is a expire module for a lighttpd
20254 + * this is a expire module for a lighttpd
20256 * set 'Expires:' HTTP Headers on demand
20259 @@ -27,51 +27,51 @@
20265 buffer *expire_tstmp;
20268 plugin_config **config_storage;
20270 - plugin_config conf;
20272 + plugin_config conf;
20275 /* init the plugin data */
20276 INIT_FUNC(mod_expire_init) {
20280 p = calloc(1, sizeof(*p));
20283 p->expire_tstmp = buffer_init();
20286 buffer_prepare_copy(p->expire_tstmp, 255);
20292 /* detroy the plugin data */
20293 FREE_FUNC(mod_expire_free) {
20294 plugin_data *p = p_d;
20299 if (!p) return HANDLER_GO_ON;
20302 buffer_free(p->expire_tstmp);
20305 if (p->config_storage) {
20307 for (i = 0; i < srv->config_context->used; i++) {
20308 plugin_config *s = p->config_storage[i];
20311 array_free(s->expire_url);
20316 free(p->config_storage);
20323 return HANDLER_GO_ON;
20326 @@ -79,25 +79,25 @@
20339 * '(access|modification) [plus] {<num> <type>}*'
20342 * e.g. 'access 1 years'
20346 if (expire->used == 0) {
20347 - log_error_write(srv, __FILE__, __LINE__, "s",
20348 + log_error_write(srv, __FILE__, __LINE__, "s",
20357 if (0 == strncmp(ts, "access ", 7)) {
20360 @@ -110,39 +110,39 @@
20361 "invalid <base>:", ts);
20366 if (0 == strncmp(ts, "plus ", 5)) {
20367 /* skip the optional plus */
20372 /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
20378 if (NULL == (space = strchr(ts, ' '))) {
20379 - log_error_write(srv, __FILE__, __LINE__, "ss",
20380 + log_error_write(srv, __FILE__, __LINE__, "ss",
20381 "missing space after <num>:", ts);
20386 num = strtol(ts, &err, 10);
20388 - log_error_write(srv, __FILE__, __LINE__, "ss",
20389 + log_error_write(srv, __FILE__, __LINE__, "ss",
20390 "missing <type> after <num>:", ts);
20398 if (NULL != (space = strchr(ts, ' '))) {
20408 0 == strncmp(ts, "years", slen)) {
20409 num *= 60 * 60 * 24 * 30 * 12;
20410 } else if (slen == 6 &&
20411 @@ -161,13 +161,13 @@
20412 0 == strncmp(ts, "seconds", slen)) {
20415 - log_error_write(srv, __FILE__, __LINE__, "ss",
20416 + log_error_write(srv, __FILE__, __LINE__, "ss",
20417 "unknown type:", ts);
20427 if (0 == strcmp(ts, "years")) {
20428 @@ -183,19 +183,19 @@
20429 } else if (0 == strcmp(ts, "seconds")) {
20432 - log_error_write(srv, __FILE__, __LINE__, "ss",
20433 + log_error_write(srv, __FILE__, __LINE__, "ss",
20434 "unknown type:", ts);
20447 if (offset != NULL) *offset = retts;
20453 @@ -205,102 +205,99 @@
20454 SETDEFAULTS_FUNC(mod_expire_set_defaults) {
20455 plugin_data *p = p_d;
20458 - config_values_t cv[] = {
20460 + config_values_t cv[] = {
20461 { "expire.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
20462 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20466 if (!p) return HANDLER_ERROR;
20469 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20472 for (i = 0; i < srv->config_context->used; i++) {
20476 s = calloc(1, sizeof(plugin_config));
20477 s->expire_url = array_init();
20480 cv[0].destination = s->expire_url;
20483 p->config_storage[i] = s;
20486 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
20487 return HANDLER_ERROR;
20491 for (k = 0; k < s->expire_url->used; k++) {
20492 data_string *ds = (data_string *)s->expire_url->data[k];
20496 if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
20497 - log_error_write(srv, __FILE__, __LINE__, "sb",
20498 + log_error_write(srv, __FILE__, __LINE__, "sb",
20499 "parsing expire.url failed:", ds->value);
20500 return HANDLER_ERROR;
20508 return HANDLER_GO_ON;
20511 -#define PATCH(x) \
20512 - p->conf.x = s->x;
20513 static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
20515 plugin_config *s = p->config_storage[0];
20517 - PATCH(expire_url);
20520 + PATCH_OPTION(expire_url);
20522 /* skip the first, the global context */
20523 for (i = 1; i < srv->config_context->used; i++) {
20524 data_config *dc = (data_config *)srv->config_context->data[i];
20525 s = p->config_storage[i];
20528 /* condition didn't match */
20529 if (!config_check_cond(srv, con, dc)) continue;
20533 for (j = 0; j < dc->value->used; j++) {
20534 data_unset *du = dc->value->data[j];
20537 if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
20538 - PATCH(expire_url);
20539 + PATCH_OPTION(expire_url);
20549 URIHANDLER_FUNC(mod_expire_path_handler) {
20550 plugin_data *p = p_d;
20555 if (con->uri.path->used == 0) return HANDLER_GO_ON;
20558 mod_expire_patch_connection(srv, con, p);
20561 s_len = con->uri.path->used - 1;
20564 for (k = 0; k < p->conf.expire_url->used; k++) {
20565 data_string *ds = (data_string *)p->conf.expire_url->data[k];
20566 int ct_len = ds->key->used - 1;
20569 if (ct_len > s_len) continue;
20570 if (ds->key->used == 0) continue;
20573 if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
20577 stat_cache_entry *sce = NULL;
20580 stat_cache_get_entry(srv, con, con->physical.path, &sce);
20583 switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
20586 @@ -308,38 +305,38 @@
20592 t = (ts + sce->st.st_mtime);
20595 /* -1 is handled at parse-time */
20600 - if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
20603 + if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
20604 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
20605 /* could not set expire header, out of mem */
20608 return HANDLER_GO_ON;
20614 p->expire_tstmp->used = len + 1;
20619 response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
20623 buffer_copy_string(p->expire_tstmp, "max-age=");
20624 buffer_append_long(p->expire_tstmp, ts);
20627 response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
20630 return HANDLER_GO_ON;
20636 return HANDLER_GO_ON;
20638 @@ -349,13 +346,13 @@
20639 int mod_expire_plugin_init(plugin *p) {
20640 p->version = LIGHTTPD_VERSION_ID;
20641 p->name = buffer_init_string("expire");
20644 p->init = mod_expire_init;
20645 p->handle_subrequest_start = mod_expire_path_handler;
20646 p->set_defaults = mod_expire_set_defaults;
20647 p->cleanup = mod_expire_free;
20655 --- ../lighttpd-1.4.11/src/mod_fastcgi.c 2006-03-09 13:18:39.000000000 +0200
20656 +++ lighttpd-1.4.12/src/mod_fastcgi.c 2006-07-11 22:07:53.000000000 +0300
20658 #include <sys/types.h>
20659 -#include <unistd.h>
20662 #include <string.h>
20664 #include "inet_ntop_cache.h"
20665 #include "stat_cache.h"
20667 -#include <fastcgi.h>
20668 +#include "fastcgi.h"
20671 #ifdef HAVE_SYS_FILIO_H
20675 #include "sys-socket.h"
20676 +#include "sys-files.h"
20677 +#include "sys-strings.h"
20678 +#include "sys-process.h"
20680 +#include "http_resp.h"
20682 #ifndef UNIX_PATH_MAX
20683 # define UNIX_PATH_MAX 108
20684 @@ -45,14 +48,13 @@
20685 #include <sys/wait.h>
20695 * - add timeout for a connect to a non-fastcgi process
20696 * (use state_timestamp + state)
20701 typedef struct fcgi_proc {
20703 unsigned port; /* config.port + pno */
20705 buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
20708 pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
20711 @@ -70,20 +72,20 @@
20712 time_t last_used; /* see idle_timeout */
20713 size_t requests; /* see max_requests */
20714 struct fcgi_proc *prev, *next; /* see first */
20717 time_t disabled_until; /* this proc is disabled until, use something else until than */
20724 PROC_STATE_UNSET, /* init-phase */
20725 PROC_STATE_RUNNING, /* alive */
20726 - PROC_STATE_OVERLOADED, /* listen-queue is full,
20727 + PROC_STATE_OVERLOADED, /* listen-queue is full,
20728 don't send something to this proc for the next 2 seconds */
20729 PROC_STATE_DIED_WAIT_FOR_PID, /* */
20730 PROC_STATE_DIED, /* marked as dead, should be restarted */
20731 PROC_STATE_KILLED /* was killed as we don't have the load anymore */
20737 @@ -94,20 +96,20 @@
20738 * sorted by lowest load
20740 * whenever a job is done move it up in the list
20741 - * until it is sorted, move it down as soon as the
20742 + * until it is sorted, move it down as soon as the
20745 - fcgi_proc *first;
20746 - fcgi_proc *unused_procs;
20747 + fcgi_proc *first;
20748 + fcgi_proc *unused_procs;
20752 * spawn at least min_procs, at max_procs.
20754 - * as soon as the load of the first entry
20755 + * as soon as the load of the first entry
20756 * is max_load_per_proc we spawn a new one
20757 - * and add it to the first entry and give it
20758 + * and add it to the first entry and give it
20764 unsigned short min_procs;
20765 @@ -119,44 +121,44 @@
20768 * kick the process from the list if it was not
20769 - * used for idle_timeout until min_procs is
20770 + * used for idle_timeout until min_procs is
20771 * reached. this helps to get the processlist
20772 * small again we had a small peak load.
20777 unsigned short idle_timeout;
20781 * time after a disabled remote connection is tried to be re-enabled
20789 unsigned short disable_time;
20792 * same fastcgi processes get a little bit larger
20793 - * than wanted. max_requests_per_proc kills a
20794 + * than wanted. max_requests_per_proc kills a
20795 * process after a number of handled requests.
20798 size_t max_requests_per_proc;
20809 - * if host is one of the local IP adresses the
20810 + * if host is one of the local IP adresses the
20811 * whole connection is local
20813 * if tcp/ip should be used host AND port have
20814 - * to be specified
20818 + * to be specified
20822 unsigned short port;
20825 @@ -169,7 +171,7 @@
20827 buffer *unixsocket;
20829 - /* if socket is local we can start the fastcgi
20830 + /* if socket is local we can start the fastcgi
20833 * bin-path is the path to the binary
20834 @@ -177,19 +179,19 @@
20835 * check min_procs and max_procs for the number
20836 * of process to start-up
20838 - buffer *bin_path;
20840 - /* bin-path is set bin-environment is taken to
20841 + buffer *bin_path;
20843 + /* bin-path is set bin-environment is taken to
20844 * create the environement before starting the
20852 array *bin_env_copy;
20856 - * docroot-translation between URL->phys and the
20857 + * docroot-translation between URL->phys and the
20861 @@ -208,7 +210,7 @@
20862 unsigned short mode;
20865 - * check_local tell you if the phys file is stat()ed
20866 + * check_local tell you if the phys file is stat()ed
20867 * or not. FastCGI doesn't care if the service is
20868 * remote. If the web-server side doesn't contain
20869 * the fastcgi-files we should not stat() for them
20870 @@ -218,11 +220,11 @@
20873 * append PATH_INFO to SCRIPT_FILENAME
20876 * php needs this if cgi.fix_pathinfo is provied
20882 unsigned short break_scriptfilename_for_php;
20885 @@ -231,12 +233,12 @@
20888 unsigned short allow_xsendfile;
20891 ssize_t load; /* replace by host->load */
20893 size_t max_id; /* corresponds most of the time to
20897 only if a process is killed max_id waits for the process itself
20898 to die and decrements its afterwards */
20900 @@ -245,17 +247,17 @@
20903 * one extension can have multiple hosts assigned
20904 - * one host can spawn additional processes on the same
20905 + * one host can spawn additional processes on the same
20906 * socket (if we control it)
20908 * ext -> host -> procs
20911 - * if the fastcgi process is remote that whole goes down
20912 + * if the fastcgi process is remote that whole goes down
20915 * ext -> host -> procs
20919 * in case of PHP and FCGI_CHILDREN we have again a procs
20920 * but we don't control it directly.
20921 @@ -268,7 +270,7 @@
20924 fcgi_extension_host **hosts;
20930 @@ -282,10 +284,10 @@
20937 array *ext_mapping;
20943 @@ -297,7 +299,7 @@
20952 @@ -306,44 +308,44 @@
20955 buffer_uint fcgi_request_id;
20962 - buffer *parse_response;
20969 plugin_config **config_storage;
20972 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
20975 /* connection specific data */
20980 - FCGI_STATE_CONNECT_DELAYED,
20981 - FCGI_STATE_PREPARE_WRITE,
20982 - FCGI_STATE_WRITE,
20985 + FCGI_STATE_CONNECT_DELAYED,
20986 + FCGI_STATE_PREPARE_WRITE,
20987 + FCGI_STATE_WRITE,
20989 } fcgi_connection_state_t;
20993 fcgi_extension_host *host;
20994 fcgi_extension *ext;
20997 fcgi_connection_state_t state;
20998 time_t state_timestamp;
21001 int reconnects; /* number of reconnect attempts */
21003 - chunkqueue *rb; /* read queue */
21005 + chunkqueue *rb; /* the raw fcgi read-queue */
21006 + chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
21007 chunkqueue *wb; /* write queue */
21009 - buffer *response_header;
21013 int fd; /* fd to the fastcgi process */
21014 int fde_ndx; /* index into the fd-event buffer */
21015 @@ -352,9 +354,9 @@
21018 int send_content_body;
21021 plugin_config conf;
21024 connection *remote_conn; /* dumb pointer */
21025 plugin_data *plugin_data; /* dumb pointer */
21027 @@ -380,7 +382,7 @@
21031 -/* dummies of the statistic framework functions
21032 +/* dummies of the statistic framework functions
21033 * they will be moved to a statistics.c later */
21034 int status_counter_inc(server *srv, const char *s, size_t len) {
21035 data_integer *di = status_counter_get_counter(srv, s, len);
21036 @@ -429,7 +431,7 @@
21037 CLEAN(".connected");
21044 fastcgi_status_copy_procname(b, host, NULL); \
21045 @@ -438,33 +440,32 @@
21055 static handler_ctx * handler_ctx_init() {
21056 handler_ctx * hctx;
21059 hctx = calloc(1, sizeof(*hctx));
21063 hctx->fde_ndx = -1;
21065 - hctx->response_header = buffer_init();
21068 hctx->request_id = 0;
21069 hctx->state = FCGI_STATE_INIT;
21076 hctx->reconnects = 0;
21077 hctx->send_content_body = 1;
21079 hctx->rb = chunkqueue_init();
21080 + hctx->http_rb = chunkqueue_init();
21081 hctx->wb = chunkqueue_init();
21087 @@ -473,10 +474,9 @@
21088 hctx->host->load--;
21092 - buffer_free(hctx->response_header);
21094 chunkqueue_free(hctx->rb);
21095 + chunkqueue_free(hctx->http_rb);
21096 chunkqueue_free(hctx->wb);
21099 @@ -488,21 +488,21 @@
21100 f = calloc(1, sizeof(*f));
21101 f->unixsocket = buffer_init();
21102 f->connection_name = buffer_init();
21112 void fastcgi_process_free(fcgi_proc *f) {
21116 fastcgi_process_free(f->next);
21119 buffer_free(f->unixsocket);
21120 buffer_free(f->connection_name);
21126 @@ -519,13 +519,13 @@
21127 f->bin_env = array_init();
21128 f->bin_env_copy = array_init();
21129 f->strip_request_uri = buffer_init();
21135 void fastcgi_host_free(fcgi_extension_host *h) {
21139 buffer_free(h->id);
21140 buffer_free(h->host);
21141 buffer_free(h->unixsocket);
21142 @@ -534,49 +534,49 @@
21143 buffer_free(h->strip_request_uri);
21144 array_free(h->bin_env);
21145 array_free(h->bin_env_copy);
21148 fastcgi_process_free(h->first);
21149 fastcgi_process_free(h->unused_procs);
21157 fcgi_exts *fastcgi_extensions_init() {
21160 f = calloc(1, sizeof(*f));
21166 void fastcgi_extensions_free(fcgi_exts *f) {
21173 for (i = 0; i < f->used; i++) {
21174 fcgi_extension *fe;
21181 for (j = 0; j < fe->used; j++) {
21182 fcgi_extension_host *h;
21188 fastcgi_host_free(h);
21192 buffer_free(fe->key);
21206 @@ -625,24 +625,25 @@
21210 - fe->hosts[fe->used++] = fh;
21211 + fe->hosts[fe->used++] = fh;
21218 INIT_FUNC(mod_fastcgi_init) {
21222 p = calloc(1, sizeof(*p));
21225 p->fcgi_env = buffer_init();
21228 p->path = buffer_init();
21229 - p->parse_response = buffer_init();
21231 + p->resp = http_response_init();
21233 p->statuskey = buffer_init();
21239 @@ -650,81 +651,82 @@
21240 FREE_FUNC(mod_fastcgi_free) {
21241 plugin_data *p = p_d;
21242 buffer_uint *r = &(p->fcgi_request_id);
21247 if (r->ptr) free(r->ptr);
21250 buffer_free(p->fcgi_env);
21251 buffer_free(p->path);
21252 - buffer_free(p->parse_response);
21253 buffer_free(p->statuskey);
21256 + http_response_free(p->resp);
21258 if (p->config_storage) {
21260 for (i = 0; i < srv->config_context->used; i++) {
21261 plugin_config *s = p->config_storage[i];
21270 for (j = 0; j < exts->used; j++) {
21271 fcgi_extension *ex;
21274 ex = exts->exts[j];
21277 for (n = 0; n < ex->used; n++) {
21279 fcgi_extension_host *host;
21282 host = ex->hosts[n];
21285 for (proc = host->first; proc; proc = proc->next) {
21286 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21288 - if (proc->is_local &&
21290 + if (proc->is_local &&
21291 !buffer_is_empty(proc->unixsocket)) {
21292 unlink(proc->unixsocket->ptr);
21297 for (proc = host->unused_procs; proc; proc = proc->next) {
21298 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21300 - if (proc->is_local &&
21302 + if (proc->is_local &&
21303 !buffer_is_empty(proc->unixsocket)) {
21304 unlink(proc->unixsocket->ptr);
21311 fastcgi_extensions_free(s->exts);
21312 array_free(s->ext_mapping);
21317 free(p->config_storage);
21324 return HANDLER_GO_ON;
21327 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
21331 if (!key || !val) return -1;
21334 dst = malloc(key_len + val_len + 3);
21335 memcpy(dst, key, key_len);
21336 dst[key_len] = '=';
21337 /* add the \0 from the value */
21338 memcpy(dst + key_len + 1, val, val_len + 1);
21341 if (env->size == 0) {
21343 env->ptr = malloc(env->size * sizeof(*env->ptr));
21344 @@ -732,9 +734,9 @@
21346 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21350 env->ptr[env->used++] = dst;
21356 @@ -753,15 +755,15 @@
21357 if (env->size == 0) {
21359 env->ptr = malloc(env->size * sizeof(*env->ptr));
21360 - } else if (env->size == env->used) {
21361 + } else if (env->size == env->used) {
21363 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21369 env->ptr[env->used++] = start;
21372 start = b->ptr + i + 1;
21375 @@ -794,7 +796,7 @@
21379 -static int fcgi_spawn_connection(server *srv,
21380 +static int fcgi_spawn_connection(server *srv,
21382 fcgi_extension_host *host,
21384 @@ -806,31 +808,27 @@
21386 struct sockaddr_in fcgi_addr_in;
21387 struct sockaddr *fcgi_addr;
21398 if (p->conf.debug) {
21399 log_error_write(srv, __FILE__, __LINE__, "sdb",
21400 "new proc, socket:", proc->port, proc->unixsocket);
21404 if (!buffer_is_empty(proc->unixsocket)) {
21405 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
21408 #ifdef HAVE_SYS_UN_H
21409 fcgi_addr_un.sun_family = AF_UNIX;
21410 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
21414 servlen = SUN_LEN(&fcgi_addr_un);
21416 - /* stevens says: */
21417 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
21420 socket_type = AF_UNIX;
21421 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
21423 @@ -844,108 +842,108 @@
21426 fcgi_addr_in.sin_family = AF_INET;
21429 if (buffer_is_empty(host->host)) {
21430 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21432 struct hostent *he;
21435 /* set a usefull default */
21436 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21441 if (NULL == (he = gethostbyname(host->host->ptr))) {
21442 - log_error_write(srv, __FILE__, __LINE__,
21443 - "sdb", "gethostbyname failed: ",
21444 + log_error_write(srv, __FILE__, __LINE__,
21445 + "sdb", "gethostbyname failed: ",
21446 h_errno, host->host);
21451 if (he->h_addrtype != AF_INET) {
21452 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
21457 if (he->h_length != sizeof(struct in_addr)) {
21458 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
21463 memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
21467 fcgi_addr_in.sin_port = htons(proc->port);
21468 servlen = sizeof(fcgi_addr_in);
21471 socket_type = AF_INET;
21472 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
21475 buffer_copy_string(proc->connection_name, "tcp:");
21476 buffer_append_string_buffer(proc->connection_name, host->host);
21477 buffer_append_string(proc->connection_name, ":");
21478 buffer_append_long(proc->connection_name, proc->port);
21482 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21483 - log_error_write(srv, __FILE__, __LINE__, "ss",
21484 + log_error_write(srv, __FILE__, __LINE__, "ss",
21485 "failed:", strerror(errno));
21490 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
21491 /* server is not up, spawn in */
21495 - if (errno != ENOENT &&
21497 + if (errno != ENOENT &&
21498 !buffer_is_empty(proc->unixsocket)) {
21499 unlink(proc->unixsocket->ptr);
21506 /* reopen socket */
21507 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21508 - log_error_write(srv, __FILE__, __LINE__, "ss",
21509 + log_error_write(srv, __FILE__, __LINE__, "ss",
21510 "socket failed:", strerror(errno));
21516 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
21517 - log_error_write(srv, __FILE__, __LINE__, "ss",
21518 + log_error_write(srv, __FILE__, __LINE__, "ss",
21519 "socketsockopt failed:", strerror(errno));
21524 /* create socket */
21525 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
21526 - log_error_write(srv, __FILE__, __LINE__, "sbs",
21527 - "bind failed for:",
21528 + log_error_write(srv, __FILE__, __LINE__, "sbs",
21529 + "bind failed for:",
21530 proc->connection_name,
21536 if (-1 == listen(fcgi_fd, 1024)) {
21537 - log_error_write(srv, __FILE__, __LINE__, "ss",
21538 + log_error_write(srv, __FILE__, __LINE__, "ss",
21539 "listen failed:", strerror(errno));
21546 switch ((child = fork())) {
21554 /* create environment */
21563 @@ -955,18 +953,18 @@
21564 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
21569 /* we don't need the client socket */
21570 for (i = 3; i < 256; i++) {
21575 /* build clean environment */
21576 if (host->bin_env_copy->used) {
21577 for (i = 0; i < host->bin_env_copy->used; i++) {
21578 data_string *ds = (data_string *)host->bin_env_copy->data[i];
21582 if (NULL != (ge = getenv(ds->value->ptr))) {
21583 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
21585 @@ -974,39 +972,39 @@
21587 for (i = 0; environ[i]; i++) {
21591 if (NULL != (eq = strchr(environ[i], '='))) {
21592 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
21598 /* create environment */
21599 for (i = 0; i < host->bin_env->used; i++) {
21600 data_string *ds = (data_string *)host->bin_env->data[i];
21603 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
21607 for (i = 0; i < env.used; i++) {
21608 /* search for PHP_FCGI_CHILDREN */
21609 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
21613 /* not found, add a default */
21614 if (i == env.used) {
21615 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
21619 env.ptr[env.used] = NULL;
21621 parse_binpath(&arg, host->bin_path);
21624 /* chdir into the base of the bin-path,
21625 * search for the last / */
21626 if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
21630 /* change to the physical directory */
21631 if (-1 == chdir(arg.ptr[0])) {
21633 @@ -1018,12 +1016,12 @@
21636 execve(arg.ptr[0], arg.ptr, env.ptr);
21638 - log_error_write(srv, __FILE__, __LINE__, "sbs",
21640 + log_error_write(srv, __FILE__, __LINE__, "sbs",
21641 "execve failed for:", host->bin_path, strerror(errno));
21650 @@ -1031,17 +1029,17 @@
21657 select(0, NULL, NULL, NULL, &tv);
21660 switch (waitpid(child, &status, WNOHANG)) {
21662 /* child still running after timeout, good */
21665 /* no PID found ? should never happen */
21666 - log_error_write(srv, __FILE__, __LINE__, "ss",
21667 + log_error_write(srv, __FILE__, __LINE__, "ss",
21668 "pid not found:", strerror(errno));
21671 @@ -1049,10 +1047,10 @@
21672 "the fastcgi-backend", host->bin_path, "failed to start:");
21673 /* the child should not terminate at all */
21674 if (WIFEXITED(status)) {
21675 - log_error_write(srv, __FILE__, __LINE__, "sdb",
21676 - "child exited with status",
21677 + log_error_write(srv, __FILE__, __LINE__, "sdb",
21678 + "child exited with status",
21679 WEXITSTATUS(status), host->bin_path);
21680 - log_error_write(srv, __FILE__, __LINE__, "s",
21681 + log_error_write(srv, __FILE__, __LINE__, "s",
21682 "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n"
21683 "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' "
21684 "in the output, NOT (cgi) NOR (cli)\n"
21685 @@ -1060,8 +1058,8 @@
21686 log_error_write(srv, __FILE__, __LINE__, "s",
21687 "If this is PHP on Gentoo add fastcgi to the USE flags");
21688 } else if (WIFSIGNALED(status)) {
21689 - log_error_write(srv, __FILE__, __LINE__, "sd",
21690 - "terminated by signal:",
21691 + log_error_write(srv, __FILE__, __LINE__, "sd",
21692 + "terminated by signal:",
21695 if (WTERMSIG(status) == 11) {
21696 @@ -1071,8 +1069,8 @@
21697 "If this is PHP try to remove the byte-code caches for now and try again.");
21700 - log_error_write(srv, __FILE__, __LINE__, "sd",
21701 - "child died somehow:",
21702 + log_error_write(srv, __FILE__, __LINE__, "sd",
21703 + "child died somehow:",
21707 @@ -1082,26 +1080,26 @@
21709 proc->last_used = srv->cur_ts;
21710 proc->is_local = 1;
21717 proc->is_local = 0;
21721 if (p->conf.debug) {
21722 log_error_write(srv, __FILE__, __LINE__, "sb",
21723 "(debug) socket is already used, won't spawn:",
21724 proc->connection_name);
21729 proc->state = PROC_STATE_RUNNING;
21730 host->active_procs++;
21739 @@ -1111,93 +1109,93 @@
21742 buffer *fcgi_mode = buffer_init();
21744 - config_values_t cv[] = {
21746 + config_values_t cv[] = {
21747 { "fastcgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
21748 { "fastcgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
21749 { "fastcgi.map-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
21750 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21754 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21757 for (i = 0; i < srv->config_context->used; i++) {
21762 s = malloc(sizeof(plugin_config));
21763 s->exts = fastcgi_extensions_init();
21765 s->ext_mapping = array_init();
21768 cv[0].destination = s->exts;
21769 cv[1].destination = &(s->debug);
21770 cv[2].destination = s->ext_mapping;
21773 p->config_storage[i] = s;
21774 ca = ((data_config *)srv->config_context->data[i])->value;
21777 if (0 != config_insert_values_global(srv, ca, cv)) {
21778 return HANDLER_ERROR;
21788 if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
21790 data_array *da = (data_array *)du;
21793 if (du->type != TYPE_ARRAY) {
21794 - log_error_write(srv, __FILE__, __LINE__, "sss",
21795 + log_error_write(srv, __FILE__, __LINE__, "sss",
21796 "unexpected type for key: ", "fastcgi.server", "array of strings");
21799 return HANDLER_ERROR;
21804 - * fastcgi.server = ( "<ext>" => ( ... ),
21808 + * fastcgi.server = ( "<ext>" => ( ... ),
21809 * "<ext>" => ( ... ) )
21813 for (j = 0; j < da->value->used; j++) {
21815 data_array *da_ext = (data_array *)da->value->data[j];
21818 if (da->value->data[j]->type != TYPE_ARRAY) {
21819 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
21820 - "unexpected type for key: ", "fastcgi.server",
21821 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
21822 + "unexpected type for key: ", "fastcgi.server",
21823 "[", da->value->data[j]->key, "](string)");
21826 return HANDLER_ERROR;
21830 - * da_ext->key == name of the extension
21833 + * da_ext->key == name of the extension
21837 - * fastcgi.server = ( "<ext>" =>
21838 - * ( "<host>" => ( ... ),
21841 + * fastcgi.server = ( "<ext>" =>
21842 + * ( "<host>" => ( ... ),
21843 * "<host>" => ( ... )
21850 for (n = 0; n < da_ext->value->used; n++) {
21851 data_array *da_host = (data_array *)da_ext->value->data[n];
21854 fcgi_extension_host *host;
21856 - config_values_t fcv[] = {
21858 + config_values_t fcv[] = {
21859 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
21860 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
21861 { "mode", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
21862 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
21863 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
21866 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
21867 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
21868 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
21869 @@ -1205,28 +1203,28 @@
21870 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
21871 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
21872 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
21875 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
21876 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
21879 { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
21880 { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
21881 { "strip-request-uri", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
21884 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21888 if (da_host->type != TYPE_ARRAY) {
21889 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
21890 - "unexpected type for key:",
21891 - "fastcgi.server",
21892 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
21893 + "unexpected type for key:",
21894 + "fastcgi.server",
21895 "[", da_host->key, "](string)");
21898 return HANDLER_ERROR;
21902 host = fastcgi_host_init();
21905 buffer_copy_string_buffer(host->id, da_host->key);
21907 host->check_local = 1;
21908 @@ -1238,13 +1236,13 @@
21909 host->disable_time = 60;
21910 host->break_scriptfilename_for_php = 0;
21911 host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
21914 fcv[0].destination = host->host;
21915 fcv[1].destination = host->docroot;
21916 fcv[2].destination = fcgi_mode;
21917 fcv[3].destination = host->unixsocket;
21918 fcv[4].destination = host->bin_path;
21921 fcv[5].destination = &(host->check_local);
21922 fcv[6].destination = &(host->port);
21923 fcv[7].destination = &(host->min_procs);
21924 @@ -1252,35 +1250,35 @@
21925 fcv[9].destination = &(host->max_load_per_proc);
21926 fcv[10].destination = &(host->idle_timeout);
21927 fcv[11].destination = &(host->disable_time);
21930 fcv[12].destination = host->bin_env;
21931 fcv[13].destination = host->bin_env_copy;
21932 fcv[14].destination = &(host->break_scriptfilename_for_php);
21933 fcv[15].destination = &(host->allow_xsendfile);
21934 fcv[16].destination = host->strip_request_uri;
21937 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
21938 return HANDLER_ERROR;
21941 - if ((!buffer_is_empty(host->host) || host->port) &&
21943 + if ((!buffer_is_empty(host->host) || host->port) &&
21944 !buffer_is_empty(host->unixsocket)) {
21945 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21946 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21947 "either host/port or socket have to be set in:",
21950 da_ext->key, " => (",
21951 da_host->key, " ( ...");
21953 return HANDLER_ERROR;
21957 if (!buffer_is_empty(host->unixsocket)) {
21958 /* unix domain socket */
21961 if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
21962 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21963 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21964 "unixsocket is too long in:",
21967 da_ext->key, " => (",
21968 da_host->key, " ( ...");
21970 @@ -1288,37 +1286,37 @@
21975 - if (buffer_is_empty(host->host) &&
21977 + if (buffer_is_empty(host->host) &&
21978 buffer_is_empty(host->bin_path)) {
21979 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21980 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21981 "host or binpath have to be set in:",
21984 da_ext->key, " => (",
21985 da_host->key, " ( ...");
21988 return HANDLER_ERROR;
21989 } else if (host->port == 0) {
21990 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21991 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21992 "port has to be set in:",
21995 da_ext->key, " => (",
21996 da_host->key, " ( ...");
21998 return HANDLER_ERROR;
22002 - if (!buffer_is_empty(host->bin_path)) {
22004 + if (!buffer_is_empty(host->bin_path)) {
22005 /* a local socket + self spawning */
22008 /* HACK: just to make sure the adaptive spawing is disabled */
22009 host->min_procs = host->max_procs;
22012 if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
22013 if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
22017 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
22018 "--- fastcgi spawning local",
22019 @@ -1328,7 +1326,7 @@
22020 "\n\tmin-procs:", host->min_procs,
22021 "\n\tmax-procs:", host->max_procs);
22025 for (pno = 0; pno < host->min_procs; pno++) {
22028 @@ -1343,7 +1341,7 @@
22029 buffer_append_string(proc->unixsocket, "-");
22030 buffer_append_long(proc->unixsocket, pno);
22035 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
22036 "--- fastcgi spawning",
22037 @@ -1351,7 +1349,7 @@
22038 "\n\tsocket", host->unixsocket,
22039 "\n\tcurrent:", pno, "/", host->min_procs);
22043 if (fcgi_spawn_connection(srv, p, host, proc)) {
22044 log_error_write(srv, __FILE__, __LINE__, "s",
22045 "[ERROR]: spawning fcgi failed.");
22046 @@ -1359,35 +1357,35 @@
22049 fastcgi_status_init(srv, p->statuskey, host, proc);
22052 proc->next = host->first;
22053 if (host->first) host->first->prev = proc;
22056 host->first = proc;
22062 proc = fastcgi_process_init();
22063 proc->id = host->num_procs++;
22065 host->active_procs++;
22066 proc->state = PROC_STATE_RUNNING;
22069 if (buffer_is_empty(host->unixsocket)) {
22070 proc->port = host->port;
22072 buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
22076 fastcgi_status_init(srv, p->statuskey, host, proc);
22078 host->first = proc;
22081 host->min_procs = 1;
22082 host->max_procs = 1;
22086 if (!buffer_is_empty(fcgi_mode)) {
22087 if (strcmp(fcgi_mode->ptr, "responder") == 0) {
22088 host->mode = FCGI_RESPONDER;
22089 @@ -1411,16 +1409,16 @@
22095 buffer_free(fcgi_mode);
22098 return HANDLER_GO_ON;
22101 static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) {
22102 hctx->state = state;
22103 hctx->state_timestamp = srv->cur_ts;
22109 @@ -1429,13 +1427,13 @@
22112 buffer_uint *r = &(p->fcgi_request_id);
22117 for (i = 0; i < r->used; i++) {
22118 if (r->ptr[i] > m) m = r->ptr[i];
22122 if (r->size == 0) {
22124 r->ptr = malloc(sizeof(*r->ptr) * r->size);
22125 @@ -1443,54 +1441,54 @@
22127 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
22131 r->ptr[r->used++] = ++m;
22137 static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
22139 buffer_uint *r = &(p->fcgi_request_id);
22144 for (i = 0; i < r->used; i++) {
22145 if (r->ptr[i] == request_id) break;
22149 if (i != r->used) {
22153 if (i != r->used - 1) {
22154 r->ptr[i] = r->ptr[r->used - 1];
22162 void fcgi_connection_close(server *srv, handler_ctx *hctx) {
22167 if (NULL == hctx) return;
22170 p = hctx->plugin_data;
22171 con = hctx->remote_conn;
22174 if (con->mode != p->id) {
22180 if (hctx->fd != -1) {
22181 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
22182 fdevent_unregister(srv->ev, hctx->fd);
22188 if (hctx->request_id != 0) {
22189 fcgi_requestid_del(srv, p, hctx->request_id);
22191 @@ -1499,7 +1497,7 @@
22192 if (hctx->got_proc) {
22193 /* after the connect the process gets a load */
22194 hctx->proc->load--;
22197 status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
22199 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
22200 @@ -1509,39 +1507,39 @@
22202 if (p->conf.debug) {
22203 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
22204 - "released proc:",
22205 - "pid:", hctx->proc->pid,
22206 - "socket:", hctx->proc->connection_name,
22207 + "released proc:",
22208 + "pid:", hctx->proc->pid,
22209 + "socket:", hctx->proc->connection_name,
22210 "load:", hctx->proc->load);
22217 handler_ctx_free(hctx);
22218 - con->plugin_ctx[p->id] = NULL;
22219 + con->plugin_ctx[p->id] = NULL;
22222 static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
22223 plugin_data *p = hctx->plugin_data;
22234 * connect was ok, connection was accepted
22235 * but the php accept loop checks after the accept if it should die or not.
22237 - * if yes we can only detect it at a write()
22240 + * if yes we can only detect it at a write()
22242 * next step is resetting this attemp and setup a connection again
22245 * if we have more then 5 reconnects for the same request, die
22252 * we have a connection but the child died by some other reason
22257 if (hctx->fd != -1) {
22258 @@ -1551,59 +1549,59 @@
22264 fcgi_requestid_del(srv, p, hctx->request_id);
22267 fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
22270 hctx->request_id = 0;
22271 hctx->reconnects++;
22274 if (p->conf.debug > 2) {
22276 log_error_write(srv, __FILE__, __LINE__, "sdb",
22277 - "release proc for reconnect:",
22278 + "release proc for reconnect:",
22279 hctx->proc->pid, hctx->proc->connection_name);
22281 log_error_write(srv, __FILE__, __LINE__, "sb",
22282 - "release proc for reconnect:",
22283 + "release proc for reconnect:",
22284 hctx->host->unixsocket);
22288 - if (hctx->proc && hctx->got_proc) {
22289 + if (hctx->proc && hctx->got_proc) {
22290 hctx->proc->load--;
22293 /* perhaps another host gives us more luck */
22294 hctx->host->load--;
22302 static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
22303 plugin_data *p = p_d;
22306 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
22309 return HANDLER_GO_ON;
22313 static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
22317 if (!key || !val) return -1;
22320 len = key_len + val_len;
22323 len += key_len > 127 ? 4 : 1;
22324 len += val_len > 127 ? 4 : 1;
22327 buffer_prepare_append(env, len);
22330 if (key_len > 127) {
22331 env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
22332 env->ptr[env->used++] = (key_len >> 16) & 0xff;
22333 @@ -1612,7 +1610,7 @@
22335 env->ptr[env->used++] = (key_len >> 0) & 0xff;
22339 if (val_len > 127) {
22340 env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
22341 env->ptr[env->used++] = (val_len >> 16) & 0xff;
22342 @@ -1621,12 +1619,12 @@
22344 env->ptr[env->used++] = (val_len >> 0) & 0xff;
22348 memcpy(env->ptr + env->used, key, key_len);
22349 env->used += key_len;
22350 memcpy(env->ptr + env->used, val, val_len);
22351 env->used += val_len;
22357 @@ -1639,11 +1637,11 @@
22358 header->contentLengthB1 = (contentLength >> 8) & 0xff;
22359 header->paddingLength = paddingLength;
22360 header->reserved = 0;
22371 @@ -1665,26 +1663,23 @@
22372 struct sockaddr_un fcgi_addr_un;
22377 fcgi_extension_host *host = hctx->host;
22378 fcgi_proc *proc = hctx->proc;
22379 int fcgi_fd = hctx->fd;
22382 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
22385 if (!buffer_is_empty(proc->unixsocket)) {
22386 #ifdef HAVE_SYS_UN_H
22387 /* use the unix domain socket */
22388 fcgi_addr_un.sun_family = AF_UNIX;
22389 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
22392 servlen = SUN_LEN(&fcgi_addr_un);
22394 - /* stevens says: */
22395 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
22398 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
22401 if (buffer_is_empty(proc->connection_name)) {
22402 /* on remote spawing we have to set the connection-name now */
22403 buffer_copy_string(proc->connection_name, "unix:");
22404 @@ -1695,16 +1690,18 @@
22407 fcgi_addr_in.sin_family = AF_INET;
22409 if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
22410 - log_error_write(srv, __FILE__, __LINE__, "sbs",
22411 - "converting IP-adress failed for", host->host,
22412 + log_error_write(srv, __FILE__, __LINE__, "sbs",
22413 + "converting IP-adress failed for", host->host,
22414 "\nBe sure to specify an IP address here");
22420 fcgi_addr_in.sin_port = htons(proc->port);
22421 servlen = sizeof(fcgi_addr_in);
22424 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
22426 if (buffer_is_empty(proc->connection_name)) {
22427 @@ -1715,20 +1712,20 @@
22428 buffer_append_long(proc->connection_name, proc->port);
22433 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
22434 - if (errno == EINPROGRESS ||
22435 + if (errno == EINPROGRESS ||
22436 errno == EALREADY ||
22438 if (hctx->conf.debug > 2) {
22439 - log_error_write(srv, __FILE__, __LINE__, "sb",
22440 + log_error_write(srv, __FILE__, __LINE__, "sb",
22441 "connect delayed, will continue later:", proc->connection_name);
22445 return CONNECTION_DELAYED;
22446 } else if (errno == EAGAIN) {
22447 if (hctx->conf.debug) {
22448 - log_error_write(srv, __FILE__, __LINE__, "sbsd",
22449 + log_error_write(srv, __FILE__, __LINE__, "sbsd",
22450 "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
22451 "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
22452 "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
22453 @@ -1736,8 +1733,8 @@
22455 return CONNECTION_OVERLOADED;
22457 - log_error_write(srv, __FILE__, __LINE__, "sssb",
22458 - "connect failed:",
22459 + log_error_write(srv, __FILE__, __LINE__, "sssb",
22460 + "connect failed:",
22461 strerror(errno), "on",
22462 proc->connection_name);
22464 @@ -1747,7 +1744,7 @@
22466 hctx->reconnects = 0;
22467 if (hctx->conf.debug > 1) {
22468 - log_error_write(srv, __FILE__, __LINE__, "sd",
22469 + log_error_write(srv, __FILE__, __LINE__, "sd",
22470 "connect succeeded: ", fcgi_fd);
22473 @@ -1756,21 +1753,21 @@
22475 static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
22479 for (i = 0; i < con->request.headers->used; i++) {
22483 ds = (data_string *)con->request.headers->data[i];
22486 if (ds->value->used && ds->key->used) {
22488 buffer_reset(srv->tmp_buf);
22491 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
22492 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
22493 srv->tmp_buf->used--;
22497 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22498 for (j = 0; j < ds->key->used - 1; j++) {
22500 @@ -1784,20 +1781,20 @@
22501 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22503 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22506 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22511 for (i = 0; i < con->environment->used; i++) {
22515 ds = (data_string *)con->environment->data[i];
22518 if (ds->value->used && ds->key->used) {
22520 buffer_reset(srv->tmp_buf);
22523 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22524 for (j = 0; j < ds->key->used - 1; j++) {
22526 @@ -1811,11 +1808,11 @@
22527 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22529 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22532 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22540 @@ -1824,24 +1821,24 @@
22541 FCGI_BeginRequestRecord beginRecord;
22542 FCGI_Header header;
22549 char b2[INET6_ADDRSTRLEN + 1];
22553 plugin_data *p = hctx->plugin_data;
22554 fcgi_extension_host *host= hctx->host;
22556 connection *con = hctx->remote_conn;
22557 server_socket *srv_sock = con->srv_socket;
22560 sock_addr our_addr;
22561 socklen_t our_addr_len;
22564 /* send FCGI_BEGIN_REQUEST */
22567 fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0);
22568 beginRecord.body.roleB0 = host->mode;
22569 beginRecord.body.roleB1 = 0;
22570 @@ -1849,21 +1846,21 @@
22571 memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
22573 b = chunkqueue_get_append_buffer(hctx->wb);
22576 buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
22579 /* send FCGI_PARAMS */
22580 buffer_prepare_copy(p->fcgi_env, 1024);
22583 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
22586 if (con->server_name->used) {
22587 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
22590 - s = inet_ntop(srv_sock->addr.plain.sa_family,
22591 - srv_sock->addr.plain.sa_family == AF_INET6 ?
22592 + s = inet_ntop(srv_sock->addr.plain.sa_family,
22593 + srv_sock->addr.plain.sa_family == AF_INET6 ?
22594 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
22595 (const void *) &(srv_sock->addr.ipv4.sin_addr),
22597 @@ -1872,50 +1869,50 @@
22599 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
22603 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
22609 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
22611 ntohs(srv_sock->addr.ipv4.sin_port)
22616 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
22619 /* get the server-side of the connection to the client */
22620 our_addr_len = sizeof(our_addr);
22623 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
22624 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
22626 s = inet_ntop_cache_get_ip(srv, &(our_addr));
22628 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
22634 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
22636 ntohs(con->dst_addr.ipv4.sin_port)
22641 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
22644 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
22645 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
22648 if (!buffer_is_empty(con->authed_user)) {
22649 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
22650 CONST_BUF_LEN(con->authed_user));
22654 if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
22655 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
22658 /* request.content_length < SSIZE_MAX, see request.c */
22659 ltostr(buf, con->request.content_length);
22660 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
22661 @@ -1930,12 +1927,12 @@
22664 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
22667 if (!buffer_is_empty(con->request.pathinfo)) {
22668 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
22671 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
22674 if (!buffer_is_empty(host->docroot)) {
22675 buffer_copy_string_buffer(p->path, host->docroot);
22677 @@ -1957,27 +1954,27 @@
22680 if (!buffer_is_empty(host->docroot)) {
22682 - * rewrite SCRIPT_FILENAME
22685 + * rewrite SCRIPT_FILENAME
22690 buffer_copy_string_buffer(p->path, host->docroot);
22691 buffer_append_string_buffer(p->path, con->uri.path);
22694 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22695 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
22697 buffer_copy_string_buffer(p->path, con->physical.path);
22699 - /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22702 + /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22704 * see src/sapi/cgi_main.c, init_request_info()
22706 if (host->break_scriptfilename_for_php) {
22707 buffer_append_string_buffer(p->path, con->request.pathinfo);
22711 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22712 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
22714 @@ -1987,7 +1984,7 @@
22718 - * stripping /app1 or /app1/ should lead to
22719 + * stripping /app1 or /app1/ should lead to
22723 @@ -2001,7 +1998,7 @@
22724 0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
22725 /* the left is the same */
22727 - fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
22728 + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
22729 con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
22730 con->request.orig_uri->used - (host->strip_request_uri->used - 2));
22732 @@ -2018,26 +2015,26 @@
22734 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
22738 s = get_http_method_name(con->request.http_method);
22739 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
22740 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
22741 s = get_http_version_name(con->request.http_version);
22742 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
22746 if (srv_sock->is_ssl) {
22747 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
22754 fcgi_env_add_request_headers(srv, con, p);
22757 fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
22758 buffer_append_memory(b, (const char *)&header, sizeof(header));
22759 buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used);
22762 fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
22763 buffer_append_memory(b, (const char *)&header, sizeof(header));
22765 @@ -2057,7 +2054,7 @@
22767 /* we announce toWrite octects
22768 * now take all the request_content chunk that we need to fill this request
22772 b = chunkqueue_get_append_buffer(hctx->wb);
22773 fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0);
22774 @@ -2080,16 +2077,16 @@
22775 if (weHave > weWant - written) weHave = weWant - written;
22777 if (p->conf.debug > 10) {
22778 - fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22779 - __FILE__, __LINE__,
22782 - req_c->file.length,
22783 + fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22784 + __FILE__, __LINE__,
22787 + req_c->file.length,
22788 req_c->file.name->ptr);
22791 assert(weHave != 0);
22794 chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
22796 req_c->offset += weHave;
22797 @@ -2104,7 +2101,7 @@
22798 * - we reference the tempfile from the request-content-queue several times
22799 * if the req_c is larger than FCGI_MAX_LENGTH
22800 * - we can't simply cleanup the request-content-queue as soon as possible
22801 - * as it would remove the tempfiles
22802 + * as it would remove the tempfiles
22803 * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
22804 * referencing chunk of the fastcgi-write-queue
22806 @@ -2141,7 +2138,7 @@
22807 req_c->offset += weHave;
22808 req_cq->bytes_out += weHave;
22812 hctx->wb->bytes_in += weHave;
22814 if (req_c->offset == req_c->mem->used - 1) {
22815 @@ -2155,12 +2152,12 @@
22821 b->used++; /* add virtual \0 */
22827 b = chunkqueue_get_append_buffer(hctx->wb);
22828 /* terminate STDIN */
22829 fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0);
22830 @@ -2175,118 +2172,19 @@
22831 if ((i+1) % 16 == 0) {
22833 for (j = i-15; j <= i; j++) {
22834 - fprintf(stderr, "%c",
22835 + fprintf(stderr, "%c",
22836 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
22838 fprintf(stderr, "\n");
22846 -static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
22849 - handler_ctx *hctx = con->plugin_ctx[p->id];
22850 - fcgi_extension_host *host= hctx->host;
22854 - buffer_copy_string_buffer(p->parse_response, in);
22856 - /* search for \n */
22857 - for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
22858 - char *key, *value;
22862 - /* a good day. Someone has read the specs and is sending a \r\n to us */
22864 - if (ns > p->parse_response->ptr &&
22865 - *(ns-1) == '\r') {
22872 - if (NULL == (value = strchr(s, ':'))) {
22873 - /* we expect: "<key>: <value>\n" */
22877 - key_len = value - key;
22881 - while (*value == ' ' || *value == '\t') value++;
22883 - if (host->mode != FCGI_AUTHORIZER ||
22884 - !(con->http_status == 0 ||
22885 - con->http_status == 200)) {
22886 - /* authorizers shouldn't affect the response headers sent back to the client */
22888 - /* don't forward Status: */
22889 - if (0 != strncasecmp(key, "Status", key_len)) {
22890 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
22891 - ds = data_response_init();
22893 - buffer_copy_string_len(ds->key, key, key_len);
22894 - buffer_copy_string(ds->value, value);
22896 - array_insert_unique(con->response.headers, (data_unset *)ds);
22900 - switch(key_len) {
22902 - if (0 == strncasecmp(key, "Date", key_len)) {
22903 - con->parsed_response |= HTTP_DATE;
22907 - if (0 == strncasecmp(key, "Status", key_len)) {
22908 - con->http_status = strtol(value, NULL, 10);
22909 - con->parsed_response |= HTTP_STATUS;
22913 - if (0 == strncasecmp(key, "Location", key_len)) {
22914 - con->parsed_response |= HTTP_LOCATION;
22918 - if (0 == strncasecmp(key, "Connection", key_len)) {
22919 - con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
22920 - con->parsed_response |= HTTP_CONNECTION;
22924 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
22925 - con->response.content_length = strtol(value, NULL, 10);
22926 - con->parsed_response |= HTTP_CONTENT_LENGTH;
22928 - if (con->response.content_length < 0) con->response.content_length = 0;
22936 - /* CGI/1.1 rev 03 - 7.2.1.2 */
22937 - if ((con->parsed_response & HTTP_LOCATION) &&
22938 - !(con->parsed_response & HTTP_STATUS)) {
22939 - con->http_status = 302;
22951 @@ -2327,9 +2225,9 @@
22955 - /* we have at least a header, now check how much me have to fetch */
22956 + /* we have at least a header, now check how much me have to fetch */
22957 header = (FCGI_Header *)(packet->b->ptr);
22960 packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
22961 packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
22962 packet->type = header->type;
22963 @@ -2348,7 +2246,7 @@
22964 size_t weHave = c->mem->used - c->offset - offset - 1;
22966 if (weHave > weWant) weHave = weWant;
22969 buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
22971 /* we only skipped the first 8 bytes as they are the fcgi header */
22972 @@ -2380,65 +2278,37 @@
22975 chunkqueue_remove_finished_chunks(hctx->rb);
22981 static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
22987 plugin_data *p = hctx->plugin_data;
22988 connection *con = hctx->remote_conn;
22989 - int fcgi_fd = hctx->fd;
22990 fcgi_extension_host *host= hctx->host;
22991 fcgi_proc *proc = hctx->proc;
22994 - * check how much we have to read
22996 - if (ioctl(hctx->fd, FIONREAD, &toread)) {
22997 - log_error_write(srv, __FILE__, __LINE__, "sd",
22998 - "unexpected end-of-file (perhaps the fastcgi process died):",
23003 - /* init read-buffer */
23005 - if (toread > 0) {
23008 - b = chunkqueue_get_append_buffer(hctx->rb);
23009 - buffer_prepare_copy(b, toread + 1);
23011 - /* append to read-buffer */
23012 - if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
23013 - log_error_write(srv, __FILE__, __LINE__, "sds",
23014 - "unexpected end-of-file (perhaps the fastcgi process died):",
23015 - fcgi_fd, strerror(errno));
23019 - /* this should be catched by the b > 0 above */
23022 - b->used = r + 1; /* one extra for the fake \0 */
23023 - b->ptr[b->used - 1] = '\0';
23025 - log_error_write(srv, __FILE__, __LINE__, "ssdsb",
23026 + switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) {
23027 + case NETWORK_STATUS_WAIT_FOR_EVENT:
23028 + /* we are only triggered when there is a event */
23029 + log_error_write(srv, __FILE__, __LINE__, "ssdsb",
23030 "unexpected end-of-file (perhaps the fastcgi process died):",
23032 "socket:", proc->connection_name);
23035 + case NETWORK_STATUS_SUCCESS:
23038 + log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
23043 * parse the fastcgi packets and forward the content to the write-queue
23048 fastcgi_response_packet packet;
23050 @@ -2454,92 +2324,135 @@
23052 /* is the header already finished */
23053 if (0 == con->file_started) {
23058 - /* search for header terminator
23060 - * if we start with \r\n check if last packet terminated with \r\n
23061 - * if we start with \n check if last packet terminated with \n
23062 - * search for \r\n\r\n
23063 - * search for \n\n
23066 - if (hctx->response_header->used == 0) {
23067 - buffer_copy_string_buffer(hctx->response_header, packet.b);
23069 - buffer_append_string_buffer(hctx->response_header, packet.b);
23072 - if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
23073 - blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
23074 - hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
23075 - c += 4; /* point the the start of the response */
23076 - } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
23077 - blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
23078 - hctx->response_header->used = c - hctx->response_header->ptr + 2;
23079 - c += 2; /* point the the start of the response */
23081 - /* no luck, no header found */
23082 + int have_content_length = 0;
23083 + int need_more = 0;
23086 + /* append the current packet to the chunk queue */
23087 + chunkqueue_append_buffer(hctx->http_rb, packet.b);
23088 + http_response_reset(p->resp);
23090 + switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
23091 + case PARSE_ERROR:
23092 + /* parsing the response header failed */
23094 + con->http_status = 502; /* Bad Gateway */
23097 + case PARSE_NEED_MORE:
23099 + break; /* leave the loop */
23100 + case PARSE_SUCCESS:
23103 + /* should not happen */
23107 - /* parse the response header */
23108 - fcgi_response_parse(srv, con, p, hctx->response_header);
23109 + if (need_more) break;
23111 - con->file_started = 1;
23112 + chunkqueue_remove_finished_chunks(hctx->http_rb);
23114 - if (host->mode == FCGI_AUTHORIZER &&
23115 - (con->http_status == 0 ||
23116 - con->http_status == 200)) {
23117 - /* a authorizer with approved the static request, ignore the content here */
23118 - hctx->send_content_body = 0;
23121 - if (host->allow_xsendfile &&
23122 - NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
23123 - stat_cache_entry *sce;
23125 - if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
23128 - http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
23129 - hctx->send_content_body = 0; /* ignore the content */
23130 - joblist_append(srv, con);
23131 + con->http_status = p->resp->status;
23133 + /* handle the header fields */
23134 + if (host->mode == FCGI_AUTHORIZER) {
23135 + /* auth mode is a bit different */
23137 + if (con->http_status == 0 ||
23138 + con->http_status == 200) {
23139 + /* a authorizer with approved the static request, ignore the content here */
23140 + hctx->send_content_body = 0;
23144 + /* copy the http-headers */
23145 + for (i = 0; i < p->resp->headers->used; i++) {
23146 + const char *ign[] = { "Status", NULL };
23150 + data_string *header = (data_string *)p->resp->headers->data[i];
23152 + /* ignore all headers in AUTHORIZER mode */
23153 + if (host->mode == FCGI_AUTHORIZER) continue;
23155 + /* some headers are ignored by default */
23156 + for (j = 0; ign[j]; j++) {
23157 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
23159 + if (ign[j]) continue;
23161 + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
23162 + /* CGI/1.1 rev 03 - 7.2.1.2 */
23163 + con->http_status = 302;
23164 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
23165 + have_content_length = 1;
23166 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) ||
23167 + 0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
23169 + stat_cache_entry *sce;
23171 - if (hctx->send_content_body && blen > 1) {
23172 - /* enable chunked-transfer-encoding */
23173 + if (host->allow_xsendfile &&
23174 + HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
23175 + http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
23176 + hctx->send_content_body = 0; /* ignore the content */
23178 + joblist_append(srv, con);
23181 + continue; /* ignore header */
23184 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
23185 + ds = data_response_init();
23187 + buffer_copy_string_buffer(ds->key, header->key);
23188 + buffer_copy_string_buffer(ds->value, header->value);
23190 + array_insert_unique(con->response.headers, (data_unset *)ds);
23193 + /* header is complete ... go on with the body */
23195 + con->file_started = 1;
23197 + if (hctx->send_content_body) {
23198 + chunk *c = hctx->http_rb->first;
23200 + /* if we don't have a content-length enable chunked encoding
23203 + * TODO: move this to a later stage in the filter-queue
23205 if (con->request.http_version == HTTP_VERSION_1_1 &&
23206 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23207 + !have_content_length) {
23208 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23211 - http_chunk_append_mem(srv, con, c, blen);
23212 + /* copy the rest of the data */
23213 + for (c = hctx->http_rb->first; c; c = c->next) {
23214 + if (c->mem->used > 1) {
23215 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
23216 + c->offset = c->mem->used - 1;
23219 + chunkqueue_remove_finished_chunks(hctx->http_rb);
23220 joblist_append(srv, con);
23222 } else if (hctx->send_content_body && packet.b->used > 1) {
23223 - if (con->request.http_version == HTTP_VERSION_1_1 &&
23224 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23225 - /* enable chunked-transfer-encoding */
23226 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23229 http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
23230 joblist_append(srv, con);
23234 - log_error_write(srv, __FILE__, __LINE__, "sb",
23235 + log_error_write(srv, __FILE__, __LINE__, "sb",
23236 "FastCGI-stderr:", packet.b);
23240 case FCGI_END_REQUEST:
23241 con->file_finished = 1;
23244 if (host->mode != FCGI_AUTHORIZER ||
23245 !(con->http_status == 0 ||
23246 con->http_status == 200)) {
23247 @@ -2547,39 +2460,39 @@
23248 http_chunk_append_mem(srv, con, NULL, 0);
23249 joblist_append(srv, con);
23256 - log_error_write(srv, __FILE__, __LINE__, "sd",
23257 + log_error_write(srv, __FILE__, __LINE__, "sd",
23258 "FastCGI: header.type not handled: ", packet.type);
23261 buffer_free(packet.b);
23268 static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
23272 for (proc = host->first; proc; proc = proc->next) {
23275 if (p->conf.debug > 2) {
23276 - log_error_write(srv, __FILE__, __LINE__, "sbdddd",
23278 + log_error_write(srv, __FILE__, __LINE__, "sbdddd",
23280 proc->connection_name,
23290 * if the remote side is overloaded, we check back after <n> seconds
23294 switch (proc->state) {
23295 case PROC_STATE_KILLED:
23296 @@ -2592,13 +2505,13 @@
23298 case PROC_STATE_OVERLOADED:
23299 if (srv->cur_ts <= proc->disabled_until) break;
23302 proc->state = PROC_STATE_RUNNING;
23303 host->active_procs++;
23305 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
23306 - "fcgi-server re-enabled:",
23307 - host->host, host->port,
23309 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
23310 + "fcgi-server re-enabled:",
23311 + host->host, host->port,
23314 case PROC_STATE_DIED_WAIT_FOR_PID:
23315 @@ -2606,7 +2519,7 @@
23316 if (!proc->is_local) break;
23318 /* the child should not terminate at all */
23321 switch(waitpid(proc->pid, &status, WNOHANG)) {
23323 /* child is still alive */
23324 @@ -2616,45 +2529,45 @@
23326 if (WIFEXITED(status)) {
23328 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
23329 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
23330 "child exited, pid:", proc->pid,
23331 "status:", WEXITSTATUS(status));
23333 } else if (WIFSIGNALED(status)) {
23334 - log_error_write(srv, __FILE__, __LINE__, "sd",
23335 - "child signaled:",
23336 + log_error_write(srv, __FILE__, __LINE__, "sd",
23337 + "child signaled:",
23340 - log_error_write(srv, __FILE__, __LINE__, "sd",
23341 - "child died somehow:",
23342 + log_error_write(srv, __FILE__, __LINE__, "sd",
23343 + "child died somehow:",
23348 proc->state = PROC_STATE_DIED;
23353 /* fall through if we have a dead proc now */
23354 if (proc->state != PROC_STATE_DIED) break;
23356 case PROC_STATE_DIED:
23357 - /* local proc get restarted by us,
23358 + /* local proc get restarted by us,
23359 * remote ones hopefully by the admin */
23362 if (proc->is_local) {
23363 /* we still have connections bound to this proc,
23364 * let them terminate first */
23365 if (proc->load != 0) break;
23368 /* restart the child */
23371 if (p->conf.debug) {
23372 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23373 "--- fastcgi spawning",
23374 "\n\tsocket", proc->connection_name,
23375 "\n\tcurrent:", 1, "/", host->min_procs);
23379 if (fcgi_spawn_connection(srv, p, host, proc)) {
23380 log_error_write(srv, __FILE__, __LINE__, "s",
23381 "ERROR: spawning fcgi failed.");
23382 @@ -2662,18 +2575,18 @@
23385 if (srv->cur_ts <= proc->disabled_until) break;
23388 proc->state = PROC_STATE_RUNNING;
23389 host->active_procs++;
23391 - log_error_write(srv, __FILE__, __LINE__, "sb",
23392 - "fcgi-server re-enabled:",
23394 + log_error_write(srv, __FILE__, __LINE__, "sb",
23395 + "fcgi-server re-enabled:",
23396 proc->connection_name);
23406 @@ -2682,19 +2595,19 @@
23407 fcgi_extension_host *host= hctx->host;
23408 connection *con = hctx->remote_conn;
23414 - /* sanity check */
23415 + /* sanity check */
23417 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
23418 - log_error_write(srv, __FILE__, __LINE__, "sxddd",
23419 + log_error_write(srv, __FILE__, __LINE__, "sxddd",
23420 "write-req: error",
23424 host->unixsocket->used);
23427 hctx->proc->disabled_until = srv->cur_ts + 10;
23428 hctx->proc->state = PROC_STATE_DIED;
23430 @@ -2705,12 +2618,12 @@
23431 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23433 socklen_t socket_error_len = sizeof(socket_error);
23436 /* try to finish the connect() */
23437 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
23438 - log_error_write(srv, __FILE__, __LINE__, "ss",
23439 + log_error_write(srv, __FILE__, __LINE__, "ss",
23440 "getsockopt failed:", strerror(errno));
23443 hctx->proc->disabled_until = srv->cur_ts + 10;
23444 hctx->proc->state = PROC_STATE_DIED;
23446 @@ -2719,12 +2632,12 @@
23447 if (socket_error != 0) {
23448 if (!hctx->proc->is_local || p->conf.debug) {
23449 /* local procs get restarted */
23452 log_error_write(srv, __FILE__, __LINE__, "sssb",
23453 - "establishing connection failed:", strerror(socket_error),
23454 + "establishing connection failed:", strerror(socket_error),
23455 "socket:", hctx->proc->connection_name);
23459 hctx->proc->disabled_until = srv->cur_ts + 5;
23461 if (hctx->proc->is_local) {
23462 @@ -2732,17 +2645,17 @@
23464 hctx->proc->state = PROC_STATE_DIED;
23468 hctx->proc->state = PROC_STATE_DIED;
23471 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23472 buffer_append_string(p->statuskey, ".died");
23474 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23477 return HANDLER_ERROR;
23479 - /* go on with preparing the request */
23480 + /* go on with preparing the request */
23481 hctx->state = FCGI_STATE_PREPARE_WRITE;
23484 @@ -2755,14 +2668,14 @@
23485 /* do we have a running process for this host (max-procs) ? */
23488 - for (proc = hctx->host->first;
23489 - proc && proc->state != PROC_STATE_RUNNING;
23490 + for (proc = hctx->host->first;
23491 + proc && proc->state != PROC_STATE_RUNNING;
23492 proc = proc->next);
23495 /* all childs are dead */
23496 if (proc == NULL) {
23497 hctx->fde_ndx = -1;
23500 return HANDLER_ERROR;
23503 @@ -2775,50 +2688,50 @@
23506 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
23509 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
23510 if (errno == EMFILE ||
23512 - log_error_write(srv, __FILE__, __LINE__, "sd",
23513 + log_error_write(srv, __FILE__, __LINE__, "sd",
23514 "wait for fd at connection:", con->fd);
23517 return HANDLER_WAIT_FOR_FD;
23520 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
23522 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
23523 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
23524 return HANDLER_ERROR;
23526 hctx->fde_ndx = -1;
23532 fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
23535 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
23536 - log_error_write(srv, __FILE__, __LINE__, "ss",
23537 + log_error_write(srv, __FILE__, __LINE__, "ss",
23538 "fcntl failed:", strerror(errno));
23541 return HANDLER_ERROR;
23545 if (hctx->proc->is_local) {
23546 hctx->pid = hctx->proc->pid;
23550 switch (fcgi_establish_connection(srv, hctx)) {
23551 case CONNECTION_DELAYED:
23552 /* connection is in progress, wait for an event and call getsockopt() below */
23555 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23558 fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED);
23559 return HANDLER_WAIT_FOR_EVENT;
23560 case CONNECTION_OVERLOADED:
23561 /* cool down the backend, it is overloaded
23564 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23565 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23566 "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
23567 "reconnects:", hctx->reconnects,
23568 "load:", host->load);
23569 @@ -2831,7 +2744,7 @@
23570 buffer_append_string(p->statuskey, ".overloaded");
23572 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23575 return HANDLER_ERROR;
23576 case CONNECTION_DEAD:
23577 /* we got a hard error from the backend like
23578 @@ -2840,19 +2753,19 @@
23580 * for check if the host is back in 5 seconds
23584 hctx->proc->disabled_until = srv->cur_ts + 5;
23585 if (hctx->proc->is_local) {
23586 hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
23588 hctx->proc->state = PROC_STATE_DIED;
23591 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23593 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23594 "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
23595 "reconnects:", hctx->reconnects,
23596 "load:", host->load);
23599 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23600 buffer_append_string(p->statuskey, ".died");
23602 @@ -2863,19 +2776,19 @@
23603 /* everything is ok, go on */
23605 fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
23609 case CONNECTION_UNSET:
23614 case FCGI_STATE_PREPARE_WRITE:
23615 /* ok, we have the connection */
23618 hctx->proc->load++;
23619 hctx->proc->last_used = srv->cur_ts;
23620 hctx->got_proc = 1;
23623 status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
23624 status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
23626 @@ -2898,9 +2811,9 @@
23628 if (p->conf.debug) {
23629 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
23631 - "pid:", hctx->proc->pid,
23632 - "socket:", hctx->proc->connection_name,
23634 + "pid:", hctx->proc->pid,
23635 + "socket:", hctx->proc->connection_name,
23636 "load:", hctx->proc->load);
23639 @@ -2908,62 +2821,63 @@
23640 if (hctx->request_id == 0) {
23641 hctx->request_id = fcgi_requestid_new(srv, p);
23643 - log_error_write(srv, __FILE__, __LINE__, "sd",
23644 + log_error_write(srv, __FILE__, __LINE__, "sd",
23645 "fcgi-request is already in use:", hctx->request_id);
23650 fcgi_create_env(srv, hctx, hctx->request_id);
23653 fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
23657 case FCGI_STATE_WRITE:
23658 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
23659 + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
23661 chunkqueue_remove_finished_chunks(hctx->wb);
23667 - /* the connection got dropped after accept()
23669 - * this is most of the time a PHP which dies
23670 + /* the connection got dropped after accept()
23672 + * this is most of the time a PHP which dies
23673 * after PHP_FCGI_MAX_REQUESTS
23678 if (hctx->wb->bytes_out == 0 &&
23679 hctx->reconnects < 5) {
23680 - usleep(10000); /* take away the load of the webserver
23681 - * to let the php a chance to restart
23683 + usleep(10000); /* take away the load of the webserver
23684 + * to let the php a chance to restart
23688 fcgi_reconnect(srv, hctx);
23691 return HANDLER_WAIT_FOR_FD;
23695 /* not reconnected ... why
23698 * far@#lighttpd report this for FreeBSD
23703 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23705 + log_error_write(srv, __FILE__, __LINE__, "ssosd",
23706 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
23707 "write-offset:", hctx->wb->bytes_out,
23708 "reconnect attempts:", hctx->reconnects);
23711 return HANDLER_ERROR;
23714 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23717 return HANDLER_WAIT_FOR_EVENT;
23719 - log_error_write(srv, __FILE__, __LINE__, "ssd",
23720 + log_error_write(srv, __FILE__, __LINE__, "ssd",
23721 "write failed:", strerror(errno), errno);
23724 return HANDLER_ERROR;
23727 @@ -2975,7 +2889,7 @@
23728 fcgi_set_state(srv, hctx, FCGI_STATE_READ);
23730 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23733 return HANDLER_WAIT_FOR_EVENT;
23736 @@ -2987,7 +2901,7 @@
23737 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
23738 return HANDLER_ERROR;
23742 return HANDLER_WAIT_FOR_EVENT;
23745 @@ -2996,18 +2910,18 @@
23747 SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
23748 plugin_data *p = p_d;
23751 handler_ctx *hctx = con->plugin_ctx[p->id];
23753 fcgi_extension_host *host;
23756 if (NULL == hctx) return HANDLER_GO_ON;
23760 if (con->mode != p->id) return HANDLER_GO_ON;
23762 /* we don't have a host yet, choose one
23763 - * -> this happens in the first round
23764 + * -> this happens in the first round
23765 * and when the host died and we have to select a new one */
23766 if (hctx->host == NULL) {
23768 @@ -3016,23 +2930,23 @@
23769 /* get best server */
23770 for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
23771 host = hctx->ext->hosts[k];
23774 /* we should have at least one proc that can do something */
23775 if (host->active_procs == 0) continue;
23777 if (used == -1 || host->load < used) {
23786 /* found a server */
23788 /* all hosts are down */
23790 fcgi_connection_close(srv, hctx);
23793 con->http_status = 500;
23794 con->mode = DIRECT;
23796 @@ -3040,16 +2954,16 @@
23799 host = hctx->ext->hosts[ndx];
23802 - * if check-local is disabled, use the uri.path handler
23806 + * if check-local is disabled, use the uri.path handler
23811 /* init handler-context */
23814 - /* we put a connection on this host, move the other new connections to other hosts
23815 + /* we put a connection on this host, move the other new connections to other hosts
23817 * as soon as hctx->host is unassigned, decrease the load again */
23818 hctx->host->load++;
23819 @@ -3063,7 +2977,7 @@
23820 case HANDLER_ERROR:
23825 if (hctx->state == FCGI_STATE_INIT ||
23826 hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23827 if (proc) host->active_procs--;
23828 @@ -3078,7 +2992,7 @@
23829 return HANDLER_WAIT_FOR_FD;
23831 fcgi_connection_close(srv, hctx);
23834 buffer_reset(con->physical.path);
23835 con->mode = DIRECT;
23836 con->http_status = 500;
23837 @@ -3088,12 +3002,12 @@
23840 fcgi_connection_close(srv, hctx);
23843 buffer_reset(con->physical.path);
23844 con->mode = DIRECT;
23845 con->http_status = 503;
23846 joblist_append(srv, con); /* really ? */
23849 return HANDLER_FINISHED;
23851 case HANDLER_WAIT_FOR_EVENT:
23852 @@ -3115,7 +3029,7 @@
23853 handler_ctx *hctx = ctx;
23854 connection *con = hctx->remote_conn;
23855 plugin_data *p = hctx->plugin_data;
23858 fcgi_proc *proc = hctx->proc;
23859 fcgi_extension_host *host= hctx->host;
23861 @@ -3125,8 +3039,8 @@
23866 - if (host->mode == FCGI_AUTHORIZER &&
23868 + if (host->mode == FCGI_AUTHORIZER &&
23869 (con->http_status == 200 ||
23870 con->http_status == 0)) {
23872 @@ -3136,26 +3050,26 @@
23875 buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
23878 buffer_copy_string_buffer(con->physical.path, host->docroot);
23879 buffer_append_string_buffer(con->physical.path, con->uri.path);
23880 fcgi_connection_close(srv, hctx);
23883 con->mode = DIRECT;
23884 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
23887 fcgi_connection_close(srv, hctx);
23891 joblist_append(srv, con);
23892 return HANDLER_FINISHED;
23894 if (proc->pid && proc->state != PROC_STATE_DIED) {
23898 /* only fetch the zombie if it is not already done */
23901 switch(waitpid(proc->pid, &status, WNOHANG)) {
23903 /* child is still alive */
23904 @@ -3165,60 +3079,61 @@
23906 /* the child should not terminate at all */
23907 if (WIFEXITED(status)) {
23908 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
23909 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
23910 "child exited, pid:", proc->pid,
23911 "status:", WEXITSTATUS(status));
23912 } else if (WIFSIGNALED(status)) {
23913 - log_error_write(srv, __FILE__, __LINE__, "sd",
23914 - "child signaled:",
23915 + log_error_write(srv, __FILE__, __LINE__, "sd",
23916 + "child signaled:",
23919 - log_error_write(srv, __FILE__, __LINE__, "sd",
23920 - "child died somehow:",
23921 + log_error_write(srv, __FILE__, __LINE__, "sd",
23922 + "child died somehow:",
23927 if (p->conf.debug) {
23928 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23929 "--- fastcgi spawning",
23930 "\n\tsocket", proc->connection_name,
23931 "\n\tcurrent:", 1, "/", host->min_procs);
23935 if (fcgi_spawn_connection(srv, p, host, proc)) {
23936 /* respawning failed, retry later */
23937 proc->state = PROC_STATE_DIED;
23939 - log_error_write(srv, __FILE__, __LINE__, "s",
23940 + log_error_write(srv, __FILE__, __LINE__, "s",
23941 "respawning failed, will retry later");
23950 if (con->file_started == 0) {
23951 /* nothing has been send out yet, try to use another child */
23954 if (hctx->wb->bytes_out == 0 &&
23955 hctx->reconnects < 5) {
23956 fcgi_reconnect(srv, hctx);
23958 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23960 + log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23961 "response not received, request not sent",
23962 - "on socket:", proc->connection_name,
23963 + "on socket:", proc->connection_name,
23964 "for", con->uri.path, ", reconnecting");
23967 return HANDLER_WAIT_FOR_FD;
23970 - log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
23972 + log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
23973 "response not received, request sent:", hctx->wb->bytes_out,
23974 - "on socket:", proc->connection_name,
23975 + "on socket:", proc->connection_name,
23976 "for", con->uri.path, ", closing connection");
23979 fcgi_connection_close(srv, hctx);
23982 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
23983 buffer_reset(con->physical.path);
23984 con->http_status = 500;
23985 @@ -3226,76 +3141,76 @@
23987 /* response might have been already started, kill the connection */
23988 fcgi_connection_close(srv, hctx);
23990 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23992 + log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
23993 "response already sent out, but backend returned error",
23994 - "on socket:", proc->connection_name,
23995 + "on socket:", proc->connection_name,
23996 "for", con->uri.path, ", terminating connection");
23999 connection_set_state(srv, con, CON_STATE_ERROR);
24007 joblist_append(srv, con);
24008 return HANDLER_FINISHED;
24013 if (revents & FDEVENT_OUT) {
24014 if (hctx->state == FCGI_STATE_CONNECT_DELAYED ||
24015 hctx->state == FCGI_STATE_WRITE) {
24016 /* we are allowed to send something out
24019 * 1. in a unfinished connect() call
24020 * 2. in a unfinished write() call (long POST request)
24022 return mod_fastcgi_handle_subrequest(srv, con, p);
24024 - log_error_write(srv, __FILE__, __LINE__, "sd",
24025 - "got a FDEVENT_OUT and didn't know why:",
24026 + log_error_write(srv, __FILE__, __LINE__, "sd",
24027 + "got a FDEVENT_OUT and didn't know why:",
24033 /* perhaps this issue is already handled */
24034 if (revents & FDEVENT_HUP) {
24035 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
24036 /* getoptsock will catch this one (right ?)
24038 - * if we are in connect we might get a EINPROGRESS
24039 - * in the first call and a FDEVENT_HUP in the
24041 + * if we are in connect we might get a EINPROGRESS
24042 + * in the first call and a FDEVENT_HUP in the
24046 * FIXME: as it is a bit ugly.
24050 return mod_fastcgi_handle_subrequest(srv, con, p);
24051 } else if (hctx->state == FCGI_STATE_READ &&
24052 hctx->proc->port == 0) {
24056 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
24057 * even if the FCGI_FIN packet is not received yet
24060 - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
24061 - "error: unexpected close of fastcgi connection for",
24062 + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
24063 + "error: unexpected close of fastcgi connection for",
24065 - "(no fastcgi process on host:",
24066 + "(no fastcgi process on host:",
24075 connection_set_state(srv, con, CON_STATE_ERROR);
24076 fcgi_connection_close(srv, hctx);
24077 joblist_append(srv, con);
24079 } else if (revents & FDEVENT_ERR) {
24080 - log_error_write(srv, __FILE__, __LINE__, "s",
24081 + log_error_write(srv, __FILE__, __LINE__, "s",
24082 "fcgi: got a FDEVENT_ERR. Don't know why.");
24083 /* kill all connections to the fastcgi process */
24085 @@ -3304,45 +3219,42 @@
24086 fcgi_connection_close(srv, hctx);
24087 joblist_append(srv, con);
24091 return HANDLER_FINISHED;
24093 -#define PATCH(x) \
24094 - p->conf.x = s->x;
24096 static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
24098 plugin_config *s = p->config_storage[0];
24102 - PATCH(ext_mapping);
24105 + PATCH_OPTION(exts);
24106 + PATCH_OPTION(debug);
24107 + PATCH_OPTION(ext_mapping);
24109 /* skip the first, the global context */
24110 for (i = 1; i < srv->config_context->used; i++) {
24111 data_config *dc = (data_config *)srv->config_context->data[i];
24112 s = p->config_storage[i];
24115 /* condition didn't match */
24116 if (!config_check_cond(srv, con, dc)) continue;
24120 for (j = 0; j < dc->value->used; j++) {
24121 data_unset *du = dc->value->data[j];
24124 if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
24126 + PATCH_OPTION(exts);
24127 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
24129 + PATCH_OPTION(debug);
24130 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
24131 - PATCH(ext_mapping);
24132 + PATCH_OPTION(ext_mapping);
24143 static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
24144 plugin_data *p = p_d;
24145 @@ -3351,16 +3263,16 @@
24147 fcgi_extension *extension = NULL;
24148 fcgi_extension_host *host = NULL;
24151 /* Possibly, we processed already this request */
24152 if (con->file_started == 1) return HANDLER_GO_ON;
24154 fn = uri_path_handler ? con->uri.path : con->physical.path;
24156 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
24159 s_len = fn->used - 1;
24162 fcgi_patch_connection(srv, con, p);
24164 /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
24165 @@ -3368,24 +3280,24 @@
24166 * fastcgi.map-extensions = ( ".php3" => ".php" )
24168 * fastcgi.server = ( ".php" => ... )
24173 /* check if extension-mapping matches */
24174 for (k = 0; k < p->conf.ext_mapping->used; k++) {
24175 data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
24176 size_t ct_len; /* length of the config entry */
24179 if (ds->key->used == 0) continue;
24182 ct_len = ds->key->used - 1;
24185 if (s_len < ct_len) continue;
24188 /* found a mapping */
24189 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
24190 /* check if we know the extension */
24193 /* we can reuse k here */
24194 for (k = 0; k < p->conf.exts->used; k++) {
24195 extension = p->conf.exts->exts[k];
24196 @@ -3407,15 +3319,15 @@
24197 /* check if extension matches */
24198 for (k = 0; k < p->conf.exts->used; k++) {
24199 size_t ct_len; /* length of the config entry */
24202 extension = p->conf.exts->exts[k];
24205 if (extension->key->used == 0) continue;
24208 ct_len = extension->key->used - 1;
24211 if (s_len < ct_len) continue;
24214 /* check extension in the form "/fcgi_pattern" */
24215 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
24217 @@ -3441,10 +3353,10 @@
24221 - /* we found one host that is alive */
24222 + /* we found one host that is alive */
24228 /* sorry, we don't have a server alive for this ext */
24229 buffer_reset(con->physical.path);
24230 @@ -3459,72 +3371,72 @@
24231 "on", extension->key,
24236 return HANDLER_FINISHED;
24239 /* a note about no handler is not sent yey */
24240 extension->note_is_sent = 0;
24243 - * if check-local is disabled, use the uri.path handler
24246 + * if check-local is disabled, use the uri.path handler
24251 /* init handler-context */
24252 if (uri_path_handler) {
24253 if (host->check_local == 0) {
24258 hctx = handler_ctx_init();
24261 hctx->remote_conn = con;
24262 hctx->plugin_data = p;
24264 hctx->ext = extension;
24268 hctx->conf.exts = p->conf.exts;
24269 hctx->conf.debug = p->conf.debug;
24272 con->plugin_ctx[p->id] = hctx;
24278 if (con->conf.log_request_handling) {
24279 - log_error_write(srv, __FILE__, __LINE__, "s",
24280 + log_error_write(srv, __FILE__, __LINE__, "s",
24281 "handling it in mod_fastcgi");
24284 - /* the prefix is the SCRIPT_NAME,
24286 + /* the prefix is the SCRIPT_NAME,
24287 * everthing from start to the next slash
24288 * this is important for check-local = "disable"
24291 * if prefix = /admin.fcgi
24294 * /admin.fcgi/foo/bar
24297 * SCRIPT_NAME = /admin.fcgi
24298 * PATH_INFO = /foo/bar
24301 * if prefix = /fcgi-bin/
24304 * /fcgi-bin/foo/bar
24307 * SCRIPT_NAME = /fcgi-bin/foo
24314 /* the rewrite is only done for /prefix/? matches */
24315 if (extension->key->ptr[0] == '/' &&
24316 con->uri.path->used > extension->key->used &&
24317 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
24318 - /* rewrite uri.path and pathinfo */
24320 + /* rewrite uri.path and pathinfo */
24322 buffer_copy_string(con->request.pathinfo, pathinfo);
24325 con->uri.path->used -= con->request.pathinfo->used - 1;
24326 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
24328 @@ -3532,19 +3444,19 @@
24331 hctx = handler_ctx_init();
24334 hctx->remote_conn = con;
24335 hctx->plugin_data = p;
24337 hctx->ext = extension;
24340 hctx->conf.exts = p->conf.exts;
24341 hctx->conf.debug = p->conf.debug;
24344 con->plugin_ctx[p->id] = hctx;
24350 if (con->conf.log_request_handling) {
24351 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
24353 @@ -3566,19 +3478,19 @@
24354 JOBLIST_FUNC(mod_fastcgi_handle_joblist) {
24355 plugin_data *p = p_d;
24356 handler_ctx *hctx = con->plugin_ctx[p->id];
24359 if (hctx == NULL) return HANDLER_GO_ON;
24361 if (hctx->fd != -1) {
24362 switch (hctx->state) {
24363 case FCGI_STATE_READ:
24364 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
24368 case FCGI_STATE_CONNECT_DELAYED:
24369 case FCGI_STATE_WRITE:
24370 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24374 case FCGI_STATE_INIT:
24376 @@ -3595,7 +3507,7 @@
24378 static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
24379 plugin_data *p = p_d;
24382 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
24384 return HANDLER_GO_ON;
24385 @@ -3604,16 +3516,39 @@
24386 TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
24387 plugin_data *p = p_d;
24393 /* perhaps we should kill a connect attempt after 10-15 seconds
24396 * currently we wait for the TCP timeout which is on Linux 180 seconds
24403 + for (i = 0; i < srv->conns->used; i++) {
24404 + connection *con = srv->conns->ptr[i];
24405 + handler_ctx *hctx = con->plugin_ctx[p->id];
24407 + /* if a connection is ours and is in handle-req for more than max-request-time
24408 + * kill the connection */
24410 + if (con->mode != p->id) continue;
24411 + if (con->state != CON_STATE_HANDLE_REQUEST) continue;
24412 + if (srv->cur_ts < con->request_start + 60) continue;
24414 + /* the request is waiting for a FCGI_STDOUT since 60 seconds */
24416 + /* kill the connection */
24418 + log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
24420 + fcgi_connection_close(srv, hctx);
24422 + con->mode = DIRECT;
24423 + con->http_status = 500;
24425 + joblist_append(srv, con);
24428 /* check all childs if they are still up */
24430 for (i = 0; i < srv->config_context->used; i++) {
24431 @@ -3628,45 +3563,45 @@
24432 fcgi_extension *ex;
24434 ex = exts->exts[j];
24437 for (n = 0; n < ex->used; n++) {
24441 unsigned long sum_load = 0;
24442 fcgi_extension_host *host;
24445 host = ex->hosts[n];
24448 fcgi_restart_dead_procs(srv, p, host);
24451 for (proc = host->first; proc; proc = proc->next) {
24452 sum_load += proc->load;
24456 if (host->num_procs &&
24457 host->num_procs < host->max_procs &&
24458 (sum_load / host->num_procs) > host->max_load_per_proc) {
24459 /* overload, spawn new child */
24460 if (p->conf.debug) {
24461 - log_error_write(srv, __FILE__, __LINE__, "s",
24462 + log_error_write(srv, __FILE__, __LINE__, "s",
24463 "overload detected, spawning a new child");
24467 for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
24471 if (proc == host->unused_procs) host->unused_procs = proc->next;
24474 if (proc->next) proc->next->prev = NULL;
24479 proc = fastcgi_process_init();
24480 proc->id = host->max_id++;
24487 if (buffer_is_empty(host->unixsocket)) {
24488 proc->port = host->port + proc->id;
24490 @@ -3674,13 +3609,13 @@
24491 buffer_append_string(proc->unixsocket, "-");
24492 buffer_append_long(proc->unixsocket, proc->id);
24496 if (fcgi_spawn_connection(srv, p, host, proc)) {
24497 log_error_write(srv, __FILE__, __LINE__, "s",
24498 "ERROR: spawning fcgi failed.");
24499 return HANDLER_ERROR;
24504 proc->next = host->first;
24506 @@ -3688,56 +3623,56 @@
24508 host->first = proc;
24512 for (proc = host->first; proc; proc = proc->next) {
24513 if (proc->load != 0) break;
24514 if (host->num_procs <= host->min_procs) break;
24515 if (proc->pid == 0) continue;
24518 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
24519 /* a proc is idling for a long time now,
24523 if (p->conf.debug) {
24524 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24525 - "idle-timeout reached, terminating child:",
24526 - "socket:", proc->connection_name,
24527 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24528 + "idle-timeout reached, terminating child:",
24529 + "socket:", proc->connection_name,
24536 if (proc->next) proc->next->prev = proc->prev;
24537 if (proc->prev) proc->prev->next = proc->next;
24540 if (proc->prev == NULL) host->first = proc->next;
24544 proc->next = host->unused_procs;
24547 if (host->unused_procs) host->unused_procs->prev = proc;
24548 host->unused_procs = proc;
24551 kill(proc->pid, SIGTERM);
24554 proc->state = PROC_STATE_KILLED;
24556 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24558 - "socket:", proc->connection_name,
24560 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24562 + "socket:", proc->connection_name,
24569 /* proc is now in unused, let the next second handle the next process */
24576 for (proc = host->unused_procs; proc; proc = proc->next) {
24580 if (proc->pid == 0) continue;
24583 switch (waitpid(proc->pid, &status, WNOHANG)) {
24585 /* child still running after timeout, good */
24586 @@ -3745,10 +3680,10 @@
24588 if (errno != EINTR) {
24589 /* no PID found ? should never happen */
24590 - log_error_write(srv, __FILE__, __LINE__, "sddss",
24591 + log_error_write(srv, __FILE__, __LINE__, "sddss",
24592 "pid ", proc->pid, proc->state,
24593 "not found:", strerror(errno));
24597 if (errno == ECHILD) {
24598 /* someone else has cleaned up for us */
24599 @@ -3762,25 +3697,26 @@
24600 /* the child should not terminate at all */
24601 if (WIFEXITED(status)) {
24602 if (proc->state != PROC_STATE_KILLED) {
24603 - log_error_write(srv, __FILE__, __LINE__, "sdb",
24605 + log_error_write(srv, __FILE__, __LINE__, "sdb",
24607 WEXITSTATUS(status), proc->connection_name);
24609 } else if (WIFSIGNALED(status)) {
24610 if (WTERMSIG(status) != SIGTERM) {
24611 - log_error_write(srv, __FILE__, __LINE__, "sd",
24612 - "child signaled:",
24613 + log_error_write(srv, __FILE__, __LINE__, "sd",
24614 + "child signaled:",
24618 - log_error_write(srv, __FILE__, __LINE__, "sd",
24619 - "child died somehow:",
24620 + log_error_write(srv, __FILE__, __LINE__, "sd",
24621 + "child died somehow:",
24625 proc->state = PROC_STATE_UNSET;
24632 @@ -3804,8 +3740,8 @@
24633 p->handle_subrequest = mod_fastcgi_handle_subrequest;
24634 p->handle_joblist = mod_fastcgi_handle_joblist;
24635 p->handle_trigger = mod_fastcgi_handle_trigger;
24643 --- ../lighttpd-1.4.11/src/mod_flv_streaming.c 2006-03-07 14:06:26.000000000 +0200
24644 +++ lighttpd-1.4.12/src/mod_flv_streaming.c 2006-07-11 22:07:52.000000000 +0300
24645 @@ -23,35 +23,35 @@
24655 plugin_config **config_storage;
24657 - plugin_config conf;
24659 + plugin_config conf;
24662 /* init the plugin data */
24663 INIT_FUNC(mod_flv_streaming_init) {
24667 p = calloc(1, sizeof(*p));
24670 p->query_str = buffer_init();
24671 p->get_params = array_init();
24677 /* detroy the plugin data */
24678 FREE_FUNC(mod_flv_streaming_free) {
24679 plugin_data *p = p_d;
24684 if (!p) return HANDLER_GO_ON;
24687 if (p->config_storage) {
24690 @@ -59,19 +59,19 @@
24691 plugin_config *s = p->config_storage[i];
24696 array_free(s->extensions);
24701 free(p->config_storage);
24705 buffer_free(p->query_str);
24706 array_free(p->get_params);
24712 return HANDLER_GO_ON;
24715 @@ -80,83 +80,80 @@
24716 SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
24717 plugin_data *p = p_d;
24720 - config_values_t cv[] = {
24722 + config_values_t cv[] = {
24723 { "flv-streaming.extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
24724 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
24728 if (!p) return HANDLER_ERROR;
24731 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24734 for (i = 0; i < srv->config_context->used; i++) {
24738 s = calloc(1, sizeof(plugin_config));
24739 s->extensions = array_init();
24742 cv[0].destination = s->extensions;
24745 p->config_storage[i] = s;
24748 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24749 return HANDLER_ERROR;
24754 return HANDLER_GO_ON;
24757 -#define PATCH(x) \
24758 - p->conf.x = s->x;
24759 static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
24761 plugin_config *s = p->config_storage[0];
24763 - PATCH(extensions);
24766 + PATCH_OPTION(extensions);
24768 /* skip the first, the global context */
24769 for (i = 1; i < srv->config_context->used; i++) {
24770 data_config *dc = (data_config *)srv->config_context->data[i];
24771 s = p->config_storage[i];
24774 /* condition didn't match */
24775 if (!config_check_cond(srv, con, dc)) continue;
24779 for (j = 0; j < dc->value->used; j++) {
24780 data_unset *du = dc->value->data[j];
24783 if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
24784 - PATCH(extensions);
24785 + PATCH_OPTION(extensions);
24795 -static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
24796 +static int split_get_params(array *get_params, buffer *qrystr) {
24799 char *key = NULL, *val = NULL;
24805 /* we need the \0 */
24806 for (i = 0; i < qrystr->used; i++) {
24807 switch(qrystr->ptr[i]) {
24810 val = qrystr->ptr + i + 1;
24813 qrystr->ptr[i] = '\0';
24822 case '\0': /* fin symbol */
24823 @@ -167,7 +164,7 @@
24824 /* terminate the value */
24825 qrystr->ptr[i] = '\0';
24827 - if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
24828 + if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
24829 ds = data_string_init();
24831 buffer_copy_string_len(ds->key, key, strlen(key));
24832 @@ -175,14 +172,14 @@
24834 array_insert_unique(get_params, (data_unset *)ds);
24838 key = qrystr->ptr + i + 1;
24849 @@ -190,34 +187,34 @@
24850 plugin_data *p = p_d;
24857 if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
24860 mod_flv_streaming_patch_connection(srv, con, p);
24862 s_len = con->physical.path->used - 1;
24865 for (k = 0; k < p->conf.extensions->used; k++) {
24866 data_string *ds = (data_string *)p->conf.extensions->data[k];
24867 int ct_len = ds->value->used - 1;
24870 if (ct_len > s_len) continue;
24871 if (ds->value->used == 0) continue;
24874 if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
24875 data_string *get_param;
24876 stat_cache_entry *sce = NULL;
24880 - /* if there is a start=[0-9]+ in the header use it as start,
24881 + /* if there is a start=[0-9]+ in the header use it as start,
24882 * otherwise send the full file */
24884 array_reset(p->get_params);
24885 buffer_copy_string_buffer(p->query_str, con->uri.query);
24886 - split_get_params(srv, con, p->get_params, p->query_str);
24887 + split_get_params(p->get_params, p->query_str);
24889 if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
24890 return HANDLER_GO_ON;
24891 @@ -256,7 +253,7 @@
24892 return HANDLER_FINISHED;
24898 return HANDLER_GO_ON;
24900 @@ -266,13 +263,13 @@
24901 int mod_flv_streaming_plugin_init(plugin *p) {
24902 p->version = LIGHTTPD_VERSION_ID;
24903 p->name = buffer_init_string("flv_streaming");
24906 p->init = mod_flv_streaming_init;
24907 p->handle_physical = mod_flv_streaming_path_handler;
24908 p->set_defaults = mod_flv_streaming_set_defaults;
24909 p->cleanup = mod_flv_streaming_free;
24917 --- ../lighttpd-1.4.11/src/mod_indexfile.c 2005-09-30 01:08:53.000000000 +0300
24918 +++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-15 22:43:21.000000000 +0300
24921 #include "stat_cache.h"
24923 +#include "sys-strings.h"
24924 +#include "sys-files.h"
24925 /* plugin config for all request/connections */
24928 @@ -20,51 +22,51 @@
24937 plugin_config **config_storage;
24939 - plugin_config conf;
24941 + plugin_config conf;
24944 /* init the plugin data */
24945 INIT_FUNC(mod_indexfile_init) {
24949 p = calloc(1, sizeof(*p));
24952 p->tmp_buf = buffer_init();
24958 /* detroy the plugin data */
24959 FREE_FUNC(mod_indexfile_free) {
24960 plugin_data *p = p_d;
24965 if (!p) return HANDLER_GO_ON;
24968 if (p->config_storage) {
24970 for (i = 0; i < srv->config_context->used; i++) {
24971 plugin_config *s = p->config_storage[i];
24976 array_free(s->indexfiles);
24981 free(p->config_storage);
24985 buffer_free(p->tmp_buf);
24991 return HANDLER_GO_ON;
24994 @@ -73,131 +75,139 @@
24995 SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
24996 plugin_data *p = p_d;
24999 - config_values_t cv[] = {
25001 + config_values_t cv[] = {
25002 { "index-file.names", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
25003 { "server.indexfiles", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
25004 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25008 if (!p) return HANDLER_ERROR;
25011 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25014 for (i = 0; i < srv->config_context->used; i++) {
25018 s = calloc(1, sizeof(plugin_config));
25019 s->indexfiles = array_init();
25022 cv[0].destination = s->indexfiles;
25023 cv[1].destination = s->indexfiles; /* old name for [0] */
25026 p->config_storage[i] = s;
25029 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
25030 return HANDLER_ERROR;
25035 return HANDLER_GO_ON;
25038 -#define PATCH(x) \
25039 - p->conf.x = s->x;
25040 static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
25042 plugin_config *s = p->config_storage[0];
25044 - PATCH(indexfiles);
25047 + PATCH_OPTION(indexfiles);
25049 /* skip the first, the global context */
25050 for (i = 1; i < srv->config_context->used; i++) {
25051 data_config *dc = (data_config *)srv->config_context->data[i];
25052 s = p->config_storage[i];
25055 /* condition didn't match */
25056 if (!config_check_cond(srv, con, dc)) continue;
25060 for (j = 0; j < dc->value->used; j++) {
25061 data_unset *du = dc->value->data[j];
25064 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
25065 - PATCH(indexfiles);
25066 + PATCH_OPTION(indexfiles);
25067 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
25068 - PATCH(indexfiles);
25069 + PATCH_OPTION(indexfiles);
25079 URIHANDLER_FUNC(mod_indexfile_subrequest) {
25080 plugin_data *p = p_d;
25082 stat_cache_entry *sce = NULL;
25085 if (con->uri.path->used == 0) return HANDLER_GO_ON;
25086 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
25089 mod_indexfile_patch_connection(srv, con, p);
25092 + /* is the physical-path really a dir ? */
25093 + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
25094 + return HANDLER_GO_ON;
25097 + if (!S_ISDIR(sce->st.st_mode)) {
25098 + return HANDLER_GO_ON;
25101 if (con->conf.log_request_handling) {
25102 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Indexfile");
25103 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
25109 for (k = 0; k < p->conf.indexfiles->used; k++) {
25110 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
25113 if (ds->value && ds->value->ptr[0] == '/') {
25114 - /* if the index-file starts with a prefix as use this file as
25115 + /* if the index-file starts with a prefix as use this file as
25116 * index-generator */
25117 buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
25119 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
25120 + PATHNAME_APPEND_SLASH(p->tmp_buf);
25122 buffer_append_string_buffer(p->tmp_buf, ds->value);
25125 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25126 if (errno == EACCES) {
25127 con->http_status = 403;
25128 buffer_reset(con->physical.path);
25131 return HANDLER_FINISHED;
25135 if (errno != ENOENT &&
25136 errno != ENOTDIR) {
25137 /* we have no idea what happend. let's tell the user so. */
25140 con->http_status = 500;
25143 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
25144 "file not found ... or so: ", strerror(errno),
25146 "->", con->physical.path);
25149 buffer_reset(con->physical.path);
25152 return HANDLER_FINISHED;
25158 /* rewrite uri.path to the real path (/ -> /index.php) */
25159 buffer_append_string_buffer(con->uri.path, ds->value);
25160 buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
25163 /* fce is already set up a few lines above */
25166 return HANDLER_GO_ON;
25171 return HANDLER_GO_ON;
25173 @@ -207,13 +217,13 @@
25174 int mod_indexfile_plugin_init(plugin *p) {
25175 p->version = LIGHTTPD_VERSION_ID;
25176 p->name = buffer_init_string("indexfile");
25179 p->init = mod_indexfile_init;
25180 p->handle_subrequest_start = mod_indexfile_subrequest;
25181 p->set_defaults = mod_indexfile_set_defaults;
25182 p->cleanup = mod_indexfile_free;
25190 --- ../lighttpd-1.4.11/src/mod_mysql_vhost.c 2006-01-14 20:35:10.000000000 +0200
25191 +++ lighttpd-1.4.12/src/mod_mysql_vhost.c 2006-07-11 22:07:52.000000000 +0300
25193 -#include <unistd.h>
25197 -#include <strings.h>
25198 +#include <string.h>
25200 #ifdef HAVE_CONFIG_H
25201 #include "config.h"
25204 +#ifdef HAVE_MYSQL_H
25205 +# ifdef HAVE_LIBMYSQL
25206 +# define HAVE_MYSQL
25213 @@ -16,61 +21,40 @@
25216 #include "stat_cache.h"
25217 -#ifdef DEBUG_MOD_MYSQL_VHOST
25220 +#include "sys-files.h"
25223 - * Plugin for lighttpd to use MySQL
25224 - * for domain to directory lookups,
25225 - * i.e virtual hosts (vhosts).
25227 - * Optionally sets fcgi_offset and fcgi_arg
25228 - * in preparation for fcgi.c to handle
25229 - * per-user fcgi chroot jails.
25231 - * /ada@riksnet.se 2004-12-06
25233 +#include "mod_sql_vhost_core.h"
25237 +#define CORE_PLUGIN "mod_sql_vhost_core"
25247 - buffer *hostname;
25248 - unsigned short port;
25252 buffer *mysql_post;
25254 + mod_sql_vhost_core_plugin_config *core;
25257 /* global plugin data */
25265 plugin_config **config_storage;
25267 - plugin_config conf;
25269 + plugin_config conf;
25272 -/* per connection plugin data */
25274 - buffer *server_name;
25275 - buffer *document_root;
25276 - buffer *fcgi_arg;
25277 - unsigned fcgi_offset;
25278 -} plugin_connection_data;
25279 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost);
25281 /* init the plugin data */
25282 INIT_FUNC(mod_mysql_vhost_init) {
25286 p = calloc(1, sizeof(*p));
25288 p->tmp_buf = buffer_init();
25289 @@ -83,144 +67,77 @@
25290 plugin_data *p = p_d;
25295 - log_error_write(srv, __FILE__, __LINE__, "ss",
25296 - "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
25299 if (!p) return HANDLER_GO_ON;
25302 if (p->config_storage) {
25304 for (i = 0; i < srv->config_context->used; i++) {
25305 plugin_config *s = p->config_storage[i];
25310 mysql_close(s->mysql);
25312 - buffer_free(s->mydb);
25313 - buffer_free(s->myuser);
25314 - buffer_free(s->mypass);
25315 - buffer_free(s->mysock);
25317 buffer_free(s->mysql_pre);
25318 buffer_free(s->mysql_post);
25323 free(p->config_storage);
25325 buffer_free(p->tmp_buf);
25329 - return HANDLER_GO_ON;
25332 -/* handle the plugin per connection data */
25333 -static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
25335 - plugin_data *p = p_d;
25336 - plugin_connection_data *c = con->plugin_ctx[p->id];
25341 - log_error_write(srv, __FILE__, __LINE__, "ss",
25342 - "mod_mysql_connection_data", c ? "old" : "NEW");
25346 - c = calloc(1, sizeof(*c));
25348 - c->server_name = buffer_init();
25349 - c->document_root = buffer_init();
25350 - c->fcgi_arg = buffer_init();
25351 - c->fcgi_offset = 0;
25353 - return con->plugin_ctx[p->id] = c;
25356 -/* destroy the plugin per connection data */
25357 -CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
25358 - plugin_data *p = p_d;
25359 - plugin_connection_data *c = con->plugin_ctx[p->id];
25364 - log_error_write(srv, __FILE__, __LINE__, "ss",
25365 - "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
25368 - if (!c) return HANDLER_GO_ON;
25370 - buffer_free(c->server_name);
25371 - buffer_free(c->document_root);
25372 - buffer_free(c->fcgi_arg);
25373 - c->fcgi_offset = 0;
25378 - con->plugin_ctx[p->id] = NULL;
25379 return HANDLER_GO_ON;
25382 /* set configuration values */
25383 SERVER_FUNC(mod_mysql_vhost_set_defaults) {
25384 plugin_data *p = p_d;
25385 + mod_sql_vhost_core_plugin_data *core_config;
25390 - config_values_t cv[] = {
25391 - { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25392 - { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25393 - { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25394 - { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25395 - { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
25396 - { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
25397 - { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER },
25398 - { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25401 + /* our very own plugin storage, one entry for each conditional
25403 + * srv->config_context->used is the number of conditionals
25405 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25408 + /* get the config of the core-plugin */
25409 + core_config = plugin_get_config(srv, CORE_PLUGIN);
25412 + /* walk through all conditionals and check for assignments */
25413 for (i = 0; i < srv->config_context->used; i++) {
25420 + /* get the config from the core plugin for this conditional-context */
25421 s = calloc(1, sizeof(plugin_config));
25422 - s->mydb = buffer_init();
25423 - s->myuser = buffer_init();
25424 - s->mypass = buffer_init();
25425 - s->mysock = buffer_init();
25426 - s->hostname = buffer_init();
25427 - s->port = 0; /* default port for mysql */
25428 - sel = buffer_init();
25431 + s->core = core_config->config_storage[i];
25435 s->mysql_pre = buffer_init();
25436 s->mysql_post = buffer_init();
25438 - cv[0].destination = s->mydb;
25439 - cv[1].destination = s->myuser;
25440 - cv[2].destination = s->mypass;
25441 - cv[3].destination = s->mysock;
25442 - cv[4].destination = sel;
25443 - cv[5].destination = s->hostname;
25444 - cv[6].destination = &(s->port);
25447 p->config_storage[i] = s;
25449 - if (config_insert_values_global(srv,
25450 - ((data_config *)srv->config_context->data[i])->value,
25451 - cv)) return HANDLER_ERROR;
25453 - s->mysql_pre = buffer_init();
25454 - s->mysql_post = buffer_init();
25457 + /* check if we are the plugin for this backend */
25458 + if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
25460 + /* attach us to the core-plugin */
25461 + s->core->backend_data = p;
25462 + s->core->get_vhost = mod_mysql_vhost_get_vhost;
25464 + sel = buffer_init();
25465 + buffer_copy_string_buffer(sel, s->core->select_vhost);
25467 if (sel->used && (qmark = index(sel->ptr, '?'))) {
25469 buffer_copy_string(s->mysql_pre, sel->ptr);
25470 @@ -228,35 +145,35 @@
25472 buffer_copy_string_buffer(s->mysql_pre, sel);
25483 * - password, default: empty
25484 * - socket, default: mysql default
25485 * - hostname, if set overrides socket
25486 * - port, default: 3306
25490 /* all have to be set */
25491 - if (!(buffer_is_empty(s->myuser) ||
25492 - buffer_is_empty(s->mydb))) {
25493 + if (!(buffer_is_empty(s->core->user) ||
25494 + buffer_is_empty(s->core->db))) {
25499 if (NULL == (s->mysql = mysql_init(NULL))) {
25500 log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
25503 return HANDLER_ERROR;
25505 -#define FOO(x) (s->x->used ? s->x->ptr : NULL)
25507 - if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass),
25508 - FOO(mydb), s->port, FOO(mysock), 0)) {
25509 +#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
25511 + if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
25512 + FOO(db), s->core->port, FOO(sock), 0)) {
25513 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
25516 return HANDLER_ERROR;
25519 @@ -265,61 +182,47 @@
25520 /* otherwise we cannot be sure that mysql is fd i-1 */
25521 if (-1 == (fd = open("/dev/null", 0))) {
25523 - fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25524 + fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25533 return HANDLER_GO_ON;
25536 -#define PATCH(x) \
25537 - p->conf.x = s->x;
25538 static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
25541 plugin_config *s = p->config_storage[0];
25543 - PATCH(mysql_pre);
25544 - PATCH(mysql_post);
25550 + PATCH_OPTION(mysql_pre);
25551 + PATCH_OPTION(mysql_post);
25552 + PATCH_OPTION(mysql);
25554 /* skip the first, the global context */
25555 for (i = 1; i < srv->config_context->used; i++) {
25556 data_config *dc = (data_config *)srv->config_context->data[i];
25557 s = p->config_storage[i];
25560 /* condition didn't match */
25561 if (!config_check_cond(srv, con, dc)) continue;
25563 - /* merge config */
25564 - for (j = 0; j < dc->value->used; j++) {
25565 - data_unset *du = dc->value->data[j];
25567 - if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
25568 - PATCH(mysql_pre);
25569 - PATCH(mysql_post);
25576 + PATCH_OPTION(mysql);
25577 + PATCH_OPTION(mysql_pre);
25578 + PATCH_OPTION(mysql_post);
25588 -/* handle document root request */
25589 -CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
25591 + * get the vhost info from the database
25593 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
25594 plugin_data *p = p_d;
25595 - plugin_connection_data *c;
25596 - stat_cache_entry *sce;
25600 @@ -332,13 +235,6 @@
25602 if (!p->conf.mysql) return HANDLER_GO_ON;
25604 - /* sets up connection data if not done yet */
25605 - c = mod_mysql_vhost_connection_data(srv, con, p_d);
25607 - /* check if cached this connection */
25608 - if (c->server_name->used && /* con->uri.authority->used && */
25609 - buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
25611 /* build and run SQL query */
25612 buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
25613 if (p->conf.mysql_post->used) {
25614 @@ -347,77 +243,43 @@
25616 if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
25617 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
25620 + mysql_free_result(result);
25621 + return HANDLER_GO_ON;
25623 result = mysql_store_result(p->conf.mysql);
25624 cols = mysql_num_fields(result);
25625 row = mysql_fetch_row(result);
25627 if (!row || cols < 1) {
25628 /* no such virtual host */
25629 mysql_free_result(result);
25630 return HANDLER_GO_ON;
25633 - /* sanity check that really is a directory */
25634 - buffer_copy_string(p->tmp_buf, row[0]);
25635 - BUFFER_APPEND_SLASH(p->tmp_buf);
25637 - if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25638 - log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
25641 - if (!S_ISDIR(sce->st.st_mode)) {
25642 - log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
25645 + buffer_copy_string(docroot, row[0]);
25647 - /* cache the data */
25648 - buffer_copy_string_buffer(c->server_name, con->uri.authority);
25649 - buffer_copy_string_buffer(c->document_root, p->tmp_buf);
25651 - /* fcgi_offset and fcgi_arg are optional */
25652 - if (cols > 1 && row[1]) {
25653 - c->fcgi_offset = atoi(row[1]);
25655 - if (cols > 2 && row[2]) {
25656 - buffer_copy_string(c->fcgi_arg, row[2]);
25658 - c->fcgi_arg->used = 0;
25661 - c->fcgi_offset = c->fcgi_arg->used = 0;
25663 mysql_free_result(result);
25665 - /* fix virtual server and docroot */
25666 -GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
25667 - buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
25670 - log_error_write(srv, __FILE__, __LINE__, "sbbdb",
25671 - result ? "NOT CACHED" : "cached",
25672 - con->server_name, con->physical.doc_root,
25673 - c->fcgi_offset, c->fcgi_arg);
25675 - return HANDLER_GO_ON;
25677 -ERR500: if (result) mysql_free_result(result);
25678 - con->http_status = 500; /* Internal Error */
25679 - return HANDLER_FINISHED;
25680 + return HANDLER_GO_ON;
25683 /* this function is called at dlopen() time and inits the callbacks */
25684 int mod_mysql_vhost_plugin_init(plugin *p) {
25687 p->version = LIGHTTPD_VERSION_ID;
25688 p->name = buffer_init_string("mysql_vhost");
25690 p->init = mod_mysql_vhost_init;
25691 p->cleanup = mod_mysql_vhost_cleanup;
25692 - p->handle_request_done = mod_mysql_vhost_handle_connection_close;
25694 p->set_defaults = mod_mysql_vhost_set_defaults;
25695 - p->handle_docroot = mod_mysql_vhost_handle_docroot;
25697 + ds = data_string_init();
25698 + buffer_copy_string(ds->value, CORE_PLUGIN);
25699 + array_insert_unique(p->required_plugins, (data_unset *)ds);
25704 --- ../lighttpd-1.4.11/src/mod_proxy.c 2006-01-31 13:01:22.000000000 +0200
25705 +++ lighttpd-1.4.12/src/mod_proxy.c 2006-07-15 22:43:21.000000000 +0300
25707 #include <sys/types.h>
25709 -#include <unistd.h>
25712 #include <string.h>
25715 #include "inet_ntop_cache.h"
25717 +#include "network.h"
25719 +#include "http_resp.h"
25726 #include "sys-socket.h"
25727 +#include "sys-files.h"
25728 +#include "sys-strings.h"
25730 #define data_proxy data_fastcgi
25731 #define data_proxy_init data_fastcgi_init
25732 @@ -38,22 +42,25 @@
25733 #define PROXY_RETRY_TIMEOUT 60
25737 - * the proxy module is based on the fastcgi module
25740 + * the proxy module is based on the fastcgi module
25742 * 28.06.2004 Jan Kneschke The first release
25743 * 01.07.2004 Evgeny Rodichev Several bugfixes and cleanups
25744 * - co-ordinate up- and downstream flows correctly (proxy_demux_response
25745 * and proxy_handle_fdevent)
25746 * - correctly transfer upstream http_response_status;
25747 * - some unused structures removed.
25750 * TODO: - delay upstream read if write_queue is too large
25751 * (to prevent memory eating, like in apache). Shoud be
25753 * - persistent connection with upstream servers
25760 PROXY_BALANCE_UNSET,
25761 PROXY_BALANCE_FAIR,
25762 @@ -66,26 +73,33 @@
25765 proxy_balance_t balance;
25767 + array *last_used_backends; /* "extension" : last_used_backend */
25774 buffer *parse_response;
25775 buffer *balance_buf;
25780 + array *ignore_headers;
25782 plugin_config **config_storage;
25785 plugin_config conf;
25789 - PROXY_STATE_INIT,
25790 - PROXY_STATE_CONNECT,
25791 - PROXY_STATE_PREPARE_WRITE,
25792 - PROXY_STATE_WRITE,
25793 - PROXY_STATE_READ,
25794 - PROXY_STATE_ERROR
25796 + PROXY_STATE_INIT,
25797 + PROXY_STATE_CONNECT,
25798 + PROXY_STATE_PREPARE_WRITE,
25799 + PROXY_STATE_WRITE,
25800 + PROXY_STATE_RESPONSE_HEADER,
25801 + PROXY_STATE_RESPONSE_CONTENT,
25802 + PROXY_STATE_ERROR
25803 } proxy_connection_state_t;
25805 enum { PROXY_STDOUT, PROXY_END_REQUEST };
25806 @@ -93,19 +107,17 @@
25808 proxy_connection_state_t state;
25809 time_t state_timestamp;
25814 - buffer *response;
25815 - buffer *response_header;
25821 int fd; /* fd to the proxy process */
25822 int fde_ndx; /* index into the fd-event buffer */
25824 size_t path_info_offset; /* start of path_info in uri.path */
25827 connection *remote_conn; /* dump pointer */
25828 plugin_data *plugin_data; /* dump pointer */
25830 @@ -116,69 +128,88 @@
25832 static handler_ctx * handler_ctx_init() {
25833 handler_ctx * hctx;
25837 hctx = calloc(1, sizeof(*hctx));
25840 hctx->state = PROXY_STATE_INIT;
25843 - hctx->response = buffer_init();
25844 - hctx->response_header = buffer_init();
25846 hctx->wb = chunkqueue_init();
25847 + hctx->rb = chunkqueue_init();
25850 hctx->fde_ndx = -1;
25856 static void handler_ctx_free(handler_ctx *hctx) {
25857 - buffer_free(hctx->response);
25858 - buffer_free(hctx->response_header);
25859 chunkqueue_free(hctx->wb);
25861 + chunkqueue_free(hctx->rb);
25866 INIT_FUNC(mod_proxy_init) {
25871 + char *hop2hop_headers[] = {
25878 p = calloc(1, sizeof(*p));
25880 - p->parse_response = buffer_init();
25882 p->balance_buf = buffer_init();
25884 + p->ignore_headers = array_init();
25885 + p->resp = http_response_init();
25887 + for (i = 0; hop2hop_headers[i]; i++) {
25890 + if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
25891 + ds = data_string_init();
25894 + buffer_copy_string(ds->key, hop2hop_headers[i]);
25895 + buffer_copy_string(ds->value, hop2hop_headers[i]);
25896 + array_insert_unique(p->ignore_headers, (data_unset *)ds);
25903 FREE_FUNC(mod_proxy_free) {
25904 plugin_data *p = p_d;
25909 - buffer_free(p->parse_response);
25910 - buffer_free(p->balance_buf);
25912 if (p->config_storage) {
25914 for (i = 0; i < srv->config_context->used; i++) {
25915 plugin_config *s = p->config_storage[i];
25920 array_free(s->extensions);
25922 + array_free(s->last_used_backends);
25927 free(p->config_storage);
25931 + array_free(p->ignore_headers);
25932 + buffer_free(p->balance_buf);
25933 + http_response_free(p->resp);
25938 return HANDLER_GO_ON;
25941 @@ -186,37 +217,38 @@
25942 plugin_data *p = p_d;
25946 - config_values_t cv[] = {
25948 + config_values_t cv[] = {
25949 { "proxy.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
25950 { "proxy.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
25951 { "proxy.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
25952 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25956 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25959 for (i = 0; i < srv->config_context->used; i++) {
25964 s = malloc(sizeof(plugin_config));
25965 - s->extensions = array_init();
25966 + s->extensions = array_init();
25967 + s->last_used_backends = array_init();
25971 cv[0].destination = s->extensions;
25972 cv[1].destination = &(s->debug);
25973 cv[2].destination = p->balance_buf;
25975 buffer_reset(p->balance_buf);
25978 p->config_storage[i] = s;
25979 ca = ((data_config *)srv->config_context->data[i])->value;
25982 if (0 != config_insert_values_global(srv, ca, cv)) {
25983 return HANDLER_ERROR;
25987 if (buffer_is_empty(p->balance_buf)) {
25988 s->balance = PROXY_BALANCE_FAIR;
25989 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
25990 @@ -226,99 +258,99 @@
25991 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
25992 s->balance = PROXY_BALANCE_HASH;
25994 - log_error_write(srv, __FILE__, __LINE__, "sb",
25995 - "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
25996 + log_error_write(srv, __FILE__, __LINE__, "sb",
25997 + "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
25998 return HANDLER_ERROR;
26001 if (NULL != (du = array_get_element(ca, "proxy.server"))) {
26003 data_array *da = (data_array *)du;
26006 if (du->type != TYPE_ARRAY) {
26007 - log_error_write(srv, __FILE__, __LINE__, "sss",
26008 + log_error_write(srv, __FILE__, __LINE__, "sss",
26009 "unexpected type for key: ", "proxy.server", "array of strings");
26012 return HANDLER_ERROR;
26018 * proxy.server = ( "<ext>" => ...,
26023 for (j = 0; j < da->value->used; j++) {
26024 data_array *da_ext = (data_array *)da->value->data[j];
26028 if (da_ext->type != TYPE_ARRAY) {
26029 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
26030 - "unexpected type for key: ", "proxy.server",
26031 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
26032 + "unexpected type for key: ", "proxy.server",
26033 "[", da->value->data[j]->key, "](string)");
26036 return HANDLER_ERROR;
26040 - * proxy.server = ( "<ext>" =>
26041 - * ( "<host>" => ( ... ),
26044 + * proxy.server = ( "<ext>" =>
26045 + * ( "<host>" => ( ... ),
26046 * "<host>" => ( ... )
26053 for (n = 0; n < da_ext->value->used; n++) {
26054 data_array *da_host = (data_array *)da_ext->value->data[n];
26060 - config_values_t pcv[] = {
26062 + config_values_t pcv[] = {
26063 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
26064 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
26065 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
26069 if (da_host->type != TYPE_ARRAY) {
26070 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
26071 - "unexpected type for key:",
26073 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
26074 + "unexpected type for key:",
26076 "[", da_ext->value->data[n]->key, "](string)");
26079 return HANDLER_ERROR;
26083 df = data_proxy_init();
26089 buffer_copy_string_buffer(df->key, da_host->key);
26092 pcv[0].destination = df->host;
26093 pcv[1].destination = &(df->port);
26096 if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
26097 return HANDLER_ERROR;
26101 if (buffer_is_empty(df->host)) {
26102 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
26103 - "missing key (string):",
26104 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
26105 + "missing key (string):",
26112 return HANDLER_ERROR;
26116 /* if extension already exists, take it */
26119 if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
26120 dfa = data_array_init();
26123 buffer_copy_string_buffer(dfa->key, da_ext->key);
26126 array_insert_unique(dfa->value, (data_unset *)df);
26127 array_insert_unique(s->extensions, (data_unset *)dfa);
26129 @@ -328,19 +360,19 @@
26135 return HANDLER_GO_ON;
26138 void proxy_connection_close(server *srv, handler_ctx *hctx) {
26143 if (NULL == hctx) return;
26146 p = hctx->plugin_data;
26147 con = hctx->remote_conn;
26150 if (hctx->fd != -1) {
26151 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26152 fdevent_unregister(srv->ev, hctx->fd);
26153 @@ -348,47 +380,56 @@
26159 handler_ctx_free(hctx);
26160 - con->plugin_ctx[p->id] = NULL;
26161 + con->plugin_ctx[p->id] = NULL;
26164 static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
26165 struct sockaddr *proxy_addr;
26166 struct sockaddr_in proxy_addr_in;
26170 plugin_data *p = hctx->plugin_data;
26171 data_proxy *host= hctx->host;
26172 int proxy_fd = hctx->fd;
26175 memset(&proxy_addr, 0, sizeof(proxy_addr));
26178 proxy_addr_in.sin_family = AF_INET;
26179 proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr);
26180 proxy_addr_in.sin_port = htons(host->port);
26181 servlen = sizeof(proxy_addr_in);
26184 proxy_addr = (struct sockaddr *) &proxy_addr_in;
26187 if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
26188 - if (errno == EINPROGRESS || errno == EALREADY) {
26190 + errno = WSAGetLastError();
26194 + case WSAEWOULDBLOCK:
26196 + case EINPROGRESS:
26198 if (p->conf.debug) {
26199 - log_error_write(srv, __FILE__, __LINE__, "sd",
26200 + log_error_write(srv, __FILE__, __LINE__, "sd",
26201 "connect delayed:", proxy_fd);
26208 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
26211 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
26212 "connect failed:", proxy_fd, strerror(errno), errno);
26218 + fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
26219 if (p->conf.debug) {
26220 - log_error_write(srv, __FILE__, __LINE__, "sd",
26221 + log_error_write(srv, __FILE__, __LINE__, "sd",
26222 "connect succeeded: ", proxy_fd);
26225 @@ -396,51 +437,52 @@
26228 void proxy_set_header(connection *con, const char *key, const char *value) {
26229 - data_string *ds_dst;
26230 + data_string *ds_dst;
26232 - if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26233 - ds_dst = data_string_init();
26236 - buffer_copy_string(ds_dst->key, key);
26237 - buffer_copy_string(ds_dst->value, value);
26238 - array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26239 + if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26240 + ds_dst = data_string_init();
26243 + buffer_copy_string(ds_dst->key, key);
26244 + buffer_copy_string(ds_dst->value, value);
26245 + array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26248 void proxy_append_header(connection *con, const char *key, const char *value) {
26249 - data_string *ds_dst;
26250 + data_string *ds_dst;
26252 - if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26253 - ds_dst = data_string_init();
26256 - buffer_copy_string(ds_dst->key, key);
26257 - buffer_append_string(ds_dst->value, value);
26258 - array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26259 + if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26260 + ds_dst = data_string_init();
26263 + buffer_copy_string(ds_dst->key, key);
26264 + buffer_append_string(ds_dst->value, value);
26265 + array_insert_unique(con->request.headers, (data_unset *)ds_dst);
26269 static int proxy_create_env(server *srv, handler_ctx *hctx) {
26273 connection *con = hctx->remote_conn;
26274 + plugin_data *p = hctx->plugin_data;
26280 b = chunkqueue_get_append_buffer(hctx->wb);
26284 buffer_copy_string(b, get_http_method_name(con->request.http_method));
26285 BUFFER_APPEND_STRING_CONST(b, " ");
26288 buffer_append_string_buffer(b, con->request.uri);
26289 BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
26291 proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
26292 - /* http_host is NOT is just a pointer to a buffer
26293 + /* http_host is NOT is just a pointer to a buffer
26294 * which is NULL if it is not set */
26295 - if (con->request.http_host &&
26296 + if (con->request.http_host &&
26297 !buffer_is_empty(con->request.http_host)) {
26298 proxy_set_header(con, "X-Host", con->request.http_host->ptr);
26300 @@ -449,24 +491,25 @@
26301 /* request header */
26302 for (i = 0; i < con->request.headers->used; i++) {
26306 ds = (data_string *)con->request.headers->data[i];
26308 - if (ds->value->used && ds->key->used) {
26309 - if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
26311 - buffer_append_string_buffer(b, ds->key);
26312 - BUFFER_APPEND_STRING_CONST(b, ": ");
26313 - buffer_append_string_buffer(b, ds->value);
26314 - BUFFER_APPEND_STRING_CONST(b, "\r\n");
26317 + if (buffer_is_empty(ds->value) || buffer_is_empty(ds->key)) continue;
26319 + if (!buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
26320 + if (!buffer_is_equal_string(ds->key, CONST_STR_LEN("Keep-Alive"))) continue;
26322 + buffer_append_string_buffer(b, ds->key);
26323 + BUFFER_APPEND_STRING_CONST(b, ": ");
26324 + buffer_append_string_buffer(b, ds->value);
26325 + BUFFER_APPEND_STRING_CONST(b, "\r\n");
26329 BUFFER_APPEND_STRING_CONST(b, "\r\n");
26332 hctx->wb->bytes_in += b->used - 1;
26336 if (con->request.content_length) {
26337 chunkqueue *req_cq = con->request_content_queue;
26339 @@ -479,7 +522,7 @@
26341 /* we announce toWrite octects
26342 * now take all the request_content chunk that we need to fill this request
26346 switch (req_c->type) {
26348 @@ -507,223 +550,161 @@
26350 req_c->offset += weHave;
26351 req_cq->bytes_out += weHave;
26354 hctx->wb->bytes_in += weHave;
26371 static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) {
26372 hctx->state = state;
26373 hctx->state_timestamp = srv->cur_ts;
26380 -static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
26382 - int http_response_status = -1;
26385 +static void chunkqueue_print(chunkqueue *cq) {
26388 - /* \r\n -> \0\0 */
26390 - buffer_copy_string_buffer(p->parse_response, in);
26392 - for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
26393 - char *key, *value;
26401 - if (-1 == http_response_status) {
26402 - /* The first line of a Response message is the Status-Line */
26404 - for (key=s; *key && *key != ' '; key++);
26407 - http_response_status = (int) strtol(key, NULL, 10);
26408 - if (http_response_status <= 0) http_response_status = 502;
26410 - http_response_status = 502;
26413 - con->http_status = http_response_status;
26414 - con->parsed_response |= HTTP_STATUS;
26418 - if (NULL == (value = strchr(s, ':'))) {
26419 - /* now we expect: "<key>: <value>\n" */
26425 - key_len = value - key;
26429 - while (*value == ' ' || *value == '\t') value++;
26433 - switch(key_len) {
26435 - if (0 == strncasecmp(key, "Date", key_len)) {
26436 - con->parsed_response |= HTTP_DATE;
26440 - if (0 == strncasecmp(key, "Location", key_len)) {
26441 - con->parsed_response |= HTTP_LOCATION;
26445 - if (0 == strncasecmp(key, "Connection", key_len)) {
26450 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
26451 - con->response.content_length = strtol(value, NULL, 10);
26452 - con->parsed_response |= HTTP_CONTENT_LENGTH;
26459 - if (copy_header) {
26460 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26461 - ds = data_response_init();
26463 - buffer_copy_string_len(ds->key, key, key_len);
26464 - buffer_copy_string(ds->value, value);
26466 - array_insert_unique(con->response.headers, (data_unset *)ds);
26468 + for (c = cq->first; c; c = c->next) {
26469 + fprintf(stderr, "%s", c->mem->ptr + c->offset);
26473 + fprintf(stderr, "\r\n");
26477 static int proxy_demux_response(server *srv, handler_ctx *hctx) {
26482 plugin_data *p = hctx->plugin_data;
26483 connection *con = hctx->remote_conn;
26484 int proxy_fd = hctx->fd;
26486 - /* check how much we have to read */
26487 - if (ioctl(hctx->fd, FIONREAD, &b)) {
26488 - log_error_write(srv, __FILE__, __LINE__, "sd",
26489 - "ioctl failed: ",
26491 + chunkqueue *next_queue = NULL;
26494 + switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
26495 + case NETWORK_STATUS_SUCCESS:
26496 + /* we got content */
26498 + case NETWORK_STATUS_WAIT_FOR_EVENT:
26499 + /* the ioctl will return WAIT_FOR_EVENT on a read */
26500 + if (0 == con->file_started) return -1;
26501 + case NETWORK_STATUS_CONNECTION_CLOSE:
26502 + /* we are done, get out of here */
26503 + con->file_finished = 1;
26505 + /* close the chunk-queue with a empty chunk */
26513 + /* looks like we got some content
26515 + * split off the header from the incoming stream
26518 - if (p->conf.debug) {
26519 - log_error_write(srv, __FILE__, __LINE__, "sd",
26520 - "proxy - have to read:", b);
26522 + if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
26524 + int have_content_length = 0;
26527 - if (hctx->response->used == 0) {
26528 - /* avoid too small buffer */
26529 - buffer_prepare_append(hctx->response, b + 1);
26530 - hctx->response->used = 1;
26532 - buffer_prepare_append(hctx->response, hctx->response->used + b);
26535 - if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
26536 - log_error_write(srv, __FILE__, __LINE__, "sds",
26537 - "unexpected end-of-file (perhaps the proxy process died):",
26538 - proxy_fd, strerror(errno));
26542 - /* this should be catched by the b > 0 above */
26545 - hctx->response->used += r;
26546 - hctx->response->ptr[hctx->response->used - 1] = '\0';
26549 - log_error_write(srv, __FILE__, __LINE__, "sdsbs",
26550 - "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
26552 + http_response_reset(p->resp);
26554 - if (0 == con->got_response) {
26555 - con->got_response = 1;
26556 - buffer_prepare_copy(hctx->response_header, 128);
26559 - if (0 == con->file_started) {
26562 - /* search for the \r\n\r\n in the string */
26563 - if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
26564 - size_t hlen = c - hctx->response->ptr + 4;
26565 - size_t blen = hctx->response->used - hlen - 1;
26568 - buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
26570 - log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
26572 - /* parse the response header */
26573 - proxy_response_parse(srv, con, p, hctx->response_header);
26575 - /* enable chunked-transfer-encoding */
26576 - if (con->request.http_version == HTTP_VERSION_1_1 &&
26577 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
26578 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26579 + /* the response header is not fully received yet,
26581 + * extract the http-response header from the rb-cq
26583 + switch (http_response_parse_cq(hctx->rb, p->resp)) {
26584 + case PARSE_ERROR:
26585 + /* parsing failed */
26587 + con->http_status = 502; /* Bad Gateway */
26589 + case PARSE_NEED_MORE:
26591 + case PARSE_SUCCESS:
26592 + con->http_status = p->resp->status;
26594 + chunkqueue_remove_finished_chunks(hctx->rb);
26596 + /* copy the http-headers */
26597 + for (i = 0; i < p->resp->headers->used; i++) {
26598 + const char *ign[] = { "Status", "Connection", NULL };
26602 + data_string *header = (data_string *)p->resp->headers->data[i];
26604 + /* some headers are ignored by default */
26605 + for (j = 0; ign[j]; j++) {
26606 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
26609 - con->file_started = 1;
26611 - http_chunk_append_mem(srv, con, c + 4, blen + 1);
26612 - joblist_append(srv, con);
26613 + if (ign[j]) continue;
26615 + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
26616 + /* CGI/1.1 rev 03 - 7.2.1.2 */
26617 + if (con->http_status == 0) con->http_status = 302;
26618 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
26619 + have_content_length = 1;
26621 - hctx->response->used = 0;
26623 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26624 + ds = data_response_init();
26626 + buffer_copy_string_buffer(ds->key, header->key);
26627 + buffer_copy_string_buffer(ds->value, header->value);
26629 + array_insert_unique(con->response.headers, (data_unset *)ds);
26632 - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
26633 - joblist_append(srv, con);
26634 - hctx->response->used = 0;
26636 + con->file_started = 1;
26638 + if (con->request.http_version == HTTP_VERSION_1_1 &&
26639 + !have_content_length) {
26640 + con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26643 + hctx->state = PROXY_STATE_RESPONSE_CONTENT;
26648 - /* reading from upstream done */
26649 - con->file_finished = 1;
26651 - http_chunk_append_mem(srv, con, NULL, 0);
26652 - joblist_append(srv, con);
26659 + /* FIXME: pass the response-header to the other plugins to
26660 + * setup the filter-queue
26662 + * - use next-queue instead of con->write_queue
26665 + next_queue = con->write_queue;
26667 + assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
26669 + /* FIXME: if we have a content-length or chunked-encoding
26672 + * for now we wait for EOF on the socket */
26674 + /* copy the content to the next cq */
26675 + for (c = hctx->rb->first; c; c = c->next) {
26676 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
26678 + c->offset = c->mem->used - 1;
26681 + chunkqueue_remove_finished_chunks(hctx->rb);
26682 + joblist_append(srv, con);
26688 @@ -731,12 +712,12 @@
26689 data_proxy *host= hctx->host;
26690 plugin_data *p = hctx->plugin_data;
26691 connection *con = hctx->remote_conn;
26697 - (!host->host->used || !host->port)) return -1;
26701 + (!host->host->used || !host->port)) return -1;
26703 switch(hctx->state) {
26704 case PROXY_STATE_INIT:
26705 if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
26706 @@ -744,19 +725,19 @@
26707 return HANDLER_ERROR;
26709 hctx->fde_ndx = -1;
26715 fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
26718 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
26719 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
26722 return HANDLER_ERROR;
26729 case PROXY_STATE_CONNECT:
26730 /* try to finish the connect() */
26731 if (hctx->state == PROXY_STATE_INIT) {
26732 @@ -764,16 +745,16 @@
26733 switch (proxy_establish_connection(srv, hctx)) {
26735 proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
26738 /* connection is in progress, wait for an event and call getsockopt() below */
26741 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26744 return HANDLER_WAIT_FOR_EVENT;
26746 /* if ECONNREFUSED choose another connection -> FIXME */
26747 hctx->fde_ndx = -1;
26750 return HANDLER_ERROR;
26752 /* everything is ok, go on */
26753 @@ -782,152 +763,152 @@
26756 socklen_t socket_error_len = sizeof(socket_error);
26758 - /* we don't need it anymore */
26760 + /* we don't need it anymore */
26761 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26763 /* try to finish the connect() */
26764 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
26765 - log_error_write(srv, __FILE__, __LINE__, "ss",
26766 + log_error_write(srv, __FILE__, __LINE__, "ss",
26767 "getsockopt failed:", strerror(errno));
26770 return HANDLER_ERROR;
26772 if (socket_error != 0) {
26773 log_error_write(srv, __FILE__, __LINE__, "ss",
26774 - "establishing connection failed:", strerror(socket_error),
26775 + "establishing connection failed:", strerror(socket_error),
26776 "port:", hctx->host->port);
26779 return HANDLER_ERROR;
26781 if (p->conf.debug) {
26782 - log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
26783 + log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
26788 proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
26790 case PROXY_STATE_PREPARE_WRITE:
26791 proxy_create_env(srv, hctx);
26794 proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
26798 case PROXY_STATE_WRITE:;
26799 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
26800 + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
26802 chunkqueue_remove_finished_chunks(hctx->wb);
26805 - if (errno != EAGAIN &&
26806 - errno != EINTR) {
26807 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26809 - return HANDLER_ERROR;
26811 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26813 + case NETWORK_STATUS_FATAL_ERROR:
26814 + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26816 - return HANDLER_WAIT_FOR_EVENT;
26818 + return HANDLER_ERROR;
26819 + case NETWORK_STATUS_WAIT_FOR_EVENT:
26821 + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26823 + return HANDLER_WAIT_FOR_EVENT;
26826 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
26827 - proxy_set_state(srv, hctx, PROXY_STATE_READ);
26828 + proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
26830 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26831 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
26833 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26836 return HANDLER_WAIT_FOR_EVENT;
26840 return HANDLER_WAIT_FOR_EVENT;
26841 - case PROXY_STATE_READ:
26842 + case PROXY_STATE_RESPONSE_CONTENT:
26843 + case PROXY_STATE_RESPONSE_HEADER:
26844 /* waiting for a response */
26846 return HANDLER_WAIT_FOR_EVENT;
26848 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
26849 return HANDLER_ERROR;
26853 return HANDLER_GO_ON;
26856 -#define PATCH(x) \
26857 - p->conf.x = s->x;
26858 static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
26860 plugin_config *s = p->config_storage[0];
26862 - PATCH(extensions);
26867 + PATCH_OPTION(extensions);
26868 + PATCH_OPTION(debug);
26869 + PATCH_OPTION(balance);
26870 + PATCH_OPTION(last_used_backends);
26872 /* skip the first, the global context */
26873 for (i = 1; i < srv->config_context->used; i++) {
26874 data_config *dc = (data_config *)srv->config_context->data[i];
26875 s = p->config_storage[i];
26878 /* condition didn't match */
26879 if (!config_check_cond(srv, con, dc)) continue;
26883 for (j = 0; j < dc->value->used; j++) {
26884 data_unset *du = dc->value->data[j];
26887 if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
26888 - PATCH(extensions);
26889 + PATCH_OPTION(extensions);
26890 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
26892 + PATCH_OPTION(debug);
26893 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
26895 + PATCH_OPTION(balance);
26896 + PATCH_OPTION(last_used_backends);
26906 SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
26907 plugin_data *p = p_d;
26910 handler_ctx *hctx = con->plugin_ctx[p->id];
26914 if (NULL == hctx) return HANDLER_GO_ON;
26916 mod_proxy_patch_connection(srv, con, p);
26923 if (con->mode != p->id) return HANDLER_GO_ON;
26926 /* ok, create the request */
26927 switch(proxy_write_request(srv, hctx)) {
26928 case HANDLER_ERROR:
26929 - log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
26930 + log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
26936 /* disable this server */
26937 host->is_disabled = 1;
26938 host->disable_ts = srv->cur_ts;
26941 proxy_connection_close(srv, hctx);
26943 - /* reset the enviroment and restart the sub-request */
26945 + /* reset the enviroment and restart the sub-request */
26946 buffer_reset(con->physical.path);
26947 con->mode = DIRECT;
26949 joblist_append(srv, con);
26951 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26952 - * and hope that the childs will be restarted
26954 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26955 + * and hope that the childs will be restarted
26959 return HANDLER_WAIT_FOR_FD;
26960 @@ -938,7 +919,7 @@
26966 if (con->file_started == 1) {
26967 return HANDLER_FINISHED;
26969 @@ -951,13 +932,14 @@
26970 handler_ctx *hctx = ctx;
26971 connection *con = hctx->remote_conn;
26972 plugin_data *p = hctx->plugin_data;
26977 if ((revents & FDEVENT_IN) &&
26978 - hctx->state == PROXY_STATE_READ) {
26979 + (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
26980 + hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
26982 if (p->conf.debug) {
26983 - log_error_write(srv, __FILE__, __LINE__, "sd",
26984 + log_error_write(srv, __FILE__, __LINE__, "sd",
26985 "proxy: fdevent-in", hctx->state);
26988 @@ -965,11 +947,15 @@
26992 + log_error_write(srv, __FILE__, __LINE__, "sd",
26993 + "proxy: request done", hctx->fd);
26994 hctx->host->usage--;
26997 + http_chunk_append_mem(srv, con, NULL, 0);
27000 proxy_connection_close(srv, hctx);
27003 joblist_append(srv, con);
27004 return HANDLER_FINISHED;
27006 @@ -982,53 +968,53 @@
27007 /* response might have been already started, kill the connection */
27008 connection_set_state(srv, con, CON_STATE_ERROR);
27012 joblist_append(srv, con);
27013 return HANDLER_FINISHED;
27018 if (revents & FDEVENT_OUT) {
27019 if (p->conf.debug) {
27020 - log_error_write(srv, __FILE__, __LINE__, "sd",
27021 + log_error_write(srv, __FILE__, __LINE__, "sd",
27022 "proxy: fdevent-out", hctx->state);
27025 if (hctx->state == PROXY_STATE_CONNECT ||
27026 hctx->state == PROXY_STATE_WRITE) {
27027 /* we are allowed to send something out
27030 * 1. in a unfinished connect() call
27031 * 2. in a unfinished write() call (long POST request)
27033 return mod_proxy_handle_subrequest(srv, con, p);
27035 - log_error_write(srv, __FILE__, __LINE__, "sd",
27036 + log_error_write(srv, __FILE__, __LINE__, "sd",
27037 "proxy: out", hctx->state);
27042 /* perhaps this issue is already handled */
27043 if (revents & FDEVENT_HUP) {
27044 if (p->conf.debug) {
27045 - log_error_write(srv, __FILE__, __LINE__, "sd",
27046 + log_error_write(srv, __FILE__, __LINE__, "sd",
27047 "proxy: fdevent-hup", hctx->state);
27051 if (hctx->state == PROXY_STATE_CONNECT) {
27052 /* connect() -> EINPROGRESS -> HUP */
27056 - * what is proxy is doing if it can't reach the next hop ?
27058 + * what is proxy is doing if it can't reach the next hop ?
27063 proxy_connection_close(srv, hctx);
27064 joblist_append(srv, con);
27067 con->http_status = 503;
27068 con->mode = DIRECT;
27071 return HANDLER_FINISHED;
27074 @@ -1038,13 +1024,13 @@
27075 joblist_append(srv, con);
27076 } else if (revents & FDEVENT_ERR) {
27077 /* kill all connections to the proxy process */
27080 log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
27082 joblist_append(srv, con);
27083 proxy_connection_close(srv, hctx);
27087 return HANDLER_FINISHED;
27090 @@ -1058,44 +1044,48 @@
27092 data_array *extension = NULL;
27093 size_t path_info_offset;
27095 + data_integer *last_used_backend;
27096 + data_proxy *host = NULL;
27097 + handler_ctx *hctx = NULL;
27099 + array *backends = NULL;
27101 /* Possibly, we processed already this request */
27102 if (con->file_started == 1) return HANDLER_GO_ON;
27105 mod_proxy_patch_connection(srv, con, p);
27108 fn = con->uri.path;
27110 if (fn->used == 0) {
27111 return HANDLER_ERROR;
27115 s_len = fn->used - 1;
27119 path_info_offset = 0;
27121 - if (p->conf.debug) {
27122 + if (p->conf.debug) {
27123 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - start");
27126 /* check if extension matches */
27127 for (k = 0; k < p->conf.extensions->used; k++) {
27131 extension = (data_array *)p->conf.extensions->data[k];
27134 if (extension->key->used == 0) continue;
27137 ct_len = extension->key->used - 1;
27140 if (s_len < ct_len) continue;
27143 /* check extension in the form "/proxy_pattern" */
27144 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
27145 if (s_len > ct_len + 1) {
27149 if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
27150 path_info_offset = pi_offset - fn->ptr;
27152 @@ -1106,12 +1096,14 @@
27158 if (k == p->conf.extensions->used) {
27159 return HANDLER_GO_ON;
27162 - if (p->conf.debug) {
27163 + backends = extension->value;
27165 + if (p->conf.debug) {
27166 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found");
27169 @@ -1120,34 +1112,34 @@
27170 /* hash balancing */
27172 if (p->conf.debug) {
27173 - log_error_write(srv, __FILE__, __LINE__, "sd",
27174 - "proxy - used hash balancing, hosts:", extension->value->used);
27175 + log_error_write(srv, __FILE__, __LINE__, "sd",
27176 + "proxy - used hash balancing, hosts:", backends->used);
27179 - for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
27180 - data_proxy *host = (data_proxy *)extension->value->data[k];
27181 + for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
27182 unsigned long cur_max;
27184 - if (host->is_disabled) continue;
27186 + data_proxy *cur = (data_proxy *)backends->data[k];
27188 + if (cur->is_disabled) continue;
27190 cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
27191 - generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
27192 + generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
27193 generate_crc32c(CONST_BUF_LEN(con->uri.authority));
27196 if (p->conf.debug) {
27197 - log_error_write(srv, __FILE__, __LINE__, "sbbbd",
27198 + log_error_write(srv, __FILE__, __LINE__, "sbbbd",
27199 "proxy - election:",
27203 con->uri.authority,
27207 - if ((last_max == ULONG_MAX) || /* first round */
27208 - (cur_max > last_max)) {
27209 + if (host == NULL || (cur_max > last_max)) {
27210 last_max = cur_max;
27217 @@ -1155,19 +1147,20 @@
27218 case PROXY_BALANCE_FAIR:
27219 /* fair balancing */
27220 if (p->conf.debug) {
27221 - log_error_write(srv, __FILE__, __LINE__, "s",
27222 + log_error_write(srv, __FILE__, __LINE__, "s",
27223 "proxy - used fair balancing");
27226 - for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27227 - data_proxy *host = (data_proxy *)extension->value->data[k];
27229 - if (host->is_disabled) continue;
27231 - if (host->usage < max_usage) {
27232 - max_usage = host->usage;
27235 + /* try to find the host with the lowest load */
27236 + for (k = 0, max_usage = 0; k < backends->used; k++) {
27237 + data_proxy *cur = (data_proxy *)backends->data[k];
27239 + if (cur->is_disabled) continue;
27241 + if (NULL == host || cur->usage < max_usage) {
27242 + max_usage = cur->usage;
27248 @@ -1175,89 +1168,100 @@
27249 case PROXY_BALANCE_RR:
27251 if (p->conf.debug) {
27252 - log_error_write(srv, __FILE__, __LINE__, "s",
27253 + log_error_write(srv, __FILE__, __LINE__, "s",
27254 "proxy - used round-robin balancing");
27257 /* just to be sure */
27258 - assert(extension->value->used < INT_MAX);
27260 - for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27261 - data_proxy *host = (data_proxy *)extension->value->data[k];
27263 - if (host->is_disabled) continue;
27265 - /* first usable ndx */
27266 - if (max_usage == INT_MAX) {
27269 + assert(backends->used < INT_MAX);
27271 - /* get next ndx */
27272 - if ((int)k > host->last_used_ndx) {
27274 - host->last_used_ndx = k;
27275 + /* send each request to another host:
27279 + * if we have three hosts it is
27281 + * 1 .. 2 .. 3 .. 1 .. 2 .. 3
27287 + /* walk through the list */
27288 + last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
27290 + if (NULL == last_used_backend) {
27291 + last_used_backend = data_integer_init();
27293 + buffer_copy_string_buffer(last_used_backend->key, extension->key);
27294 + last_used_backend->value = 0;
27296 + array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
27299 + /* scan all but the last host to see if they are up
27300 + * take the first running host */
27301 + for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
27302 + data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
27304 + if (cur->is_disabled) continue;
27308 + last_used_backend->value = k;
27313 - /* didn't found a higher id, wrap to the start */
27314 - if (ndx != -1 && max_usage != INT_MAX) {
27317 + if (NULL == host) {
27318 + /* we found nothing better, fallback to the last used backend
27319 + * and check if it is still up */
27320 + host = (data_proxy *)backends->data[last_used_backend->value];
27322 + if (host->is_disabled) host = NULL;
27330 - /* found a server */
27332 - data_proxy *host = (data_proxy *)extension->value->data[ndx];
27335 - * if check-local is disabled, use the uri.path handler
27339 - /* init handler-context */
27340 - handler_ctx *hctx;
27341 - hctx = handler_ctx_init();
27343 - hctx->path_info_offset = path_info_offset;
27344 - hctx->remote_conn = con;
27345 - hctx->plugin_data = p;
27346 - hctx->host = host;
27348 - con->plugin_ctx[p->id] = hctx;
27352 - con->mode = p->id;
27354 - if (p->conf.debug) {
27355 - log_error_write(srv, __FILE__, __LINE__, "sbd",
27356 - "proxy - found a host",
27357 - host->host, host->port);
27360 - return HANDLER_GO_ON;
27362 - /* no handler found */
27363 + /* we havn't found a host */
27364 + if (NULL == host) {
27365 con->http_status = 500;
27367 - log_error_write(srv, __FILE__, __LINE__, "sb",
27368 - "no proxy-handler found for:",
27370 + log_error_write(srv, __FILE__, __LINE__, "sb",
27371 + "no proxy-handler found for:",
27375 return HANDLER_FINISHED;
27378 + /* init handler-context */
27379 + hctx = handler_ctx_init();
27381 + hctx->path_info_offset = path_info_offset;
27382 + hctx->remote_conn = con;
27383 + hctx->plugin_data = p;
27384 + hctx->host = host;
27386 + con->plugin_ctx[p->id] = hctx;
27390 + /* we handle this request */
27391 + con->mode = p->id;
27393 + if (p->conf.debug) {
27394 + log_error_write(srv, __FILE__, __LINE__, "sbd",
27395 + "proxy - found a host",
27396 + host->host, host->port);
27399 return HANDLER_GO_ON;
27402 static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
27403 plugin_data *p = p_d;
27406 proxy_connection_close(srv, con->plugin_ctx[p->id]);
27408 return HANDLER_GO_ON;
27409 @@ -1276,11 +1280,11 @@
27411 for (i = 0; i < srv->config_context->used; i++) {
27412 plugin_config *s = p->config_storage[i];
27414 - if (!s) continue;
27416 + if (!s) continue;
27418 /* get the extensions for all configs */
27421 for (k = 0; k < s->extensions->used; k++) {
27422 data_array *extension = (data_array *)s->extensions->data[k];
27424 @@ -1290,8 +1294,8 @@
27426 if (!host->is_disabled ||
27427 srv->cur_ts - host->disable_ts < 5) continue;
27429 - log_error_write(srv, __FILE__, __LINE__, "sbd",
27431 + log_error_write(srv, __FILE__, __LINE__, "sbd",
27432 "proxy - re-enabled:",
27433 host->host, host->port);
27435 @@ -1317,8 +1321,8 @@
27436 p->handle_uri_clean = mod_proxy_check_extension;
27437 p->handle_subrequest = mod_proxy_handle_subrequest;
27438 p->handle_trigger = mod_proxy_trigger;
27446 --- ../lighttpd-1.4.11/src/mod_redirect.c 2006-02-08 15:38:06.000000000 +0200
27447 +++ lighttpd-1.4.12/src/mod_redirect.c 2006-07-11 22:07:52.000000000 +0300
27448 @@ -22,35 +22,35 @@
27454 plugin_config **config_storage;
27456 - plugin_config conf;
27458 + plugin_config conf;
27461 INIT_FUNC(mod_redirect_init) {
27465 p = calloc(1, sizeof(*p));
27468 p->match_buf = buffer_init();
27469 p->location = buffer_init();
27475 FREE_FUNC(mod_redirect_free) {
27476 plugin_data *p = p_d;
27479 if (!p) return HANDLER_GO_ON;
27481 if (p->config_storage) {
27483 for (i = 0; i < srv->config_context->used; i++) {
27484 plugin_config *s = p->config_storage[i];
27487 pcre_keyvalue_buffer_free(s->redirect);
27492 free(p->config_storage);
27495 buffer_free(p->match_buf);
27496 buffer_free(p->location);
27502 return HANDLER_GO_ON;
27505 @@ -69,195 +69,137 @@
27506 plugin_data *p = p_d;
27510 - config_values_t cv[] = {
27512 + config_values_t cv[] = {
27513 { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27514 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27518 if (!p) return HANDLER_ERROR;
27522 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27525 for (i = 0; i < srv->config_context->used; i++) {
27529 data_array *da = (data_array *)du;
27532 s = calloc(1, sizeof(plugin_config));
27533 s->redirect = pcre_keyvalue_buffer_init();
27536 cv[0].destination = s->redirect;
27539 p->config_storage[i] = s;
27540 ca = ((data_config *)srv->config_context->data[i])->value;
27543 if (0 != config_insert_values_global(srv, ca, cv)) {
27544 return HANDLER_ERROR;
27548 if (NULL == (du = array_get_element(ca, "url.redirect"))) {
27549 /* no url.redirect defined */
27554 if (du->type != TYPE_ARRAY) {
27555 - log_error_write(srv, __FILE__, __LINE__, "sss",
27556 + log_error_write(srv, __FILE__, __LINE__, "sss",
27557 "unexpected type for key: ", "url.redirect", "array of strings");
27560 return HANDLER_ERROR;
27564 da = (data_array *)du;
27567 for (j = 0; j < da->value->used; j++) {
27568 if (da->value->data[j]->type != TYPE_STRING) {
27569 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
27570 - "unexpected type for key: ",
27572 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
27573 + "unexpected type for key: ",
27575 "[", da->value->data[j]->key, "](string)");
27578 return HANDLER_ERROR;
27581 - if (0 != pcre_keyvalue_buffer_append(s->redirect,
27583 + if (0 != pcre_keyvalue_buffer_append(s->redirect,
27584 ((data_string *)(da->value->data[j]))->key->ptr,
27585 ((data_string *)(da->value->data[j]))->value->ptr)) {
27587 - log_error_write(srv, __FILE__, __LINE__, "sb",
27589 + log_error_write(srv, __FILE__, __LINE__, "sb",
27590 "pcre-compile failed for", da->value->data[j]->key);
27596 return HANDLER_GO_ON;
27599 static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
27601 plugin_config *s = p->config_storage[0];
27604 p->conf.redirect = s->redirect;
27607 /* skip the first, the global context */
27608 for (i = 1; i < srv->config_context->used; i++) {
27609 data_config *dc = (data_config *)srv->config_context->data[i];
27610 s = p->config_storage[i];
27613 /* condition didn't match */
27614 if (!config_check_cond(srv, con, dc)) continue;
27618 for (j = 0; j < dc->value->used; j++) {
27619 data_unset *du = dc->value->data[j];
27622 if (0 == strcmp(du->key->ptr, "url.redirect")) {
27623 p->conf.redirect = s->redirect;
27624 p->conf.context = dc;
27633 static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
27635 plugin_data *p = p_data;
27644 * e.g. redirect /base/ to /index.php?section=base
27650 mod_redirect_patch_connection(srv, con, p);
27653 buffer_copy_string_buffer(p->match_buf, con->request.uri);
27655 - for (i = 0; i < p->conf.redirect->used; i++) {
27657 - pcre_extra *extra;
27658 - const char *pattern;
27659 - size_t pattern_len;
27661 - pcre_keyvalue *kv = p->conf.redirect->kv[i];
27666 - extra = kv->key_extra;
27667 - pattern = kv->value->ptr;
27668 - pattern_len = kv->value->used - 1;
27670 - if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
27671 - if (n != PCRE_ERROR_NOMATCH) {
27672 - log_error_write(srv, __FILE__, __LINE__, "sd",
27673 - "execution error while matching: ", n);
27674 - return HANDLER_ERROR;
27677 - const char **list;
27678 - size_t start, end;
27682 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
27684 - /* search for $[0-9] */
27686 - buffer_reset(p->location);
27688 - start = 0; end = pattern_len;
27689 - for (k = 0; k < pattern_len; k++) {
27690 - if ((pattern[k] == '$' || pattern[k] == '%') &&
27691 - isdigit((unsigned char)pattern[k + 1])) {
27694 - size_t num = pattern[k + 1] - '0';
27698 - buffer_append_string_len(p->location, pattern + start, end - start);
27700 - if (pattern[k] == '$') {
27701 - /* n is always > 0 */
27702 - if (num < (size_t)n) {
27703 - buffer_append_string(p->location, list[num]);
27706 - config_append_cond_match_buffer(con, p->conf.context, p->location, num);
27714 - buffer_append_string_len(p->location, pattern + start, pattern_len - start);
27718 - response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27720 - con->http_status = 301;
27721 - con->file_finished = 1;
27723 - return HANDLER_FINISHED;
27725 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
27728 + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27730 + con->http_status = 301;
27731 + con->file_finished = 1;
27733 + return HANDLER_FINISHED;
27735 + else if (i != PCRE_ERROR_NOMATCH) {
27736 + log_error_write(srv, __FILE__, __LINE__, "s",
27737 + "execution error while matching", i);
27749 return HANDLER_GO_ON;
27752 @@ -265,13 +207,13 @@
27753 int mod_redirect_plugin_init(plugin *p) {
27754 p->version = LIGHTTPD_VERSION_ID;
27755 p->name = buffer_init_string("redirect");
27758 p->init = mod_redirect_init;
27759 p->handle_uri_clean = mod_redirect_uri_handler;
27760 p->set_defaults = mod_redirect_set_defaults;
27761 p->cleanup = mod_redirect_free;
27769 --- ../lighttpd-1.4.11/src/mod_rewrite.c 2005-09-29 20:59:10.000000000 +0300
27770 +++ lighttpd-1.4.12/src/mod_rewrite.c 2006-07-11 22:07:51.000000000 +0300
27775 -#ifdef HAVE_PCRE_H
27785 - rewrite_rule **ptr;
27789 -} rewrite_rule_buffer;
27792 - rewrite_rule_buffer *rewrite;
27793 + pcre_keyvalue_buffer *rewrite;
27795 data_config *context; /* to which apply me */
27798 @@ -42,20 +26,20 @@
27804 plugin_config **config_storage;
27806 - plugin_config conf;
27808 + plugin_config conf;
27811 static handler_ctx * handler_ctx_init() {
27812 handler_ctx * hctx;
27815 hctx = calloc(1, sizeof(*hctx));
27818 hctx->state = REWRITE_STATE_UNSET;
27825 @@ -63,207 +47,136 @@
27829 -rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
27830 - rewrite_rule_buffer *kvb;
27832 - kvb = calloc(1, sizeof(*kvb));
27837 -int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
27838 -#ifdef HAVE_PCRE_H
27840 - const char *errptr;
27843 - if (!key) return -1;
27845 - if (kvb->size == 0) {
27849 - kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
27851 - for(i = 0; i < kvb->size; i++) {
27852 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27854 - } else if (kvb->used == kvb->size) {
27857 - kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
27859 - for(i = kvb->used; i < kvb->size; i++) {
27860 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27864 - if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
27865 - 0, &errptr, &erroff, NULL))) {
27870 - kvb->ptr[kvb->used]->value = buffer_init();
27871 - buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
27872 - kvb->ptr[kvb->used]->once = once;
27887 -void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
27888 -#ifdef HAVE_PCRE_H
27891 - for (i = 0; i < kvb->size; i++) {
27892 - if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
27893 - if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
27894 - free(kvb->ptr[i]);
27897 - if (kvb->ptr) free(kvb->ptr);
27904 INIT_FUNC(mod_rewrite_init) {
27908 p = calloc(1, sizeof(*p));
27911 p->match_buf = buffer_init();
27917 FREE_FUNC(mod_rewrite_free) {
27918 plugin_data *p = p_d;
27923 if (!p) return HANDLER_GO_ON;
27926 buffer_free(p->match_buf);
27927 if (p->config_storage) {
27929 for (i = 0; i < srv->config_context->used; i++) {
27930 plugin_config *s = p->config_storage[i];
27931 - rewrite_rule_buffer_free(s->rewrite);
27933 + pcre_keyvalue_buffer_free(s->rewrite);
27934 + buffer_free(s->once);
27938 free(p->config_storage);
27945 return HANDLER_GO_ON;
27948 static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
27952 if (NULL != (du = array_get_element(ca, option))) {
27953 data_array *da = (data_array *)du;
27957 if (du->type != TYPE_ARRAY) {
27958 - log_error_write(srv, __FILE__, __LINE__, "sss",
27959 + log_error_write(srv, __FILE__, __LINE__, "sss",
27960 "unexpected type for key: ", option, "array of strings");
27963 return HANDLER_ERROR;
27967 da = (data_array *)du;
27970 for (j = 0; j < da->value->used; j++) {
27971 if (da->value->data[j]->type != TYPE_STRING) {
27972 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
27973 - "unexpected type for key: ",
27975 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
27976 + "unexpected type for key: ",
27978 "[", da->value->data[j]->key, "](string)");
27981 return HANDLER_ERROR;
27984 - if (0 != rewrite_rule_buffer_append(s->rewrite,
27985 - ((data_string *)(da->value->data[j]))->key,
27986 - ((data_string *)(da->value->data[j]))->value,
27989 + if (0 != pcre_keyvalue_buffer_append(s->rewrite,
27990 + ((data_string *)(da->value->data[j]))->key->ptr,
27991 + ((data_string *)(da->value->data[j]))->value->ptr)) {
27993 - log_error_write(srv, __FILE__, __LINE__, "sb",
27994 + log_error_write(srv, __FILE__, __LINE__, "sb",
27995 "pcre-compile failed for", da->value->data[j]->key);
27997 - log_error_write(srv, __FILE__, __LINE__, "s",
27998 + log_error_write(srv, __FILE__, __LINE__, "s",
27999 "pcre support is missing, please install libpcre and the headers");
28004 + buffer_append_string_len(s->once, CONST_STR_LEN("1"));
28006 + buffer_append_string_len(s->once, CONST_STR_LEN("0"));
28015 SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
28016 plugin_data *p = p_d;
28019 - config_values_t cv[] = {
28021 + config_values_t cv[] = {
28022 { "url.rewrite-repeat", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
28023 { "url.rewrite-once", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
28025 - /* old names, still supported
28028 + /* old names, still supported
28030 * url.rewrite remapped to url.rewrite-once
28031 * url.rewrite-final is url.rewrite-once
28035 { "url.rewrite", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
28036 { "url.rewrite-final", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
28037 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
28041 if (!p) return HANDLER_ERROR;
28045 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28048 for (i = 0; i < srv->config_context->used; i++) {
28053 s = calloc(1, sizeof(plugin_config));
28054 - s->rewrite = rewrite_rule_buffer_init();
28056 - cv[0].destination = s->rewrite;
28057 - cv[1].destination = s->rewrite;
28058 - cv[2].destination = s->rewrite;
28060 + s->rewrite = pcre_keyvalue_buffer_init();
28061 + s->once = buffer_init();
28063 p->config_storage[i] = s;
28064 ca = ((data_config *)srv->config_context->data[i])->value;
28067 if (0 != config_insert_values_global(srv, ca, cv)) {
28068 return HANDLER_ERROR;
28072 parse_config_entry(srv, s, ca, "url.rewrite-once", 1);
28073 parse_config_entry(srv, s, ca, "url.rewrite-final", 1);
28074 parse_config_entry(srv, s, ca, "url.rewrite", 1);
28075 parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
28079 return HANDLER_GO_ON;
28082 @@ -271,157 +184,107 @@
28084 plugin_config *s = p->config_storage[0];
28085 p->conf.rewrite = s->rewrite;
28087 + p->conf.once = s->once;
28089 /* skip the first, the global context */
28090 for (i = 1; i < srv->config_context->used; i++) {
28091 data_config *dc = (data_config *)srv->config_context->data[i];
28092 s = p->config_storage[i];
28095 if (COMP_HTTP_URL == dc->comp) continue;
28098 /* condition didn't match */
28099 if (!config_check_cond(srv, con, dc)) continue;
28103 for (j = 0; j < dc->value->used; j++) {
28104 data_unset *du = dc->value->data[j];
28107 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
28108 p->conf.rewrite = s->rewrite;
28109 + p->conf.once = s->once;
28110 p->conf.context = dc;
28111 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
28112 p->conf.rewrite = s->rewrite;
28113 + p->conf.once = s->once;
28114 p->conf.context = dc;
28115 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
28116 p->conf.rewrite = s->rewrite;
28117 + p->conf.once = s->once;
28118 p->conf.context = dc;
28119 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
28120 p->conf.rewrite = s->rewrite;
28121 + p->conf.once = s->once;
28122 p->conf.context = dc;
28131 URIHANDLER_FUNC(mod_rewrite_con_reset) {
28132 plugin_data *p = p_d;
28138 if (con->plugin_ctx[p->id]) {
28139 handler_ctx_free(con->plugin_ctx[p->id]);
28140 con->plugin_ctx[p->id] = NULL;
28144 return HANDLER_GO_ON;
28147 URIHANDLER_FUNC(mod_rewrite_uri_handler) {
28149 plugin_data *p = p_d;
28159 * e.g. rewrite /base/ to /index.php?section=base
28165 if (con->plugin_ctx[p->id]) {
28166 hctx = con->plugin_ctx[p->id];
28169 if (hctx->loops++ > 100) {
28170 - log_error_write(srv, __FILE__, __LINE__, "s",
28171 + log_error_write(srv, __FILE__, __LINE__, "s",
28172 "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
28175 return HANDLER_ERROR;
28179 if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
28183 mod_rewrite_patch_connection(srv, con, p);
28185 if (!p->conf.rewrite) return HANDLER_GO_ON;
28188 buffer_copy_string_buffer(p->match_buf, con->request.uri);
28190 - for (i = 0; i < p->conf.rewrite->used; i++) {
28192 - const char *pattern;
28193 - size_t pattern_len;
28195 - rewrite_rule *rule = p->conf.rewrite->ptr[i];
28199 - match = rule->key;
28200 - pattern = rule->value->ptr;
28201 - pattern_len = rule->value->used - 1;
28203 - if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
28204 - if (n != PCRE_ERROR_NOMATCH) {
28205 - log_error_write(srv, __FILE__, __LINE__, "sd",
28206 - "execution error while matching: ", n);
28207 - return HANDLER_ERROR;
28210 - const char **list;
28211 - size_t start, end;
28215 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
28217 - /* search for $[0-9] */
28219 - buffer_reset(con->request.uri);
28221 - start = 0; end = pattern_len;
28222 - for (k = 0; k < pattern_len; k++) {
28223 - if ((pattern[k] == '$' || pattern[k] == '%') &&
28224 - isdigit((unsigned char)pattern[k + 1])) {
28227 - size_t num = pattern[k + 1] - '0';
28231 - buffer_append_string_len(con->request.uri, pattern + start, end - start);
28233 - if (pattern[k] == '$') {
28234 - /* n is always > 0 */
28235 - if (num < (size_t)n) {
28236 - buffer_append_string(con->request.uri, list[num]);
28239 - config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
28247 - buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
28251 - hctx = handler_ctx_init();
28253 - con->plugin_ctx[p->id] = hctx;
28255 - if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
28257 - return HANDLER_COMEBACK;
28259 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
28262 + hctx = handler_ctx_init();
28264 + con->plugin_ctx[p->id] = hctx;
28266 + if (p->conf.once->ptr[i] == '1')
28267 + hctx->state = REWRITE_STATE_FINISHED;
28269 + return HANDLER_COMEBACK;
28271 + else if (i != PCRE_ERROR_NOMATCH) {
28272 + log_error_write(srv, __FILE__, __LINE__, "s",
28273 + "execution error while matching", i);
28281 @@ -434,17 +297,17 @@
28282 int mod_rewrite_plugin_init(plugin *p) {
28283 p->version = LIGHTTPD_VERSION_ID;
28284 p->name = buffer_init_string("rewrite");
28287 p->init = mod_rewrite_init;
28288 /* it has to stay _raw as we are matching on uri + querystring
28292 p->handle_uri_raw = mod_rewrite_uri_handler;
28293 p->set_defaults = mod_rewrite_set_defaults;
28294 p->cleanup = mod_rewrite_free;
28295 p->connection_reset = mod_rewrite_con_reset;
28303 --- ../lighttpd-1.4.11/src/mod_rrdtool.c 2005-08-22 01:52:24.000000000 +0300
28304 +++ lighttpd-1.4.12/src/mod_rrdtool.c 2006-07-11 22:07:52.000000000 +0300
28306 #include <stdlib.h>
28308 #include <string.h>
28309 -#include <unistd.h>
28313 @@ -20,10 +19,14 @@
28314 /* no need for waitpid if we don't have fork */
28315 #include <sys/wait.h>
28318 +#include "sys-files.h"
28319 +#include "sys-process.h"
28322 buffer *path_rrdtool_bin;
28326 double requests, *requests_ptr;
28327 double bytes_written, *bytes_written_ptr;
28328 double bytes_read, *bytes_read_ptr;
28329 @@ -31,84 +34,84 @@
28339 int read_fd, write_fd;
28343 int rrdtool_running;
28346 plugin_config **config_storage;
28347 plugin_config conf;
28350 INIT_FUNC(mod_rrd_init) {
28354 p = calloc(1, sizeof(*p));
28357 p->resp = buffer_init();
28358 p->cmd = buffer_init();
28364 FREE_FUNC(mod_rrd_free) {
28365 plugin_data *p = p_d;
28369 if (!p) return HANDLER_GO_ON;
28372 if (p->config_storage) {
28373 for (i = 0; i < srv->config_context->used; i++) {
28374 plugin_config *s = p->config_storage[i];
28377 buffer_free(s->path_rrdtool_bin);
28378 buffer_free(s->path_rrd);
28384 buffer_free(p->cmd);
28385 buffer_free(p->resp);
28388 free(p->config_storage);
28391 if (p->rrdtool_pid) {
28394 close(p->write_fd);
28397 /* collect status */
28398 waitpid(p->rrdtool_pid, &status, 0);
28406 return HANDLER_GO_ON;
28409 int mod_rrd_create_pipe(server *srv, plugin_data *p) {
28413 int to_rrdtool_fds[2];
28414 int from_rrdtool_fds[2];
28417 if (pipe(to_rrdtool_fds)) {
28418 - log_error_write(srv, __FILE__, __LINE__, "ss",
28419 + log_error_write(srv, __FILE__, __LINE__, "ss",
28420 "pipe failed: ", strerror(errno));
28425 if (pipe(from_rrdtool_fds)) {
28426 - log_error_write(srv, __FILE__, __LINE__, "ss",
28427 + log_error_write(srv, __FILE__, __LINE__, "ss",
28428 "pipe failed: ", strerror(errno));
28434 switch (pid = fork()) {
28436 @@ -117,33 +120,33 @@
28442 /* move stdout to from_rrdtool_fd[1] */
28443 close(STDOUT_FILENO);
28444 dup2(from_rrdtool_fds[1], STDOUT_FILENO);
28445 close(from_rrdtool_fds[1]);
28447 close(from_rrdtool_fds[0]);
28450 /* move the stdin to to_rrdtool_fd[0] */
28451 close(STDIN_FILENO);
28452 dup2(to_rrdtool_fds[0], STDIN_FILENO);
28453 close(to_rrdtool_fds[0]);
28455 close(to_rrdtool_fds[1]);
28458 close(STDERR_FILENO);
28461 if (srv->errorlog_mode == ERRORLOG_FILE) {
28462 dup2(srv->errorlog_fd, STDERR_FILENO);
28463 close(srv->errorlog_fd);
28469 args = malloc(sizeof(*args) * argc);
28473 args[i++] = p->conf.path_rrdtool_bin->ptr;
28476 @@ -152,12 +155,12 @@
28477 for (i = 3; i < 256; i++) {
28483 execv(args[0], args);
28486 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
28492 @@ -168,19 +171,19 @@
28498 close(from_rrdtool_fds[1]);
28499 close(to_rrdtool_fds[0]);
28502 /* register PID and wait for them asyncronously */
28503 p->write_fd = to_rrdtool_fds[1];
28504 p->read_fd = from_rrdtool_fds[0];
28505 p->rrdtool_pid = pid;
28516 @@ -189,19 +192,19 @@
28518 static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
28522 /* check if DB already exists */
28523 if (0 == stat(s->path_rrd->ptr, &st)) {
28524 /* check if it is plain file */
28525 if (!S_ISREG(st.st_mode)) {
28526 - log_error_write(srv, __FILE__, __LINE__, "sb",
28527 + log_error_write(srv, __FILE__, __LINE__, "sb",
28528 "not a regular file:", s->path_rrd);
28529 return HANDLER_ERROR;
28533 /* create a new one */
28536 BUFFER_COPY_STRING_CONST(p->cmd, "create ");
28537 buffer_append_string_buffer(p->cmd, s->path_rrd);
28538 buffer_append_string(p->cmd, " --step 60 ");
28539 @@ -220,158 +223,155 @@
28540 buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
28541 buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
28542 buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
28545 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28546 - log_error_write(srv, __FILE__, __LINE__, "ss",
28547 + log_error_write(srv, __FILE__, __LINE__, "ss",
28548 "rrdtool-write: failed", strerror(errno));
28551 return HANDLER_ERROR;
28555 buffer_prepare_copy(p->resp, 4096);
28556 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28557 - log_error_write(srv, __FILE__, __LINE__, "ss",
28558 + log_error_write(srv, __FILE__, __LINE__, "ss",
28559 "rrdtool-read: failed", strerror(errno));
28562 return HANDLER_ERROR;
28569 if (p->resp->ptr[0] != 'O' ||
28570 p->resp->ptr[1] != 'K') {
28571 - log_error_write(srv, __FILE__, __LINE__, "sbb",
28572 + log_error_write(srv, __FILE__, __LINE__, "sbb",
28573 "rrdtool-response:", p->cmd, p->resp);
28576 return HANDLER_ERROR;
28581 return HANDLER_GO_ON;
28584 -#define PATCH(x) \
28585 - p->conf.x = s->x;
28586 static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
28588 plugin_config *s = p->config_storage[0];
28590 - PATCH(path_rrdtool_bin);
28594 + PATCH_OPTION(path_rrdtool_bin);
28595 + PATCH_OPTION(path_rrd);
28597 p->conf.bytes_written_ptr = &(s->bytes_written);
28598 p->conf.bytes_read_ptr = &(s->bytes_read);
28599 p->conf.requests_ptr = &(s->requests);
28602 /* skip the first, the global context */
28603 for (i = 1; i < srv->config_context->used; i++) {
28604 data_config *dc = (data_config *)srv->config_context->data[i];
28605 s = p->config_storage[i];
28608 /* condition didn't match */
28609 if (!config_check_cond(srv, con, dc)) continue;
28613 for (j = 0; j < dc->value->used; j++) {
28614 data_unset *du = dc->value->data[j];
28617 if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
28619 + PATCH_OPTION(path_rrd);
28620 /* get pointers to double values */
28623 p->conf.bytes_written_ptr = &(s->bytes_written);
28624 p->conf.bytes_read_ptr = &(s->bytes_read);
28625 p->conf.requests_ptr = &(s->requests);
28635 SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
28636 plugin_data *p = p_d;
28639 - config_values_t cv[] = {
28641 + config_values_t cv[] = {
28642 { "rrdtool.binary", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
28643 { "rrdtool.db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
28644 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
28648 if (!p) return HANDLER_ERROR;
28651 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28654 for (i = 0; i < srv->config_context->used; i++) {
28658 s = calloc(1, sizeof(plugin_config));
28659 s->path_rrdtool_bin = buffer_init();
28660 s->path_rrd = buffer_init();
28662 s->bytes_written = 0;
28666 cv[0].destination = s->path_rrdtool_bin;
28667 cv[1].destination = s->path_rrd;
28670 p->config_storage[i] = s;
28673 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
28674 return HANDLER_ERROR;
28678 if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
28679 /* path_rrdtool_bin is a global option */
28681 - log_error_write(srv, __FILE__, __LINE__, "s",
28683 + log_error_write(srv, __FILE__, __LINE__, "s",
28684 "rrdtool.binary can only be set as a global option.");
28687 return HANDLER_ERROR;
28694 p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
28695 p->rrdtool_running = 0;
28698 /* check for dir */
28701 if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
28702 - log_error_write(srv, __FILE__, __LINE__, "s",
28703 + log_error_write(srv, __FILE__, __LINE__, "s",
28704 "rrdtool.binary has to be set");
28705 return HANDLER_ERROR;
28709 /* open the pipe to rrdtool */
28710 if (mod_rrd_create_pipe(srv, p)) {
28711 return HANDLER_ERROR;
28715 p->rrdtool_running = 1;
28718 return HANDLER_GO_ON;
28721 TRIGGER_FUNC(mod_rrd_trigger) {
28722 plugin_data *p = p_d;
28726 if (!p->rrdtool_running) return HANDLER_GO_ON;
28727 if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
28730 for (i = 0; i < srv->config_context->used; i++) {
28731 plugin_config *s = p->config_storage[i];
28735 if (buffer_is_empty(s->path_rrd)) continue;
28738 /* write the data down every minute */
28741 if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
28744 BUFFER_COPY_STRING_CONST(p->cmd, "update ");
28745 buffer_append_string_buffer(p->cmd, s->path_rrd);
28746 BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
28747 @@ -381,69 +381,69 @@
28748 BUFFER_APPEND_STRING_CONST(p->cmd, ":");
28749 buffer_append_long(p->cmd, s->requests);
28750 BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
28753 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28754 p->rrdtool_running = 0;
28756 - log_error_write(srv, __FILE__, __LINE__, "ss",
28758 + log_error_write(srv, __FILE__, __LINE__, "ss",
28759 "rrdtool-write: failed", strerror(errno));
28762 return HANDLER_ERROR;
28766 buffer_prepare_copy(p->resp, 4096);
28767 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28768 p->rrdtool_running = 0;
28770 - log_error_write(srv, __FILE__, __LINE__, "ss",
28772 + log_error_write(srv, __FILE__, __LINE__, "ss",
28773 "rrdtool-read: failed", strerror(errno));
28776 return HANDLER_ERROR;
28783 if (p->resp->ptr[0] != 'O' ||
28784 p->resp->ptr[1] != 'K') {
28785 p->rrdtool_running = 0;
28787 - log_error_write(srv, __FILE__, __LINE__, "sbb",
28789 + log_error_write(srv, __FILE__, __LINE__, "sbb",
28790 "rrdtool-response:", p->cmd, p->resp);
28793 return HANDLER_ERROR;
28796 s->bytes_written = 0;
28801 return HANDLER_GO_ON;
28804 REQUESTDONE_FUNC(mod_rrd_account) {
28805 plugin_data *p = p_d;
28808 mod_rrd_patch_connection(srv, con, p);
28811 *(p->conf.requests_ptr) += 1;
28812 *(p->conf.bytes_written_ptr) += con->bytes_written;
28813 *(p->conf.bytes_read_ptr) += con->bytes_read;
28816 return HANDLER_GO_ON;
28819 int mod_rrdtool_plugin_init(plugin *p) {
28820 p->version = LIGHTTPD_VERSION_ID;
28821 p->name = buffer_init_string("rrd");
28824 p->init = mod_rrd_init;
28825 p->cleanup = mod_rrd_free;
28826 p->set_defaults= mod_rrd_set_defaults;
28829 p->handle_trigger = mod_rrd_trigger;
28830 p->handle_request_done = mod_rrd_account;
28838 --- ../lighttpd-1.4.11/src/mod_scgi.c 2006-03-04 17:15:26.000000000 +0200
28839 +++ lighttpd-1.4.12/src/mod_scgi.c 2006-07-11 22:07:51.000000000 +0300
28841 #include <sys/types.h>
28842 -#include <unistd.h>
28845 #include <string.h>
28849 #include "sys-socket.h"
28851 +#include "sys-files.h"
28852 +#include "sys-strings.h"
28853 +#include "sys-process.h"
28855 #ifndef UNIX_PATH_MAX
28856 # define UNIX_PATH_MAX 108
28857 @@ -46,30 +47,29 @@
28858 enum {EOL_UNSET, EOL_N, EOL_RN};
28866 * - add timeout for a connect to a non-scgi process
28867 * (use state_timestamp + state)
28872 typedef struct scgi_proc {
28873 size_t id; /* id will be between 1 and max_procs */
28874 buffer *socket; /* config.socket + "-" + id */
28875 unsigned port; /* config.port + pno */
28877 - pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
28879 + pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
28881 size_t load; /* number of requests waiting on this process */
28883 time_t last_used; /* see idle_timeout */
28884 size_t requests; /* see max_requests */
28885 struct scgi_proc *prev, *next; /* see first */
28888 time_t disable_ts; /* replace by host->something */
28893 enum { PROC_STATE_UNSET, /* init-phase */
28895 PROC_STATE_KILLED, /* was killed as we don't have the load anymore */
28896 PROC_STATE_DIED, /* marked as dead, should be restarted */
28897 PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
28903 @@ -86,20 +86,20 @@
28904 * sorted by lowest load
28906 * whenever a job is done move it up in the list
28907 - * until it is sorted, move it down as soon as the
28908 + * until it is sorted, move it down as soon as the
28911 - scgi_proc *first;
28912 - scgi_proc *unused_procs;
28913 + scgi_proc *first;
28914 + scgi_proc *unused_procs;
28918 * spawn at least min_procs, at max_procs.
28920 - * as soon as the load of the first entry
28921 + * as soon as the load of the first entry
28922 * is max_load_per_proc we spawn a new one
28923 - * and add it to the first entry and give it
28924 + * and add it to the first entry and give it
28930 unsigned short min_procs;
28931 @@ -111,44 +111,44 @@
28934 * kick the process from the list if it was not
28935 - * used for idle_timeout until min_procs is
28936 + * used for idle_timeout until min_procs is
28937 * reached. this helps to get the processlist
28938 * small again we had a small peak load.
28943 unsigned short idle_timeout;
28947 * time after a disabled remote connection is tried to be re-enabled
28955 unsigned short disable_time;
28958 * same scgi processes get a little bit larger
28959 - * than wanted. max_requests_per_proc kills a
28960 + * than wanted. max_requests_per_proc kills a
28961 * process after a number of handled requests.
28964 size_t max_requests_per_proc;
28975 - * if host is one of the local IP adresses the
28976 + * if host is one of the local IP adresses the
28977 * whole connection is local
28979 * if tcp/ip should be used host AND port have
28980 - * to be specified
28984 + * to be specified
28988 unsigned short port;
28991 @@ -161,7 +161,7 @@
28993 buffer *unixsocket;
28995 - /* if socket is local we can start the scgi
28996 + /* if socket is local we can start the scgi
28999 * bin-path is the path to the binary
29000 @@ -169,19 +169,19 @@
29001 * check min_procs and max_procs for the number
29002 * of process to start-up
29004 - buffer *bin_path;
29006 - /* bin-path is set bin-environment is taken to
29007 + buffer *bin_path;
29009 + /* bin-path is set bin-environment is taken to
29010 * create the environement before starting the
29018 array *bin_env_copy;
29022 - * docroot-translation between URL->phys and the
29023 + * docroot-translation between URL->phys and the
29027 @@ -192,7 +192,7 @@
29031 - * check_local tell you if the phys file is stat()ed
29032 + * check_local tell you if the phys file is stat()ed
29033 * or not. FastCGI doesn't care if the service is
29034 * remote. If the web-server side doesn't contain
29035 * the scgi-files we should not stat() for them
29036 @@ -202,33 +202,33 @@
29039 * append PATH_INFO to SCRIPT_FILENAME
29042 * php needs this if cgi.fix_pathinfo is provied
29048 ssize_t load; /* replace by host->load */
29050 size_t max_id; /* corresponds most of the time to
29054 only if a process is killed max_id waits for the process itself
29055 to die and decrements its afterwards */
29056 } scgi_extension_host;
29059 * one extension can have multiple hosts assigned
29060 - * one host can spawn additional processes on the same
29061 + * one host can spawn additional processes on the same
29062 * socket (if we control it)
29064 * ext -> host -> procs
29067 - * if the scgi process is remote that whole goes down
29068 + * if the scgi process is remote that whole goes down
29071 * ext -> host -> procs
29075 * in case of PHP and FCGI_CHILDREN we have again a procs
29076 * but we don't control it directly.
29077 @@ -239,7 +239,7 @@
29078 buffer *key; /* like .php */
29080 scgi_extension_host **hosts;
29086 @@ -253,14 +253,14 @@
29104 @@ -268,52 +268,51 @@
29105 /* generic plugin data, shared between all connections */
29114 buffer *parse_response;
29117 plugin_config **config_storage;
29120 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
29123 /* connection specific data */
29124 -typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
29125 - FCGI_STATE_WRITE, FCGI_STATE_READ
29126 +typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
29127 + FCGI_STATE_WRITE, FCGI_STATE_READ
29128 } scgi_connection_state_t;
29131 - buffer *response;
29132 + buffer *response;
29133 size_t response_len;
29135 int response_padding;
29139 scgi_extension_host *host;
29142 scgi_connection_state_t state;
29143 time_t state_timestamp;
29146 int reconnects; /* number of reconnect attempts */
29153 buffer *response_header;
29156 int delayed; /* flag to mark that the connect() is delayed */
29160 int fd; /* fd to the scgi process */
29161 int fde_ndx; /* index into the fd-event buffer */
29167 plugin_config conf;
29170 connection *remote_conn; /* dumb pointer */
29171 plugin_data *plugin_data; /* dumb pointer */
29173 @@ -328,28 +327,28 @@
29175 static handler_ctx * handler_ctx_init() {
29176 handler_ctx * hctx;
29179 hctx = calloc(1, sizeof(*hctx));
29183 hctx->fde_ndx = -1;
29186 hctx->response = buffer_init();
29187 hctx->response_header = buffer_init();
29190 hctx->request_id = 0;
29191 hctx->state = FCGI_STATE_INIT;
29195 hctx->response_len = 0;
29196 hctx->response_type = 0;
29197 hctx->response_padding = 0;
29201 hctx->reconnects = 0;
29203 hctx->wb = chunkqueue_init();
29209 @@ -358,12 +357,12 @@
29210 buffer_free(hctx->response_header);
29212 chunkqueue_free(hctx->wb);
29216 if (hctx->rb->ptr) free(hctx->rb->ptr);
29224 @@ -372,20 +371,20 @@
29226 f = calloc(1, sizeof(*f));
29227 f->socket = buffer_init();
29237 void scgi_process_free(scgi_proc *f) {
29241 scgi_process_free(f->next);
29244 buffer_free(f->socket);
29250 @@ -400,62 +399,62 @@
29251 f->bin_path = buffer_init();
29252 f->bin_env = array_init();
29253 f->bin_env_copy = array_init();
29259 void scgi_host_free(scgi_extension_host *h) {
29263 buffer_free(h->host);
29264 buffer_free(h->unixsocket);
29265 buffer_free(h->docroot);
29266 buffer_free(h->bin_path);
29267 array_free(h->bin_env);
29268 array_free(h->bin_env_copy);
29271 scgi_process_free(h->first);
29272 scgi_process_free(h->unused_procs);
29280 scgi_exts *scgi_extensions_init() {
29283 f = calloc(1, sizeof(*f));
29289 void scgi_extensions_free(scgi_exts *f) {
29296 for (i = 0; i < f->used; i++) {
29297 scgi_extension *fe;
29304 for (j = 0; j < fe->used; j++) {
29305 scgi_extension_host *h;
29315 buffer_free(fe->key);
29329 @@ -504,99 +503,103 @@
29333 - fe->hosts[fe->used++] = fh;
29334 + fe->hosts[fe->used++] = fh;
29341 INIT_FUNC(mod_scgi_init) {
29345 p = calloc(1, sizeof(*p));
29348 p->scgi_env = buffer_init();
29351 p->path = buffer_init();
29352 p->parse_response = buffer_init();
29359 FREE_FUNC(mod_scgi_free) {
29360 plugin_data *p = p_d;
29365 buffer_free(p->scgi_env);
29366 buffer_free(p->path);
29367 buffer_free(p->parse_response);
29370 if (p->config_storage) {
29372 for (i = 0; i < srv->config_context->used; i++) {
29373 plugin_config *s = p->config_storage[i];
29382 for (j = 0; j < exts->used; j++) {
29383 scgi_extension *ex;
29386 ex = exts->exts[j];
29389 for (n = 0; n < ex->used; n++) {
29391 scgi_extension_host *host;
29394 host = ex->hosts[n];
29397 for (proc = host->first; proc; proc = proc->next) {
29399 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29401 - if (proc->is_local &&
29404 + if (proc->is_local &&
29405 !buffer_is_empty(proc->socket)) {
29406 unlink(proc->socket->ptr);
29411 for (proc = host->unused_procs; proc; proc = proc->next) {
29413 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29415 - if (proc->is_local &&
29418 + if (proc->is_local &&
29419 !buffer_is_empty(proc->socket)) {
29420 unlink(proc->socket->ptr);
29427 scgi_extensions_free(s->exts);
29432 free(p->config_storage);
29439 return HANDLER_GO_ON;
29442 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
29446 if (!key || !val) return -1;
29449 dst = malloc(key_len + val_len + 3);
29450 memcpy(dst, key, key_len);
29451 dst[key_len] = '=';
29452 /* add the \0 from the value */
29453 memcpy(dst + key_len + 1, val, val_len + 1);
29456 if (env->size == 0) {
29458 env->ptr = malloc(env->size * sizeof(*env->ptr));
29459 @@ -604,13 +607,13 @@
29461 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
29465 env->ptr[env->used++] = dst;
29471 -static int scgi_spawn_connection(server *srv,
29472 +static int scgi_spawn_connection(server *srv,
29474 scgi_extension_host *host,
29476 @@ -622,31 +625,27 @@
29478 struct sockaddr_in scgi_addr_in;
29479 struct sockaddr *scgi_addr;
29490 if (p->conf.debug) {
29491 log_error_write(srv, __FILE__, __LINE__, "sdb",
29492 "new proc, socket:", proc->port, proc->socket);
29496 if (!buffer_is_empty(proc->socket)) {
29497 memset(&scgi_addr, 0, sizeof(scgi_addr));
29500 #ifdef HAVE_SYS_UN_H
29501 scgi_addr_un.sun_family = AF_UNIX;
29502 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
29506 servlen = SUN_LEN(&scgi_addr_un);
29508 - /* stevens says: */
29509 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
29512 socket_type = AF_UNIX;
29513 scgi_addr = (struct sockaddr *) &scgi_addr_un;
29515 @@ -656,115 +655,115 @@
29518 scgi_addr_in.sin_family = AF_INET;
29521 if (buffer_is_empty(host->host)) {
29522 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29524 struct hostent *he;
29527 /* set a usefull default */
29528 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29533 if (NULL == (he = gethostbyname(host->host->ptr))) {
29534 - log_error_write(srv, __FILE__, __LINE__,
29535 - "sdb", "gethostbyname failed: ",
29536 + log_error_write(srv, __FILE__, __LINE__,
29537 + "sdb", "gethostbyname failed: ",
29538 h_errno, host->host);
29543 if (he->h_addrtype != AF_INET) {
29544 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
29549 if (he->h_length != sizeof(struct in_addr)) {
29550 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
29555 memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
29559 scgi_addr_in.sin_port = htons(proc->port);
29560 servlen = sizeof(scgi_addr_in);
29563 socket_type = AF_INET;
29564 scgi_addr = (struct sockaddr *) &scgi_addr_in;
29568 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29569 - log_error_write(srv, __FILE__, __LINE__, "ss",
29570 + log_error_write(srv, __FILE__, __LINE__, "ss",
29571 "failed:", strerror(errno));
29576 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
29577 /* server is not up, spawn in */
29582 if (!buffer_is_empty(proc->socket)) {
29583 unlink(proc->socket->ptr);
29590 /* reopen socket */
29591 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29592 - log_error_write(srv, __FILE__, __LINE__, "ss",
29593 + log_error_write(srv, __FILE__, __LINE__, "ss",
29594 "socket failed:", strerror(errno));
29600 if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
29601 - log_error_write(srv, __FILE__, __LINE__, "ss",
29602 + log_error_write(srv, __FILE__, __LINE__, "ss",
29603 "socketsockopt failed:", strerror(errno));
29608 /* create socket */
29609 if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
29610 - log_error_write(srv, __FILE__, __LINE__, "sbds",
29611 - "bind failed for:",
29614 + log_error_write(srv, __FILE__, __LINE__, "sbds",
29615 + "bind failed for:",
29623 if (-1 == listen(scgi_fd, 1024)) {
29624 - log_error_write(srv, __FILE__, __LINE__, "ss",
29625 + log_error_write(srv, __FILE__, __LINE__, "ss",
29626 "listen failed:", strerror(errno));
29633 switch ((child = fork())) {
29643 /* create environment */
29649 /* we don't need the client socket */
29650 for (fd = 3; fd < 256; fd++) {
29651 if (fd != 2 && fd != scgi_fd) close(fd);
29655 /* build clean environment */
29656 if (host->bin_env_copy->used) {
29657 for (i = 0; i < host->bin_env_copy->used; i++) {
29658 data_string *ds = (data_string *)host->bin_env_copy->data[i];
29662 if (NULL != (ge = getenv(ds->value->ptr))) {
29663 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
29665 @@ -772,44 +771,44 @@
29667 for (i = 0; environ[i]; i++) {
29671 if (NULL != (eq = strchr(environ[i], '='))) {
29672 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
29678 /* create environment */
29679 for (i = 0; i < host->bin_env->used; i++) {
29680 data_string *ds = (data_string *)host->bin_env->data[i];
29683 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
29687 for (i = 0; i < env.used; i++) {
29688 /* search for PHP_FCGI_CHILDREN */
29689 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
29693 /* not found, add a default */
29694 if (i == env.used) {
29695 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
29699 env.ptr[env.used] = NULL;
29703 buffer_copy_string(b, "exec ");
29704 buffer_append_string_buffer(b, host->bin_path);
29708 execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
29710 - log_error_write(srv, __FILE__, __LINE__, "sbs",
29712 + log_error_write(srv, __FILE__, __LINE__, "sbs",
29713 "execl failed for:", host->bin_path, strerror(errno));
29722 @@ -817,32 +816,32 @@
29729 select(0, NULL, NULL, NULL, &tv);
29732 switch (waitpid(child, &status, WNOHANG)) {
29734 /* child still running after timeout, good */
29737 /* no PID found ? should never happen */
29738 - log_error_write(srv, __FILE__, __LINE__, "ss",
29739 + log_error_write(srv, __FILE__, __LINE__, "ss",
29740 "pid not found:", strerror(errno));
29743 /* the child should not terminate at all */
29744 if (WIFEXITED(status)) {
29745 - log_error_write(srv, __FILE__, __LINE__, "sd",
29746 - "child exited (is this a SCGI binary ?):",
29747 + log_error_write(srv, __FILE__, __LINE__, "sd",
29748 + "child exited (is this a SCGI binary ?):",
29749 WEXITSTATUS(status));
29750 } else if (WIFSIGNALED(status)) {
29751 - log_error_write(srv, __FILE__, __LINE__, "sd",
29752 - "child signaled:",
29753 + log_error_write(srv, __FILE__, __LINE__, "sd",
29754 + "child signaled:",
29757 - log_error_write(srv, __FILE__, __LINE__, "sd",
29758 - "child died somehow:",
29759 + log_error_write(srv, __FILE__, __LINE__, "sd",
29760 + "child died somehow:",
29764 @@ -852,26 +851,26 @@
29766 proc->last_used = srv->cur_ts;
29767 proc->is_local = 1;
29774 proc->is_local = 0;
29778 if (p->conf.debug) {
29779 log_error_write(srv, __FILE__, __LINE__, "sb",
29780 "(debug) socket is already used, won't spawn:",
29786 proc->state = PROC_STATE_RUNNING;
29787 host->active_procs++;
29796 @@ -880,89 +879,89 @@
29797 plugin_data *p = p_d;
29801 - config_values_t cv[] = {
29803 + config_values_t cv[] = {
29804 { "scgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
29805 { "scgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
29806 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29810 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
29813 for (i = 0; i < srv->config_context->used; i++) {
29818 s = malloc(sizeof(plugin_config));
29819 s->exts = scgi_extensions_init();
29823 cv[0].destination = s->exts;
29824 cv[1].destination = &(s->debug);
29827 p->config_storage[i] = s;
29828 ca = ((data_config *)srv->config_context->data[i])->value;
29831 if (0 != config_insert_values_global(srv, ca, cv)) {
29832 return HANDLER_ERROR;
29842 if (NULL != (du = array_get_element(ca, "scgi.server"))) {
29844 data_array *da = (data_array *)du;
29847 if (du->type != TYPE_ARRAY) {
29848 - log_error_write(srv, __FILE__, __LINE__, "sss",
29849 + log_error_write(srv, __FILE__, __LINE__, "sss",
29850 "unexpected type for key: ", "scgi.server", "array of strings");
29853 return HANDLER_ERROR;
29858 - * scgi.server = ( "<ext>" => ( ... ),
29862 + * scgi.server = ( "<ext>" => ( ... ),
29863 * "<ext>" => ( ... ) )
29867 for (j = 0; j < da->value->used; j++) {
29869 data_array *da_ext = (data_array *)da->value->data[j];
29872 if (da->value->data[j]->type != TYPE_ARRAY) {
29873 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
29874 - "unexpected type for key: ", "scgi.server",
29875 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
29876 + "unexpected type for key: ", "scgi.server",
29877 "[", da->value->data[j]->key, "](string)");
29880 return HANDLER_ERROR;
29884 - * da_ext->key == name of the extension
29887 + * da_ext->key == name of the extension
29891 - * scgi.server = ( "<ext>" =>
29892 - * ( "<host>" => ( ... ),
29895 + * scgi.server = ( "<ext>" =>
29896 + * ( "<host>" => ( ... ),
29897 * "<host>" => ( ... )
29904 for (n = 0; n < da_ext->value->used; n++) {
29905 data_array *da_host = (data_array *)da_ext->value->data[n];
29908 scgi_extension_host *df;
29910 - config_values_t fcv[] = {
29912 + config_values_t fcv[] = {
29913 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
29914 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
29915 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
29916 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
29919 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
29920 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
29921 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
29922 @@ -970,37 +969,37 @@
29923 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
29924 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
29925 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
29928 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
29929 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
29934 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29938 if (da_host->type != TYPE_ARRAY) {
29939 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29940 - "unexpected type for key:",
29942 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29943 + "unexpected type for key:",
29945 "[", da_host->key, "](string)");
29948 return HANDLER_ERROR;
29952 df = scgi_host_init();
29955 df->check_local = 1;
29958 df->max_load_per_proc = 1;
29959 df->idle_timeout = 60;
29960 df->disable_time = 60;
29963 fcv[0].destination = df->host;
29964 fcv[1].destination = df->docroot;
29965 fcv[2].destination = df->unixsocket;
29966 fcv[3].destination = df->bin_path;
29969 fcv[4].destination = &(df->check_local);
29970 fcv[5].destination = &(df->port);
29971 fcv[6].destination = &(df->min_procs);
29972 @@ -1008,47 +1007,47 @@
29973 fcv[8].destination = &(df->max_load_per_proc);
29974 fcv[9].destination = &(df->idle_timeout);
29975 fcv[10].destination = &(df->disable_time);
29978 fcv[11].destination = df->bin_env;
29979 fcv[12].destination = df->bin_env_copy;
29984 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
29985 return HANDLER_ERROR;
29988 - if ((!buffer_is_empty(df->host) || df->port) &&
29990 + if ((!buffer_is_empty(df->host) || df->port) &&
29991 !buffer_is_empty(df->unixsocket)) {
29992 - log_error_write(srv, __FILE__, __LINE__, "s",
29993 + log_error_write(srv, __FILE__, __LINE__, "s",
29994 "either host+port or socket");
29997 return HANDLER_ERROR;
30001 if (!buffer_is_empty(df->unixsocket)) {
30002 /* unix domain socket */
30005 if (df->unixsocket->used > UNIX_PATH_MAX - 2) {
30006 - log_error_write(srv, __FILE__, __LINE__, "s",
30007 + log_error_write(srv, __FILE__, __LINE__, "s",
30008 "path of the unixdomain socket is too large");
30009 return HANDLER_ERROR;
30014 - if (buffer_is_empty(df->host) &&
30016 + if (buffer_is_empty(df->host) &&
30017 buffer_is_empty(df->bin_path)) {
30018 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
30019 - "missing key (string):",
30020 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
30021 + "missing key (string):",
30028 return HANDLER_ERROR;
30029 } else if (df->port == 0) {
30030 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
30031 - "missing key (short):",
30032 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
30033 + "missing key (short):",
30037 @@ -1056,14 +1055,14 @@
30038 return HANDLER_ERROR;
30042 - if (!buffer_is_empty(df->bin_path)) {
30044 + if (!buffer_is_empty(df->bin_path)) {
30045 /* a local socket + self spawning */
30049 if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
30050 if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
30054 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
30055 "--- scgi spawning local",
30056 @@ -1073,7 +1072,7 @@
30057 "\n\tmin-procs:", df->min_procs,
30058 "\n\tmax-procs:", df->max_procs);
30062 for (pno = 0; pno < df->min_procs; pno++) {
30065 @@ -1088,7 +1087,7 @@
30066 buffer_append_string(proc->socket, "-");
30067 buffer_append_long(proc->socket, pno);
30072 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
30073 "--- scgi spawning",
30074 @@ -1096,53 +1095,53 @@
30075 "\n\tsocket", df->unixsocket,
30076 "\n\tcurrent:", pno, "/", df->min_procs);
30080 if (scgi_spawn_connection(srv, p, df, proc)) {
30081 log_error_write(srv, __FILE__, __LINE__, "s",
30082 "[ERROR]: spawning fcgi failed.");
30083 return HANDLER_ERROR;
30087 proc->next = df->first;
30088 if (df->first) df->first->prev = proc;
30097 fp = scgi_process_init();
30098 fp->id = df->num_procs++;
30100 df->active_procs++;
30101 fp->state = PROC_STATE_RUNNING;
30104 if (buffer_is_empty(df->unixsocket)) {
30105 fp->port = df->port;
30107 buffer_copy_string_buffer(fp->socket, df->unixsocket);
30119 /* if extension already exists, take it */
30120 scgi_extension_insert(s->exts, da_ext->key, df);
30127 return HANDLER_GO_ON;
30130 static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) {
30131 hctx->state = state;
30132 hctx->state_timestamp = srv->cur_ts;
30138 @@ -1150,34 +1149,34 @@
30139 void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
30144 if (NULL == hctx) return;
30147 p = hctx->plugin_data;
30148 con = hctx->remote_conn;
30151 if (con->mode != p->id) {
30157 if (hctx->fd != -1) {
30158 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30159 fdevent_unregister(srv->ev, hctx->fd);
30165 if (hctx->host && hctx->proc) {
30166 hctx->host->load--;
30169 if (hctx->got_proc) {
30170 /* after the connect the process gets a load */
30171 hctx->proc->load--;
30174 if (p->conf.debug) {
30175 log_error_write(srv, __FILE__, __LINE__, "sddb",
30179 hctx->proc->pid, hctx->proc->socket);
30181 @@ -1186,87 +1185,87 @@
30182 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30187 handler_ctx_free(hctx);
30188 - con->plugin_ctx[p->id] = NULL;
30189 + con->plugin_ctx[p->id] = NULL;
30192 static int scgi_reconnect(server *srv, handler_ctx *hctx) {
30193 plugin_data *p = hctx->plugin_data;
30204 * connect was ok, connection was accepted
30205 * but the php accept loop checks after the accept if it should die or not.
30207 - * if yes we can only detect it at a write()
30210 + * if yes we can only detect it at a write()
30212 * next step is resetting this attemp and setup a connection again
30215 * if we have more then 5 reconnects for the same request, die
30222 * we have a connection but the child died by some other reason
30228 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30229 fdevent_unregister(srv->ev, hctx->fd);
30234 scgi_set_state(srv, hctx, FCGI_STATE_INIT);
30237 hctx->request_id = 0;
30238 hctx->reconnects++;
30241 if (p->conf.debug) {
30242 log_error_write(srv, __FILE__, __LINE__, "sddb",
30246 hctx->proc->pid, hctx->proc->socket);
30250 hctx->proc->load--;
30251 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30258 static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
30259 plugin_data *p = p_d;
30262 scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
30265 return HANDLER_GO_ON;
30269 static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
30273 if (!key || !val) return -1;
30276 len = key_len + val_len + 2;
30279 buffer_prepare_append(env, len);
30281 - /* include the NUL */
30282 + /* include the NUL */
30283 memcpy(env->ptr + env->used, key, key_len + 1);
30284 env->used += key_len + 1;
30285 memcpy(env->ptr + env->used, val, val_len + 1);
30286 env->used += val_len + 1;
30299 @@ -1280,24 +1279,21 @@
30300 struct sockaddr_un scgi_addr_un;
30305 scgi_extension_host *host = hctx->host;
30306 scgi_proc *proc = hctx->proc;
30307 int scgi_fd = hctx->fd;
30310 memset(&scgi_addr, 0, sizeof(scgi_addr));
30313 if (!buffer_is_empty(proc->socket)) {
30314 #ifdef HAVE_SYS_UN_H
30315 /* use the unix domain socket */
30316 scgi_addr_un.sun_family = AF_UNIX;
30317 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
30320 servlen = SUN_LEN(&scgi_addr_un);
30322 - /* stevens says: */
30323 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
30326 scgi_addr = (struct sockaddr *) &scgi_addr_un;
30329 @@ -1305,105 +1301,105 @@
30331 scgi_addr_in.sin_family = AF_INET;
30332 if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) {
30333 - log_error_write(srv, __FILE__, __LINE__, "sbs",
30334 - "converting IP-adress failed for", host->host,
30335 + log_error_write(srv, __FILE__, __LINE__, "sbs",
30336 + "converting IP-adress failed for", host->host,
30337 "\nBe sure to specify an IP address here");
30342 scgi_addr_in.sin_port = htons(proc->port);
30343 servlen = sizeof(scgi_addr_in);
30346 scgi_addr = (struct sockaddr *) &scgi_addr_in;
30350 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
30351 - if (errno == EINPROGRESS ||
30352 + if (errno == EINPROGRESS ||
30353 errno == EALREADY ||
30355 if (hctx->conf.debug) {
30356 - log_error_write(srv, __FILE__, __LINE__, "sd",
30357 + log_error_write(srv, __FILE__, __LINE__, "sd",
30358 "connect delayed, will continue later:", scgi_fd);
30364 - log_error_write(srv, __FILE__, __LINE__, "sdsddb",
30365 - "connect failed:", scgi_fd,
30366 + log_error_write(srv, __FILE__, __LINE__, "sdsddb",
30367 + "connect failed:", scgi_fd,
30368 strerror(errno), errno,
30369 proc->port, proc->socket);
30371 if (errno == EAGAIN) {
30372 /* this is Linux only */
30374 - log_error_write(srv, __FILE__, __LINE__, "s",
30376 + log_error_write(srv, __FILE__, __LINE__, "s",
30377 "If this happend on Linux: You have been run out of local ports. "
30378 "Check the manual, section Performance how to handle this.");
30386 if (hctx->conf.debug > 1) {
30387 - log_error_write(srv, __FILE__, __LINE__, "sd",
30388 + log_error_write(srv, __FILE__, __LINE__, "sd",
30389 "connect succeeded: ", scgi_fd);
30398 static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
30402 for (i = 0; i < con->request.headers->used; i++) {
30406 ds = (data_string *)con->request.headers->data[i];
30409 if (ds->value->used && ds->key->used) {
30411 buffer_reset(srv->tmp_buf);
30414 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
30415 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
30416 srv->tmp_buf->used--;
30420 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30421 for (j = 0; j < ds->key->used - 1; j++) {
30422 - srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30423 - light_isalpha(ds->key->ptr[j]) ?
30424 + srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30425 + light_isalpha(ds->key->ptr[j]) ?
30426 ds->key->ptr[j] & ~32 : '_';
30428 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30431 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30436 for (i = 0; i < con->environment->used; i++) {
30440 ds = (data_string *)con->environment->data[i];
30443 if (ds->value->used && ds->key->used) {
30445 buffer_reset(srv->tmp_buf);
30448 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30449 for (j = 0; j < ds->key->used - 1; j++) {
30450 - srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30451 - isalpha((unsigned char)ds->key->ptr[j]) ?
30452 + srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30453 + isalpha((unsigned char)ds->key->ptr[j]) ?
30454 toupper((unsigned char)ds->key->ptr[j]) : '_';
30456 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30459 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30467 @@ -1415,20 +1411,20 @@
30468 char b2[INET6_ADDRSTRLEN + 1];
30473 plugin_data *p = hctx->plugin_data;
30474 scgi_extension_host *host= hctx->host;
30476 connection *con = hctx->remote_conn;
30477 server_socket *srv_sock = con->srv_socket;
30480 sock_addr our_addr;
30481 socklen_t our_addr_len;
30484 buffer_prepare_copy(p->scgi_env, 1024);
30486 /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
30489 /* request.content_length < SSIZE_MAX, see request.c */
30490 ltostr(buf, con->request.content_length);
30491 scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
30492 @@ -1436,13 +1432,13 @@
30495 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
30498 if (con->server_name->used) {
30499 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
30502 - s = inet_ntop(srv_sock->addr.plain.sa_family,
30503 - srv_sock->addr.plain.sa_family == AF_INET6 ?
30504 + s = inet_ntop(srv_sock->addr.plain.sa_family,
30505 + srv_sock->addr.plain.sa_family == AF_INET6 ?
30506 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
30507 (const void *) &(srv_sock->addr.ipv4.sin_addr),
30509 @@ -1451,47 +1447,47 @@
30511 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
30515 scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
30521 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
30523 ntohs(srv_sock->addr.ipv4.sin_port)
30528 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
30531 /* get the server-side of the connection to the client */
30532 our_addr_len = sizeof(our_addr);
30535 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
30536 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
30538 s = inet_ntop_cache_get_ip(srv, &(our_addr));
30540 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
30546 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
30548 ntohs(con->dst_addr.ipv4.sin_port)
30553 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
30556 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
30557 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
30560 if (!buffer_is_empty(con->authed_user)) {
30561 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
30562 CONST_BUF_LEN(con->authed_user));
30568 * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
30569 @@ -1500,12 +1496,12 @@
30572 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
30575 if (!buffer_is_empty(con->request.pathinfo)) {
30576 scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
30579 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
30582 if (!buffer_is_empty(host->docroot)) {
30583 buffer_copy_string_buffer(p->path, host->docroot);
30585 @@ -1526,19 +1522,19 @@
30588 if (!buffer_is_empty(host->docroot)) {
30590 - * rewrite SCRIPT_FILENAME
30593 + * rewrite SCRIPT_FILENAME
30598 buffer_copy_string_buffer(p->path, host->docroot);
30599 buffer_append_string_buffer(p->path, con->uri.path);
30602 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30603 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
30605 buffer_copy_string_buffer(p->path, con->physical.path);
30608 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30609 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
30611 @@ -1551,30 +1547,30 @@
30613 scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
30617 s = get_http_method_name(con->request.http_method);
30618 scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
30619 scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
30620 s = get_http_version_name(con->request.http_version);
30621 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
30625 if (srv_sock->is_ssl) {
30626 scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
30631 scgi_env_add_request_headers(srv, con, p);
30633 b = chunkqueue_get_append_buffer(hctx->wb);
30636 buffer_append_long(b, p->scgi_env->used);
30637 buffer_append_string_len(b, CONST_STR_LEN(":"));
30638 buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used);
30639 buffer_append_string_len(b, CONST_STR_LEN(","));
30641 hctx->wb->bytes_in += b->used - 1;
30644 if (con->request.content_length) {
30645 chunkqueue *req_cq = con->request_content_queue;
30647 @@ -1587,7 +1583,7 @@
30649 /* we announce toWrite octects
30650 * now take all the request_content chunk that we need to fill this request
30654 switch (req_c->type) {
30656 @@ -1615,32 +1611,32 @@
30658 req_c->offset += weHave;
30659 req_cq->bytes_out += weHave;
30662 hctx->wb->bytes_in += weHave;
30676 for (i = 0; i < hctx->write_buffer->used; i++) {
30677 fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]);
30678 if ((i+1) % 16 == 0) {
30680 for (j = i-15; j <= i; j++) {
30681 - fprintf(stderr, "%c",
30682 + fprintf(stderr, "%c",
30683 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
30685 fprintf(stderr, "\n");
30694 @@ -1648,32 +1644,32 @@
30703 buffer_copy_string_buffer(p->parse_response, in);
30705 - for (s = p->parse_response->ptr;
30706 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
30708 + for (s = p->parse_response->ptr;
30709 + NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
30710 s = ns + (eol == EOL_RN ? 2 : 1), line++) {
30711 const char *key, *value;
30721 0 == strncmp(s, "HTTP/1.", 7)) {
30722 /* non-parsed header ... we parse them anyway */
30725 if ((s[7] == '1' ||
30729 /* after the space should be a status code for us */
30732 status = strtol(s+9, NULL, 10);
30735 if (con->http_status >= 100 &&
30736 con->http_status < 1000) {
30737 /* we expected 3 digits and didn't got them */
30738 @@ -1682,27 +1678,27 @@
30745 if (NULL == (value = strchr(s, ':'))) {
30746 /* we expect: "<key>: <value>\r\n" */
30751 key_len = value - key;
30756 while (*value == ' ' || *value == '\t') value++;
30759 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
30760 ds = data_response_init();
30762 buffer_copy_string_len(ds->key, key, key_len);
30763 buffer_copy_string(ds->value, value);
30766 array_insert_unique(con->response.headers, (data_unset *)ds);
30771 if (0 == strncasecmp(key, "Date", key_len)) {
30772 @@ -1737,13 +1733,13 @@
30778 /* CGI/1.1 rev 03 - 7.2.1.2 */
30779 if ((con->parsed_response & HTTP_LOCATION) &&
30780 !(con->parsed_response & HTTP_STATUS)) {
30781 con->http_status = 302;
30788 @@ -1751,10 +1747,10 @@
30789 static int scgi_demux_response(server *srv, handler_ctx *hctx) {
30790 plugin_data *p = hctx->plugin_data;
30791 connection *con = hctx->remote_conn;
30798 buffer_prepare_copy(hctx->response, 1024);
30799 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
30800 if (errno == EAGAIN || errno == EINTR) {
30801 @@ -1765,143 +1761,143 @@
30802 log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
30808 /* read finished */
30811 con->file_finished = 1;
30814 /* send final chunk */
30815 http_chunk_append_mem(srv, con, NULL, 0);
30816 joblist_append(srv, con);
30823 hctx->response->ptr[n] = '\0';
30824 hctx->response->used = n+1;
30827 /* split header from body */
30830 if (con->file_started == 0) {
30833 int header_end = 0;
30834 int cp, eol = EOL_UNSET;
30838 buffer_append_string_buffer(hctx->response_header, hctx->response);
30841 /* nph (non-parsed headers) */
30842 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
30845 /* search for the \r\n\r\n or \n\n in the string */
30846 for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
30847 if (*c == ':') in_header = 1;
30848 else if (*c == '\n') {
30849 if (in_header == 0) {
30850 /* got a response without a response header */
30859 if (eol == EOL_UNSET) eol = EOL_N;
30862 if (*(c+1) == '\n') {
30868 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
30869 if (in_header == 0) {
30870 /* got a response without a response header */
30879 if (eol == EOL_UNSET) eol = EOL_RN;
30883 - *(c+2) == '\r' &&
30884 + *(c+2) == '\r' &&
30901 /* no header, but a body */
30904 if (con->request.http_version == HTTP_VERSION_1_1) {
30905 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30909 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
30910 joblist_append(srv, con);
30912 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
30913 size_t blen = hctx->response_header->used - hlen - 1;
30916 /* a small hack: terminate after at the second \r */
30917 hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
30918 hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
30921 /* parse the response header */
30922 scgi_response_parse(srv, con, p, hctx->response_header, eol);
30925 /* enable chunked-transfer-encoding */
30926 if (con->request.http_version == HTTP_VERSION_1_1 &&
30927 !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
30928 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30932 if ((hctx->response->used != hlen) && blen > 0) {
30933 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
30934 joblist_append(srv, con);
30939 con->file_started = 1;
30942 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
30943 joblist_append(srv, con);
30949 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
30958 int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30964 - /* we have been the smallest of the current list
30965 - * and we want to insert the node sorted as soon
30967 + /* we have been the smallest of the current list
30968 + * and we want to insert the node sorted as soon
30981 /* nothing to sort, only one element */
30982 @@ -1909,9 +1905,9 @@
30984 for (p = proc; p->next && p->next->load < proc->load; p = p->next);
30986 - /* no need to move something
30987 + /* no need to move something
30994 @@ -1930,16 +1926,16 @@
30996 if (proc->prev) proc->prev->next = proc->next;
30997 if (proc->next) proc->next->prev = proc->prev;
31000 /* proc should be right of p */
31003 proc->next = p->next;
31005 if (p->next) p->next->prev = proc;
31008 for(p = host->first; p; p = p->next) {
31009 - log_error_write(srv, __FILE__, __LINE__, "dd",
31010 + log_error_write(srv, __FILE__, __LINE__, "dd",
31014 @@ -1951,21 +1947,21 @@
31016 int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
31022 - /* we have been the smallest of the current list
31023 - * and we want to insert the node sorted as soon
31025 + /* we have been the smallest of the current list
31026 + * and we want to insert the node sorted as soon
31036 * the basic is idea is:
31037 - * - the last active scgi process should be still
31038 + * - the last active scgi process should be still
31039 * in ram and is not swapped out yet
31040 * - processes that are not reused will be killed
31041 * after some time by the trigger-handler
31042 @@ -1975,7 +1971,7 @@
31043 * ice-cold processes are propably unused since more
31044 * than 'unused-timeout', are swaped out and won't be
31045 * reused in the next seconds anyway.
31050 /* nothing to sort, only one element */
31051 @@ -1984,16 +1980,16 @@
31052 for (p = host->first; p != proc && p->load < proc->load; p = p->next);
31055 - /* no need to move something
31056 + /* no need to move something
31065 if (p == proc) return 0;
31068 /* we have to move left. If we are already the first element
31070 if (host->first == proc) return 0;
31071 @@ -2009,9 +2005,9 @@
31074 if (proc->prev == NULL) host->first = proc;
31077 for(p = host->first; p; p = p->next) {
31078 - log_error_write(srv, __FILE__, __LINE__, "dd",
31079 + log_error_write(srv, __FILE__, __LINE__, "dd",
31083 @@ -2023,41 +2019,42 @@
31085 static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
31089 for (proc = host->first; proc; proc = proc->next) {
31090 if (p->conf.debug) {
31091 - log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
31093 - host->host, proc->port,
31094 + log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
31096 + host->host, proc->port,
31105 if (0 == proc->is_local) {
31107 - * external servers might get disabled
31109 - * enable the server again, perhaps it is back again
31111 + * external servers might get disabled
31113 + * enable the server again, perhaps it is back again
31117 if ((proc->state == PROC_STATE_DISABLED) &&
31118 (srv->cur_ts - proc->disable_ts > host->disable_time)) {
31119 proc->state = PROC_STATE_RUNNING;
31120 host->active_procs++;
31122 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
31123 - "fcgi-server re-enabled:",
31124 - host->host, host->port,
31126 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
31127 + "fcgi-server re-enabled:",
31128 + host->host, host->port,
31132 /* the child should not terminate at all */
31136 if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
31138 switch(waitpid(proc->pid, &status, WNOHANG)) {
31140 /* child is still alive */
31141 @@ -2067,33 +2064,34 @@
31143 if (WIFEXITED(status)) {
31145 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
31146 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
31147 "child exited, pid:", proc->pid,
31148 "status:", WEXITSTATUS(status));
31150 } else if (WIFSIGNALED(status)) {
31151 - log_error_write(srv, __FILE__, __LINE__, "sd",
31152 - "child signaled:",
31153 + log_error_write(srv, __FILE__, __LINE__, "sd",
31154 + "child signaled:",
31157 - log_error_write(srv, __FILE__, __LINE__, "sd",
31158 - "child died somehow:",
31159 + log_error_write(srv, __FILE__, __LINE__, "sd",
31160 + "child died somehow:",
31165 proc->state = PROC_STATE_DIED;
31174 * local servers might died, but we restart them
31178 if (proc->state == PROC_STATE_DIED &&
31180 /* restart the child */
31183 if (p->conf.debug) {
31184 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31185 "--- scgi spawning",
31186 @@ -2101,18 +2099,18 @@
31187 "\n\tsocket", host->unixsocket,
31188 "\n\tcurrent:", 1, "/", host->min_procs);
31192 if (scgi_spawn_connection(srv, p, host, proc)) {
31193 log_error_write(srv, __FILE__, __LINE__, "s",
31194 "ERROR: spawning fcgi failed.");
31195 return HANDLER_ERROR;
31199 scgi_proclist_sort_down(srv, host, proc);
31208 @@ -2121,13 +2119,13 @@
31209 plugin_data *p = hctx->plugin_data;
31210 scgi_extension_host *host= hctx->host;
31211 connection *con = hctx->remote_conn;
31216 - /* sanity check */
31217 + /* sanity check */
31219 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
31220 - log_error_write(srv, __FILE__, __LINE__, "sxddd",
31221 + log_error_write(srv, __FILE__, __LINE__, "sxddd",
31222 "write-req: error",
31225 @@ -2135,179 +2133,180 @@
31226 host->unixsocket->used);
31227 return HANDLER_ERROR;
31232 switch(hctx->state) {
31233 case FCGI_STATE_INIT:
31234 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
31237 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
31238 if (errno == EMFILE ||
31240 - log_error_write(srv, __FILE__, __LINE__, "sd",
31241 + log_error_write(srv, __FILE__, __LINE__, "sd",
31242 "wait for fd at connection:", con->fd);
31245 return HANDLER_WAIT_FOR_FD;
31248 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
31250 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
31251 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
31252 return HANDLER_ERROR;
31254 hctx->fde_ndx = -1;
31260 fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
31263 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
31264 - log_error_write(srv, __FILE__, __LINE__, "ss",
31265 + log_error_write(srv, __FILE__, __LINE__, "ss",
31266 "fcntl failed: ", strerror(errno));
31269 return HANDLER_ERROR;
31274 case FCGI_STATE_CONNECT:
31275 if (hctx->state == FCGI_STATE_INIT) {
31276 - for (hctx->proc = hctx->host->first;
31277 - hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
31278 + for (hctx->proc = hctx->host->first;
31279 + hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
31280 hctx->proc = hctx->proc->next);
31283 /* all childs are dead */
31284 if (hctx->proc == NULL) {
31285 hctx->fde_ndx = -1;
31288 return HANDLER_ERROR;
31292 if (hctx->proc->is_local) {
31293 hctx->pid = hctx->proc->pid;
31297 switch (scgi_establish_connection(srv, hctx)) {
31299 scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
31302 /* connection is in progress, wait for an event and call getsockopt() below */
31305 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31308 return HANDLER_WAIT_FOR_EVENT;
31310 /* if ECONNREFUSED choose another connection -> FIXME */
31311 hctx->fde_ndx = -1;
31314 return HANDLER_ERROR;
31316 /* everything is ok, go on */
31324 socklen_t socket_error_len = sizeof(socket_error);
31327 /* try to finish the connect() */
31328 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
31329 - log_error_write(srv, __FILE__, __LINE__, "ss",
31330 + log_error_write(srv, __FILE__, __LINE__, "ss",
31331 "getsockopt failed:", strerror(errno));
31334 return HANDLER_ERROR;
31336 if (socket_error != 0) {
31337 if (!hctx->proc->is_local || p->conf.debug) {
31338 /* local procs get restarted */
31341 log_error_write(srv, __FILE__, __LINE__, "ss",
31342 - "establishing connection failed:", strerror(socket_error),
31343 + "establishing connection failed:", strerror(socket_error),
31344 "port:", hctx->proc->port);
31348 return HANDLER_ERROR;
31353 /* ok, we have the connection */
31356 hctx->proc->load++;
31357 hctx->proc->last_used = srv->cur_ts;
31358 hctx->got_proc = 1;
31361 if (p->conf.debug) {
31362 log_error_write(srv, __FILE__, __LINE__, "sddbdd",
31367 - hctx->proc->socket,
31369 + hctx->proc->socket,
31374 /* move the proc-list entry down the list */
31375 scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
31378 scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
31380 case FCGI_STATE_PREPARE_WRITE:
31381 scgi_create_env(srv, hctx);
31384 scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
31388 case FCGI_STATE_WRITE:
31389 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
31390 + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
31392 chunkqueue_remove_finished_chunks(hctx->wb);
31396 if (errno == ENOTCONN) {
31397 - /* the connection got dropped after accept()
31399 - * this is most of the time a PHP which dies
31400 + /* the connection got dropped after accept()
31402 + * this is most of the time a PHP which dies
31403 * after PHP_FCGI_MAX_REQUESTS
31408 if (hctx->wb->bytes_out == 0 &&
31409 hctx->reconnects < 5) {
31410 - usleep(10000); /* take away the load of the webserver
31411 - * to let the php a chance to restart
31413 + usleep(10000); /* take away the load of the webserver
31414 + * to let the php a chance to restart
31418 scgi_reconnect(srv, hctx);
31421 return HANDLER_WAIT_FOR_FD;
31425 /* not reconnected ... why
31428 * far@#lighttpd report this for FreeBSD
31433 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31435 + log_error_write(srv, __FILE__, __LINE__, "ssosd",
31436 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
31437 "write-offset:", hctx->wb->bytes_out,
31438 "reconnect attempts:", hctx->reconnects);
31441 return HANDLER_ERROR;
31445 if ((errno != EAGAIN) &&
31446 (errno != EINTR)) {
31448 - log_error_write(srv, __FILE__, __LINE__, "ssd",
31450 + log_error_write(srv, __FILE__, __LINE__, "ssd",
31451 "write failed:", strerror(errno), errno);
31454 return HANDLER_ERROR;
31456 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31459 return HANDLER_WAIT_FOR_EVENT;
31464 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
31465 /* we don't need the out event anymore */
31466 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
31467 @@ -2315,10 +2314,10 @@
31468 scgi_set_state(srv, hctx, FCGI_STATE_READ);
31470 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31473 return HANDLER_WAIT_FOR_EVENT;
31478 case FCGI_STATE_READ:
31479 /* waiting for a response */
31480 @@ -2327,67 +2326,67 @@
31481 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
31482 return HANDLER_ERROR;
31486 return HANDLER_WAIT_FOR_EVENT;
31489 SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
31490 plugin_data *p = p_d;
31493 handler_ctx *hctx = con->plugin_ctx[p->id];
31495 scgi_extension_host *host;
31498 if (NULL == hctx) return HANDLER_GO_ON;
31502 if (con->mode != p->id) return HANDLER_GO_ON;
31505 /* ok, create the request */
31506 switch(scgi_write_request(srv, hctx)) {
31507 case HANDLER_ERROR:
31514 0 == proc->is_local &&
31515 proc->state != PROC_STATE_DISABLED) {
31516 /* only disable remote servers as we don't manage them*/
31518 - log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
31520 + log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
31526 /* disable this server */
31527 proc->disable_ts = srv->cur_ts;
31528 proc->state = PROC_STATE_DISABLED;
31529 host->active_procs--;
31533 if (hctx->state == FCGI_STATE_INIT ||
31534 hctx->state == FCGI_STATE_CONNECT) {
31535 - /* connect() or getsockopt() failed,
31536 - * restart the request-handling
31537 + /* connect() or getsockopt() failed,
31538 + * restart the request-handling
31540 if (proc && proc->is_local) {
31542 if (p->conf.debug) {
31543 - log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
31544 + log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
31552 * several hctx might reference the same proc
31555 * Only one of them should mark the proc as dead all the other
31556 * ones should just take a new one.
31559 * If a new proc was started with the old struct this might lead
31560 * the mark a perfect proc as dead otherwise
31564 if (proc->state == PROC_STATE_RUNNING &&
31565 hctx->pid == proc->pid) {
31566 @@ -2395,25 +2394,25 @@
31569 scgi_restart_dead_procs(srv, p, host);
31572 scgi_connection_cleanup(srv, hctx);
31575 buffer_reset(con->physical.path);
31576 con->mode = DIRECT;
31577 joblist_append(srv, con);
31579 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31580 - * and hope that the childs will be restarted
31583 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31584 + * and hope that the childs will be restarted
31587 return HANDLER_WAIT_FOR_FD;
31589 scgi_connection_cleanup(srv, hctx);
31592 buffer_reset(con->physical.path);
31593 con->mode = DIRECT;
31594 con->http_status = 503;
31597 return HANDLER_FINISHED;
31599 case HANDLER_WAIT_FOR_EVENT:
31600 @@ -2433,23 +2432,23 @@
31601 static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
31606 if (NULL == hctx) return HANDLER_GO_ON;
31609 p = hctx->plugin_data;
31610 con = hctx->remote_conn;
31613 if (con->mode != p->id) return HANDLER_GO_ON;
31615 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31616 - "emergency exit: scgi:",
31618 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31619 + "emergency exit: scgi:",
31620 "connection-fd:", con->fd,
31621 "fcgi-fd:", hctx->fd);
31628 scgi_connection_cleanup(srv, hctx);
31631 return HANDLER_FINISHED;
31634 @@ -2459,7 +2458,7 @@
31635 handler_ctx *hctx = ctx;
31636 connection *con = hctx->remote_conn;
31637 plugin_data *p = hctx->plugin_data;
31640 scgi_proc *proc = hctx->proc;
31641 scgi_extension_host *host= hctx->host;
31643 @@ -2471,15 +2470,15 @@
31646 scgi_connection_cleanup(srv, hctx);
31649 joblist_append(srv, con);
31650 return HANDLER_FINISHED;
31652 if (proc->pid && proc->state != PROC_STATE_DIED) {
31656 /* only fetch the zombie if it is not already done */
31659 switch(waitpid(proc->pid, &status, WNOHANG)) {
31661 /* child is still alive */
31662 @@ -2489,19 +2488,19 @@
31664 /* the child should not terminate at all */
31665 if (WIFEXITED(status)) {
31666 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
31667 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
31668 "child exited, pid:", proc->pid,
31669 "status:", WEXITSTATUS(status));
31670 } else if (WIFSIGNALED(status)) {
31671 - log_error_write(srv, __FILE__, __LINE__, "sd",
31672 - "child signaled:",
31673 + log_error_write(srv, __FILE__, __LINE__, "sd",
31674 + "child signaled:",
31677 - log_error_write(srv, __FILE__, __LINE__, "sd",
31678 - "child died somehow:",
31679 + log_error_write(srv, __FILE__, __LINE__, "sd",
31680 + "child died somehow:",
31685 if (p->conf.debug) {
31686 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31687 "--- scgi spawning",
31688 @@ -2509,40 +2508,41 @@
31689 "\n\tsocket", host->unixsocket,
31690 "\n\tcurrent:", 1, "/", host->min_procs);
31694 if (scgi_spawn_connection(srv, p, host, proc)) {
31696 proc->state = PROC_STATE_DIED;
31698 scgi_proclist_sort_down(srv, host, proc);
31707 if (con->file_started == 0) {
31708 /* nothing has been send out yet, try to use another child */
31711 if (hctx->wb->bytes_out == 0 &&
31712 hctx->reconnects < 5) {
31713 scgi_reconnect(srv, hctx);
31715 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31717 + log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31718 "response not sent, request not sent, reconnection.",
31719 "connection-fd:", con->fd,
31720 "fcgi-fd:", hctx->fd);
31723 return HANDLER_WAIT_FOR_FD;
31726 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31728 + log_error_write(srv, __FILE__, __LINE__, "sosdsd",
31729 "response not sent, request sent:", hctx->wb->bytes_out,
31730 "connection-fd:", con->fd,
31731 "fcgi-fd:", hctx->fd);
31734 scgi_connection_cleanup(srv, hctx);
31737 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
31738 buffer_reset(con->physical.path);
31739 con->http_status = 500;
31740 @@ -2550,76 +2550,76 @@
31742 /* response might have been already started, kill the connection */
31743 scgi_connection_cleanup(srv, hctx);
31745 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31747 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31748 "response already sent out, termination connection",
31749 "connection-fd:", con->fd,
31750 "fcgi-fd:", hctx->fd);
31753 connection_set_state(srv, con, CON_STATE_ERROR);
31761 joblist_append(srv, con);
31762 return HANDLER_FINISHED;
31767 if (revents & FDEVENT_OUT) {
31768 if (hctx->state == FCGI_STATE_CONNECT ||
31769 hctx->state == FCGI_STATE_WRITE) {
31770 /* we are allowed to send something out
31773 * 1. in a unfinished connect() call
31774 * 2. in a unfinished write() call (long POST request)
31776 return mod_scgi_handle_subrequest(srv, con, p);
31778 - log_error_write(srv, __FILE__, __LINE__, "sd",
31779 - "got a FDEVENT_OUT and didn't know why:",
31780 + log_error_write(srv, __FILE__, __LINE__, "sd",
31781 + "got a FDEVENT_OUT and didn't know why:",
31787 /* perhaps this issue is already handled */
31788 if (revents & FDEVENT_HUP) {
31789 if (hctx->state == FCGI_STATE_CONNECT) {
31790 /* getoptsock will catch this one (right ?)
31792 - * if we are in connect we might get a EINPROGRESS
31793 - * in the first call and a FDEVENT_HUP in the
31795 + * if we are in connect we might get a EINPROGRESS
31796 + * in the first call and a FDEVENT_HUP in the
31800 * FIXME: as it is a bit ugly.
31804 return mod_scgi_handle_subrequest(srv, con, p);
31805 } else if (hctx->state == FCGI_STATE_READ &&
31806 hctx->proc->port == 0) {
31810 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
31811 * even if the FCGI_FIN packet is not received yet
31814 - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
31815 - "error: unexpected close of scgi connection for",
31816 + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
31817 + "error: unexpected close of scgi connection for",
31819 - "(no scgi process on host: ",
31820 + "(no scgi process on host: ",
31829 connection_set_state(srv, con, CON_STATE_ERROR);
31830 scgi_connection_close(srv, hctx);
31831 joblist_append(srv, con);
31833 } else if (revents & FDEVENT_ERR) {
31834 - log_error_write(srv, __FILE__, __LINE__, "s",
31835 + log_error_write(srv, __FILE__, __LINE__, "s",
31836 "fcgi: got a FDEVENT_ERR. Don't know why.");
31837 /* kill all connections to the scgi process */
31839 @@ -2628,42 +2628,39 @@
31840 scgi_connection_close(srv, hctx);
31841 joblist_append(srv, con);
31845 return HANDLER_FINISHED;
31847 -#define PATCH(x) \
31848 - p->conf.x = s->x;
31850 static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
31852 plugin_config *s = p->config_storage[0];
31858 + PATCH_OPTION(exts);
31859 + PATCH_OPTION(debug);
31861 /* skip the first, the global context */
31862 for (i = 1; i < srv->config_context->used; i++) {
31863 data_config *dc = (data_config *)srv->config_context->data[i];
31864 s = p->config_storage[i];
31867 /* condition didn't match */
31868 if (!config_check_cond(srv, con, dc)) continue;
31872 for (j = 0; j < dc->value->used; j++) {
31873 data_unset *du = dc->value->data[j];
31876 if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
31878 + PATCH_OPTION(exts);
31879 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
31881 + PATCH_OPTION(debug);
31892 static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
31893 plugin_data *p = p_d;
31894 @@ -2673,30 +2670,30 @@
31897 scgi_extension *extension = NULL;
31900 /* Possibly, we processed already this request */
31901 if (con->file_started == 1) return HANDLER_GO_ON;
31904 fn = uri_path_handler ? con->uri.path : con->physical.path;
31906 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
31908 s_len = fn->used - 1;
31911 scgi_patch_connection(srv, con, p);
31913 /* check if extension matches */
31914 for (k = 0; k < p->conf.exts->used; k++) {
31918 extension = p->conf.exts->exts[k];
31921 if (extension->key->used == 0) continue;
31924 ct_len = extension->key->used - 1;
31927 if (s_len < ct_len) continue;
31930 /* check extension in the form "/scgi_pattern" */
31931 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
31933 @@ -2710,17 +2707,17 @@
31934 if (k == p->conf.exts->used) {
31935 return HANDLER_GO_ON;
31939 /* get best server */
31940 for (k = 0, ndx = -1; k < extension->used; k++) {
31941 scgi_extension_host *host = extension->hosts[k];
31944 /* we should have at least one proc that can do somthing */
31945 if (host->active_procs == 0) continue;
31947 if (used == -1 || host->load < used) {
31954 @@ -2728,12 +2725,12 @@
31955 /* found a server */
31957 scgi_extension_host *host = extension->hosts[ndx];
31960 - * if check-local is disabled, use the uri.path handler
31964 + * if check-local is disabled, use the uri.path handler
31969 /* init handler-context */
31970 if (uri_path_handler) {
31971 if (host->check_local == 0) {
31972 @@ -2741,7 +2738,7 @@
31975 hctx = handler_ctx_init();
31978 hctx->remote_conn = con;
31979 hctx->plugin_data = p;
31981 @@ -2749,45 +2746,45 @@
31983 hctx->conf.exts = p->conf.exts;
31984 hctx->conf.debug = p->conf.debug;
31987 con->plugin_ctx[p->id] = hctx;
31995 if (con->conf.log_request_handling) {
31996 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
31999 - /* the prefix is the SCRIPT_NAME,
32000 + /* the prefix is the SCRIPT_NAME,
32001 * everthing from start to the next slash
32002 * this is important for check-local = "disable"
32005 * if prefix = /admin.fcgi
32008 * /admin.fcgi/foo/bar
32011 * SCRIPT_NAME = /admin.fcgi
32012 * PATH_INFO = /foo/bar
32015 * if prefix = /fcgi-bin/
32018 * /fcgi-bin/foo/bar
32021 * SCRIPT_NAME = /fcgi-bin/foo
32028 /* the rewrite is only done for /prefix/? matches */
32029 if (extension->key->ptr[0] == '/' &&
32030 con->uri.path->used > extension->key->used &&
32031 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
32032 - /* rewrite uri.path and pathinfo */
32034 + /* rewrite uri.path and pathinfo */
32036 buffer_copy_string(con->request.pathinfo, pathinfo);
32039 con->uri.path->used -= con->request.pathinfo->used - 1;
32040 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
32042 @@ -2796,21 +2793,21 @@
32045 hctx = handler_ctx_init();
32048 hctx->remote_conn = con;
32049 hctx->plugin_data = p;
32054 hctx->conf.exts = p->conf.exts;
32055 hctx->conf.debug = p->conf.debug;
32058 con->plugin_ctx[p->id] = hctx;
32067 if (con->conf.log_request_handling) {
32068 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
32070 @@ -2821,11 +2818,11 @@
32071 /* no handler found */
32072 buffer_reset(con->physical.path);
32073 con->http_status = 500;
32075 - log_error_write(srv, __FILE__, __LINE__, "sb",
32076 - "no fcgi-handler found for:",
32078 + log_error_write(srv, __FILE__, __LINE__, "sb",
32079 + "no fcgi-handler found for:",
32083 return HANDLER_FINISHED;
32085 return HANDLER_GO_ON;
32086 @@ -2844,19 +2841,19 @@
32087 JOBLIST_FUNC(mod_scgi_handle_joblist) {
32088 plugin_data *p = p_d;
32089 handler_ctx *hctx = con->plugin_ctx[p->id];
32092 if (hctx == NULL) return HANDLER_GO_ON;
32094 if (hctx->fd != -1) {
32095 switch (hctx->state) {
32096 case FCGI_STATE_READ:
32097 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
32101 case FCGI_STATE_CONNECT:
32102 case FCGI_STATE_WRITE:
32103 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
32107 case FCGI_STATE_INIT:
32109 @@ -2873,21 +2870,21 @@
32111 static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
32112 plugin_data *p = p_d;
32115 return scgi_connection_close(srv, con->plugin_ctx[p->id]);
32118 TRIGGER_FUNC(mod_scgi_handle_trigger) {
32119 plugin_data *p = p_d;
32125 /* perhaps we should kill a connect attempt after 10-15 seconds
32128 * currently we wait for the TCP timeout which is on Linux 180 seconds
32137 /* check all childs if they are still up */
32138 @@ -2904,47 +2901,47 @@
32139 scgi_extension *ex;
32141 ex = exts->exts[j];
32144 for (n = 0; n < ex->used; n++) {
32148 unsigned long sum_load = 0;
32149 scgi_extension_host *host;
32152 host = ex->hosts[n];
32155 scgi_restart_dead_procs(srv, p, host);
32158 for (proc = host->first; proc; proc = proc->next) {
32159 sum_load += proc->load;
32163 if (host->num_procs &&
32164 host->num_procs < host->max_procs &&
32165 (sum_load / host->num_procs) > host->max_load_per_proc) {
32166 /* overload, spawn new child */
32167 scgi_proc *fp = NULL;
32170 if (p->conf.debug) {
32171 - log_error_write(srv, __FILE__, __LINE__, "s",
32172 + log_error_write(srv, __FILE__, __LINE__, "s",
32173 "overload detected, spawning a new child");
32177 for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
32181 if (fp == host->unused_procs) host->unused_procs = fp->next;
32184 if (fp->next) fp->next->prev = NULL;
32189 fp = scgi_process_init();
32190 fp->id = host->max_id++;
32197 if (buffer_is_empty(host->unixsocket)) {
32198 fp->port = host->port + fp->id;
32200 @@ -2952,13 +2949,13 @@
32201 buffer_append_string(fp->socket, "-");
32202 buffer_append_long(fp->socket, fp->id);
32206 if (scgi_spawn_connection(srv, p, host, fp)) {
32207 log_error_write(srv, __FILE__, __LINE__, "s",
32208 "ERROR: spawning fcgi failed.");
32209 return HANDLER_ERROR;
32214 fp->next = host->first;
32216 @@ -2966,56 +2963,57 @@
32222 for (proc = host->first; proc; proc = proc->next) {
32223 if (proc->load != 0) break;
32224 if (host->num_procs <= host->min_procs) break;
32225 if (proc->pid == 0) continue;
32228 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
32229 /* a proc is idling for a long time now,
32233 if (p->conf.debug) {
32234 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32235 - "idle-timeout reached, terminating child:",
32236 - "socket:", proc->socket,
32237 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32238 + "idle-timeout reached, terminating child:",
32239 + "socket:", proc->socket,
32246 if (proc->next) proc->next->prev = proc->prev;
32247 if (proc->prev) proc->prev->next = proc->next;
32250 if (proc->prev == NULL) host->first = proc->next;
32254 proc->next = host->unused_procs;
32257 if (host->unused_procs) host->unused_procs->prev = proc;
32258 host->unused_procs = proc;
32261 kill(proc->pid, SIGTERM);
32264 proc->state = PROC_STATE_KILLED;
32266 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32268 - "socket:", proc->socket,
32270 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32272 + "socket:", proc->socket,
32279 /* proc is now in unused, let the next second handle the next process */
32287 for (proc = host->unused_procs; proc; proc = proc->next) {
32291 if (proc->pid == 0) continue;
32294 switch (waitpid(proc->pid, &status, WNOHANG)) {
32296 /* child still running after timeout, good */
32297 @@ -3023,10 +3021,10 @@
32299 if (errno != EINTR) {
32300 /* no PID found ? should never happen */
32301 - log_error_write(srv, __FILE__, __LINE__, "sddss",
32302 + log_error_write(srv, __FILE__, __LINE__, "sddss",
32303 "pid ", proc->pid, proc->state,
32304 "not found:", strerror(errno));
32308 if (errno == ECHILD) {
32309 /* someone else has cleaned up for us */
32310 @@ -3040,25 +3038,26 @@
32311 /* the child should not terminate at all */
32312 if (WIFEXITED(status)) {
32313 if (proc->state != PROC_STATE_KILLED) {
32314 - log_error_write(srv, __FILE__, __LINE__, "sdb",
32316 + log_error_write(srv, __FILE__, __LINE__, "sdb",
32318 WEXITSTATUS(status), proc->socket);
32320 } else if (WIFSIGNALED(status)) {
32321 if (WTERMSIG(status) != SIGTERM) {
32322 - log_error_write(srv, __FILE__, __LINE__, "sd",
32323 - "child signaled:",
32324 + log_error_write(srv, __FILE__, __LINE__, "sd",
32325 + "child signaled:",
32329 - log_error_write(srv, __FILE__, __LINE__, "sd",
32330 - "child died somehow:",
32331 + log_error_write(srv, __FILE__, __LINE__, "sd",
32332 + "child died somehow:",
32336 proc->state = PROC_STATE_UNSET;
32343 @@ -3082,8 +3081,8 @@
32344 p->handle_subrequest = mod_scgi_handle_subrequest;
32345 p->handle_joblist = mod_scgi_handle_joblist;
32346 p->handle_trigger = mod_scgi_handle_trigger;
32354 --- ../lighttpd-1.4.11/src/mod_secure_download.c 2005-12-14 14:37:29.000000000 +0200
32355 +++ lighttpd-1.4.12/src/mod_secure_download.c 2006-07-11 22:07:51.000000000 +0300
32365 @@ -36,28 +36,28 @@
32368 buffer *uri_prefix;
32371 unsigned short timeout;
32381 plugin_config **config_storage;
32383 - plugin_config conf;
32385 + plugin_config conf;
32388 /* init the plugin data */
32389 INIT_FUNC(mod_secdownload_init) {
32393 p = calloc(1, sizeof(*p));
32396 p->md5 = buffer_init();
32402 @@ -65,27 +65,27 @@
32403 FREE_FUNC(mod_secdownload_free) {
32404 plugin_data *p = p_d;
32408 if (!p) return HANDLER_GO_ON;
32411 if (p->config_storage) {
32413 for (i = 0; i < srv->config_context->used; i++) {
32414 plugin_config *s = p->config_storage[i];
32417 buffer_free(s->secret);
32418 buffer_free(s->doc_root);
32419 buffer_free(s->uri_prefix);
32424 free(p->config_storage);
32428 buffer_free(p->md5);
32434 return HANDLER_GO_ON;
32437 @@ -94,107 +94,103 @@
32438 SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
32439 plugin_data *p = p_d;
32442 - config_values_t cv[] = {
32444 + config_values_t cv[] = {
32445 { "secdownload.secret", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
32446 { "secdownload.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
32447 { "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
32448 { "secdownload.timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
32449 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32453 if (!p) return HANDLER_ERROR;
32456 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32459 for (i = 0; i < srv->config_context->used; i++) {
32463 s = calloc(1, sizeof(plugin_config));
32464 s->secret = buffer_init();
32465 s->doc_root = buffer_init();
32466 s->uri_prefix = buffer_init();
32470 cv[0].destination = s->secret;
32471 cv[1].destination = s->doc_root;
32472 cv[2].destination = s->uri_prefix;
32473 cv[3].destination = &(s->timeout);
32476 p->config_storage[i] = s;
32479 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32480 return HANDLER_ERROR;
32485 return HANDLER_GO_ON;
32489 * checks if the supplied string is a MD5 string
32492 * @param str a possible MD5 string
32493 * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
32496 int is_hex_len(const char *str, size_t len) {
32500 if (NULL == str) return 0;
32503 for (i = 0; i < len && *str; i++, str++) {
32504 /* illegal characters */
32505 if (!((*str >= '0' && *str <= '9') ||
32506 (*str >= 'a' && *str <= 'f') ||
32507 - (*str >= 'A' && *str <= 'F'))
32508 + (*str >= 'A' && *str <= 'F'))
32518 -#define PATCH(x) \
32519 - p->conf.x = s->x;
32520 static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
32522 plugin_config *s = p->config_storage[0];
32526 - PATCH(uri_prefix);
32530 + PATCH_OPTION(secret);
32531 + PATCH_OPTION(doc_root);
32532 + PATCH_OPTION(uri_prefix);
32533 + PATCH_OPTION(timeout);
32535 /* skip the first, the global context */
32536 for (i = 1; i < srv->config_context->used; i++) {
32537 data_config *dc = (data_config *)srv->config_context->data[i];
32538 s = p->config_storage[i];
32541 /* condition didn't match */
32542 if (!config_check_cond(srv, con, dc)) continue;
32546 for (j = 0; j < dc->value->used; j++) {
32547 data_unset *du = dc->value->data[j];
32550 if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
32552 + PATCH_OPTION(secret);
32553 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
32555 + PATCH_OPTION(doc_root);
32556 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
32557 - PATCH(uri_prefix);
32558 + PATCH_OPTION(uri_prefix);
32559 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
32561 + PATCH_OPTION(timeout);
32572 URIHANDLER_FUNC(mod_secdownload_uri_handler) {
32573 plugin_data *p = p_d;
32574 @@ -203,88 +199,88 @@
32575 const char *rel_uri, *ts_str, *md5_str;
32580 if (con->uri.path->used == 0) return HANDLER_GO_ON;
32583 mod_secdownload_patch_connection(srv, con, p);
32585 if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
32588 if (buffer_is_empty(p->conf.secret)) {
32589 log_error_write(srv, __FILE__, __LINE__, "s",
32590 "secdownload.secret has to be set");
32591 return HANDLER_ERROR;
32595 if (buffer_is_empty(p->conf.doc_root)) {
32596 log_error_write(srv, __FILE__, __LINE__, "s",
32597 "secdownload.document-root has to be set");
32598 return HANDLER_ERROR;
32604 * /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
32608 if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
32611 md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
32614 if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
32615 if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
32618 ts_str = md5_str + 32 + 1;
32621 if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
32622 if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
32625 for (i = 0; i < 8; i++) {
32626 ts = (ts << 4) + hex2int(*(ts_str + i));
32631 - if (srv->cur_ts - ts > p->conf.timeout ||
32632 + if (srv->cur_ts - ts > p->conf.timeout ||
32633 srv->cur_ts - ts < -p->conf.timeout) {
32634 con->http_status = 408;
32637 return HANDLER_FINISHED;
32641 rel_uri = ts_str + 8;
32648 * <secret><rel-path><timestamp-hex>
32652 buffer_copy_string_buffer(p->md5, p->conf.secret);
32653 buffer_append_string(p->md5, rel_uri);
32654 buffer_append_string_len(p->md5, ts_str, 8);
32658 MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
32659 MD5_Final(HA1, &Md5Ctx);
32662 buffer_copy_string_hex(p->md5, (char *)HA1, 16);
32665 if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
32666 con->http_status = 403;
32668 - log_error_write(srv, __FILE__, __LINE__, "sss",
32670 + log_error_write(srv, __FILE__, __LINE__, "sss",
32672 md5_str, p->md5->ptr);
32675 return HANDLER_FINISHED;
32679 /* starting with the last / we should have relative-path to the docroot
32683 buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
32684 buffer_copy_string(con->physical.rel_path, rel_uri);
32685 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
32686 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
32689 return HANDLER_GO_ON;
32692 @@ -293,13 +289,13 @@
32693 int mod_secdownload_plugin_init(plugin *p) {
32694 p->version = LIGHTTPD_VERSION_ID;
32695 p->name = buffer_init_string("secdownload");
32698 p->init = mod_secdownload_init;
32699 p->handle_physical = mod_secdownload_uri_handler;
32700 p->set_defaults = mod_secdownload_set_defaults;
32701 p->cleanup = mod_secdownload_free;
32709 --- ../lighttpd-1.4.11/src/mod_setenv.c 2006-01-14 20:33:12.000000000 +0200
32710 +++ lighttpd-1.4.12/src/mod_setenv.c 2006-07-11 22:07:53.000000000 +0300
32711 @@ -18,25 +18,25 @@
32713 array *request_header;
32714 array *response_header;
32717 array *environment;
32724 plugin_config **config_storage;
32726 - plugin_config conf;
32728 + plugin_config conf;
32731 static handler_ctx * handler_ctx_init() {
32732 handler_ctx * hctx;
32735 hctx = calloc(1, sizeof(*hctx));
32744 @@ -48,36 +48,36 @@
32745 /* init the plugin data */
32746 INIT_FUNC(mod_setenv_init) {
32750 p = calloc(1, sizeof(*p));
32756 /* detroy the plugin data */
32757 FREE_FUNC(mod_setenv_free) {
32758 plugin_data *p = p_d;
32763 if (!p) return HANDLER_GO_ON;
32766 if (p->config_storage) {
32768 for (i = 0; i < srv->config_context->used; i++) {
32769 plugin_config *s = p->config_storage[i];
32772 array_free(s->request_header);
32773 array_free(s->response_header);
32774 array_free(s->environment);
32779 free(p->config_storage);
32786 return HANDLER_GO_ON;
32789 @@ -86,86 +86,83 @@
32790 SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
32791 plugin_data *p = p_d;
32794 - config_values_t cv[] = {
32796 + config_values_t cv[] = {
32797 { "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
32798 { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
32799 { "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
32800 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32804 if (!p) return HANDLER_ERROR;
32807 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32810 for (i = 0; i < srv->config_context->used; i++) {
32814 s = calloc(1, sizeof(plugin_config));
32815 s->request_header = array_init();
32816 s->response_header = array_init();
32817 s->environment = array_init();
32820 cv[0].destination = s->request_header;
32821 cv[1].destination = s->response_header;
32822 cv[2].destination = s->environment;
32825 p->config_storage[i] = s;
32828 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32829 return HANDLER_ERROR;
32834 return HANDLER_GO_ON;
32837 -#define PATCH(x) \
32838 - p->conf.x = s->x;
32839 static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
32841 plugin_config *s = p->config_storage[0];
32843 - PATCH(request_header);
32844 - PATCH(response_header);
32845 - PATCH(environment);
32848 + PATCH_OPTION(request_header);
32849 + PATCH_OPTION(response_header);
32850 + PATCH_OPTION(environment);
32852 /* skip the first, the global context */
32853 for (i = 1; i < srv->config_context->used; i++) {
32854 data_config *dc = (data_config *)srv->config_context->data[i];
32855 s = p->config_storage[i];
32858 /* condition didn't match */
32859 if (!config_check_cond(srv, con, dc)) continue;
32863 for (j = 0; j < dc->value->used; j++) {
32864 data_unset *du = dc->value->data[j];
32867 if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
32868 - PATCH(request_header);
32869 + PATCH_OPTION(request_header);
32870 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
32871 - PATCH(response_header);
32872 + PATCH_OPTION(response_header);
32873 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
32874 - PATCH(environment);
32875 + PATCH_OPTION(environment);
32885 URIHANDLER_FUNC(mod_setenv_uri_handler) {
32886 plugin_data *p = p_d;
32891 if (con->plugin_ctx[p->id]) {
32892 hctx = con->plugin_ctx[p->id];
32894 hctx = handler_ctx_init();
32897 con->plugin_ctx[p->id] = hctx;
32900 @@ -180,52 +177,52 @@
32901 for (k = 0; k < p->conf.request_header->used; k++) {
32902 data_string *ds = (data_string *)p->conf.request_header->data[k];
32903 data_string *ds_dst;
32906 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
32907 ds_dst = data_string_init();
32911 buffer_copy_string_buffer(ds_dst->key, ds->key);
32912 buffer_copy_string_buffer(ds_dst->value, ds->value);
32915 array_insert_unique(con->request.headers, (data_unset *)ds_dst);
32919 for (k = 0; k < p->conf.environment->used; k++) {
32920 data_string *ds = (data_string *)p->conf.environment->data[k];
32921 data_string *ds_dst;
32924 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
32925 ds_dst = data_string_init();
32929 buffer_copy_string_buffer(ds_dst->key, ds->key);
32930 buffer_copy_string_buffer(ds_dst->value, ds->value);
32933 array_insert_unique(con->environment, (data_unset *)ds_dst);
32937 for (k = 0; k < p->conf.response_header->used; k++) {
32938 data_string *ds = (data_string *)p->conf.response_header->data[k];
32941 response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
32946 return HANDLER_GO_ON;
32949 REQUESTDONE_FUNC(mod_setenv_reset) {
32950 plugin_data *p = p_d;
32956 if (con->plugin_ctx[p->id]) {
32957 handler_ctx_free(con->plugin_ctx[p->id]);
32958 con->plugin_ctx[p->id] = NULL;
32961 - return HANDLER_GO_ON;
32962 + return HANDLER_GO_ON;
32965 /* this function is called at dlopen() time and inits the callbacks */
32966 @@ -233,15 +230,15 @@
32967 int mod_setenv_plugin_init(plugin *p) {
32968 p->version = LIGHTTPD_VERSION_ID;
32969 p->name = buffer_init_string("setenv");
32972 p->init = mod_setenv_init;
32973 p->handle_uri_clean = mod_setenv_uri_handler;
32974 p->set_defaults = mod_setenv_set_defaults;
32975 p->cleanup = mod_setenv_free;
32978 p->handle_request_done = mod_setenv_reset;
32985 --- ../lighttpd-1.4.11/src/mod_simple_vhost.c 2005-11-18 15:16:13.000000000 +0200
32986 +++ lighttpd-1.4.12/src/mod_simple_vhost.c 2006-07-11 22:07:52.000000000 +0300
32989 #include "plugin.h"
32991 +#include "sys-files.h"
32993 #ifdef HAVE_CONFIG_H
32994 #include "config.h"
32997 buffer *server_root;
32998 buffer *default_host;
32999 buffer *document_root;
33002 buffer *docroot_cache_key;
33003 buffer *docroot_cache_value;
33004 buffer *docroot_cache_servername;
33005 @@ -28,138 +30,138 @@
33014 plugin_config **config_storage;
33015 - plugin_config conf;
33016 + plugin_config conf;
33019 INIT_FUNC(mod_simple_vhost_init) {
33023 p = calloc(1, sizeof(*p));
33026 p->doc_root = buffer_init();
33032 FREE_FUNC(mod_simple_vhost_free) {
33033 plugin_data *p = p_d;
33038 if (!p) return HANDLER_GO_ON;
33041 if (p->config_storage) {
33043 for (i = 0; i < srv->config_context->used; i++) {
33044 plugin_config *s = p->config_storage[i];
33047 buffer_free(s->document_root);
33048 buffer_free(s->default_host);
33049 buffer_free(s->server_root);
33052 buffer_free(s->docroot_cache_key);
33053 buffer_free(s->docroot_cache_value);
33054 buffer_free(s->docroot_cache_servername);
33061 free(p->config_storage);
33065 buffer_free(p->doc_root);
33071 return HANDLER_GO_ON;
33074 SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
33075 plugin_data *p = p_d;
33078 - config_values_t cv[] = {
33080 + config_values_t cv[] = {
33081 { "simple-vhost.server-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33082 { "simple-vhost.default-host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33083 { "simple-vhost.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33084 { "simple-vhost.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
33085 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33089 if (!p) return HANDLER_ERROR;
33092 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33095 for (i = 0; i < srv->config_context->used; i++) {
33099 s = calloc(1, sizeof(plugin_config));
33102 s->server_root = buffer_init();
33103 s->default_host = buffer_init();
33104 s->document_root = buffer_init();
33107 s->docroot_cache_key = buffer_init();
33108 s->docroot_cache_value = buffer_init();
33109 s->docroot_cache_servername = buffer_init();
33114 cv[0].destination = s->server_root;
33115 cv[1].destination = s->default_host;
33116 cv[2].destination = s->document_root;
33117 cv[3].destination = &(s->debug);
33122 p->config_storage[i] = s;
33125 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33126 return HANDLER_ERROR;
33131 return HANDLER_GO_ON;
33134 static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
33135 stat_cache_entry *sce = NULL;
33138 buffer_prepare_copy(out, 128);
33140 if (p->conf.server_root->used) {
33141 buffer_copy_string_buffer(out, p->conf.server_root);
33145 /* a hostname has to start with a alpha-numerical character
33146 * and must not contain a slash "/"
33150 - BUFFER_APPEND_SLASH(out);
33153 + PATHNAME_APPEND_SLASH(out);
33155 if (NULL == (dp = strchr(host->ptr, ':'))) {
33156 buffer_append_string_buffer(out, host);
33158 buffer_append_string_len(out, host->ptr, dp - host->ptr);
33161 - BUFFER_APPEND_SLASH(out);
33163 + PATHNAME_APPEND_SLASH(out);
33165 if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
33166 buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
33168 buffer_append_string_buffer(out, p->conf.document_root);
33169 - BUFFER_APPEND_SLASH(out);
33170 + PATHNAME_APPEND_SLASH(out);
33173 buffer_copy_string_buffer(out, con->conf.document_root);
33174 - BUFFER_APPEND_SLASH(out);
33175 + PATHNAME_APPEND_SLASH(out);
33179 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
33180 if (p->conf.debug) {
33181 log_error_write(srv, __FILE__, __LINE__, "sb",
33182 @@ -169,57 +171,53 @@
33183 } else if (!S_ISDIR(sce->st.st_mode)) {
33192 -#define PATCH(x) \
33193 - p->conf.x = s->x;
33194 static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
33196 plugin_config *s = p->config_storage[0];
33198 - PATCH(server_root);
33199 - PATCH(default_host);
33200 - PATCH(document_root);
33202 - PATCH(docroot_cache_key);
33203 - PATCH(docroot_cache_value);
33204 - PATCH(docroot_cache_servername);
33208 + PATCH_OPTION(server_root);
33209 + PATCH_OPTION(default_host);
33210 + PATCH_OPTION(document_root);
33212 + PATCH_OPTION(docroot_cache_key);
33213 + PATCH_OPTION(docroot_cache_value);
33214 + PATCH_OPTION(docroot_cache_servername);
33216 + PATCH_OPTION(debug);
33218 /* skip the first, the global context */
33219 for (i = 1; i < srv->config_context->used; i++) {
33220 data_config *dc = (data_config *)srv->config_context->data[i];
33221 s = p->config_storage[i];
33224 /* condition didn't match */
33225 if (!config_check_cond(srv, con, dc)) continue;
33229 for (j = 0; j < dc->value->used; j++) {
33230 data_unset *du = dc->value->data[j];
33233 if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
33234 - PATCH(server_root);
33235 - PATCH(docroot_cache_key);
33236 - PATCH(docroot_cache_value);
33237 - PATCH(docroot_cache_servername);
33238 + PATCH_OPTION(server_root);
33239 + PATCH_OPTION(docroot_cache_key);
33240 + PATCH_OPTION(docroot_cache_value);
33241 + PATCH_OPTION(docroot_cache_servername);
33242 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
33243 - PATCH(default_host);
33244 + PATCH_OPTION(default_host);
33245 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
33246 - PATCH(document_root);
33247 + PATCH_OPTION(document_root);
33248 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
33250 + PATCH_OPTION(debug);
33260 static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
33261 plugin_data *p = p_data;
33262 @@ -227,12 +225,12 @@
33264 * cache the last successfull translation from hostname (authority) to docroot
33265 * - this saves us a stat() call
33271 mod_simple_vhost_patch_connection(srv, con, p);
33273 - if (p->conf.docroot_cache_key->used &&
33275 + if (p->conf.docroot_cache_key->used &&
33276 con->uri.authority->used &&
33277 buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
33279 @@ -243,8 +241,8 @@
33280 if ((con->uri.authority->used == 0) ||
33281 build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
33282 /* not found, fallback the default-host */
33283 - if (build_doc_root(srv, con, p,
33285 + if (build_doc_root(srv, con, p,
33287 p->conf.default_host)) {
33288 return HANDLER_GO_ON;
33290 @@ -253,15 +251,15 @@
33292 buffer_copy_string_buffer(con->server_name, con->uri.authority);
33296 /* copy to cache */
33297 buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority);
33298 buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root);
33299 buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
33302 buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
33306 return HANDLER_GO_ON;
33309 @@ -269,13 +267,13 @@
33310 int mod_simple_vhost_plugin_init(plugin *p) {
33311 p->version = LIGHTTPD_VERSION_ID;
33312 p->name = buffer_init_string("simple_vhost");
33315 p->init = mod_simple_vhost_init;
33316 p->set_defaults = mod_simple_vhost_set_defaults;
33317 p->handle_docroot = mod_simple_vhost_docroot;
33318 p->cleanup = mod_simple_vhost_free;
33326 --- ../lighttpd-1.4.11/src/mod_skeleton.c 2005-10-02 18:30:51.000000000 +0300
33327 +++ lighttpd-1.4.12/src/mod_skeleton.c 2006-07-11 22:07:51.000000000 +0300
33328 @@ -14,13 +14,13 @@
33331 * this is a skeleton for a lighttpd plugin
33334 * just replaces every occurance of 'skeleton' by your plugin name
33340 * :%s/skeleton/myhandler/
33346 @@ -33,12 +33,12 @@
33355 plugin_config **config_storage;
33357 - plugin_config conf;
33359 + plugin_config conf;
33363 @@ -47,36 +47,36 @@
33365 static handler_ctx * handler_ctx_init() {
33366 handler_ctx * hctx;
33369 hctx = calloc(1, sizeof(*hctx));
33375 static void handler_ctx_free(handler_ctx *hctx) {
33381 /* init the plugin data */
33382 INIT_FUNC(mod_skeleton_init) {
33386 p = calloc(1, sizeof(*p));
33389 p->match_buf = buffer_init();
33395 /* detroy the plugin data */
33396 FREE_FUNC(mod_skeleton_free) {
33397 plugin_data *p = p_d;
33402 if (!p) return HANDLER_GO_ON;
33405 if (p->config_storage) {
33408 @@ -84,18 +84,18 @@
33409 plugin_config *s = p->config_storage[i];
33414 array_free(s->match);
33419 free(p->config_storage);
33423 buffer_free(p->match_buf);
33429 return HANDLER_GO_ON;
33432 @@ -104,91 +104,88 @@
33433 SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
33434 plugin_data *p = p_d;
33437 - config_values_t cv[] = {
33439 + config_values_t cv[] = {
33440 { "skeleton.array", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
33441 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33445 if (!p) return HANDLER_ERROR;
33448 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33451 for (i = 0; i < srv->config_context->used; i++) {
33455 s = calloc(1, sizeof(plugin_config));
33456 s->match = array_init();
33459 cv[0].destination = s->match;
33462 p->config_storage[i] = s;
33465 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33466 return HANDLER_ERROR;
33471 return HANDLER_GO_ON;
33474 -#define PATCH(x) \
33475 - p->conf.x = s->x;
33476 static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
33478 plugin_config *s = p->config_storage[0];
33483 + PATCH_OPTION(match);
33485 /* skip the first, the global context */
33486 for (i = 1; i < srv->config_context->used; i++) {
33487 data_config *dc = (data_config *)srv->config_context->data[i];
33488 s = p->config_storage[i];
33491 /* condition didn't match */
33492 if (!config_check_cond(srv, con, dc)) continue;
33496 for (j = 0; j < dc->value->used; j++) {
33497 data_unset *du = dc->value->data[j];
33500 if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
33502 + PATCH_OPTION(match);
33512 URIHANDLER_FUNC(mod_skeleton_uri_handler) {
33513 plugin_data *p = p_d;
33520 if (con->uri.path->used == 0) return HANDLER_GO_ON;
33523 mod_skeleton_patch_connection(srv, con, p);
33525 s_len = con->uri.path->used - 1;
33528 for (k = 0; k < p->conf.match->used; k++) {
33529 data_string *ds = (data_string *)p->conf.match->data[k];
33530 int ct_len = ds->value->used - 1;
33533 if (ct_len > s_len) continue;
33534 if (ds->value->used == 0) continue;
33537 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
33538 con->http_status = 403;
33541 return HANDLER_FINISHED;
33547 return HANDLER_GO_ON;
33549 @@ -198,13 +195,13 @@
33550 int mod_skeleton_plugin_init(plugin *p) {
33551 p->version = LIGHTTPD_VERSION_ID;
33552 p->name = buffer_init_string("skeleton");
33555 p->init = mod_skeleton_init;
33556 p->handle_uri_clean = mod_skeleton_uri_handler;
33557 p->set_defaults = mod_skeleton_set_defaults;
33558 p->cleanup = mod_skeleton_free;
33566 --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.c 1970-01-01 03:00:00.000000000 +0300
33567 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.c 2006-07-11 22:07:53.000000000 +0300
33569 +#include <stdio.h>
33570 +#include <errno.h>
33571 +#include <fcntl.h>
33572 +#include <string.h>
33574 +#ifdef HAVE_CONFIG_H
33575 +#include "config.h"
33578 +#include "plugin.h"
33581 +#include "stat_cache.h"
33583 +#include "mod_sql_vhost_core.h"
33585 +#define plugin_data mod_sql_vhost_core_plugin_data
33586 +#define plugin_config mod_sql_vhost_core_plugin_config
33588 +/* init the plugin data */
33589 +INIT_FUNC(mod_sql_vhost_core_init) {
33592 + p = calloc(1, sizeof(*p));
33594 + p->docroot = buffer_init();
33595 + p->host = buffer_init();
33600 +/* cleanup the plugin data */
33601 +SERVER_FUNC(mod_sql_vhost_core_cleanup) {
33602 + plugin_data *p = p_d;
33606 + if (!p) return HANDLER_GO_ON;
33608 + if (p->config_storage) {
33610 + for (i = 0; i < srv->config_context->used; i++) {
33611 + plugin_config *s = p->config_storage[i];
33613 + if (!s) continue;
33615 + buffer_free(s->db);
33616 + buffer_free(s->user);
33617 + buffer_free(s->pass);
33618 + buffer_free(s->sock);
33619 + buffer_free(s->backend);
33623 + free(p->config_storage);
33625 + buffer_free(p->docroot);
33626 + buffer_free(p->host);
33630 + return HANDLER_GO_ON;
33633 +/* set configuration values */
33634 +SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
33635 + plugin_data *p = p_d;
33639 + config_values_t cv[] = {
33640 + { "sql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
33641 + { "sql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
33642 + { "sql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
33643 + { "sql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
33644 + { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
33645 + { "sql-vhost.hostname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
33646 + { "sql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
33647 + { "sql-vhost.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
33649 + /* backward compat */
33650 + { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
33651 + { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
33652 + { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
33653 + { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
33654 + { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
33655 + { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
33656 + { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
33658 + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33661 + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33663 + for (i = 0; i < srv->config_context->used; i++) {
33664 + plugin_config *s;
33666 + s = calloc(1, sizeof(plugin_config));
33667 + s->db = buffer_init();
33668 + s->user = buffer_init();
33669 + s->pass = buffer_init();
33670 + s->sock = buffer_init();
33671 + s->hostname = buffer_init();
33672 + s->backend = buffer_init();
33673 + s->port = 0; /* default port for mysql */
33674 + s->select_vhost = buffer_init();
33675 + s->backend_data = NULL;
33677 + cv[0].destination = s->db;
33678 + cv[1].destination = s->user;
33679 + cv[2].destination = s->pass;
33680 + cv[3].destination = s->sock;
33681 + cv[4].destination = s->select_vhost;
33682 + cv[5].destination = s->hostname;
33683 + cv[6].destination = &(s->port);
33684 + cv[7].destination = s->backend;
33686 + /* backend compat */
33687 + cv[8].destination = cv[0].destination;
33688 + cv[9].destination = cv[1].destination;
33689 + cv[10].destination = cv[2].destination;
33690 + cv[11].destination = cv[3].destination;
33691 + cv[12].destination = cv[4].destination;
33692 + cv[13].destination = cv[5].destination;
33693 + cv[14].destination = cv[6].destination;
33695 + p->config_storage[i] = s;
33697 + if (config_insert_values_global(srv,
33698 + ((data_config *)srv->config_context->data[i])->value,
33699 + cv)) return HANDLER_ERROR;
33701 + /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
33704 + return HANDLER_GO_ON;
33707 +static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
33709 + plugin_config *s = p->config_storage[0];
33711 + PATCH_OPTION(backend_data);
33712 + PATCH_OPTION(get_vhost);
33714 + /* skip the first, the global context */
33715 + for (i = 1; i < srv->config_context->used; i++) {
33716 + data_config *dc = (data_config *)srv->config_context->data[i];
33717 + s = p->config_storage[i];
33719 + /* condition didn't match */
33720 + if (!config_check_cond(srv, con, dc)) continue;
33722 + if (s->backend_data) {
33723 + PATCH_OPTION(backend_data);
33724 + PATCH_OPTION(get_vhost);
33731 +/* handle document root request */
33732 +CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
33733 + plugin_data *p = p_d;
33734 + stat_cache_entry *sce;
33736 + /* no host specified? */
33737 + if (!con->uri.authority->used) return HANDLER_GO_ON;
33739 + mod_sql_vhost_core_patch_connection(srv, con, p);
33741 + /* do we have backend ? */
33742 + if (!p->conf.get_vhost) return HANDLER_GO_ON;
33744 + /* ask the backend for the data */
33745 + if (0 != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
33746 + return HANDLER_GO_ON;
33749 + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
33750 + log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->docroot);
33751 + return HANDLER_GO_ON;
33753 + if (!S_ISDIR(sce->st.st_mode)) {
33754 + log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->docroot);
33755 + return HANDLER_GO_ON;
33758 + buffer_copy_string_buffer(con->server_name, p->host);
33759 + buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
33761 + return HANDLER_GO_ON;
33764 +/* this function is called at dlopen() time and inits the callbacks */
33765 +int mod_sql_vhost_core_plugin_init(plugin *p) {
33766 + p->version = LIGHTTPD_VERSION_ID;
33767 + p->name = buffer_init_string("mod_sql_vhost_core");
33769 + p->init = mod_sql_vhost_core_init;
33770 + p->cleanup = mod_sql_vhost_core_cleanup;
33772 + p->set_defaults = mod_sql_vhost_core_set_defaults;
33773 + p->handle_docroot = mod_sql_vhost_core_handle_docroot;
33778 --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.h 1970-01-01 03:00:00.000000000 +0300
33779 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.h 2006-07-11 22:07:53.000000000 +0300
33781 +#ifndef _MOD_SQL_VHOST_CORE_H_
33782 +#define _MOD_SQL_VHOST_CORE_H_
33784 +#include "buffer.h"
33785 +#include "plugin.h"
33787 +#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
33788 + (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
33790 +#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
33792 +#define SQLVHOST_BACKEND_GETVHOST(name) \
33793 + SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
33795 +#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
33796 + SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
33804 + buffer *hostname;
33805 + unsigned short port;
33808 + void *backend_data;
33810 + buffer *select_vhost;
33812 + SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
33813 +} mod_sql_vhost_core_plugin_config;
33815 +/* global plugin data */
33822 + mod_sql_vhost_core_plugin_config **config_storage;
33824 + mod_sql_vhost_core_plugin_config conf;
33825 +} mod_sql_vhost_core_plugin_data;
33830 --- ../lighttpd-1.4.11/src/mod_ssi.c 2006-03-04 17:09:48.000000000 +0200
33831 +++ lighttpd-1.4.12/src/mod_ssi.c 2006-07-11 22:07:53.000000000 +0300
33833 #include <string.h>
33836 -#include <unistd.h>
33841 #include "inet_ntop_cache.h"
33843 #include "sys-socket.h"
33844 +#include "sys-strings.h"
33845 +#include "sys-files.h"
33849 @@ -39,15 +40,15 @@
33850 /* init the plugin data */
33851 INIT_FUNC(mod_ssi_init) {
33855 p = calloc(1, sizeof(*p));
33858 p->timefmt = buffer_init();
33859 p->stat_fn = buffer_init();
33862 p->ssi_vars = array_init();
33863 p->ssi_cgi_env = array_init();
33869 @@ -55,21 +56,21 @@
33870 FREE_FUNC(mod_ssi_free) {
33871 plugin_data *p = p_d;
33875 if (!p) return HANDLER_GO_ON;
33878 if (p->config_storage) {
33880 for (i = 0; i < srv->config_context->used; i++) {
33881 plugin_config *s = p->config_storage[i];
33884 array_free(s->ssi_extension);
33889 free(p->config_storage);
33893 array_free(p->ssi_vars);
33894 array_free(p->ssi_cgi_env);
33898 buffer_free(p->timefmt);
33899 buffer_free(p->stat_fn);
33905 return HANDLER_GO_ON;
33908 @@ -92,36 +93,36 @@
33909 const char *errptr;
33913 - config_values_t cv[] = {
33915 + config_values_t cv[] = {
33916 { "ssi.extension", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
33917 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33921 if (!p) return HANDLER_ERROR;
33924 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33927 for (i = 0; i < srv->config_context->used; i++) {
33931 s = calloc(1, sizeof(plugin_config));
33932 s->ssi_extension = array_init();
33935 cv[0].destination = s->ssi_extension;
33938 p->config_storage[i] = s;
33941 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33942 return HANDLER_ERROR;
33948 /* allow 2 params */
33949 if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
33950 log_error_write(srv, __FILE__, __LINE__, "sds",
33954 return HANDLER_ERROR;
33956 @@ -130,52 +131,52 @@
33957 "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
33958 return HANDLER_ERROR;
33962 return HANDLER_GO_ON;
33965 int ssi_env_add(array *env, const char *key, const char *val) {
33969 if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
33970 ds = data_string_init();
33972 buffer_copy_string(ds->key, key);
33973 buffer_copy_string(ds->value, val);
33976 array_insert_unique(env, (data_unset *)ds);
33984 * the next two functions are take from fcgi.c
33989 static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
33993 for (i = 0; i < con->request.headers->used; i++) {
33997 ds = (data_string *)con->request.headers->data[i];
34000 if (ds->value->used && ds->key->used) {
34002 buffer_reset(srv->tmp_buf);
34005 /* don't forward the Authorization: Header */
34006 if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
34011 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
34012 buffer_copy_string(srv->tmp_buf, "HTTP_");
34013 srv->tmp_buf->used--;
34017 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
34018 for (j = 0; j < ds->key->used - 1; j++) {
34020 @@ -189,33 +190,33 @@
34021 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
34023 srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
34026 ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
34034 static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
34038 server_socket *srv_sock = con->srv_socket;
34042 char b2[INET6_ADDRSTRLEN + 1];
34045 #define CONST_STRING(x) \
34049 array_reset(p->ssi_cgi_env);
34052 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
34053 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
34055 - inet_ntop(srv_sock->addr.plain.sa_family,
34056 - srv_sock->addr.plain.sa_family == AF_INET6 ?
34057 + inet_ntop(srv_sock->addr.plain.sa_family,
34058 + srv_sock->addr.plain.sa_family == AF_INET6 ?
34059 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
34060 (const void *) &(srv_sock->addr.ipv4.sin_addr),
34062 @@ -224,28 +225,28 @@
34065 ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
34071 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
34073 ntohs(srv_sock->addr.ipv4.sin_port)
34078 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
34081 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
34082 inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
34085 if (con->authed_user->used) {
34086 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
34087 con->authed_user->ptr);
34091 if (con->request.content_length > 0) {
34092 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
34095 /* request.content_length < SSIZE_MAX, see request.c */
34096 ltostr(buf, con->request.content_length);
34097 ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
34098 @@ -271,30 +272,30 @@
34099 if (con->request.pathinfo->used) {
34100 ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
34104 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
34105 ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
34108 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
34109 ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
34110 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
34111 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
34112 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
34115 ssi_env_add_request_headers(srv, con, p);
34121 -static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
34122 +static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
34123 const char **l, size_t n) {
34124 size_t i, ssicmd = 0;
34132 - enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
34133 + enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
34134 SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
34135 SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
34137 @@ -310,27 +311,27 @@
34138 { "endif", SSI_ENDIF },
34139 { "else", SSI_ELSE },
34140 { "exec", SSI_EXEC },
34143 { NULL, SSI_UNSET }
34147 for (i = 0; ssicmds[i].var; i++) {
34148 if (0 == strcmp(l[1], ssicmds[i].var)) {
34149 ssicmd = ssicmds[i].type;
34158 int var = 0, enc = 0;
34159 const char *var_val = NULL;
34160 stat_cache_entry *sce = NULL;
34166 - enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
34167 + enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
34168 SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
34170 { "DATE_GMT", SSI_ECHO_DATE_GMT },
34171 @@ -339,27 +340,27 @@
34172 { "DOCUMENT_URI", SSI_ECHO_DOCUMENT_URI },
34173 { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
34174 { "USER_NAME", SSI_ECHO_USER_NAME },
34177 { NULL, SSI_ECHO_UNSET }
34184 enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
34186 { "url", SSI_ENC_URL },
34187 { "none", SSI_ENC_NONE },
34188 { "entity", SSI_ENC_ENTITY },
34191 { NULL, SSI_ENC_UNSET }
34195 for (i = 2; i < n; i += 2) {
34196 if (0 == strcmp(l[i], "var")) {
34203 for (j = 0; echovars[j].var; j++) {
34204 if (0 == strcmp(l[i+1], echovars[j].var)) {
34205 var = echovars[j].type;
34206 @@ -368,7 +369,7 @@
34208 } else if (0 == strcmp(l[i], "encoding")) {
34212 for (j = 0; encvars[j].var; j++) {
34213 if (0 == strcmp(l[i+1], encvars[j].var)) {
34214 enc = encvars[j].type;
34215 @@ -377,26 +378,26 @@
34218 log_error_write(srv, __FILE__, __LINE__, "sss",
34219 - "ssi: unknow attribute for ",
34220 + "ssi: unknow attribute for ",
34226 if (p->if_is_false) break;
34230 log_error_write(srv, __FILE__, __LINE__, "sss",
34233 l[1], "var is missing");
34237 stat_cache_get_entry(srv, con, con->physical.path, &sce);
34241 case SSI_ECHO_USER_NAME: {
34245 b = chunkqueue_get_append_buffer(con->write_queue);
34247 if (NULL == (pw = getpwuid(sce->st.st_uid))) {
34248 @@ -411,7 +412,7 @@
34250 case SSI_ECHO_LAST_MODIFIED: {
34251 time_t t = sce->st.st_mtime;
34254 b = chunkqueue_get_append_buffer(con->write_queue);
34255 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34256 buffer_copy_string(b, "(none)");
34257 @@ -422,7 +423,7 @@
34259 case SSI_ECHO_DATE_LOCAL: {
34260 time_t t = time(NULL);
34263 b = chunkqueue_get_append_buffer(con->write_queue);
34264 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34265 buffer_copy_string(b, "(none)");
34266 @@ -433,7 +434,7 @@
34268 case SSI_ECHO_DATE_GMT: {
34269 time_t t = time(NULL);
34272 b = chunkqueue_get_append_buffer(con->write_queue);
34273 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
34274 buffer_copy_string(b, "(none)");
34275 @@ -444,7 +445,7 @@
34277 case SSI_ECHO_DOCUMENT_NAME: {
34281 b = chunkqueue_get_append_buffer(con->write_queue);
34282 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34283 buffer_copy_string_buffer(b, con->physical.path);
34284 @@ -461,15 +462,15 @@
34287 /* check if it is a cgi-var */
34290 b = chunkqueue_get_append_buffer(con->write_queue);
34293 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
34294 buffer_copy_string_buffer(b, ds->value);
34296 buffer_copy_string(b, "(none)");
34303 @@ -481,7 +482,7 @@
34304 const char * file_path = NULL, *virt_path = NULL;
34309 for (i = 2; i < n; i += 2) {
34310 if (0 == strcmp(l[i], "file")) {
34311 file_path = l[i+1];
34312 @@ -489,28 +490,28 @@
34313 virt_path = l[i+1];
34315 log_error_write(srv, __FILE__, __LINE__, "sss",
34316 - "ssi: unknow attribute for ",
34317 + "ssi: unknow attribute for ",
34323 if (!file_path && !virt_path) {
34324 log_error_write(srv, __FILE__, __LINE__, "sss",
34327 l[1], "file or virtual are missing");
34332 if (file_path && virt_path) {
34333 log_error_write(srv, __FILE__, __LINE__, "sss",
34336 l[1], "only one of file and virtual is allowed here");
34343 if (p->if_is_false) break;
34347 /* current doc-root */
34348 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34349 @@ -519,46 +520,46 @@
34350 buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
34353 - buffer_copy_string(srv->tmp_buf, file_path);
34354 + buffer_copy_string(srv->tmp_buf, file_path);
34355 buffer_urldecode_path(srv->tmp_buf);
34356 - buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
34357 - buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34358 + buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
34359 + buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34364 if (virt_path[0] == '/') {
34365 buffer_copy_string(p->stat_fn, virt_path);
34367 /* there is always a / */
34368 sl = strrchr(con->uri.path->ptr, '/');
34371 buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
34372 buffer_append_string(p->stat_fn, virt_path);
34376 buffer_urldecode_path(p->stat_fn);
34377 buffer_path_simplify(srv->tmp_buf, p->stat_fn);
34380 /* we have an uri */
34383 buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
34384 buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34388 if (0 == stat(p->stat_fn->ptr, &st)) {
34389 time_t t = st.st_mtime;
34394 b = chunkqueue_get_append_buffer(con->write_queue);
34397 const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
34400 off_t s = st.st_size;
34403 for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
34406 buffer_copy_off_t(b, s);
34407 buffer_append_string(b, abr[j]);
34409 @@ -579,7 +580,7 @@
34412 log_error_write(srv, __FILE__, __LINE__, "sbs",
34413 - "ssi: stating failed ",
34414 + "ssi: stating failed ",
34415 p->stat_fn, strerror(errno));
34418 @@ -593,33 +594,33 @@
34421 log_error_write(srv, __FILE__, __LINE__, "sss",
34422 - "ssi: unknow attribute for ",
34423 + "ssi: unknow attribute for ",
34429 if (p->if_is_false) break;
34436 if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
34437 ds = data_string_init();
34439 buffer_copy_string(ds->key, key);
34440 buffer_copy_string(ds->value, val);
34443 array_insert_unique(p->ssi_vars, (data_unset *)ds);
34445 log_error_write(srv, __FILE__, __LINE__, "sss",
34446 - "ssi: var and value have to be set in",
34447 + "ssi: var and value have to be set in",
34454 if (p->if_is_false) break;
34457 for (i = 2; i < n; i += 2) {
34458 if (0 == strcmp(l[i], "timefmt")) {
34459 buffer_copy_string(p->timefmt, l[i+1]);
34460 @@ -632,63 +633,65 @@
34461 log_error_write(srv, __FILE__, __LINE__, "sssss",
34462 "ssi: unknow value for attribute '",
34469 log_error_write(srv, __FILE__, __LINE__, "sss",
34470 - "ssi: unknow attribute for ",
34471 + "ssi: unknow attribute for ",
34477 if (p->if_is_false) break;
34480 b = chunkqueue_get_append_buffer(con->write_queue);
34481 buffer_copy_string(b, "<pre>");
34482 for (i = 0; i < p->ssi_vars->used; i++) {
34483 data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
34486 buffer_append_string_buffer(b, ds->key);
34487 buffer_append_string(b, ": ");
34488 buffer_append_string_buffer(b, ds->value);
34489 buffer_append_string(b, "<br />");
34493 buffer_append_string(b, "</pre>");
34500 const char *cmd = NULL;
34502 int from_exec_fds[2];
34505 for (i = 2; i < n; i += 2) {
34506 if (0 == strcmp(l[i], "cmd")) {
34509 log_error_write(srv, __FILE__, __LINE__, "sss",
34510 - "ssi: unknow attribute for ",
34511 + "ssi: unknow attribute for ",
34517 if (p->if_is_false) break;
34520 /* create a return pipe and send output to the html-page
34522 - * as exec is assumed evil it is implemented synchronously
34524 + * as exec is assumed evil it is implemented synchronously
34531 if (pipe(from_exec_fds)) {
34532 - log_error_write(srv, __FILE__, __LINE__, "ss",
34533 + log_error_write(srv, __FILE__, __LINE__, "ss",
34534 "pipe failed: ", strerror(errno));
34540 switch (pid = fork()) {
34542 @@ -698,14 +701,14 @@
34543 close(from_exec_fds[1]);
34545 close(from_exec_fds[0]);
34549 close(STDIN_FILENO);
34552 execl("/bin/sh", "sh", "-c", cmd, NULL);
34555 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
34561 @@ -718,9 +721,9 @@
34567 close(from_exec_fds[1]);
34570 /* wait for the client to end */
34571 if (-1 == waitpid(pid, &status, 0)) {
34572 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
34573 @@ -730,7 +733,7 @@
34576 if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
34577 - log_error_write(srv, __FILE__, __LINE__, "s",
34578 + log_error_write(srv, __FILE__, __LINE__, "s",
34579 "unexpected end-of-file (perhaps the ssi-exec process died)");
34582 @@ -738,10 +741,10 @@
34584 b = chunkqueue_get_append_buffer(con->write_queue);
34586 - buffer_prepare_copy(b, toread + 1);
34587 + buffer_prepare_copy(b, toread + 1);
34589 if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
34590 - /* read failed */
34591 + /* read failed */
34595 @@ -755,59 +758,58 @@
34596 log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
34598 close(from_exec_fds[0]);
34613 const char *expr = NULL;
34616 for (i = 2; i < n; i += 2) {
34617 if (0 == strcmp(l[i], "expr")) {
34620 log_error_write(srv, __FILE__, __LINE__, "sss",
34621 - "ssi: unknow attribute for ",
34622 + "ssi: unknow attribute for ",
34629 log_error_write(srv, __FILE__, __LINE__, "sss",
34632 l[1], "expr missing");
34637 if ((!p->if_is_false) &&
34638 - ((p->if_is_false_level == 0) ||
34639 + ((p->if_is_false_level == 0) ||
34640 (p->if_level < p->if_is_false_level))) {
34641 switch (ssi_eval_expr(srv, con, p, expr)) {
34644 - p->if_is_false = 1;
34646 + p->if_is_false = 1;
34647 p->if_is_false_level = p->if_level;
34650 - p->if_is_false = 0;
34652 + p->if_is_false = 0;
34667 if (p->if_is_false) {
34668 if ((p->if_level == p->if_is_false_level) &&
34669 (p->if_is_false_endif == 0)) {
34670 @@ -815,11 +817,11 @@
34673 p->if_is_false = 1;
34676 p->if_is_false_level = p->if_level;
34683 const char *expr = NULL;
34684 @@ -828,52 +830,52 @@
34687 log_error_write(srv, __FILE__, __LINE__, "sss",
34688 - "ssi: unknow attribute for ",
34689 + "ssi: unknow attribute for ",
34696 log_error_write(srv, __FILE__, __LINE__, "sss",
34699 l[1], "expr missing");
34707 if (p->if_level == p->if_is_false_level) {
34708 if ((p->if_is_false) &&
34709 (p->if_is_false_endif == 0)) {
34710 switch (ssi_eval_expr(srv, con, p, expr)) {
34713 - p->if_is_false = 1;
34715 + p->if_is_false = 1;
34716 p->if_is_false_level = p->if_level;
34719 - p->if_is_false = 0;
34721 + p->if_is_false = 0;
34725 - p->if_is_false = 1;
34726 + p->if_is_false = 1;
34727 p->if_is_false_level = p->if_level;
34728 p->if_is_false_endif = 1;
34742 if (p->if_level == p->if_is_false_level) {
34743 p->if_is_false = 0;
34744 p->if_is_false_endif = 0;
34750 log_error_write(srv, __FILE__, __LINE__, "ss",
34751 @@ -881,41 +883,41 @@
34762 static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
34773 /* get a stream to the file */
34776 array_reset(p->ssi_vars);
34777 array_reset(p->ssi_cgi_env);
34778 buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z");
34780 build_ssi_cgi_vars(srv, con, p);
34781 p->if_is_false = 0;
34784 if (-1 == stream_open(&s, con->physical.path)) {
34785 log_error_write(srv, __FILE__, __LINE__, "sb",
34786 "stream-open: ", con->physical.path);
34794 - * <!--#element attribute=value attribute=value ... -->
34796 + * <!--#element attribute=value attribute=value ... -->
34799 - * errmsg -- missing
34800 + * errmsg -- missing
34804 @@ -937,13 +939,13 @@
34821 @@ -951,118 +953,115 @@
34833 - * The current date in Greenwich Mean Time.
34835 - * The current date in the local time zone.
34837 - * The filename (excluding directories) of the document requested by the user.
34839 - * 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.
34841 - * The last modification date of the document requested by the user.
34844 + * The current date in Greenwich Mean Time.
34846 + * The current date in the local time zone.
34848 + * The filename (excluding directories) of the document requested by the user.
34850 + * 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.
34852 + * The last modification date of the document requested by the user.
34854 * Contains the owner of the file which included it.
34858 -#ifdef HAVE_PCRE_H
34859 +#ifdef HAVE_PCRE_H
34860 for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
34862 /* take everything from last offset to current match pos */
34865 if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
34868 pcre_get_substring_list(s.start, ovec, n, &l);
34869 process_ssi_stmt(srv, con, p, l, n);
34870 pcre_free_substring_list(l);
34875 case PCRE_ERROR_NOMATCH:
34876 /* copy everything/the rest */
34877 chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
34882 log_error_write(srv, __FILE__, __LINE__, "sd",
34883 "execution error while matching: ", n);
34895 con->file_started = 1;
34896 con->file_finished = 1;
34899 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
34902 /* reset physical.path */
34903 buffer_reset(con->physical.path);
34909 -#define PATCH(x) \
34910 - p->conf.x = s->x;
34911 static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
34913 plugin_config *s = p->config_storage[0];
34915 - PATCH(ssi_extension);
34918 + PATCH_OPTION(ssi_extension);
34920 /* skip the first, the global context */
34921 for (i = 1; i < srv->config_context->used; i++) {
34922 data_config *dc = (data_config *)srv->config_context->data[i];
34923 s = p->config_storage[i];
34926 /* condition didn't match */
34927 if (!config_check_cond(srv, con, dc)) continue;
34931 for (j = 0; j < dc->value->used; j++) {
34932 data_unset *du = dc->value->data[j];
34935 if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
34936 - PATCH(ssi_extension);
34937 + PATCH_OPTION(ssi_extension);
34947 URIHANDLER_FUNC(mod_ssi_physical_path) {
34948 plugin_data *p = p_d;
34952 if (con->physical.path->used == 0) return HANDLER_GO_ON;
34955 mod_ssi_patch_connection(srv, con, p);
34958 for (k = 0; k < p->conf.ssi_extension->used; k++) {
34959 data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
34962 if (ds->value->used == 0) continue;
34965 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
34966 /* handle ssi-request */
34969 if (mod_ssi_handle_request(srv, con, p)) {
34971 con->http_status = 500;
34975 return HANDLER_FINISHED;
34981 return HANDLER_GO_ON;
34983 @@ -1072,13 +1071,13 @@
34984 int mod_ssi_plugin_init(plugin *p) {
34985 p->version = LIGHTTPD_VERSION_ID;
34986 p->name = buffer_init_string("ssi");
34989 p->init = mod_ssi_init;
34990 p->handle_subrequest_start = mod_ssi_physical_path;
34991 p->set_defaults = mod_ssi_set_defaults;
34992 p->cleanup = mod_ssi_free;
35000 --- ../lighttpd-1.4.11/src/mod_ssi.h 2005-08-11 01:26:39.000000000 +0300
35001 +++ lighttpd-1.4.12/src/mod_ssi.h 2006-07-11 22:07:53.000000000 +0300
35002 @@ -19,23 +19,23 @@
35007 -#ifdef HAVE_PCRE_H
35009 +#ifdef HAVE_PCRE_H
35021 array *ssi_cgi_env;
35024 int if_level, if_is_false_level, if_is_false, if_is_false_endif;
35027 plugin_config **config_storage;
35029 - plugin_config conf;
35031 + plugin_config conf;
35034 int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
35035 --- ../lighttpd-1.4.11/src/mod_ssi_expr.c 2005-08-11 01:26:48.000000000 +0300
35036 +++ lighttpd-1.4.12/src/mod_ssi_expr.c 2006-07-11 22:07:52.000000000 +0300
35049 @@ -21,15 +21,15 @@
35051 ssi_val_t *ssi_val_init() {
35055 s = calloc(1, sizeof(*s));
35061 void ssi_val_free(ssi_val_t *s) {
35062 if (s->str) buffer_free(s->str);
35068 @@ -45,175 +45,175 @@
35069 ssi_tokenizer_t *t, int *token_id, buffer *token) {
35076 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
35077 char c = t->input[t->offset];
35091 buffer_copy_string(token, "(=)");
35096 if (t->input[t->offset + 1] == '=') {
35104 buffer_copy_string(token, "(>=)");
35113 buffer_copy_string(token, "(>)");
35119 if (t->input[t->offset + 1] == '=') {
35127 buffer_copy_string(token, "(<=)");
35136 buffer_copy_string(token, "(<)");
35144 if (t->input[t->offset + 1] == '=') {
35152 buffer_copy_string(token, "(!=)");
35161 buffer_copy_string(token, "(!)");
35167 if (t->input[t->offset + 1] == '&') {
35175 buffer_copy_string(token, "(&&)");
35177 - log_error_write(srv, __FILE__, __LINE__, "sds",
35178 - "pos:", t->line_pos,
35179 + log_error_write(srv, __FILE__, __LINE__, "sds",
35180 + "pos:", t->line_pos,
35181 "missing second &");
35188 if (t->input[t->offset + 1] == '|') {
35196 buffer_copy_string(token, "(||)");
35198 - log_error_write(srv, __FILE__, __LINE__, "sds",
35199 - "pos:", t->line_pos,
35200 + log_error_write(srv, __FILE__, __LINE__, "sds",
35201 + "pos:", t->line_pos,
35202 "missing second |");
35216 /* search for the terminating " */
35217 for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
35220 if (t->input[t->offset + i]) {
35224 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35227 t->offset += i + 1;
35228 t->line_pos += i + 1;
35232 - log_error_write(srv, __FILE__, __LINE__, "sds",
35233 - "pos:", t->line_pos,
35235 + log_error_write(srv, __FILE__, __LINE__, "sds",
35236 + "pos:", t->line_pos,
35237 "missing closing quote");
35253 buffer_copy_string(token, "(");
35263 buffer_copy_string(token, ")");
35266 if (t->input[t->offset + 1] == '{') {
35267 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
35270 if (t->input[t->offset + i] != '}') {
35271 - log_error_write(srv, __FILE__, __LINE__, "sds",
35272 - "pos:", t->line_pos,
35273 + log_error_write(srv, __FILE__, __LINE__, "sds",
35274 + "pos:", t->line_pos,
35275 "missing closing quote");
35282 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
35284 for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_'; i++);
35287 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35294 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
35295 buffer_copy_string_buffer(token, ds->value);
35296 } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
35297 @@ -221,16 +221,16 @@
35299 buffer_copy_string(token, "");
35309 for (i = 0; isgraph(t->input[t->offset + i]); i++) {
35310 char d = t->input[t->offset + i];
35317 @@ -244,25 +244,25 @@
35326 buffer_copy_string_len(token, t->input + t->offset, i);
35343 } else if (t->offset < t->size) {
35344 - log_error_write(srv, __FILE__, __LINE__, "sds",
35345 - "pos:", t->line_pos,
35346 + log_error_write(srv, __FILE__, __LINE__, "sds",
35347 + "pos:", t->line_pos,
35351 @@ -275,50 +275,50 @@
35359 t.size = strlen(expr);
35372 /* default context */
35375 pParser = ssiexprparserAlloc( malloc );
35376 token = buffer_init();
35377 while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
35378 ssiexprparser(pParser, token_id, token, &context);
35381 token = buffer_init();
35383 ssiexprparser(pParser, 0, token, &context);
35384 ssiexprparserFree(pParser, free );
35387 buffer_free(token);
35391 - log_error_write(srv, __FILE__, __LINE__, "s",
35392 + log_error_write(srv, __FILE__, __LINE__, "s",
35393 "expr parser failed");
35398 if (context.ok == 0) {
35399 - log_error_write(srv, __FILE__, __LINE__, "sds",
35400 - "pos:", t.line_pos,
35401 + log_error_write(srv, __FILE__, __LINE__, "sds",
35402 + "pos:", t.line_pos,
35403 "parser failed somehow near here");
35407 - log_error_write(srv, __FILE__, __LINE__, "ssd",
35408 + log_error_write(srv, __FILE__, __LINE__, "ssd",
35414 return context.val.bo;
35416 --- ../lighttpd-1.4.11/src/mod_ssi_expr.h 2005-08-11 01:26:48.000000000 +0300
35417 +++ lighttpd-1.4.12/src/mod_ssi_expr.h 2006-07-11 22:07:52.000000000 +0300
35421 enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
35438 --- ../lighttpd-1.4.11/src/mod_ssi_exprparser.c 2005-10-03 00:40:25.000000000 +0300
35439 +++ lighttpd-1.4.12/src/mod_ssi_exprparser.c 2006-07-11 22:08:02.000000000 +0300
35440 @@ -18,10 +18,10 @@
35441 /* Next is all token values, in a form suitable for use by makeheaders.
35442 ** This section will be null unless lemon is run with the -m switch.
35446 ** These constants (all generated automatically by the parser generator)
35447 ** specify the various kinds of tokens (terminals) that the parser
35451 ** Each symbol here is a terminal symbol in the grammar.
35454 ** and nonterminals. "int" is used otherwise.
35455 ** YYNOCODE is a number of type YYCODETYPE which corresponds
35456 ** to no legal terminal or nonterminal number. This
35457 -** number is used to fill in empty slots of the hash
35458 +** number is used to fill in empty slots of the hash
35460 ** YYFALLBACK If defined, this indicates that one or more tokens
35461 ** have fall-back values which should be used if the
35463 ** and nonterminal numbers. "unsigned char" is
35464 ** used if there are fewer than 250 rules and
35465 ** states combined. "int" is used otherwise.
35466 -** ssiexprparserTOKENTYPE is the data type used for minor tokens given
35467 +** ssiexprparserTOKENTYPE is the data type used for minor tokens given
35468 ** directly to the parser from the tokenizer.
35469 ** YYMINORTYPE is the data type used for all minor tokens.
35470 ** This is typically a union of many types, one of
35472 /* Next are that tables used to determine what action to take based on the
35473 ** current state and lookahead token. These tables are used to implement
35474 ** functions that take a state number and lookahead value and return an
35475 -** action integer.
35476 +** action integer.
35478 ** Suppose the action integer is N. Then the action is determined as
35480 @@ -116,7 +116,7 @@
35481 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
35482 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
35483 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
35484 -** and that yy_default[S] should be used instead.
35485 +** and that yy_default[S] should be used instead.
35487 ** The formula above is for computing the action when the lookahead is
35488 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
35489 @@ -168,7 +168,7 @@
35491 /* The next table maps tokens into fallback tokens. If a construct
35492 ** like the following:
35495 ** %fallback ID X Y Z.
35497 ** appears in the grammer, then ID becomes a fallback token for X, Y,
35498 @@ -219,10 +219,10 @@
35499 #endif /* NDEBUG */
35504 ** Turn parser tracing on by giving a stream to which to write the trace
35505 ** and a prompt to preface each trace message. Tracing is turned off
35506 -** by making either argument NULL
35507 +** by making either argument NULL
35511 @@ -247,7 +247,7 @@
35513 /* For tracing shifts, the names of all terminals and nonterminals
35514 ** are required. The following table supplies these names */
35515 -static const char *yyTokenName[] = {
35516 +static const char *yyTokenName[] = {
35517 "$", "AND", "OR", "EQ",
35518 "NE", "GT", "GE", "LT",
35519 "LE", "NOT", "LPARAN", "RPARAN",
35520 @@ -295,7 +295,7 @@
35526 ** This function allocates a new parser.
35527 ** The only argument is a pointer to a function which works like
35529 @@ -326,7 +326,7 @@
35530 /* Here is inserted the actions which take place when a
35531 ** terminal or non-terminal is destroyed. This can happen
35532 ** when the symbol is popped from the stack during a
35533 - ** reduce or during error processing or when a parser is
35534 + ** reduce or during error processing or when a parser is
35535 ** being destroyed before it is finished parsing.
35537 ** Note: during a reduce, the only symbols destroyed are those
35538 @@ -379,7 +379,7 @@
35544 ** Deallocate and destroy a parser. Destructors are all called for
35545 ** all stack elements before shutting the parser down.
35547 @@ -415,7 +415,7 @@
35550 int stateno = pParser->yystack[pParser->yyidx].stateno;
35553 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
35554 i = yy_shift_ofst[stateno];
35555 if( i==YY_SHIFT_USE_DFLT ){
35556 @@ -459,7 +459,7 @@
35559 int stateno = pParser->yystack[pParser->yyidx].stateno;
35562 i = yy_reduce_ofst[stateno];
35563 if( i==YY_REDUCE_USE_DFLT ){
35564 return yy_default[stateno];
35565 @@ -559,7 +559,7 @@
35566 ssiexprparserARG_FETCH;
35567 yymsp = &yypParser->yystack[yypParser->yyidx];
35569 - if( yyTraceFILE && yyruleno>=0
35570 + if( yyTraceFILE && yyruleno>=0
35571 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
35572 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
35573 yyRuleName[yyruleno]);
35574 @@ -872,7 +872,7 @@
35575 #ifdef YYERRORSYMBOL
35576 /* A syntax error has occurred.
35577 ** The response to an error depends upon whether or not the
35578 - ** grammar defines an error token "ERROR".
35579 + ** grammar defines an error token "ERROR".
35581 ** This is what we do if the grammar does define ERROR:
35583 --- ../lighttpd-1.4.11/src/mod_staticfile.c 2006-02-15 14:31:14.000000000 +0200
35584 +++ lighttpd-1.4.12/src/mod_staticfile.c 2006-07-11 22:07:51.000000000 +0300
35586 #include "http_chunk.h"
35587 #include "response.h"
35589 +#include "sys-files.h"
35590 +#include "sys-strings.h"
35592 * this is a staticfile for a lighttpd plugin
35598 @@ -29,48 +31,48 @@
35607 plugin_config **config_storage;
35609 - plugin_config conf;
35611 + plugin_config conf;
35614 /* init the plugin data */
35615 INIT_FUNC(mod_staticfile_init) {
35619 p = calloc(1, sizeof(*p));
35622 p->range_buf = buffer_init();
35628 -/* detroy the plugin data */
35629 +/* destroy the plugin data */
35630 FREE_FUNC(mod_staticfile_free) {
35631 plugin_data *p = p_d;
35636 if (!p) return HANDLER_GO_ON;
35639 if (p->config_storage) {
35641 for (i = 0; i < srv->config_context->used; i++) {
35642 plugin_config *s = p->config_storage[i];
35645 array_free(s->exclude_ext);
35650 free(p->config_storage);
35652 buffer_free(p->range_buf);
35658 return HANDLER_GO_ON;
35661 @@ -79,63 +81,60 @@
35662 SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
35663 plugin_data *p = p_d;
35666 - config_values_t cv[] = {
35668 + config_values_t cv[] = {
35669 { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
35670 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
35674 if (!p) return HANDLER_ERROR;
35677 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
35680 for (i = 0; i < srv->config_context->used; i++) {
35684 s = calloc(1, sizeof(plugin_config));
35685 s->exclude_ext = array_init();
35688 cv[0].destination = s->exclude_ext;
35691 p->config_storage[i] = s;
35694 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
35695 return HANDLER_ERROR;
35700 return HANDLER_GO_ON;
35703 -#define PATCH(x) \
35704 - p->conf.x = s->x;
35705 static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
35707 plugin_config *s = p->config_storage[0];
35709 - PATCH(exclude_ext);
35712 + PATCH_OPTION(exclude_ext);
35714 /* skip the first, the global context */
35715 for (i = 1; i < srv->config_context->used; i++) {
35716 data_config *dc = (data_config *)srv->config_context->data[i];
35717 s = p->config_storage[i];
35720 /* condition didn't match */
35721 if (!config_check_cond(srv, con, dc)) continue;
35725 for (j = 0; j < dc->value->used; j++) {
35726 data_unset *du = dc->value->data[j];
35729 if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
35730 - PATCH(exclude_ext);
35731 + PATCH_OPTION(exclude_ext);
35741 static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
35743 @@ -146,69 +145,69 @@
35745 stat_cache_entry *sce = NULL;
35746 buffer *content_type = NULL;
35749 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35755 end = sce->st.st_size - 1;
35758 con->response.content_length = 0;
35761 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
35762 content_type = ds->value;
35766 for (s = con->request.http_range, error = 0;
35767 !error && *s && NULL != (minus = strchr(s, '-')); ) {
35776 le = strtoll(s, &err, 10);
35780 /* RFC 2616 - 14.35.1 */
35783 con->http_status = 416;
35785 } else if (*err == '\0') {
35790 end = sce->st.st_size - 1;
35791 start = sce->st.st_size + le;
35792 } else if (*err == ',') {
35797 end = sce->st.st_size - 1;
35798 start = sce->st.st_size + le;
35804 } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
35808 la = strtoll(s, &err, 10);
35811 if (err == minus) {
35815 if (*(err + 1) == '\0') {
35819 end = sce->st.st_size - 1;
35823 } else if (*(err + 1) == ',') {
35828 end = sce->st.st_size - 1;
35831 @@ -220,64 +219,64 @@
35834 /* <start>-<stop> */
35837 la = strtoll(s, &err, 10);
35840 if (err == minus) {
35841 le = strtoll(minus+1, &err, 10);
35844 /* RFC 2616 - 14.35.1 */
35850 if (*err == '\0') {
35857 } else if (*err == ',') {
35880 if (start < 0) start = 0;
35883 /* RFC 2616 - 14.35.1 */
35884 if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
35887 if (start > sce->st.st_size - 1) {
35891 con->http_status = 416;
35898 /* write boundary-header */
35902 b = chunkqueue_get_append_buffer(con->write_queue);
35905 buffer_copy_string(b, "\r\n--");
35906 buffer_append_string(b, boundary);
35909 /* write Content-Range */
35910 buffer_append_string(b, "\r\nContent-Range: bytes ");
35911 buffer_append_off_t(b, start);
35912 @@ -285,54 +284,54 @@
35913 buffer_append_off_t(b, end);
35914 buffer_append_string(b, "/");
35915 buffer_append_off_t(b, sce->st.st_size);
35918 buffer_append_string(b, "\r\nContent-Type: ");
35919 buffer_append_string_buffer(b, content_type);
35922 /* write END-OF-HEADER */
35923 buffer_append_string(b, "\r\n\r\n");
35926 con->response.content_length += b->used - 1;
35932 chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
35933 con->response.content_length += end - start + 1;
35938 /* something went wrong */
35939 if (error) return -1;
35943 /* add boundary end */
35947 b = chunkqueue_get_append_buffer(con->write_queue);
35950 buffer_copy_string_len(b, "\r\n--", 4);
35951 buffer_append_string(b, boundary);
35952 buffer_append_string_len(b, "--\r\n", 4);
35955 con->response.content_length += b->used - 1;
35958 /* set header-fields */
35961 buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
35962 buffer_append_string(p->range_buf, boundary);
35965 /* overwrite content-type */
35966 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
35968 /* add Content-Range-header */
35971 buffer_copy_string(p->range_buf, "bytes ");
35972 buffer_append_off_t(p->range_buf, start);
35973 buffer_append_string(p->range_buf, "-");
35974 buffer_append_off_t(p->range_buf, end);
35975 buffer_append_string(p->range_buf, "/");
35976 buffer_append_off_t(p->range_buf, sce->st.st_size);
35979 response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
35982 @@ -347,12 +346,12 @@
35983 stat_cache_entry *sce = NULL;
35988 /* someone else has done a decision for us */
35989 if (con->http_status != 0) return HANDLER_GO_ON;
35990 if (con->uri.path->used == 0) return HANDLER_GO_ON;
35991 if (con->physical.path->used == 0) return HANDLER_GO_ON;
35994 /* someone else has handled this request */
35995 if (con->mode != DIRECT) return HANDLER_GO_ON;
35997 @@ -365,52 +364,52 @@
35999 return HANDLER_GO_ON;
36003 mod_staticfile_patch_connection(srv, con, p);
36006 s_len = con->uri.path->used - 1;
36009 /* ignore certain extensions */
36010 for (k = 0; k < p->conf.exclude_ext->used; k++) {
36011 - ds = (data_string *)p->conf.exclude_ext->data[k];
36013 + ds = (data_string *)p->conf.exclude_ext->data[k];
36015 if (ds->value->used == 0) continue;
36017 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
36018 return HANDLER_GO_ON;
36024 if (con->conf.log_request_handling) {
36025 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling file as static file");
36029 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
36030 con->http_status = 403;
36033 log_error_write(srv, __FILE__, __LINE__, "sbsb",
36034 "not a regular file:", con->uri.path,
36035 "->", con->physical.path);
36038 return HANDLER_FINISHED;
36041 - /* we only handline regular files */
36043 + /* we only handle regular files */
36044 if (!S_ISREG(sce->st.st_mode)) {
36045 con->http_status = 404;
36048 if (con->conf.log_file_not_found) {
36049 log_error_write(srv, __FILE__, __LINE__, "sbsb",
36050 "not a regular file:", con->uri.path,
36055 return HANDLER_FINISHED;
36058 - /* mod_compress might set several data directly, don't overwrite them */
36060 + /* mod_compress might set several parameters directly; don't overwrite them */
36062 /* set response content-type, if not set already */
36064 if (NULL == array_get_element(con->response.headers, "Content-Type")) {
36065 @@ -420,15 +419,15 @@
36066 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
36071 if (NULL == array_get_element(con->response.headers, "ETag")) {
36072 /* generate e-tag */
36073 etag_mutate(con->physical.etag, sce->etag);
36076 response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
36078 response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
36081 /* prepare header */
36082 if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
36083 mtime = strftime_cache_get(srv, sce->st.st_mtime);
36084 @@ -444,34 +443,34 @@
36085 /* check if we have a conditional GET */
36087 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) {
36088 - /* if the value is the same as our ETag, we do a Range-request,
36089 + /* if the value is the same as our ETag, we do a Range-request,
36090 * otherwise a full 200 */
36092 if (!buffer_is_equal(ds->value, con->physical.etag)) {
36093 do_range_request = 0;
36098 if (do_range_request) {
36099 /* content prepared, I'm done */
36100 con->file_finished = 1;
36103 if (0 == http_response_parse_range(srv, con, p)) {
36104 con->http_status = 206;
36106 return HANDLER_FINISHED;
36111 /* if we are still here, prepare body */
36113 - /* we add it here for all requests
36114 - * the HEAD request will drop it afterwards again
36116 + /* we add it here for all requests
36117 + * the HEAD request will drop it afterwards again
36119 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
36122 con->file_finished = 1;
36125 return HANDLER_FINISHED;
36128 @@ -480,13 +479,13 @@
36129 int mod_staticfile_plugin_init(plugin *p) {
36130 p->version = LIGHTTPD_VERSION_ID;
36131 p->name = buffer_init_string("staticfile");
36134 p->init = mod_staticfile_init;
36135 p->handle_subrequest_start = mod_staticfile_subrequest;
36136 p->set_defaults = mod_staticfile_set_defaults;
36137 p->cleanup = mod_staticfile_free;
36145 --- ../lighttpd-1.4.11/src/mod_status.c 2006-01-10 21:45:32.000000000 +0200
36146 +++ lighttpd-1.4.12/src/mod_status.c 2006-07-11 22:07:53.000000000 +0300
36149 #include <stdlib.h>
36150 #include <string.h>
36151 -#include <unistd.h>
36155 @@ -29,114 +28,114 @@
36161 double traffic_out;
36165 double mod_5s_traffic_out[5];
36166 double mod_5s_requests[5];
36170 double rel_traffic_out;
36171 double rel_requests;
36174 double abs_traffic_out;
36175 double abs_requests;
36178 double bytes_written;
36181 buffer *module_list;
36184 plugin_config **config_storage;
36186 - plugin_config conf;
36188 + plugin_config conf;
36191 INIT_FUNC(mod_status_init) {
36196 p = calloc(1, sizeof(*p));
36199 p->traffic_out = p->requests = 0;
36200 p->rel_traffic_out = p->rel_requests = 0;
36201 p->abs_traffic_out = p->abs_requests = 0;
36202 p->bytes_written = 0;
36203 p->module_list = buffer_init();
36206 for (i = 0; i < 5; i++) {
36207 p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
36214 FREE_FUNC(mod_status_free) {
36215 plugin_data *p = p_d;
36220 if (!p) return HANDLER_GO_ON;
36223 buffer_free(p->module_list);
36226 if (p->config_storage) {
36228 for (i = 0; i < srv->config_context->used; i++) {
36229 plugin_config *s = p->config_storage[i];
36232 buffer_free(s->status_url);
36233 buffer_free(s->statistics_url);
36234 buffer_free(s->config_url);
36239 free(p->config_storage);
36248 return HANDLER_GO_ON;
36251 SETDEFAULTS_FUNC(mod_status_set_defaults) {
36252 plugin_data *p = p_d;
36255 - config_values_t cv[] = {
36257 + config_values_t cv[] = {
36258 { "status.status-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36259 { "status.config-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36260 { "status.enable-sort", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
36261 { "status.statistics-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36262 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36266 if (!p) return HANDLER_ERROR;
36269 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36272 for (i = 0; i < srv->config_context->used; i++) {
36276 s = calloc(1, sizeof(plugin_config));
36277 s->config_url = buffer_init();
36278 s->status_url = buffer_init();
36280 s->statistics_url = buffer_init();
36283 cv[0].destination = s->status_url;
36284 cv[1].destination = s->config_url;
36285 cv[2].destination = &(s->sort);
36286 cv[3].destination = s->statistics_url;
36289 p->config_storage[i] = s;
36292 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36293 return HANDLER_ERROR;
36298 return HANDLER_GO_ON;
36301 @@ -151,7 +150,7 @@
36302 buffer_append_string(b, value);
36303 BUFFER_APPEND_STRING_CONST(b, "</td>\n");
36304 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
36310 @@ -161,13 +160,13 @@
36311 buffer_append_string(b, key);
36312 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36313 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
36319 static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
36320 plugin_data *p = p_d;
36323 if (p->conf.sort) {
36324 BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">");
36325 buffer_append_string(b, key);
36326 @@ -177,13 +176,13 @@
36327 buffer_append_string(b, key);
36328 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36335 static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
36339 if (*avg > size) { *avg /= size; *multiplier = 'k'; }
36340 if (*avg > size) { *avg /= size; *multiplier = 'M'; }
36341 if (*avg > size) { *avg /= size; *multiplier = 'G'; }
36342 @@ -202,21 +201,21 @@
36345 char multiplier = '\0';
36351 int days, hours, mins, seconds;
36354 b = chunkqueue_get_append_buffer(con->write_queue);
36356 - BUFFER_COPY_STRING_CONST(b,
36357 + BUFFER_COPY_STRING_CONST(b,
36358 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36359 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36360 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36361 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
36363 " <title>Status</title>\n");
36366 BUFFER_APPEND_STRING_CONST(b,
36367 " <style type=\"text/css\">\n"
36368 " table.status { border: black solid thin; }\n"
36369 @@ -226,14 +225,14 @@
36370 " a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
36371 " span.sortarrow { color: white; text-decoration: none; }\n"
36375 if (p->conf.sort) {
36376 BUFFER_APPEND_STRING_CONST(b,
36377 "<script type=\"text/javascript\">\n"
36379 "var sort_column;\n"
36380 "var prev_span = null;\n");
36383 BUFFER_APPEND_STRING_CONST(b,
36384 "function get_inner_text(el) {\n"
36385 " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
36386 @@ -251,7 +250,7 @@
36392 BUFFER_APPEND_STRING_CONST(b,
36393 "function sortfn(a,b) {\n"
36394 " var at = get_inner_text(a.cells[sort_column]);\n"
36395 @@ -266,7 +265,7 @@
36396 " else return 1;\n"
36401 BUFFER_APPEND_STRING_CONST(b,
36402 "function resort(lnk) {\n"
36403 " var span = lnk.childNodes[1];\n"
36404 @@ -276,7 +275,7 @@
36405 " rows[j-1] = table.rows[j];\n"
36406 " sort_column = lnk.parentNode.cellIndex;\n"
36407 " rows.sort(sortfn);\n");
36410 BUFFER_APPEND_STRING_CONST(b,
36411 " if (prev_span != null) prev_span.innerHTML = '';\n"
36412 " if (span.getAttribute('sortdir')=='down') {\n"
36413 @@ -294,175 +293,175 @@
36418 - BUFFER_APPEND_STRING_CONST(b,
36420 + BUFFER_APPEND_STRING_CONST(b,
36429 /* connection listing */
36430 BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
36432 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
36433 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
36435 + BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
36436 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
36437 buffer_append_string_buffer(b, con->uri.authority);
36438 - BUFFER_APPEND_STRING_CONST(b, " (");
36439 + BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
36440 buffer_append_string_buffer(b, con->server_name);
36441 - BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
36442 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
36444 + BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
36445 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
36447 ts = srv->cur_ts - srv->startup_ts;
36450 days = ts / (60 * 60 * 24);
36451 ts %= (60 * 60 * 24);
36454 hours = ts / (60 * 60);
36466 buffer_append_long(b, days);
36467 BUFFER_APPEND_STRING_CONST(b, " days ");
36472 buffer_append_long(b, hours);
36473 BUFFER_APPEND_STRING_CONST(b, " hours ");
36478 buffer_append_long(b, mins);
36479 BUFFER_APPEND_STRING_CONST(b, " min ");
36483 buffer_append_long(b, seconds);
36484 BUFFER_APPEND_STRING_CONST(b, " s");
36487 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36488 BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
36491 ts = srv->startup_ts;
36493 - strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
36495 + strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
36496 buffer_append_string(b, buf);
36497 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36502 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
36504 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36506 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
36507 avg = p->abs_requests;
36509 mod_status_get_multiplier(&avg, &multiplier, 1000);
36512 buffer_append_long(b, avg);
36513 - BUFFER_APPEND_STRING_CONST(b, " ");
36514 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
36515 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36516 - BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
36518 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36519 + BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
36521 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
36522 avg = p->abs_traffic_out;
36524 mod_status_get_multiplier(&avg, &multiplier, 1024);
36526 sprintf(buf, "%.2f", avg);
36527 buffer_append_string(b, buf);
36528 - BUFFER_APPEND_STRING_CONST(b, " ");
36529 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_mult\">");
36530 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36531 - BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
36532 + BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
36536 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
36538 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36540 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
36541 avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
36543 mod_status_get_multiplier(&avg, &multiplier, 1000);
36545 buffer_append_long(b, avg);
36546 - BUFFER_APPEND_STRING_CONST(b, " ");
36547 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
36548 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36549 - BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36551 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36552 + BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36554 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
36555 avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
36557 mod_status_get_multiplier(&avg, &multiplier, 1024);
36559 sprintf(buf, "%.2f", avg);
36560 buffer_append_string(b, buf);
36561 - BUFFER_APPEND_STRING_CONST(b, " ");
36562 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
36563 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36564 - BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36565 + BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36571 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n");
36572 for (j = 0, avg = 0; j < 5; j++) {
36573 avg += p->mod_5s_requests[j];
36579 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36581 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
36583 mod_status_get_multiplier(&avg, &multiplier, 1000);
36585 buffer_append_long(b, avg);
36586 - BUFFER_APPEND_STRING_CONST(b, " ");
36587 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
36588 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36590 - BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36593 + BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36595 for (j = 0, avg = 0; j < 5; j++) {
36596 avg += p->mod_5s_traffic_out[j];
36602 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36604 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
36606 mod_status_get_multiplier(&avg, &multiplier, 1024);
36608 sprintf(buf, "%.2f", avg);
36609 buffer_append_string(b, buf);
36610 - BUFFER_APPEND_STRING_CONST(b, " ");
36611 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
36612 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36613 - BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36615 + BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36617 BUFFER_APPEND_STRING_CONST(b, "</table>\n");
36622 BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n");
36623 BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n");
36624 BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n");
36625 BUFFER_APPEND_STRING_CONST(b, "q = request-start, Q = request-end\n");
36626 BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
36628 - BUFFER_APPEND_STRING_CONST(b, "<b>");
36630 + BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
36631 buffer_append_long(b, srv->conns->used);
36632 - BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
36634 + BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
36636 for (j = 0; j < srv->conns->used; j++) {
36637 connection *c = srv->conns->ptr[j];
36638 const char *state = connection_get_short_state(c->state);
36641 buffer_append_string_len(b, state, 1);
36644 if (((j + 1) % 50) == 0) {
36645 BUFFER_APPEND_STRING_CONST(b, "\n");
36650 BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
36652 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
36654 + BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
36655 BUFFER_APPEND_STRING_CONST(b, "<tr>");
36656 mod_status_header_append_sort(b, p_d, "Client IP");
36657 mod_status_header_append_sort(b, p_d, "Read");
36658 @@ -473,16 +472,16 @@
36659 mod_status_header_append_sort(b, p_d, "URI");
36660 mod_status_header_append_sort(b, p_d, "File");
36661 BUFFER_APPEND_STRING_CONST(b, "</tr>\n");
36664 for (j = 0; j < srv->conns->used; j++) {
36665 connection *c = srv->conns->ptr[j];
36667 - BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
36670 + BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
36672 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
36674 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36677 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
36679 if (con->request.content_length) {
36680 buffer_append_long(b, c->request_content_queue->bytes_in);
36681 BUFFER_APPEND_STRING_CONST(b, "/");
36682 @@ -490,55 +489,55 @@
36684 BUFFER_APPEND_STRING_CONST(b, "0/0");
36687 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36690 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
36692 buffer_append_off_t(b, chunkqueue_written(c->write_queue));
36693 BUFFER_APPEND_STRING_CONST(b, "/");
36694 buffer_append_off_t(b, chunkqueue_length(c->write_queue));
36696 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36699 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
36701 buffer_append_string(b, connection_get_state(c->state));
36703 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36706 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
36708 buffer_append_long(b, srv->cur_ts - c->request_start);
36710 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36713 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
36715 if (buffer_is_empty(c->server_name)) {
36716 buffer_append_string_buffer(b, c->uri.authority);
36719 buffer_append_string_buffer(b, c->server_name);
36722 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36725 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
36727 if (!buffer_is_empty(c->uri.path)) {
36728 buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
36731 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36734 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
36736 buffer_append_string_buffer(b, c->physical.path);
36739 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36743 - BUFFER_APPEND_STRING_CONST(b,
36746 + BUFFER_APPEND_STRING_CONST(b,
36750 - BUFFER_APPEND_STRING_CONST(b,
36753 + BUFFER_APPEND_STRING_CONST(b,
36759 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36765 @@ -548,7 +547,7 @@
36771 b = chunkqueue_get_append_buffer(con->write_queue);
36773 /* output total number of requests */
36774 @@ -556,19 +555,19 @@
36775 avg = p->abs_requests;
36776 buffer_append_long(b, avg);
36777 BUFFER_APPEND_STRING_CONST(b, "\n");
36780 /* output total traffic out in kbytes */
36781 BUFFER_APPEND_STRING_CONST(b, "Total kBytes: ");
36782 avg = p->abs_traffic_out / 1024;
36783 buffer_append_long(b, avg);
36784 BUFFER_APPEND_STRING_CONST(b, "\n");
36787 /* output uptime */
36788 BUFFER_APPEND_STRING_CONST(b, "Uptime: ");
36789 ts = srv->cur_ts - srv->startup_ts;
36790 buffer_append_long(b, ts);
36791 BUFFER_APPEND_STRING_CONST(b, "\n");
36794 /* output busy servers */
36795 BUFFER_APPEND_STRING_CONST(b, "BusyServers: ");
36796 buffer_append_long(b, srv->conns->used);
36797 @@ -577,7 +576,7 @@
36798 /* set text/plain output */
36800 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36806 @@ -591,10 +590,10 @@
36807 /* we have nothing to send */
36808 con->http_status = 204;
36809 con->file_finished = 1;
36812 return HANDLER_FINISHED;
36816 b = chunkqueue_get_append_buffer(con->write_queue);
36818 for (i = 0; i < st->used; i++) {
36819 @@ -605,27 +604,27 @@
36820 buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
36821 buffer_append_string(b, "\n");
36825 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36828 con->http_status = 200;
36829 con->file_finished = 1;
36832 return HANDLER_FINISHED;
36836 static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
36839 if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
36840 mod_status_handle_server_status_text(srv, con, p_d);
36842 mod_status_handle_server_status_html(srv, con, p_d);
36846 con->http_status = 200;
36847 con->file_finished = 1;
36850 return HANDLER_FINISHED;
36853 @@ -634,9 +633,9 @@
36854 plugin_data *p = p_d;
36855 buffer *b, *m = p->module_list;
36858 - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36861 + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36863 /* - poll is most reliable
36864 * - select works everywhere
36865 * - linux-* are experimental
36866 @@ -661,10 +660,10 @@
36868 { FDEVENT_HANDLER_UNSET, NULL }
36872 b = chunkqueue_get_append_buffer(con->write_queue);
36874 - BUFFER_COPY_STRING_CONST(b,
36876 + BUFFER_COPY_STRING_CONST(b,
36877 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36878 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36879 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36880 @@ -675,7 +674,7 @@
36882 " <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
36883 " <table border=\"1\">\n");
36886 mod_status_header_append(b, "Server-Features");
36888 mod_status_row_append(b, "RegEx Conditionals", "enabled");
36889 @@ -683,21 +682,21 @@
36890 mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
36892 mod_status_header_append(b, "Network Engine");
36895 for (i = 0; event_handlers[i].name; i++) {
36896 if (event_handlers[i].et == srv->event_handler) {
36897 mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
36903 mod_status_header_append(b, "Config-File-Settings");
36906 for (i = 0; i < srv->plugins.used; i++) {
36907 plugin **ps = srv->plugins.ptr;
36910 plugin *pl = ps[i];
36914 buffer_copy_string_buffer(m, pl->name);
36916 @@ -705,137 +704,135 @@
36917 buffer_append_string_buffer(m, pl->name);
36922 mod_status_row_append(b, "Loaded Modules", m->ptr);
36925 BUFFER_APPEND_STRING_CONST(b, " </table>\n");
36927 - BUFFER_APPEND_STRING_CONST(b,
36929 + BUFFER_APPEND_STRING_CONST(b,
36935 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36938 con->http_status = 200;
36939 con->file_finished = 1;
36942 return HANDLER_FINISHED;
36945 -#define PATCH(x) \
36946 - p->conf.x = s->x;
36947 static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
36949 plugin_config *s = p->config_storage[0];
36951 - PATCH(status_url);
36952 - PATCH(config_url);
36954 - PATCH(statistics_url);
36957 + PATCH_OPTION(status_url);
36958 + PATCH_OPTION(config_url);
36959 + PATCH_OPTION(sort);
36960 + PATCH_OPTION(statistics_url);
36962 /* skip the first, the global context */
36963 for (i = 1; i < srv->config_context->used; i++) {
36964 data_config *dc = (data_config *)srv->config_context->data[i];
36965 s = p->config_storage[i];
36968 /* condition didn't match */
36969 if (!config_check_cond(srv, con, dc)) continue;
36973 for (j = 0; j < dc->value->used; j++) {
36974 data_unset *du = dc->value->data[j];
36977 if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
36978 - PATCH(status_url);
36979 + PATCH_OPTION(status_url);
36980 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
36981 - PATCH(config_url);
36982 + PATCH_OPTION(config_url);
36983 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
36985 + PATCH_OPTION(sort);
36986 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
36987 - PATCH(statistics_url);
36989 + PATCH_OPTION(statistics_url);
36998 static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
36999 plugin_data *p = p_d;
37002 mod_status_patch_connection(srv, con, p);
37004 - if (!buffer_is_empty(p->conf.status_url) &&
37006 + if (!buffer_is_empty(p->conf.status_url) &&
37007 buffer_is_equal(p->conf.status_url, con->uri.path)) {
37008 return mod_status_handle_server_status(srv, con, p_d);
37009 - } else if (!buffer_is_empty(p->conf.config_url) &&
37010 + } else if (!buffer_is_empty(p->conf.config_url) &&
37011 buffer_is_equal(p->conf.config_url, con->uri.path)) {
37012 return mod_status_handle_server_config(srv, con, p_d);
37013 - } else if (!buffer_is_empty(p->conf.statistics_url) &&
37014 + } else if (!buffer_is_empty(p->conf.statistics_url) &&
37015 buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
37016 return mod_status_handle_server_statistics(srv, con, p_d);
37020 return HANDLER_GO_ON;
37023 TRIGGER_FUNC(mod_status_trigger) {
37024 plugin_data *p = p_d;
37028 /* check all connections */
37029 for (i = 0; i < srv->conns->used; i++) {
37030 connection *c = srv->conns->ptr[i];
37033 p->bytes_written += c->bytes_written_cur_second;
37037 /* a sliding average */
37038 p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
37039 p->mod_5s_requests [p->mod_5s_ndx] = p->requests;
37042 p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
37045 p->abs_traffic_out += p->bytes_written;
37046 p->rel_traffic_out += p->bytes_written;
37049 p->bytes_written = 0;
37052 /* reset storage - second */
37053 p->traffic_out = 0;
37057 return HANDLER_GO_ON;
37060 REQUESTDONE_FUNC(mod_status_account) {
37061 plugin_data *p = p_d;
37071 p->bytes_written += con->bytes_written_cur_second;
37074 return HANDLER_GO_ON;
37077 int mod_status_plugin_init(plugin *p) {
37078 p->version = LIGHTTPD_VERSION_ID;
37079 p->name = buffer_init_string("status");
37082 p->init = mod_status_init;
37083 p->cleanup = mod_status_free;
37084 p->set_defaults= mod_status_set_defaults;
37087 p->handle_uri_clean = mod_status_handler;
37088 p->handle_trigger = mod_status_trigger;
37089 p->handle_request_done = mod_status_account;
37097 --- ../lighttpd-1.4.11/src/mod_trigger_b4_dl.c 2005-09-23 22:53:55.000000000 +0300
37098 +++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c 2006-07-11 22:07:51.000000000 +0300
37099 @@ -24,18 +24,18 @@
37102 * this is a trigger_b4_dl for a lighttpd plugin
37107 /* plugin config for all request/connections */
37110 buffer *db_filename;
37113 buffer *trigger_url;
37114 buffer *download_url;
37119 buffer *mc_namespace;
37120 #if defined(HAVE_PCRE_H)
37121 @@ -46,58 +46,58 @@
37125 -#if defined(HAVE_MEMCACHE_H)
37126 +#if defined(HAVE_MEMCACHE_H)
37127 struct memcache *mc;
37131 unsigned short trigger_timeout;
37132 unsigned short debug;
37142 plugin_config **config_storage;
37144 - plugin_config conf;
37146 + plugin_config conf;
37149 /* init the plugin data */
37150 INIT_FUNC(mod_trigger_b4_dl_init) {
37154 p = calloc(1, sizeof(*p));
37157 p->tmp_buf = buffer_init();
37163 /* detroy the plugin data */
37164 FREE_FUNC(mod_trigger_b4_dl_free) {
37165 plugin_data *p = p_d;
37170 if (!p) return HANDLER_GO_ON;
37173 if (p->config_storage) {
37175 for (i = 0; i < srv->config_context->used; i++) {
37176 plugin_config *s = p->config_storage[i];
37181 buffer_free(s->db_filename);
37182 buffer_free(s->download_url);
37183 buffer_free(s->trigger_url);
37184 buffer_free(s->deny_url);
37187 buffer_free(s->mc_namespace);
37188 array_free(s->mc_hosts);
37191 #if defined(HAVE_PCRE_H)
37192 if (s->trigger_regex) pcre_free(s->trigger_regex);
37193 if (s->download_regex) pcre_free(s->download_regex);
37194 @@ -108,16 +108,16 @@
37195 #if defined(HAVE_MEMCACHE_H)
37196 if (s->mc) mc_free(s->mc);
37202 free(p->config_storage);
37206 buffer_free(p->tmp_buf);
37212 return HANDLER_GO_ON;
37215 @@ -126,9 +126,9 @@
37216 SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
37217 plugin_data *p = p_d;
37221 - config_values_t cv[] = {
37224 + config_values_t cv[] = {
37225 { "trigger-before-download.gdbm-filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
37226 { "trigger-before-download.trigger-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
37227 { "trigger-before-download.download-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
37228 @@ -139,18 +139,18 @@
37229 { "trigger-before-download.debug", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
37230 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37234 if (!p) return HANDLER_ERROR;
37237 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37240 for (i = 0; i < srv->config_context->used; i++) {
37242 #if defined(HAVE_PCRE_H)
37243 const char *errptr;
37248 s = calloc(1, sizeof(plugin_config));
37249 s->db_filename = buffer_init();
37250 s->download_url = buffer_init();
37251 @@ -158,7 +158,7 @@
37252 s->deny_url = buffer_init();
37253 s->mc_hosts = array_init();
37254 s->mc_namespace = buffer_init();
37257 cv[0].destination = s->db_filename;
37258 cv[1].destination = s->trigger_url;
37259 cv[2].destination = s->download_url;
37260 @@ -167,41 +167,41 @@
37261 cv[5].destination = s->mc_hosts;
37262 cv[6].destination = s->mc_namespace;
37263 cv[7].destination = &(s->debug);
37266 p->config_storage[i] = s;
37269 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37270 return HANDLER_ERROR;
37272 #if defined(HAVE_GDBM_H)
37273 if (!buffer_is_empty(s->db_filename)) {
37274 if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
37275 - log_error_write(srv, __FILE__, __LINE__, "s",
37276 + log_error_write(srv, __FILE__, __LINE__, "s",
37277 "gdbm-open failed");
37278 return HANDLER_ERROR;
37282 -#if defined(HAVE_PCRE_H)
37283 +#if defined(HAVE_PCRE_H)
37284 if (!buffer_is_empty(s->download_url)) {
37285 if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
37286 0, &errptr, &erroff, NULL))) {
37288 - log_error_write(srv, __FILE__, __LINE__, "sbss",
37289 - "compiling regex for download-url failed:",
37291 + log_error_write(srv, __FILE__, __LINE__, "sbss",
37292 + "compiling regex for download-url failed:",
37293 s->download_url, "pos:", erroff);
37294 return HANDLER_ERROR;
37299 if (!buffer_is_empty(s->trigger_url)) {
37300 if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
37301 0, &errptr, &erroff, NULL))) {
37303 - log_error_write(srv, __FILE__, __LINE__, "sbss",
37304 - "compiling regex for trigger-url failed:",
37306 + log_error_write(srv, __FILE__, __LINE__, "sbss",
37307 + "compiling regex for trigger-url failed:",
37308 s->trigger_url, "pos:", erroff);
37311 return HANDLER_ERROR;
37314 @@ -211,100 +211,97 @@
37315 #if defined(HAVE_MEMCACHE_H)
37320 for (k = 0; k < s->mc_hosts->used; k++) {
37321 data_string *ds = (data_string *)s->mc_hosts->data[k];
37324 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
37325 - log_error_write(srv, __FILE__, __LINE__, "sb",
37326 - "connection to host failed:",
37327 + log_error_write(srv, __FILE__, __LINE__, "sb",
37328 + "connection to host failed:",
37332 return HANDLER_ERROR;
37336 - log_error_write(srv, __FILE__, __LINE__, "s",
37337 + log_error_write(srv, __FILE__, __LINE__, "s",
37338 "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
37339 return HANDLER_ERROR;
37345 #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
37346 - log_error_write(srv, __FILE__, __LINE__, "s",
37347 + log_error_write(srv, __FILE__, __LINE__, "s",
37348 "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
37349 return HANDLER_ERROR;
37354 return HANDLER_GO_ON;
37357 -#define PATCH(x) \
37358 - p->conf.x = s->x;
37359 static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
37361 plugin_config *s = p->config_storage[0];
37364 #if defined(HAVE_GDBM)
37367 + PATCH_OPTION(db);
37369 #if defined(HAVE_PCRE_H)
37370 - PATCH(download_regex);
37371 - PATCH(trigger_regex);
37373 - PATCH(trigger_timeout);
37375 - PATCH(mc_namespace);
37377 + PATCH_OPTION(download_regex);
37378 + PATCH_OPTION(trigger_regex);
37380 + PATCH_OPTION(trigger_timeout);
37381 + PATCH_OPTION(deny_url);
37382 + PATCH_OPTION(mc_namespace);
37383 + PATCH_OPTION(debug);
37384 #if defined(HAVE_MEMCACHE_H)
37386 + PATCH_OPTION(mc);
37390 /* skip the first, the global context */
37391 for (i = 1; i < srv->config_context->used; i++) {
37392 data_config *dc = (data_config *)srv->config_context->data[i];
37393 s = p->config_storage[i];
37396 /* condition didn't match */
37397 if (!config_check_cond(srv, con, dc)) continue;
37401 for (j = 0; j < dc->value->used; j++) {
37402 data_unset *du = dc->value->data[j];
37404 if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
37405 #if defined(HAVE_PCRE_H)
37406 - PATCH(download_regex);
37407 + PATCH_OPTION(download_regex);
37409 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
37410 # if defined(HAVE_PCRE_H)
37411 - PATCH(trigger_regex);
37412 + PATCH_OPTION(trigger_regex);
37414 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
37415 #if defined(HAVE_GDBM_H)
37417 + PATCH_OPTION(db);
37419 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
37420 - PATCH(trigger_timeout);
37421 + PATCH_OPTION(trigger_timeout);
37422 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
37424 + PATCH_OPTION(debug);
37425 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
37427 + PATCH_OPTION(deny_url);
37428 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
37429 - PATCH(mc_namespace);
37430 + PATCH_OPTION(mc_namespace);
37431 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
37432 #if defined(HAVE_MEMCACHE_H)
37434 + PATCH_OPTION(mc);
37445 URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
37446 plugin_data *p = p_d;
37447 @@ -315,20 +312,20 @@
37453 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37456 mod_trigger_b4_dl_patch_connection(srv, con, p);
37459 if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
37462 # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
37463 return HANDLER_GO_ON;
37464 # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
37465 if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
37466 if (p->conf.db && p->conf.mc) {
37467 /* can't decide which one */
37470 return HANDLER_GO_ON;
37472 # elif defined(HAVE_GDBM_H)
37473 @@ -336,12 +333,12 @@
37475 if (!p->conf.mc) return HANDLER_GO_ON;
37479 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) {
37480 /* X-Forwarded-For contains the ip behind the proxy */
37483 remote_ip = ds->value->ptr;
37486 /* memcache can't handle spaces */
37488 remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
37489 @@ -350,13 +347,13 @@
37490 if (p->conf.debug) {
37491 log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
37495 /* check if URL is a trigger -> insert IP into DB */
37496 if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37497 if (n != PCRE_ERROR_NOMATCH) {
37498 log_error_write(srv, __FILE__, __LINE__, "sd",
37499 "execution error while matching:", n);
37502 return HANDLER_ERROR;
37505 @@ -364,34 +361,34 @@
37507 /* the trigger matched */
37511 key.dptr = (char *)remote_ip;
37512 key.dsize = strlen(remote_ip);
37515 val.dptr = (char *)&(srv->cur_ts);
37516 val.dsize = sizeof(srv->cur_ts);
37519 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37520 log_error_write(srv, __FILE__, __LINE__, "s",
37525 -# if defined(HAVE_MEMCACHE_H)
37526 +# if defined(HAVE_MEMCACHE_H)
37529 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37530 buffer_append_string(p->tmp_buf, remote_ip);
37533 for (i = 0; i < p->tmp_buf->used - 1; i++) {
37534 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37538 if (p->conf.debug) {
37539 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
37542 - if (0 != mc_set(p->conf.mc,
37543 + if (0 != mc_set(p->conf.mc,
37544 CONST_BUF_LEN(p->tmp_buf),
37545 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37546 p->conf.trigger_timeout, 0)) {
37547 @@ -401,7 +398,7 @@
37553 /* check if URL is a download -> check IP in DB, update timestamp */
37554 if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37555 if (n != PCRE_ERROR_NOMATCH) {
37556 @@ -411,93 +408,93 @@
37559 /* the download uri matched */
37560 -# if defined(HAVE_GDBM_H)
37561 +# if defined(HAVE_GDBM_H)
37567 key.dptr = (char *)remote_ip;
37568 key.dsize = strlen(remote_ip);
37571 val = gdbm_fetch(p->conf.db, key);
37574 if (val.dptr == NULL) {
37575 /* not found, redirect */
37578 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37581 con->http_status = 307;
37584 return HANDLER_FINISHED;
37588 last_hit = *(time_t *)(val.dptr);
37594 if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
37595 /* found, but timeout, redirect */
37598 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37599 con->http_status = 307;
37603 if (0 != gdbm_delete(p->conf.db, key)) {
37604 log_error_write(srv, __FILE__, __LINE__, "s",
37610 return HANDLER_FINISHED;
37614 val.dptr = (char *)&(srv->cur_ts);
37615 val.dsize = sizeof(srv->cur_ts);
37618 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37619 log_error_write(srv, __FILE__, __LINE__, "s",
37625 -# if defined(HAVE_MEMCACHE_H)
37627 +# if defined(HAVE_MEMCACHE_H)
37633 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37634 buffer_append_string(p->tmp_buf, remote_ip);
37637 for (i = 0; i < p->tmp_buf->used - 1; i++) {
37638 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37642 if (p->conf.debug) {
37643 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
37649 * memcached is do expiration for us, as long as we can fetch it every thing is ok
37650 - * and the timestamp is updated
37652 + * and the timestamp is updated
37655 - if (NULL == (r = mc_aget(p->conf.mc,
37656 + if (NULL == (r = mc_aget(p->conf.mc,
37657 CONST_BUF_LEN(p->tmp_buf)
37661 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37664 con->http_status = 307;
37667 return HANDLER_FINISHED;
37674 /* set a new timeout */
37675 - if (0 != mc_set(p->conf.mc,
37676 + if (0 != mc_set(p->conf.mc,
37677 CONST_BUF_LEN(p->tmp_buf),
37678 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37679 p->conf.trigger_timeout, 0)) {
37680 @@ -507,13 +504,13 @@
37693 return HANDLER_GO_ON;
37696 @@ -521,21 +518,21 @@
37697 TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
37698 plugin_data *p = p_d;
37702 /* check DB each minute */
37703 if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
37707 for (i = 0; i < srv->config_context->used; i++) {
37708 plugin_config *s = p->config_storage[i];
37709 datum key, val, okey;
37712 if (!s->db) continue;
37717 - /* according to the manual this loop + delete does delete all entries on its way
37720 + /* according to the manual this loop + delete does delete all entries on its way
37722 * we don't care as the next round will remove them. We don't have to perfect here.
37724 for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
37725 @@ -544,21 +541,21 @@
37731 val = gdbm_fetch(s->db, key);
37734 last_hit = *(time_t *)(val.dptr);
37740 if (srv->cur_ts - last_hit > s->trigger_timeout) {
37741 gdbm_delete(s->db, key);
37747 if (okey.dptr) free(okey.dptr);
37750 /* reorg once a day */
37751 if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
37753 @@ -571,7 +568,7 @@
37754 int mod_trigger_b4_dl_plugin_init(plugin *p) {
37755 p->version = LIGHTTPD_VERSION_ID;
37756 p->name = buffer_init_string("trigger_b4_dl");
37759 p->init = mod_trigger_b4_dl_init;
37760 p->handle_uri_clean = mod_trigger_b4_dl_uri_handler;
37761 p->set_defaults = mod_trigger_b4_dl_set_defaults;
37762 @@ -579,8 +576,8 @@
37763 p->handle_trigger = mod_trigger_b4_dl_handle_trigger;
37765 p->cleanup = mod_trigger_b4_dl_free;
37773 --- ../lighttpd-1.4.11/src/mod_userdir.c 2005-10-28 16:48:28.000000000 +0300
37774 +++ lighttpd-1.4.12/src/mod_userdir.c 2006-07-11 22:07:52.000000000 +0300
37776 #include "response.h"
37778 #include "plugin.h"
37779 +#include "sys-files.h"
37783 @@ -25,54 +26,54 @@
37793 plugin_config **config_storage;
37795 - plugin_config conf;
37797 + plugin_config conf;
37800 /* init the plugin data */
37801 INIT_FUNC(mod_userdir_init) {
37805 p = calloc(1, sizeof(*p));
37808 p->username = buffer_init();
37809 p->temp_path = buffer_init();
37815 /* detroy the plugin data */
37816 FREE_FUNC(mod_userdir_free) {
37817 plugin_data *p = p_d;
37820 if (!p) return HANDLER_GO_ON;
37823 if (p->config_storage) {
37827 for (i = 0; i < srv->config_context->used; i++) {
37828 plugin_config *s = p->config_storage[i];
37831 array_free(s->include_user);
37832 array_free(s->exclude_user);
37833 buffer_free(s->path);
37834 buffer_free(s->basepath);
37839 free(p->config_storage);
37843 buffer_free(p->username);
37844 buffer_free(p->temp_path);
37850 return HANDLER_GO_ON;
37853 @@ -81,81 +82,78 @@
37854 SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
37855 plugin_data *p = p_d;
37858 - config_values_t cv[] = {
37860 + config_values_t cv[] = {
37861 { "userdir.path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
37862 { "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
37863 { "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
37864 { "userdir.basepath", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
37865 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37869 if (!p) return HANDLER_ERROR;
37872 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37875 for (i = 0; i < srv->config_context->used; i++) {
37879 s = calloc(1, sizeof(plugin_config));
37880 s->exclude_user = array_init();
37881 s->include_user = array_init();
37882 s->path = buffer_init();
37883 s->basepath = buffer_init();
37886 cv[0].destination = s->path;
37887 cv[1].destination = s->exclude_user;
37888 cv[2].destination = s->include_user;
37889 cv[3].destination = s->basepath;
37892 p->config_storage[i] = s;
37895 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37896 return HANDLER_ERROR;
37901 return HANDLER_GO_ON;
37904 -#define PATCH(x) \
37905 - p->conf.x = s->x;
37906 static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
37908 plugin_config *s = p->config_storage[0];
37911 - PATCH(exclude_user);
37912 - PATCH(include_user);
37916 + PATCH_OPTION(path);
37917 + PATCH_OPTION(exclude_user);
37918 + PATCH_OPTION(include_user);
37919 + PATCH_OPTION(basepath);
37921 /* skip the first, the global context */
37922 for (i = 1; i < srv->config_context->used; i++) {
37923 data_config *dc = (data_config *)srv->config_context->data[i];
37924 s = p->config_storage[i];
37927 /* condition didn't match */
37928 if (!config_check_cond(srv, con, dc)) continue;
37932 for (j = 0; j < dc->value->used; j++) {
37933 data_unset *du = dc->value->data[j];
37936 if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
37938 + PATCH_OPTION(path);
37939 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
37940 - PATCH(exclude_user);
37941 + PATCH_OPTION(exclude_user);
37942 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
37943 - PATCH(include_user);
37944 + PATCH_OPTION(include_user);
37945 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
37947 + PATCH_OPTION(basepath);
37957 URIHANDLER_FUNC(mod_userdir_docroot_handler) {
37958 plugin_data *p = p_d;
37959 @@ -169,18 +167,18 @@
37960 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37962 mod_userdir_patch_connection(srv, con, p);
37965 uri_len = con->uri.path->used - 1;
37968 /* /~user/foo.html -> /home/user/public_html/foo.html */
37971 if (con->uri.path->ptr[0] != '/' ||
37972 con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
37975 if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
37976 /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
37977 http_response_redirect_to_directory(srv, con);
37980 return HANDLER_FINISHED;
37983 @@ -188,10 +186,10 @@
37984 if (0 == rel_url - (con->uri.path->ptr + 2)) {
37985 return HANDLER_GO_ON;
37989 buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
37991 - if (buffer_is_empty(p->conf.basepath)
37993 + if (buffer_is_empty(p->conf.basepath)
37995 && NULL == (pwd = getpwnam(p->username->ptr))
37997 @@ -200,31 +198,31 @@
37998 return HANDLER_GO_ON;
38003 for (k = 0; k < p->conf.exclude_user->used; k++) {
38004 data_string *ds = (data_string *)p->conf.exclude_user->data[k];
38007 if (buffer_is_equal(ds->value, p->username)) {
38008 /* user in exclude list */
38009 return HANDLER_GO_ON;
38014 if (p->conf.include_user->used) {
38015 int found_user = 0;
38016 for (k = 0; k < p->conf.include_user->used; k++) {
38017 data_string *ds = (data_string *)p->conf.include_user->data[k];
38020 if (buffer_is_equal(ds->value, p->username)) {
38021 /* user in include list */
38028 if (!found_user) return HANDLER_GO_ON;
38032 /* we build the physical path */
38034 if (buffer_is_empty(p->conf.basepath)) {
38035 @@ -252,23 +250,23 @@
38038 buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
38039 - BUFFER_APPEND_SLASH(p->temp_path);
38040 + PATHNAME_APPEND_SLASH(p->temp_path);
38041 buffer_append_string_buffer(p->temp_path, p->username);
38043 - BUFFER_APPEND_SLASH(p->temp_path);
38044 - buffer_append_string_buffer(p->temp_path, p->conf.path);
38045 + PATHNAME_APPEND_SLASH(p->temp_path);
38046 + buffer_append_string_buffer(p->temp_path, p->conf.path);
38048 if (buffer_is_empty(p->conf.basepath)) {
38053 ret = stat(p->temp_path->ptr, &st);
38054 if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
38055 return HANDLER_GO_ON;
38060 - BUFFER_APPEND_SLASH(p->temp_path);
38061 + PATHNAME_APPEND_SLASH(p->temp_path);
38062 buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
38063 buffer_copy_string_buffer(con->physical.path, p->temp_path);
38065 @@ -282,13 +280,13 @@
38066 int mod_userdir_plugin_init(plugin *p) {
38067 p->version = LIGHTTPD_VERSION_ID;
38068 p->name = buffer_init_string("userdir");
38071 p->init = mod_userdir_init;
38072 p->handle_physical = mod_userdir_docroot_handler;
38073 p->set_defaults = mod_userdir_set_defaults;
38074 p->cleanup = mod_userdir_free;
38082 --- ../lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200
38083 +++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-11 22:07:53.000000000 +0300
38084 @@ -24,44 +24,44 @@
38090 plugin_config **config_storage;
38092 - plugin_config conf;
38094 + plugin_config conf;
38097 /* init the plugin data */
38098 INIT_FUNC(mod_usertrack_init) {
38102 p = calloc(1, sizeof(*p));
38108 /* detroy the plugin data */
38109 FREE_FUNC(mod_usertrack_free) {
38110 plugin_data *p = p_d;
38116 if (!p) return HANDLER_GO_ON;
38119 if (p->config_storage) {
38121 for (i = 0; i < srv->config_context->used; i++) {
38122 plugin_config *s = p->config_storage[i];
38125 buffer_free(s->cookie_name);
38126 buffer_free(s->cookie_domain);
38131 free(p->config_storage);
38138 return HANDLER_GO_ON;
38141 @@ -70,38 +70,38 @@
38142 SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
38143 plugin_data *p = p_d;
38146 - config_values_t cv[] = {
38148 + config_values_t cv[] = {
38149 { "usertrack.cookie-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
38150 { "usertrack.cookie-max-age", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
38151 { "usertrack.cookie-domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
38153 - { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38155 + { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38156 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38160 if (!p) return HANDLER_ERROR;
38163 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38166 for (i = 0; i < srv->config_context->used; i++) {
38170 s = calloc(1, sizeof(plugin_config));
38171 s->cookie_name = buffer_init();
38172 s->cookie_domain = buffer_init();
38173 s->cookie_max_age = 0;
38176 cv[0].destination = s->cookie_name;
38177 cv[1].destination = &(s->cookie_max_age);
38178 cv[2].destination = s->cookie_domain;
38181 p->config_storage[i] = s;
38184 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38185 return HANDLER_ERROR;
38189 if (buffer_is_empty(s->cookie_name)) {
38190 buffer_copy_string(s->cookie_name, "TRACKID");
38192 @@ -109,68 +109,65 @@
38193 for (j = 0; j < s->cookie_name->used - 1; j++) {
38194 char c = s->cookie_name->ptr[j] | 32;
38195 if (c < 'a' || c > 'z') {
38196 - log_error_write(srv, __FILE__, __LINE__, "sb",
38197 - "invalid character in usertrack.cookie-name:",
38198 + log_error_write(srv, __FILE__, __LINE__, "sb",
38199 + "invalid character in usertrack.cookie-name:",
38203 return HANDLER_ERROR;
38209 if (!buffer_is_empty(s->cookie_domain)) {
38211 for (j = 0; j < s->cookie_domain->used - 1; j++) {
38212 char c = s->cookie_domain->ptr[j];
38213 if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
38214 - log_error_write(srv, __FILE__, __LINE__, "sb",
38215 - "invalid character in usertrack.cookie-domain:",
38216 + log_error_write(srv, __FILE__, __LINE__, "sb",
38217 + "invalid character in usertrack.cookie-domain:",
38221 return HANDLER_ERROR;
38228 return HANDLER_GO_ON;
38231 -#define PATCH(x) \
38232 - p->conf.x = s->x;
38233 static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
38235 plugin_config *s = p->config_storage[0];
38237 - PATCH(cookie_name);
38238 - PATCH(cookie_domain);
38239 - PATCH(cookie_max_age);
38242 + PATCH_OPTION(cookie_name);
38243 + PATCH_OPTION(cookie_domain);
38244 + PATCH_OPTION(cookie_max_age);
38246 /* skip the first, the global context */
38247 for (i = 1; i < srv->config_context->used; i++) {
38248 data_config *dc = (data_config *)srv->config_context->data[i];
38249 s = p->config_storage[i];
38252 /* condition didn't match */
38253 if (!config_check_cond(srv, con, dc)) continue;
38257 for (j = 0; j < dc->value->used; j++) {
38258 data_unset *du = dc->value->data[j];
38261 if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
38262 - PATCH(cookie_name);
38263 + PATCH_OPTION(cookie_name);
38264 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
38265 - PATCH(cookie_max_age);
38266 + PATCH_OPTION(cookie_max_age);
38267 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
38268 - PATCH(cookie_domain);
38269 + PATCH_OPTION(cookie_domain);
38279 URIHANDLER_FUNC(mod_usertrack_uri_handler) {
38280 plugin_data *p = p_d;
38281 @@ -178,38 +175,38 @@
38282 unsigned char h[16];
38287 if (con->uri.path->used == 0) return HANDLER_GO_ON;
38290 mod_usertrack_patch_connection(srv, con, p);
38293 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
38295 /* we have a cookie, does it contain a valid name ? */
38297 - /* parse the cookie
38300 + /* parse the cookie
38302 * check for cookiename + (WS | '=')
38308 if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
38313 for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
38317 /* ok, found the key of our own cookie */
38320 if (strlen(nc) > 32) {
38322 return HANDLER_GO_ON;
38331 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
38332 ds = data_response_init();
38333 @@ -217,39 +214,39 @@
38334 buffer_copy_string(ds->key, "Set-Cookie");
38335 buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
38336 buffer_append_string(ds->value, "=");
38340 /* taken from mod_auth.c */
38343 /* generate shared-secret */
38345 MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
38346 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
38349 /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
38350 ltostr(hh, srv->cur_ts);
38351 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38352 ltostr(hh, rand());
38353 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38356 MD5_Final(h, &Md5Ctx);
38359 buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
38360 buffer_append_string(ds->value, "; Path=/");
38361 buffer_append_string(ds->value, "; Version=1");
38364 if (!buffer_is_empty(p->conf.cookie_domain)) {
38365 buffer_append_string(ds->value, "; Domain=");
38366 buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
38370 if (p->conf.cookie_max_age) {
38371 buffer_append_string(ds->value, "; max-age=");
38372 buffer_append_long(ds->value, p->conf.cookie_max_age);
38376 array_insert_unique(con->response.headers, (data_unset *)ds);
38379 return HANDLER_GO_ON;
38382 @@ -258,13 +255,13 @@
38383 int mod_usertrack_plugin_init(plugin *p) {
38384 p->version = LIGHTTPD_VERSION_ID;
38385 p->name = buffer_init_string("usertrack");
38388 p->init = mod_usertrack_init;
38389 p->handle_uri_clean = mod_usertrack_uri_handler;
38390 p->set_defaults = mod_usertrack_set_defaults;
38391 p->cleanup = mod_usertrack_free;
38399 --- ../lighttpd-1.4.11/src/mod_webdav.c 2006-03-03 01:28:58.000000000 +0200
38400 +++ lighttpd-1.4.12/src/mod_webdav.c 2006-07-11 22:07:53.000000000 +0300
38403 #include <stdlib.h>
38404 #include <string.h>
38405 -#include <dirent.h>
38407 -#include <unistd.h>
38410 #include <assert.h>
38411 -#include <sys/mman.h>
38413 #ifdef HAVE_CONFIG_H
38414 #include "config.h"
38416 #include <sqlite3.h>
38419 +#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
38421 +#include <uuid/uuid.h>
38426 #include "buffer.h"
38427 @@ -33,13 +35,16 @@
38428 #include "stream.h"
38429 #include "stat_cache.h"
38431 +#include "sys-files.h"
38432 +#include "sys-mmap.h"
38433 +#include "sys-strings.h"
38436 * this is a webdav for a lighttpd plugin
38438 - * at least a very basic one.
38439 + * at least a very basic one.
38440 * - for now it is read-only and we only support PROPFIND
38446 @@ -58,64 +63,70 @@
38447 sqlite3_stmt *stmt_delete_prop;
38448 sqlite3_stmt *stmt_select_prop;
38449 sqlite3_stmt *stmt_select_propnames;
38452 sqlite3_stmt *stmt_delete_uri;
38453 sqlite3_stmt *stmt_move_uri;
38454 sqlite3_stmt *stmt_copy_uri;
38456 + sqlite3_stmt *stmt_remove_lock;
38457 + sqlite3_stmt *stmt_create_lock;
38458 + sqlite3_stmt *stmt_read_lock;
38459 + sqlite3_stmt *stmt_read_lock_by_uri;
38460 + sqlite3_stmt *stmt_refresh_lock;
38472 plugin_config **config_storage;
38474 - plugin_config conf;
38476 + plugin_config conf;
38479 /* init the plugin data */
38480 INIT_FUNC(mod_webdav_init) {
38484 p = calloc(1, sizeof(*p));
38487 p->tmp_buf = buffer_init();
38489 p->uri.scheme = buffer_init();
38490 p->uri.path_raw = buffer_init();
38491 p->uri.path = buffer_init();
38492 p->uri.authority = buffer_init();
38495 p->physical.path = buffer_init();
38496 p->physical.rel_path = buffer_init();
38497 p->physical.doc_root = buffer_init();
38498 p->physical.basedir = buffer_init();
38504 /* detroy the plugin data */
38505 FREE_FUNC(mod_webdav_free) {
38506 plugin_data *p = p_d;
38511 if (!p) return HANDLER_GO_ON;
38514 if (p->config_storage) {
38516 for (i = 0; i < srv->config_context->used; i++) {
38517 plugin_config *s = p->config_storage[i];
38522 buffer_free(s->sqlite_db_name);
38523 #ifdef USE_PROPPATCH
38526 sqlite3_finalize(s->stmt_delete_prop);
38527 sqlite3_finalize(s->stmt_delete_uri);
38528 sqlite3_finalize(s->stmt_copy_uri);
38529 @@ -123,9 +134,15 @@
38530 sqlite3_finalize(s->stmt_update_prop);
38531 sqlite3_finalize(s->stmt_select_prop);
38532 sqlite3_finalize(s->stmt_select_propnames);
38534 + sqlite3_finalize(s->stmt_read_lock);
38535 + sqlite3_finalize(s->stmt_read_lock_by_uri);
38536 + sqlite3_finalize(s->stmt_create_lock);
38537 + sqlite3_finalize(s->stmt_remove_lock);
38538 + sqlite3_finalize(s->stmt_refresh_lock);
38539 sqlite3_close(s->sql);
38545 free(p->config_storage);
38546 @@ -135,16 +152,16 @@
38547 buffer_free(p->uri.path_raw);
38548 buffer_free(p->uri.path);
38549 buffer_free(p->uri.authority);
38552 buffer_free(p->physical.path);
38553 buffer_free(p->physical.rel_path);
38554 buffer_free(p->physical.doc_root);
38555 buffer_free(p->physical.basedir);
38558 buffer_free(p->tmp_buf);
38564 return HANDLER_GO_ON;
38567 @@ -153,32 +170,32 @@
38568 SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
38569 plugin_data *p = p_d;
38572 - config_values_t cv[] = {
38574 + config_values_t cv[] = {
38575 { "webdav.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
38576 { "webdav.is-readonly", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
38577 { "webdav.sqlite-db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
38578 { "webdav.log-xml", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
38579 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38583 if (!p) return HANDLER_ERROR;
38586 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38589 for (i = 0; i < srv->config_context->used; i++) {
38593 s = calloc(1, sizeof(plugin_config));
38594 s->sqlite_db_name = buffer_init();
38597 cv[0].destination = &(s->enabled);
38598 cv[1].destination = &(s->is_readonly);
38599 cv[2].destination = s->sqlite_db_name;
38600 cv[3].destination = &(s->log_xml);
38603 p->config_storage[i] = s;
38606 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38607 return HANDLER_ERROR;
38609 @@ -193,8 +210,26 @@
38610 return HANDLER_ERROR;
38613 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38614 - CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38615 + if (SQLITE_OK != sqlite3_exec(s->sql,
38616 + "CREATE TABLE properties ("
38617 + " resource TEXT NOT NULL,"
38618 + " prop TEXT NOT NULL,"
38619 + " ns TEXT NOT NULL,"
38620 + " value TEXT NOT NULL,"
38621 + " PRIMARY KEY(resource, prop, ns))",
38622 + NULL, NULL, &err)) {
38624 + if (0 != strcmp(err, "table properties already exists")) {
38625 + log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38626 + sqlite3_free(err);
38628 + return HANDLER_ERROR;
38630 + sqlite3_free(err);
38633 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38634 + CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38635 &(s->stmt_select_prop), &next_stmt)) {
38636 /* prepare failed */
38638 @@ -202,8 +237,8 @@
38639 return HANDLER_ERROR;
38642 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38643 - CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
38644 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38645 + CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
38646 &(s->stmt_select_propnames), &next_stmt)) {
38647 /* prepare failed */
38649 @@ -211,16 +246,67 @@
38650 return HANDLER_ERROR;
38653 - if (SQLITE_OK != sqlite3_exec(s->sql,
38654 - "CREATE TABLE properties ("
38656 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38657 + CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
38658 + &(s->stmt_update_prop), &next_stmt)) {
38659 + /* prepare failed */
38661 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38662 + return HANDLER_ERROR;
38665 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38666 + CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38667 + &(s->stmt_delete_prop), &next_stmt)) {
38668 + /* prepare failed */
38669 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38671 + return HANDLER_ERROR;
38674 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38675 + CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
38676 + &(s->stmt_delete_uri), &next_stmt)) {
38677 + /* prepare failed */
38678 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38680 + return HANDLER_ERROR;
38683 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38684 + CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
38685 + &(s->stmt_copy_uri), &next_stmt)) {
38686 + /* prepare failed */
38687 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38689 + return HANDLER_ERROR;
38692 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38693 + CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
38694 + &(s->stmt_move_uri), &next_stmt)) {
38695 + /* prepare failed */
38696 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38698 + return HANDLER_ERROR;
38703 + if (SQLITE_OK != sqlite3_exec(s->sql,
38704 + "CREATE TABLE locks ("
38705 + " locktoken TEXT NOT NULL,"
38706 " resource TEXT NOT NULL,"
38707 - " prop TEXT NOT NULL,"
38708 - " ns TEXT NOT NULL,"
38709 - " value TEXT NOT NULL,"
38710 - " PRIMARY KEY(resource, prop, ns))",
38711 + " lockscope TEXT NOT NULL,"
38712 + " locktype TEXT NOT NULL,"
38713 + " owner TEXT NOT NULL,"
38714 + " depth INT NOT NULL,"
38715 + " timeout TIMESTAMP NOT NULL,"
38716 + " PRIMARY KEY(locktoken))",
38717 NULL, NULL, &err)) {
38719 - if (0 != strcmp(err, "table properties already exists")) {
38720 + if (0 != strcmp(err, "table locks already exists")) {
38721 log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38724 @@ -228,127 +314,138 @@
38729 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38730 - CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
38731 - &(s->stmt_update_prop), &next_stmt)) {
38733 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38734 + CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
38735 + &(s->stmt_create_lock), &next_stmt)) {
38736 /* prepare failed */
38737 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38739 - log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38740 return HANDLER_ERROR;
38743 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38744 - CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38745 - &(s->stmt_delete_prop), &next_stmt)) {
38746 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38747 + CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
38748 + &(s->stmt_remove_lock), &next_stmt)) {
38749 /* prepare failed */
38750 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38752 return HANDLER_ERROR;
38755 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38756 - CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
38757 - &(s->stmt_delete_uri), &next_stmt)) {
38758 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38759 + CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
38760 + &(s->stmt_read_lock), &next_stmt)) {
38761 /* prepare failed */
38762 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38764 return HANDLER_ERROR;
38767 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38768 - CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
38769 - &(s->stmt_copy_uri), &next_stmt)) {
38770 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38771 + CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
38772 + &(s->stmt_read_lock_by_uri), &next_stmt)) {
38773 /* prepare failed */
38774 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38776 return HANDLER_ERROR;
38779 - if (SQLITE_OK != sqlite3_prepare(s->sql,
38780 - CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
38781 - &(s->stmt_move_uri), &next_stmt)) {
38782 + if (SQLITE_OK != sqlite3_prepare(s->sql,
38783 + CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
38784 + &(s->stmt_refresh_lock), &next_stmt)) {
38785 /* prepare failed */
38786 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38788 return HANDLER_ERROR;
38793 log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
38794 return HANDLER_ERROR;
38800 return HANDLER_GO_ON;
38803 -#define PATCH(x) \
38804 - p->conf.x = s->x;
38805 static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
38807 plugin_config *s = p->config_storage[0];
38810 - PATCH(is_readonly);
38814 + PATCH_OPTION(enabled);
38815 + PATCH_OPTION(is_readonly);
38816 + PATCH_OPTION(log_xml);
38818 #ifdef USE_PROPPATCH
38820 - PATCH(stmt_update_prop);
38821 - PATCH(stmt_delete_prop);
38822 - PATCH(stmt_select_prop);
38823 - PATCH(stmt_select_propnames);
38825 - PATCH(stmt_delete_uri);
38826 - PATCH(stmt_move_uri);
38827 - PATCH(stmt_copy_uri);
38828 + PATCH_OPTION(sql);
38829 + PATCH_OPTION(stmt_update_prop);
38830 + PATCH_OPTION(stmt_delete_prop);
38831 + PATCH_OPTION(stmt_select_prop);
38832 + PATCH_OPTION(stmt_select_propnames);
38834 + PATCH_OPTION(stmt_delete_uri);
38835 + PATCH_OPTION(stmt_move_uri);
38836 + PATCH_OPTION(stmt_copy_uri);
38838 + PATCH_OPTION(stmt_remove_lock);
38839 + PATCH_OPTION(stmt_refresh_lock);
38840 + PATCH_OPTION(stmt_create_lock);
38841 + PATCH_OPTION(stmt_read_lock);
38842 + PATCH_OPTION(stmt_read_lock_by_uri);
38844 /* skip the first, the global context */
38845 for (i = 1; i < srv->config_context->used; i++) {
38846 data_config *dc = (data_config *)srv->config_context->data[i];
38847 s = p->config_storage[i];
38850 /* condition didn't match */
38851 if (!config_check_cond(srv, con, dc)) continue;
38855 for (j = 0; j < dc->value->used; j++) {
38856 data_unset *du = dc->value->data[j];
38859 if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
38861 + PATCH_OPTION(enabled);
38862 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
38863 - PATCH(is_readonly);
38864 + PATCH_OPTION(is_readonly);
38865 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
38867 + PATCH_OPTION(log_xml);
38868 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
38869 #ifdef USE_PROPPATCH
38871 - PATCH(stmt_update_prop);
38872 - PATCH(stmt_delete_prop);
38873 - PATCH(stmt_select_prop);
38874 - PATCH(stmt_select_propnames);
38876 - PATCH(stmt_delete_uri);
38877 - PATCH(stmt_move_uri);
38878 - PATCH(stmt_copy_uri);
38879 + PATCH_OPTION(sql);
38880 + PATCH_OPTION(stmt_update_prop);
38881 + PATCH_OPTION(stmt_delete_prop);
38882 + PATCH_OPTION(stmt_select_prop);
38883 + PATCH_OPTION(stmt_select_propnames);
38885 + PATCH_OPTION(stmt_delete_uri);
38886 + PATCH_OPTION(stmt_move_uri);
38887 + PATCH_OPTION(stmt_copy_uri);
38889 + PATCH_OPTION(stmt_remove_lock);
38890 + PATCH_OPTION(stmt_refresh_lock);
38891 + PATCH_OPTION(stmt_create_lock);
38892 + PATCH_OPTION(stmt_read_lock);
38893 + PATCH_OPTION(stmt_read_lock_by_uri);
38904 URIHANDLER_FUNC(mod_webdav_uri_handler) {
38905 plugin_data *p = p_d;
38910 if (con->uri.path->used == 0) return HANDLER_GO_ON;
38913 mod_webdav_patch_connection(srv, con, p);
38915 if (!p->conf.enabled) return HANDLER_GO_ON;
38916 @@ -362,20 +459,20 @@
38917 if (p->conf.is_readonly) {
38918 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
38920 - response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
38921 + response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
38930 return HANDLER_GO_ON;
38932 -static int webdav_gen_prop_tag(server *srv, connection *con,
38936 +static int webdav_gen_prop_tag(server *srv, connection *con,
38943 @@ -414,7 +511,7 @@
38944 buffer_append_string_buffer(b, dst->rel_path);
38945 buffer_append_string(b,"</D:href>\n");
38946 buffer_append_string(b,"<D:status>\n");
38949 if (con->request.http_version == HTTP_VERSION_1_1) {
38950 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
38952 @@ -458,11 +555,11 @@
38954 /* bind the values to the insert */
38956 - sqlite3_bind_text(stmt, 1,
38957 - dst->rel_path->ptr,
38958 + sqlite3_bind_text(stmt, 1,
38959 + dst->rel_path->ptr,
38960 dst->rel_path->used - 1,
38964 if (SQLITE_DONE != sqlite3_step(stmt)) {
38967 @@ -493,14 +590,14 @@
38968 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38970 /* ignore the parent dir */
38974 buffer_copy_string_buffer(d.path, dst->path);
38975 - BUFFER_APPEND_SLASH(d.path);
38976 + PATHNAME_APPEND_SLASH(d.path);
38977 buffer_append_string(d.path, de->d_name);
38980 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
38981 - BUFFER_APPEND_SLASH(d.rel_path);
38982 + PATHNAME_APPEND_SLASH(d.rel_path);
38983 buffer_append_string(d.rel_path, de->d_name);
38985 /* stat and unlink afterwards */
38986 @@ -508,7 +605,7 @@
38987 /* don't about it yet, rmdir will fail too */
38988 } else if (S_ISDIR(st.st_mode)) {
38989 have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
38992 /* try to unlink it */
38993 if (-1 == rmdir(d.path->ptr)) {
38995 @@ -535,11 +632,11 @@
38997 /* bind the values to the insert */
38999 - sqlite3_bind_text(stmt, 1,
39001 + sqlite3_bind_text(stmt, 1,
39003 d.rel_path->used - 1,
39007 if (SQLITE_DONE != sqlite3_step(stmt)) {
39010 @@ -569,7 +666,7 @@
39011 if (stream_open(&s, src->path)) {
39016 if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) {
39017 /* opening the destination failed for some reason */
39019 @@ -601,7 +698,7 @@
39028 @@ -614,16 +711,16 @@
39029 sqlite3_reset(stmt);
39031 /* bind the values to the insert */
39032 - sqlite3_bind_text(stmt, 1,
39033 - dst->rel_path->ptr,
39034 + sqlite3_bind_text(stmt, 1,
39035 + dst->rel_path->ptr,
39036 dst->rel_path->used - 1,
39039 - sqlite3_bind_text(stmt, 2,
39040 - src->rel_path->ptr,
39041 + sqlite3_bind_text(stmt, 2,
39042 + src->rel_path->ptr,
39043 src->rel_path->used - 1,
39047 if (SQLITE_DONE != sqlite3_step(stmt)) {
39050 @@ -655,21 +752,21 @@
39051 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
39056 buffer_copy_string_buffer(s.path, src->path);
39057 - BUFFER_APPEND_SLASH(s.path);
39058 + PATHNAME_APPEND_SLASH(s.path);
39059 buffer_append_string(s.path, de->d_name);
39061 buffer_copy_string_buffer(d.path, dst->path);
39062 - BUFFER_APPEND_SLASH(d.path);
39063 + PATHNAME_APPEND_SLASH(d.path);
39064 buffer_append_string(d.path, de->d_name);
39066 buffer_copy_string_buffer(s.rel_path, src->rel_path);
39067 - BUFFER_APPEND_SLASH(s.rel_path);
39068 + PATHNAME_APPEND_SLASH(s.rel_path);
39069 buffer_append_string(s.rel_path, de->d_name);
39071 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39072 - BUFFER_APPEND_SLASH(d.rel_path);
39073 + PATHNAME_APPEND_SLASH(d.rel_path);
39074 buffer_append_string(d.rel_path, de->d_name);
39076 if (-1 == stat(s.path->ptr, &st)) {
39077 @@ -692,16 +789,16 @@
39078 sqlite3_reset(stmt);
39080 /* bind the values to the insert */
39081 - sqlite3_bind_text(stmt, 1,
39082 - dst->rel_path->ptr,
39083 + sqlite3_bind_text(stmt, 1,
39084 + dst->rel_path->ptr,
39085 dst->rel_path->used - 1,
39088 - sqlite3_bind_text(stmt, 2,
39089 - src->rel_path->ptr,
39090 + sqlite3_bind_text(stmt, 2,
39091 + src->rel_path->ptr,
39092 src->rel_path->used - 1,
39096 if (SQLITE_DONE != sqlite3_step(stmt)) {
39099 @@ -721,7 +818,7 @@
39100 buffer_free(s.rel_path);
39101 buffer_free(d.path);
39102 buffer_free(d.rel_path);
39108 @@ -748,12 +845,12 @@
39109 if (S_ISDIR(sce->st.st_mode)) {
39110 buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
39112 - } else if(S_ISREG(sce->st.st_mode)) {
39113 + } else if(S_ISREG(sce->st.st_mode)) {
39114 for (k = 0; k < con->conf.mimetypes->used; k++) {
39115 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
39118 if (ds->key->used == 0) continue;
39121 if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
39122 buffer_append_string(b,"<D:getcontenttype>");
39123 buffer_append_string_buffer(b, ds->value);
39124 @@ -807,23 +904,23 @@
39126 /* bind the values to the insert */
39128 - sqlite3_bind_text(stmt, 1,
39129 - dst->rel_path->ptr,
39130 + sqlite3_bind_text(stmt, 1,
39131 + dst->rel_path->ptr,
39132 dst->rel_path->used - 1,
39134 - sqlite3_bind_text(stmt, 2,
39135 + sqlite3_bind_text(stmt, 2,
39139 - sqlite3_bind_text(stmt, 3,
39140 + sqlite3_bind_text(stmt, 3,
39146 - while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
39147 + while (SQLITE_ROW == sqlite3_step(stmt)) {
39148 /* there is a row for us, we only expect a single col 'value' */
39149 - webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
39150 + webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
39154 @@ -840,7 +937,7 @@
39158 -webdav_property live_properties[] = {
39159 +webdav_property live_properties[] = {
39160 { "DAV:", "creationdate" },
39161 { "DAV:", "displayname" },
39162 { "DAV:", "getcontentlanguage" },
39163 @@ -871,8 +968,8 @@
39164 webdav_property *prop;
39166 prop = props->ptr[i];
39168 - if (0 != webdav_get_property(srv, con, p,
39170 + if (0 != webdav_get_property(srv, con, p,
39171 dst, prop->prop, prop->ns, b_200)) {
39172 webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
39174 @@ -916,12 +1013,12 @@
39175 if (-1 == c->file.fd && /* open the file if not already open */
39176 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39177 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39184 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39185 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39186 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39187 strerror(errno), c->file.name, c->file.fd);
39190 @@ -938,7 +1035,7 @@
39191 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
39192 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39196 c->offset += weHave;
39197 cq->bytes_out += weHave;
39199 @@ -956,7 +1053,7 @@
39200 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
39201 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39205 c->offset += weHave;
39206 cq->bytes_out += weHave;
39208 @@ -991,6 +1088,113 @@
39212 +int webdav_lockdiscovery(server *srv, connection *con,
39213 + buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
39217 + response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
39219 + response_header_overwrite(srv, con,
39220 + CONST_STR_LEN("Content-Type"),
39221 + CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39223 + b = chunkqueue_get_append_buffer(con->write_queue);
39225 + buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39227 + buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39228 + buffer_append_string(b,"<D:lockdiscovery>\n");
39229 + buffer_append_string(b,"<D:activelock>\n");
39231 + buffer_append_string(b,"<D:lockscope>");
39232 + buffer_append_string(b,"<D:");
39233 + buffer_append_string(b, lockscope);
39234 + buffer_append_string(b, "/>");
39235 + buffer_append_string(b,"</D:lockscope>\n");
39237 + buffer_append_string(b,"<D:locktype>");
39238 + buffer_append_string(b,"<D:");
39239 + buffer_append_string(b, locktype);
39240 + buffer_append_string(b, "/>");
39241 + buffer_append_string(b,"</D:locktype>\n");
39243 + buffer_append_string(b,"<D:depth>");
39244 + buffer_append_string(b, depth == 0 ? "0" : "infinity");
39245 + buffer_append_string(b,"</D:depth>\n");
39247 + buffer_append_string(b,"<D:timeout>");
39248 + buffer_append_string(b, "Second-600");
39249 + buffer_append_string(b,"</D:timeout>\n");
39251 + buffer_append_string(b,"<D:owner>");
39252 + buffer_append_string(b,"</D:owner>\n");
39254 + buffer_append_string(b,"<D:locktoken>");
39255 + buffer_append_string(b, "<D:href>");
39256 + buffer_append_string_buffer(b, locktoken);
39257 + buffer_append_string(b, "</D:href>");
39258 + buffer_append_string(b,"</D:locktoken>\n");
39260 + buffer_append_string(b,"</D:activelock>\n");
39261 + buffer_append_string(b,"</D:lockdiscovery>\n");
39262 + buffer_append_string(b,"</D:prop>\n");
39267 + * check if resource is having the right locks to access to resource
39272 +int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
39273 + int has_lock = 1;
39283 + * there is NOT, AND and OR
39284 + * and a list can be tagged
39286 + * (<lock-token>) is untagged
39287 + * <tag> (<lock-token>) is tagged
39289 + * as long as we don't handle collections it is simple. :)
39291 + * X-Litmus: locks: 11 (owner_modify)
39292 + * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
39294 + * X-Litmus: locks: 16 (fail_cond_put)
39295 + * If: (<DAV:no-lock> ["-1622396671"])
39297 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39299 + /* we didn't provided a lock-token -> */
39300 + /* if the resource is locked -> 423 */
39302 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39304 + sqlite3_reset(stmt);
39306 + sqlite3_bind_text(stmt, 1,
39307 + CONST_BUF_LEN(uri),
39308 + SQLITE_TRANSIENT);
39310 + while (SQLITE_ROW == sqlite3_step(stmt)) {
39319 URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
39320 plugin_data *p = p_d;
39322 @@ -1001,7 +1205,8 @@
39325 webdav_properties *req_props;
39327 + stat_cache_entry *sce = NULL;
39331 if (!p->conf.enabled) return HANDLER_GO_ON;
39332 @@ -1019,7 +1224,19 @@
39335 /* is there a content-body ? */
39338 + switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
39339 + case HANDLER_ERROR:
39340 + if (errno == ENOENT) {
39341 + con->http_status = 404;
39342 + return HANDLER_FINISHED;
39350 #ifdef USE_PROPPATCH
39351 /* any special requests or just allprop ? */
39352 if (con->request.content_length) {
39353 @@ -1087,12 +1304,12 @@
39354 /* get all property names (EMPTY) */
39355 sqlite3_reset(stmt);
39356 /* bind the values to the insert */
39358 - sqlite3_bind_text(stmt, 1,
39359 - con->uri.path->ptr,
39361 + sqlite3_bind_text(stmt, 1,
39362 + con->uri.path->ptr,
39363 con->uri.path->used - 1,
39367 if (SQLITE_DONE != sqlite3_step(stmt)) {
39370 @@ -1115,13 +1332,13 @@
39371 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39373 b = chunkqueue_get_append_buffer(con->write_queue);
39376 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39378 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39383 prop_200 = buffer_init();
39384 prop_404 = buffer_init();
39386 @@ -1129,7 +1346,7 @@
39389 webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
39392 buffer_append_string(b,"<D:response>\n");
39393 buffer_append_string(b,"<D:href>");
39394 buffer_append_string_buffer(b, con->uri.scheme);
39395 @@ -1145,9 +1362,9 @@
39396 buffer_append_string_buffer(b, prop_200);
39398 buffer_append_string(b,"</D:prop>\n");
39401 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39404 buffer_append_string(b,"</D:propstat>\n");
39406 if (!buffer_is_empty(prop_404)) {
39407 @@ -1157,16 +1374,16 @@
39408 buffer_append_string_buffer(b, prop_404);
39410 buffer_append_string(b,"</D:prop>\n");
39413 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39416 buffer_append_string(b,"</D:propstat>\n");
39419 buffer_append_string(b,"</D:response>\n");
39424 if (NULL != (dir = opendir(con->physical.path->ptr))) {
39427 @@ -1179,16 +1396,16 @@
39428 if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
39430 /* ignore the parent dir */
39434 buffer_copy_string_buffer(d.path, dst->path);
39435 - BUFFER_APPEND_SLASH(d.path);
39436 + PATHNAME_APPEND_SLASH(d.path);
39438 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39439 - BUFFER_APPEND_SLASH(d.rel_path);
39440 + PATHNAME_APPEND_SLASH(d.rel_path);
39442 if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
39443 - /* don't append the . */
39444 + /* don't append the . */
39446 buffer_append_string(d.path, de->d_name);
39447 buffer_append_string(d.rel_path, de->d_name);
39448 @@ -1198,7 +1415,7 @@
39449 buffer_reset(prop_404);
39451 webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
39454 buffer_append_string(b,"<D:response>\n");
39455 buffer_append_string(b,"<D:href>");
39456 buffer_append_string_buffer(b, con->uri.scheme);
39457 @@ -1214,9 +1431,9 @@
39458 buffer_append_string_buffer(b, prop_200);
39460 buffer_append_string(b,"</D:prop>\n");
39463 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39466 buffer_append_string(b,"</D:propstat>\n");
39468 if (!buffer_is_empty(prop_404)) {
39469 @@ -1226,9 +1443,9 @@
39470 buffer_append_string_buffer(b, prop_404);
39472 buffer_append_string(b,"</D:prop>\n");
39475 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39478 buffer_append_string(b,"</D:propstat>\n");
39481 @@ -1275,7 +1492,7 @@
39483 return HANDLER_FINISHED;
39487 /* let's create the directory */
39489 if (-1 == mkdir(con->physical.path->ptr, 0700)) {
39490 @@ -1303,7 +1520,13 @@
39491 con->http_status = 403;
39492 return HANDLER_FINISHED;
39496 + /* does the client have a lock for this connection ? */
39497 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39498 + con->http_status = 423;
39499 + return HANDLER_FINISHED;
39502 /* stat and unlink afterwards */
39503 if (-1 == stat(con->physical.path->ptr, &st)) {
39504 /* don't about it yet, unlink will fail too */
39505 @@ -1323,7 +1546,7 @@
39506 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39508 b = chunkqueue_get_append_buffer(con->write_queue);
39511 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39513 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
39514 @@ -1331,7 +1554,7 @@
39515 buffer_append_string_buffer(b, multi_status_resp);
39517 buffer_append_string(b,"</D:multistatus>\n");
39520 if (p->conf.log_xml) {
39521 log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
39523 @@ -1340,7 +1563,7 @@
39524 con->file_finished = 1;
39526 /* everything went fine, remove the directory */
39529 if (-1 == rmdir(con->physical.path->ptr)) {
39532 @@ -1375,97 +1598,174 @@
39533 case HTTP_METHOD_PUT: {
39535 chunkqueue *cq = con->request_content_queue;
39537 + data_string *ds_range;
39539 if (p->conf.is_readonly) {
39540 con->http_status = 403;
39541 return HANDLER_FINISHED;
39544 + /* is a exclusive lock set on the source */
39545 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39546 + con->http_status = 423;
39547 + return HANDLER_FINISHED;
39551 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
39553 - /* taken what we have in the request-body and write it to a file */
39554 - if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
39555 - /* we can't open the file */
39556 - con->http_status = 403;
39559 + /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
39560 + * - most important Content-Range
39563 + * Example: Content-Range: bytes 100-1037/1038 */
39565 - con->http_status = 201; /* created */
39566 - con->file_finished = 1;
39567 + if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
39568 + const char *num = ds_range->value->ptr;
39570 + char *err = NULL;
39572 - for (c = cq->first; c; c = cq->first) {
39574 + if (0 != strncmp(num, "bytes ", 6)) {
39575 + con->http_status = 501; /* not implemented */
39577 - /* copy all chunks */
39578 - switch(c->type) {
39581 - if (c->file.mmap.start == MAP_FAILED) {
39582 - if (-1 == c->file.fd && /* open the file if not already open */
39583 - -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39584 - log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39589 - if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39590 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39591 - strerror(errno), c->file.name, c->file.fd);
39592 + return HANDLER_FINISHED;
39597 + /* we only support <num>- ... */
39599 - c->file.mmap.length = c->file.length;
39602 - close(c->file.fd);
39605 - /* chunk_reset() or chunk_free() will cleanup for us */
39608 - if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39611 - con->http_status = 507;
39615 - con->http_status = 403;
39621 - if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39624 - con->http_status = 507;
39628 - con->http_status = 403;
39633 + while (*num == ' ' || *num == '\t') num++;
39635 + if (*num == '\0') {
39636 + con->http_status = 501; /* not implemented */
39638 + return HANDLER_FINISHED;
39641 + offset = strtoll(num, &err, 10);
39643 + if (*err != '-' || offset < 0) {
39644 + con->http_status = 501; /* not implemented */
39646 + return HANDLER_FINISHED;
39649 + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
39652 + con->http_status = 404; /* not found */
39654 - case UNUSED_CHUNK:
39656 + con->http_status = 403; /* not found */
39659 + return HANDLER_FINISHED;
39662 + if (-1 == lseek(fd, offset, SEEK_SET)) {
39663 + con->http_status = 501; /* not implemented */
39667 + return HANDLER_FINISHED;
39669 + con->http_status = 200; /* modified */
39671 + /* take what we have in the request-body and write it to a file */
39673 + /* if the file doesn't exist, create it */
39674 + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
39675 + if (errno == ENOENT &&
39676 + -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
39677 + /* we can't open the file */
39678 + con->http_status = 403;
39682 - cq->bytes_out += r;
39683 + return HANDLER_FINISHED;
39686 + con->http_status = 201; /* created */
39689 + con->http_status = 200; /* modified */
39693 + con->file_finished = 1;
39695 + for (c = cq->first; c; c = cq->first) {
39698 + /* copy all chunks */
39699 + switch(c->type) {
39702 + if (c->file.mmap.start == MAP_FAILED) {
39703 + if (-1 == c->file.fd && /* open the file if not already open */
39704 + -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39705 + log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39710 + if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39711 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39712 + strerror(errno), c->file.name, c->file.fd);
39717 + c->file.mmap.length = c->file.length;
39719 + close(c->file.fd);
39722 + /* chunk_reset() or chunk_free() will cleanup for us */
39725 + if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39728 + con->http_status = 507;
39732 + con->http_status = 403;
39736 - chunkqueue_remove_finished_chunks(cq);
39739 + if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39742 + con->http_status = 507;
39746 + con->http_status = 403;
39751 + case UNUSED_CHUNK:
39758 + cq->bytes_out += r;
39762 + chunkqueue_remove_finished_chunks(cq);
39766 return HANDLER_FINISHED;
39768 - case HTTP_METHOD_MOVE:
39769 + case HTTP_METHOD_MOVE:
39770 case HTTP_METHOD_COPY: {
39771 buffer *destination = NULL;
39773 @@ -1475,7 +1775,15 @@
39774 con->http_status = 403;
39775 return HANDLER_FINISHED;
39779 + /* is a exclusive lock set on the source */
39780 + if (con->request.http_method == HTTP_METHOD_MOVE) {
39781 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39782 + con->http_status = 423;
39783 + return HANDLER_FINISHED;
39787 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
39788 destination = ds->value;
39790 @@ -1549,10 +1857,10 @@
39793 buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
39794 - BUFFER_APPEND_SLASH(p->physical.path);
39795 + PATHNAME_APPEND_SLASH(p->physical.path);
39796 buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
39798 - /* don't add a second / */
39799 + /* don't add a second / */
39800 if (p->physical.rel_path->ptr[0] == '/') {
39801 buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
39803 @@ -1613,6 +1921,12 @@
39804 /* it is just a file, good */
39807 + /* does the client have a lock for this connection ? */
39808 + if (!webdav_has_lock(srv, con, p, p->uri.path)) {
39809 + con->http_status = 423;
39810 + return HANDLER_FINISHED;
39813 /* destination exists */
39814 if (0 == (r = stat(p->physical.path->ptr, &st))) {
39815 if (S_ISDIR(st.st_mode)) {
39816 @@ -1636,7 +1950,7 @@
39817 return HANDLER_FINISHED;
39819 } else if (overwrite == 0) {
39820 - /* destination exists, but overwrite is not set */
39821 + /* destination exists, but overwrite is not set */
39822 con->http_status = 412;
39823 return HANDLER_FINISHED;
39825 @@ -1655,16 +1969,16 @@
39826 sqlite3_reset(stmt);
39828 /* bind the values to the insert */
39829 - sqlite3_bind_text(stmt, 1,
39830 - p->uri.path->ptr,
39831 + sqlite3_bind_text(stmt, 1,
39832 + p->uri.path->ptr,
39833 p->uri.path->used - 1,
39836 - sqlite3_bind_text(stmt, 2,
39837 - con->uri.path->ptr,
39838 + sqlite3_bind_text(stmt, 2,
39839 + con->uri.path->ptr,
39840 con->uri.path->used - 1,
39844 if (SQLITE_DONE != sqlite3_step(stmt)) {
39845 log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
39847 @@ -1691,12 +2005,17 @@
39849 return HANDLER_FINISHED;
39851 - case HTTP_METHOD_PROPPATCH: {
39852 + case HTTP_METHOD_PROPPATCH:
39853 if (p->conf.is_readonly) {
39854 con->http_status = 403;
39855 return HANDLER_FINISHED;
39858 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39859 + con->http_status = 423;
39860 + return HANDLER_FINISHED;
39863 /* check if destination exists */
39864 if (-1 == stat(con->physical.path->ptr, &st)) {
39866 @@ -1737,7 +2056,7 @@
39868 sqlite3_stmt *stmt;
39870 - stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
39871 + stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
39872 p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
39874 for (props = cmd->children; props; props = props->next) {
39875 @@ -1762,34 +2081,35 @@
39877 /* bind the values to the insert */
39879 - sqlite3_bind_text(stmt, 1,
39880 - con->uri.path->ptr,
39881 + sqlite3_bind_text(stmt, 1,
39882 + con->uri.path->ptr,
39883 con->uri.path->used - 1,
39885 - sqlite3_bind_text(stmt, 2,
39886 + sqlite3_bind_text(stmt, 2,
39887 (char *)prop->name,
39888 strlen((char *)prop->name),
39891 - sqlite3_bind_text(stmt, 3,
39892 + sqlite3_bind_text(stmt, 3,
39893 (char *)prop->ns->href,
39894 strlen((char *)prop->ns->href),
39897 - sqlite3_bind_text(stmt, 3,
39898 + sqlite3_bind_text(stmt, 3,
39903 if (stmt == p->conf.stmt_update_prop) {
39904 - sqlite3_bind_text(stmt, 4,
39905 + sqlite3_bind_text(stmt, 4,
39906 (char *)xmlNodeGetContent(prop),
39907 strlen((char *)xmlNodeGetContent(prop)),
39912 if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
39913 - log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39914 + log_error_write(srv, __FILE__, __LINE__, "ss",
39915 + "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39919 @@ -1804,7 +2124,7 @@
39921 goto propmatch_cleanup;
39925 con->http_status = 400;
39927 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
39928 @@ -1821,6 +2141,7 @@
39935 con->http_status = 400;
39936 @@ -1830,11 +2151,307 @@
39938 con->http_status = 501;
39939 return HANDLER_FINISHED;
39941 + case HTTP_METHOD_LOCK:
39943 + * a mac wants to write
39945 + * LOCK /dav/expire.txt HTTP/1.1\r\n
39946 + * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
39947 + * Accept: * / *\r\n
39949 + * Timeout: Second-600\r\n
39950 + * Content-Type: text/xml; charset=\"utf-8\"\r\n
39951 + * Content-Length: 229\r\n
39952 + * Connection: keep-alive\r\n
39953 + * Host: 192.168.178.23:1025\r\n
39955 + * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
39956 + * <D:lockinfo xmlns:D=\"DAV:\">\n
39957 + * <D:lockscope><D:exclusive/></D:lockscope>\n
39958 + * <D:locktype><D:write/></D:locktype>\n
39960 + * <D:href>http://www.apple.com/webdav_fs/</D:href>\n
39962 + * </D:lockinfo>\n
39965 + if (depth != 0 && depth != -1) {
39966 + con->http_status = 400;
39968 + return HANDLER_FINISHED;
39972 + if (con->request.content_length) {
39974 + buffer *hdr_if = NULL;
39976 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39977 + hdr_if = ds->value;
39980 + /* we don't support Depth: Infinity on locks */
39981 + if (hdr_if == NULL && depth == -1) {
39982 + con->http_status = 409; /* Conflict */
39984 + return HANDLER_FINISHED;
39987 + if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
39988 + xmlNode *rootnode = xmlDocGetRootElement(xml);
39990 + assert(rootnode);
39992 + if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
39993 + xmlNode *lockinfo;
39994 + const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
39996 + for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
39997 + if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
39999 + for (value = lockinfo->children; value; value = value->next) {
40000 + if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
40001 + (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
40002 + lockscope = value->name;
40004 + con->http_status = 400;
40007 + return HANDLER_FINISHED;
40010 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
40012 + for (value = lockinfo->children; value; value = value->next) {
40013 + if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
40014 + locktype = value->name;
40016 + con->http_status = 400;
40019 + return HANDLER_FINISHED;
40023 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
40027 + if (lockscope && locktype) {
40028 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
40030 + /* is this resourse already locked ? */
40032 + /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
40034 + * WHERE resource = ? */
40038 + sqlite3_reset(stmt);
40040 + sqlite3_bind_text(stmt, 1,
40041 + p->uri.path->ptr,
40042 + p->uri.path->used - 1,
40043 + SQLITE_TRANSIENT);
40045 + /* it is the PK */
40046 + while (SQLITE_ROW == sqlite3_step(stmt)) {
40047 + /* we found a lock
40048 + * 1. is it compatible ?
40049 + * 2. is it ours */
40050 + char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
40052 + if (strcmp(sql_lockscope, "exclusive")) {
40053 + con->http_status = 423;
40054 + } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
40055 + /* resourse is locked with a shared lock
40056 + * client wants exclusive */
40057 + con->http_status = 423;
40060 + if (con->http_status == 423) {
40062 + return HANDLER_FINISHED;
40066 + stmt = p->conf.stmt_create_lock;
40068 + /* create a lock-token */
40070 + char uuid[37] /* 36 + \0 */;
40072 + uuid_generate(id);
40073 + uuid_unparse(id, uuid);
40075 + buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
40076 + buffer_append_string(p->tmp_buf, uuid);
40078 + /* "CREATE TABLE locks ("
40079 + * " locktoken TEXT NOT NULL,"
40080 + * " resource TEXT NOT NULL,"
40081 + * " lockscope TEXT NOT NULL,"
40082 + * " locktype TEXT NOT NULL,"
40083 + * " owner TEXT NOT NULL,"
40084 + * " depth INT NOT NULL,"
40087 + sqlite3_reset(stmt);
40089 + sqlite3_bind_text(stmt, 1,
40090 + CONST_BUF_LEN(p->tmp_buf),
40091 + SQLITE_TRANSIENT);
40093 + sqlite3_bind_text(stmt, 2,
40094 + CONST_BUF_LEN(con->uri.path),
40095 + SQLITE_TRANSIENT);
40097 + sqlite3_bind_text(stmt, 3,
40099 + xmlStrlen(lockscope),
40100 + SQLITE_TRANSIENT);
40102 + sqlite3_bind_text(stmt, 4,
40104 + xmlStrlen(locktype),
40105 + SQLITE_TRANSIENT);
40108 + sqlite3_bind_text(stmt, 5,
40111 + SQLITE_TRANSIENT);
40114 + sqlite3_bind_int(stmt, 6,
40118 + if (SQLITE_DONE != sqlite3_step(stmt)) {
40119 + log_error_write(srv, __FILE__, __LINE__, "ss",
40120 + "create lock:", sqlite3_errmsg(p->conf.sql));
40123 + /* looks like we survived */
40124 + webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
40126 + con->http_status = 201;
40127 + con->file_finished = 1;
40133 + return HANDLER_FINISHED;
40135 + con->http_status = 400;
40136 + return HANDLER_FINISHED;
40140 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
40141 + buffer *locktoken = ds->value;
40142 + sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
40144 + /* remove the < > around the token */
40145 + if (locktoken->used < 6) {
40146 + con->http_status = 400;
40148 + return HANDLER_FINISHED;
40151 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
40153 + sqlite3_reset(stmt);
40155 + sqlite3_bind_text(stmt, 1,
40156 + CONST_BUF_LEN(p->tmp_buf),
40157 + SQLITE_TRANSIENT);
40159 + if (SQLITE_DONE != sqlite3_step(stmt)) {
40160 + log_error_write(srv, __FILE__, __LINE__, "ss",
40161 + "refresh lock:", sqlite3_errmsg(p->conf.sql));
40164 + webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
40166 + con->http_status = 200;
40167 + con->file_finished = 1;
40168 + return HANDLER_FINISHED;
40170 + /* we need a lock-token to refresh */
40171 + con->http_status = 400;
40173 + return HANDLER_FINISHED;
40178 + con->http_status = 501;
40179 + return HANDLER_FINISHED;
40181 + case HTTP_METHOD_UNLOCK:
40183 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
40184 + buffer *locktoken = ds->value;
40185 + sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
40187 + /* remove the < > around the token */
40188 + if (locktoken->used < 4) {
40189 + con->http_status = 400;
40191 + return HANDLER_FINISHED;
40197 + * if the resourse is locked:
40198 + * - by us: unlock
40199 + * - by someone else: 401
40200 + * if the resource is not locked:
40204 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
40206 + sqlite3_reset(stmt);
40208 + sqlite3_bind_text(stmt, 1,
40209 + CONST_BUF_LEN(p->tmp_buf),
40210 + SQLITE_TRANSIENT);
40212 + sqlite3_bind_text(stmt, 2,
40213 + CONST_BUF_LEN(con->uri.path),
40214 + SQLITE_TRANSIENT);
40216 + if (SQLITE_DONE != sqlite3_step(stmt)) {
40217 + log_error_write(srv, __FILE__, __LINE__, "ss",
40218 + "remove lock:", sqlite3_errmsg(p->conf.sql));
40221 + if (0 == sqlite3_changes(p->conf.sql)) {
40222 + con->http_status = 401;
40224 + con->http_status = 204;
40226 + return HANDLER_FINISHED;
40228 + /* we need a lock-token to unlock */
40229 + con->http_status = 400;
40231 + return HANDLER_FINISHED;
40235 + con->http_status = 501;
40236 + return HANDLER_FINISHED;
40244 return HANDLER_GO_ON;
40246 @@ -1845,14 +2462,14 @@
40247 int mod_webdav_plugin_init(plugin *p) {
40248 p->version = LIGHTTPD_VERSION_ID;
40249 p->name = buffer_init_string("webdav");
40252 p->init = mod_webdav_init;
40253 p->handle_uri_clean = mod_webdav_uri_handler;
40254 p->handle_physical = mod_webdav_subrequest_handler;
40255 p->set_defaults = mod_webdav_set_defaults;
40256 p->cleanup = mod_webdav_free;
40264 --- ../lighttpd-1.4.11/src/network.c 2006-03-04 16:45:46.000000000 +0200
40265 +++ lighttpd-1.4.12/src/network.c 2006-07-11 22:07:51.000000000 +0300
40267 #include <sys/types.h>
40268 #include <sys/stat.h>
40269 -#include <sys/time.h>
40273 -#include <unistd.h>
40274 #include <string.h>
40275 #include <stdlib.h>
40276 #include <assert.h>
40278 +#include <stdio.h>
40280 #include "network.h"
40281 #include "fdevent.h"
40283 @@ -19,11 +19,12 @@
40284 #include "network_backends.h"
40285 #include "sys-mmap.h"
40286 #include "sys-socket.h"
40287 +#include "sys-files.h"
40290 -# include <openssl/ssl.h>
40291 -# include <openssl/err.h>
40292 -# include <openssl/rand.h>
40293 +# include <openssl/ssl.h>
40294 +# include <openssl/err.h>
40295 +# include <openssl/rand.h>
40298 handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
40299 @@ -31,11 +32,11 @@
40300 server_socket *srv_socket = (server_socket *)context;
40308 if (revents != FDEVENT_IN) {
40309 - log_error_write(srv, __FILE__, __LINE__, "sdd",
40310 + log_error_write(srv, __FILE__, __LINE__, "sdd",
40311 "strange event for server socket",
40314 @@ -44,12 +45,12 @@
40316 /* accept()s at most 100 connections directly
40318 - * we jump out after 100 to give the waiting connections a chance */
40319 + * we jump out after 100 to give the waiting connections a chance */
40320 for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
40324 connection_state_machine(srv, con);
40327 switch(r = plugins_call_handle_joblist(srv, con)) {
40328 case HANDLER_FINISHED:
40329 case HANDLER_GO_ON:
40330 @@ -72,18 +73,18 @@
40332 int is_unix_domain_socket = 0;
40336 #ifdef SO_ACCEPTFILTER
40337 struct accept_filter_arg afa;
40342 WORD wVersionRequested;
40347 wVersionRequested = MAKEWORD( 2, 2 );
40350 err = WSAStartup( wVersionRequested, &wsaData );
40352 /* Tell the user that we could not find a usable */
40353 @@ -91,37 +92,37 @@
40359 srv_socket = calloc(1, sizeof(*srv_socket));
40360 srv_socket->fd = -1;
40363 srv_socket->srv_token = buffer_init();
40364 buffer_copy_string_buffer(srv_socket->srv_token, host_token);
40368 buffer_copy_string_buffer(b, host_token);
40375 if (NULL == (sp = strrchr(b->ptr, ':'))) {
40376 log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
40386 /* check for [ and ] */
40387 if (b->ptr[0] == '[' && *(sp-1) == ']') {
40399 port = strtol(sp, NULL, 10);
40401 if (host[0] == '/') {
40402 @@ -129,17 +130,17 @@
40403 is_unix_domain_socket = 1;
40404 } else if (port == 0 || port > 65535) {
40405 log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
40412 if (*host == '\0') host = NULL;
40414 if (is_unix_domain_socket) {
40415 #ifdef HAVE_SYS_UN_H
40417 srv_socket->addr.plain.sa_family = AF_UNIX;
40420 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
40421 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40423 @@ -154,7 +155,7 @@
40426 srv_socket->addr.plain.sa_family = AF_INET6;
40429 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40430 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40432 @@ -162,7 +163,7 @@
40433 srv_socket->use_ipv6 = 1;
40438 if (srv_socket->fd == -1) {
40439 srv_socket->addr.plain.sa_family = AF_INET;
40440 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40441 @@ -170,16 +171,16 @@
40448 srv->cur_fds = srv_socket->fd;
40452 if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
40453 log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
40458 switch(srv_socket->addr.plain.sa_family) {
40461 @@ -190,23 +191,23 @@
40463 struct addrinfo hints, *res;
40467 memset(&hints, 0, sizeof(hints));
40470 hints.ai_family = AF_INET6;
40471 hints.ai_socktype = SOCK_STREAM;
40472 hints.ai_protocol = IPPROTO_TCP;
40475 if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
40476 - log_error_write(srv, __FILE__, __LINE__,
40477 - "sssss", "getaddrinfo failed: ",
40478 + log_error_write(srv, __FILE__, __LINE__,
40479 + "sssss", "getaddrinfo failed: ",
40480 gai_strerror(r), "'", host, "'");
40487 memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
40492 srv_socket->addr.ipv6.sin6_port = htons(port);
40493 @@ -221,33 +222,34 @@
40495 struct hostent *he;
40496 if (NULL == (he = gethostbyname(host))) {
40497 - log_error_write(srv, __FILE__, __LINE__,
40498 - "sds", "gethostbyname failed: ",
40499 + log_error_write(srv, __FILE__, __LINE__,
40500 + "sds", "gethostbyname failed: ",
40506 if (he->h_addrtype != AF_INET) {
40507 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
40512 if (he->h_length != sizeof(struct in_addr)) {
40513 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
40518 memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
40520 srv_socket->addr.ipv4.sin_port = htons(port);
40523 addr_len = sizeof(struct sockaddr_in);
40529 srv_socket->addr.un.sun_family = AF_UNIX;
40530 strcpy(srv_socket->addr.un.sun_path, host);
40534 addr_len = SUN_LEN(&srv_socket->addr.un);
40536 @@ -259,8 +261,8 @@
40537 if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
40540 - log_error_write(srv, __FILE__, __LINE__, "ss",
40541 - "server socket is still in use:",
40542 + log_error_write(srv, __FILE__, __LINE__, "ss",
40543 + "server socket is still in use:",
40547 @@ -275,88 +277,89 @@
40551 - log_error_write(srv, __FILE__, __LINE__, "sds",
40552 - "testing socket failed:",
40553 + log_error_write(srv, __FILE__, __LINE__, "sds",
40554 + "testing socket failed:",
40555 host, strerror(errno));
40570 if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
40571 switch(srv_socket->addr.plain.sa_family) {
40573 - log_error_write(srv, __FILE__, __LINE__, "sds",
40574 - "can't bind to socket:",
40575 + log_error_write(srv, __FILE__, __LINE__, "sds",
40576 + "can't bind to socket:",
40577 host, strerror(errno));
40580 - log_error_write(srv, __FILE__, __LINE__, "ssds",
40581 - "can't bind to port:",
40582 + log_error_write(srv, __FILE__, __LINE__, "ssds",
40583 + "can't bind to port:",
40584 host, port, strerror(errno));
40591 if (-1 == listen(srv_socket->fd, 128 * 8)) {
40592 log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
40599 if (srv->ssl_is_init == 0) {
40600 SSL_load_error_strings();
40601 SSL_library_init();
40602 srv->ssl_is_init = 1;
40605 if (0 == RAND_status()) {
40606 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40607 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40608 "not enough entropy in the pool");
40614 if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
40615 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40616 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40617 ERR_error_string(ERR_get_error(), NULL));
40622 if (buffer_is_empty(s->ssl_pemfile)) {
40623 log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
40628 if (!buffer_is_empty(s->ssl_ca_file)) {
40629 if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
40630 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40631 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40632 ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
40638 if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40639 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40640 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40641 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40646 if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40647 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40648 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40649 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40654 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
40655 - log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
40656 + log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
40657 "Private key does not match the certificate public key, reason:",
40658 ERR_error_string(ERR_get_error(), NULL),
40660 @@ -364,15 +367,15 @@
40662 srv_socket->ssl_ctx = s->ssl_ctx;
40666 buffer_free(srv_socket->srv_token);
40672 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40674 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40675 "ssl requested but openssl support is not compiled in");
40681 @@ -390,10 +393,10 @@
40687 srv_socket->is_ssl = s->is_ssl;
40688 srv_socket->fde_ndx = -1;
40691 if (srv->srv_sockets.size == 0) {
40692 srv->srv_sockets.size = 4;
40693 srv->srv_sockets.used = 0;
40694 @@ -402,11 +405,10 @@
40695 srv->srv_sockets.size += 4;
40696 srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
40700 srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
40708 @@ -414,45 +416,58 @@
40710 for (i = 0; i < srv->srv_sockets.used; i++) {
40711 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40714 if (srv_socket->fd != -1) {
40715 /* check if server fd are already registered */
40716 if (srv_socket->fde_ndx != -1) {
40717 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
40718 fdevent_unregister(srv->ev, srv_socket->fd);
40722 close(srv_socket->fd);
40726 + if (srv_socket->is_ssl) {
40727 +#ifdef USE_OPENSSL
40728 + SSL_CTX_free(srv_socket->ssl_ctx);
40732 buffer_free(srv_socket->srv_token);
40739 +#ifdef USE_OPENSSL
40740 + ERR_free_strings();
40742 free(srv->srv_sockets.ptr);
40749 NETWORK_BACKEND_UNSET,
40751 NETWORK_BACKEND_WRITE,
40752 NETWORK_BACKEND_WRITEV,
40753 NETWORK_BACKEND_LINUX_SENDFILE,
40754 NETWORK_BACKEND_FREEBSD_SENDFILE,
40755 - NETWORK_BACKEND_SOLARIS_SENDFILEV
40756 + NETWORK_BACKEND_SOLARIS_SENDFILEV,
40758 + NETWORK_BACKEND_WIN32_SEND,
40759 + NETWORK_BACKEND_WIN32_TRANSMITFILE,
40760 } network_backend_t;
40762 int network_init(server *srv) {
40765 network_backend_t backend;
40768 - network_backend_t nb;
40769 - const char *name;
40770 - } network_backends[] = {
40773 + network_backend_t nb;
40774 + const char *name;
40775 + } network_backends[] = {
40776 /* lowest id wins */
40777 #if defined USE_LINUX_SENDFILE
40778 { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" },
40779 @@ -466,21 +481,30 @@
40780 #if defined USE_WRITEV
40781 { NETWORK_BACKEND_WRITEV, "writev" },
40783 +#if defined USE_WRITE
40784 { NETWORK_BACKEND_WRITE, "write" },
40786 +#if defined USE_WIN32_TRANSMITFILE
40787 + { NETWORK_BACKEND_WIN32_TRANSMITFILE, "win32-transmitfile" },
40789 +#if defined USE_WIN32_SEND
40790 + { NETWORK_BACKEND_WIN32_SEND, "win32-send" },
40793 { NETWORK_BACKEND_UNSET, NULL }
40800 buffer_copy_string_buffer(b, srv->srvconf.bindhost);
40801 buffer_append_string(b, ":");
40802 buffer_append_long(b, srv->srvconf.port);
40805 if (0 != network_server_init(srv, b, srv->config_storage[0])) {
40812 srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
40814 @@ -500,54 +524,80 @@
40815 if (NULL == network_backends[i].name) {
40816 /* we don't know it */
40818 - log_error_write(srv, __FILE__, __LINE__, "sb",
40819 - "server.network-backend has a unknown value:",
40820 + log_error_write(srv, __FILE__, __LINE__, "sb",
40821 + "server.network-backend has a unknown value:",
40822 srv->srvconf.network_backend);
40828 +#define SET_NETWORK_BACKEND(read, write) \
40829 + srv->network_backend_write = network_write_chunkqueue_##write;\
40830 + srv->network_backend_read = network_read_chunkqueue_##read
40832 +#define SET_NETWORK_BACKEND_SSL(read, write) \
40833 + srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
40834 + srv->network_ssl_backend_read = network_read_chunkqueue_##read
40838 +#ifdef USE_WIN32_SEND
40839 + case NETWORK_BACKEND_WIN32_SEND:
40840 + SET_NETWORK_BACKEND(win32recv, win32send);
40842 +#ifdef USE_WIN32_TRANSMITFILE
40843 + case NETWORK_BACKEND_WIN32_TRANSMITFILE:
40844 + SET_NETWORK_BACKEND(win32recv, win32transmitfile);
40850 case NETWORK_BACKEND_WRITE:
40851 - srv->network_backend_write = network_write_chunkqueue_write;
40852 + SET_NETWORK_BACKEND(read, write);
40856 case NETWORK_BACKEND_WRITEV:
40857 - srv->network_backend_write = network_write_chunkqueue_writev;
40858 + SET_NETWORK_BACKEND(read, writev);
40861 #ifdef USE_LINUX_SENDFILE
40862 case NETWORK_BACKEND_LINUX_SENDFILE:
40863 - srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
40864 + SET_NETWORK_BACKEND(read, linuxsendfile);
40867 #ifdef USE_FREEBSD_SENDFILE
40868 case NETWORK_BACKEND_FREEBSD_SENDFILE:
40869 - srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
40870 + SET_NETWORK_BACKEND(read, freebsdsendfile);
40873 #ifdef USE_SOLARIS_SENDFILEV
40874 case NETWORK_BACKEND_SOLARIS_SENDFILEV:
40875 - srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
40876 + SET_NETWORK_BACKEND(read, solarissendfilev);
40883 +#ifdef USE_OPENSSL
40884 + SET_NETWORK_BACKEND_SSL(openssl, openssl);
40887 /* check for $SERVER["socket"] */
40888 for (i = 1; i < srv->config_context->used; i++) {
40889 data_config *dc = (data_config *)srv->config_context->data[i];
40890 specific_config *s = srv->config_storage[i];
40894 /* not our stage */
40895 if (COMP_SERVER_SOCKET != dc->comp) continue;
40898 if (dc->cond != CONFIG_COND_EQ) {
40899 log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
40905 @@ -558,36 +608,47 @@
40911 if (j == srv->srv_sockets.used) {
40912 if (0 != network_server_init(srv, dc->string, s)) return -1;
40920 int network_register_fdevents(server *srv) {
40923 if (-1 == fdevent_reset(srv->ev)) {
40927 /* register fdevents after reset */
40928 for (i = 0; i < srv->srv_sockets.used; i++) {
40929 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40931 fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
40932 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
40937 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40939 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40940 + server_socket *srv_socket = con->srv_socket;
40942 + if (srv_socket->is_ssl) {
40943 +#ifdef USE_OPENSSL
40944 + return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
40946 + return NETWORK_STATUS_FATAL_ERROR;
40949 + return srv->network_backend_read(srv, con, con->fd, cq);
40953 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40954 + network_status_t ret = NETWORK_STATUS_UNSET;
40960 server_socket *srv_socket = con->srv_socket;
40961 @@ -600,11 +661,11 @@
40962 joblist_append(srv, con);
40968 written = cq->bytes_out;
40972 /* Linux: put a cork into the socket as we want to combine the write() calls
40973 * but only if we really have multiple chunks
40975 @@ -613,7 +674,7 @@
40976 setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
40981 if (srv_socket->is_ssl) {
40983 ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
40984 @@ -621,12 +682,17 @@
40986 ret = srv->network_backend_write(srv, con, con->fd, cq);
40992 + case NETWORK_STATUS_WAIT_FOR_EVENT:
40993 + case NETWORK_STATUS_SUCCESS:
40994 chunkqueue_remove_finished_chunks(cq);
40995 - ret = chunkqueue_is_empty(cq) ? 0 : 1;
41006 @@ -639,13 +705,13 @@
41007 con->bytes_written_cur_second += written;
41009 *(con->conf.global_bytes_per_second_cnt_ptr) += written;
41012 if (con->conf.kbytes_per_second &&
41013 (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
41014 /* we reached the traffic limit */
41016 con->traffic_limit_reached = 1;
41017 joblist_append(srv, con);
41022 --- ../lighttpd-1.4.11/src/network.h 2005-08-11 01:26:42.000000000 +0300
41023 +++ lighttpd-1.4.12/src/network.h 2006-07-11 22:07:51.000000000 +0300
41026 #include "server.h"
41028 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
41029 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
41030 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
41032 int network_init(server *srv);
41033 int network_close(server *srv);
41034 --- ../lighttpd-1.4.11/src/network_backends.h 2005-10-24 15:13:51.000000000 +0300
41035 +++ lighttpd-1.4.12/src/network_backends.h 2006-07-11 22:07:52.000000000 +0300
41036 @@ -43,16 +43,52 @@
41037 # define USE_AIX_SENDFILE
41041 +* unix can use read/write or recv/send on sockets
41042 +* win32 only recv/send
41045 +# define USE_WIN32_SEND
41046 +/* wait for async-io support
41047 +# define USE_WIN32_TRANSMITFILE
41050 +# define USE_WRITE
41054 +#include "network.h"
41056 +#define NETWORK_BACKEND_WRITE_CHUNK(x) \
41057 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c)
41059 +#define NETWORK_BACKEND_WRITE(x) \
41060 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
41061 +#define NETWORK_BACKEND_READ(x) \
41062 + network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
41064 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
41066 +NETWORK_BACKEND_WRITE(write);
41067 +NETWORK_BACKEND_WRITE(writev);
41068 +NETWORK_BACKEND_WRITE(linuxsendfile);
41069 +NETWORK_BACKEND_WRITE(freebsdsendfile);
41070 +NETWORK_BACKEND_WRITE(solarissendfilev);
41072 +NETWORK_BACKEND_WRITE(win32transmitfile);
41073 +NETWORK_BACKEND_WRITE(win32send);
41075 +NETWORK_BACKEND_READ(read);
41076 +NETWORK_BACKEND_READ(win32recv);
41078 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
41079 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
41080 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
41081 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
41082 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
41084 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
41085 +#define NETWORK_BACKEND_WRITE_SSL(x) \
41086 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
41087 +#define NETWORK_BACKEND_READ_SSL(x) \
41088 + network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
41090 +NETWORK_BACKEND_WRITE_SSL(openssl);
41091 +NETWORK_BACKEND_READ_SSL(openssl);
41095 --- ../lighttpd-1.4.11/src/network_freebsd_sendfile.c 2005-10-22 12:28:18.000000000 +0300
41096 +++ lighttpd-1.4.12/src/network_freebsd_sendfile.c 2006-07-11 22:07:52.000000000 +0300
41097 @@ -26,142 +26,61 @@
41100 # ifdef __FreeBSD__
41101 -/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
41102 +/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
41103 # define UIO_MAXIOV 1024
41107 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41108 +NETWORK_BACKEND_WRITE(freebsdsendfile) {
41110 size_t chunks_written = 0;
41113 for(c = cq->first; c; c = c->next, chunks_written++) {
41114 int chunk_finished = 0;
41116 + network_status_t ret;
41119 - case MEM_CHUNK: {
41124 - size_t num_chunks, i;
41125 - struct iovec chunks[UIO_MAXIOV];
41127 - size_t num_bytes = 0;
41129 - /* we can't send more then SSIZE_MAX bytes in one chunk */
41131 - /* build writev list
41133 - * 1. limit: num_chunks < UIO_MAXIOV
41134 - * 2. limit: num_bytes < SSIZE_MAX
41136 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41138 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41139 - if (tc->mem->used == 0) {
41140 - chunks[i].iov_base = tc->mem->ptr;
41141 - chunks[i].iov_len = 0;
41143 - offset = tc->mem->ptr + tc->offset;
41144 - toSend = tc->mem->used - 1 - tc->offset;
41146 - chunks[i].iov_base = offset;
41148 - /* protect the return value of writev() */
41149 - if (toSend > SSIZE_MAX ||
41150 - num_bytes + toSend > SSIZE_MAX) {
41151 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
41153 - num_chunks = i + 1;
41156 - chunks[i].iov_len = toSend;
41159 - num_bytes += toSend;
41163 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
41173 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41174 - "writev failed:", strerror(errno), fd);
41179 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41184 - /* check which chunks have been written */
41185 - cq->bytes_out += r;
41187 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41188 - if (r >= (ssize_t)chunks[i].iov_len) {
41190 - r -= chunks[i].iov_len;
41191 - tc->offset += chunks[i].iov_len;
41193 - if (chunk_finished) {
41194 - /* skip the chunks from further touches */
41195 - chunks_written++;
41198 - /* chunks_written + c = c->next is done in the for()*/
41199 - chunk_finished++;
41202 - /* partially written */
41205 - chunk_finished = 0;
41209 + if (ret != NETWORK_STATUS_SUCCESS) {
41214 + chunk_finished = 1;
41221 stat_cache_entry *sce = NULL;
41225 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41226 log_error_write(srv, __FILE__, __LINE__, "sb",
41227 strerror(errno), c->file.name);
41229 + return NETWORK_STATUS_FATAL_ERROR;
41233 offset = c->file.start + c->offset;
41234 /* limit the toSend to 2^31-1 bytes in a chunk */
41235 - toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41236 + toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41237 ((1 << 30) - 1) : c->file.length - c->offset;
41240 if (offset > sce->st.st_size) {
41241 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41245 + return NETWORK_STATUS_FATAL_ERROR;
41249 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41250 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41254 + return NETWORK_STATUS_FATAL_ERROR;
41261 /* FreeBSD sendfile() */
41262 if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
41264 @@ -169,39 +88,39 @@
41269 + return NETWORK_STATUS_CONNECTION_CLOSE;
41271 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41274 + return NETWORK_STATUS_FATAL_ERROR;
41281 cq->bytes_out += r;
41284 if (c->offset == c->file.length) {
41285 chunk_finished = 1;
41294 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41301 if (!chunk_finished) {
41302 /* not finished yet */
41309 - return chunks_written;
41310 + return NETWORK_STATUS_SUCCESS;
41314 --- ../lighttpd-1.4.11/src/network_linux_sendfile.c 2006-02-15 20:02:36.000000000 +0200
41315 +++ lighttpd-1.4.12/src/network_linux_sendfile.c 2006-07-15 22:43:21.000000000 +0300
41316 @@ -26,122 +26,54 @@
41317 /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
41318 #undef HAVE_POSIX_FADVISE
41320 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41322 +NETWORK_BACKEND_WRITE(linuxsendfile) {
41324 size_t chunks_written = 0;
41327 for(c = cq->first; c; c = c->next, chunks_written++) {
41328 int chunk_finished = 0;
41330 + network_status_t ret;
41333 - case MEM_CHUNK: {
41338 - size_t num_chunks, i;
41339 - struct iovec chunks[UIO_MAXIOV];
41341 - size_t num_bytes = 0;
41343 - /* we can't send more then SSIZE_MAX bytes in one chunk */
41345 - /* build writev list
41347 - * 1. limit: num_chunks < UIO_MAXIOV
41348 - * 2. limit: num_bytes < SSIZE_MAX
41350 - for (num_chunks = 0, tc = c;
41351 - tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
41352 - tc = tc->next, num_chunks++);
41354 - for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41355 - if (tc->mem->used == 0) {
41356 - chunks[i].iov_base = tc->mem->ptr;
41357 - chunks[i].iov_len = 0;
41359 - offset = tc->mem->ptr + tc->offset;
41360 - toSend = tc->mem->used - 1 - tc->offset;
41362 - chunks[i].iov_base = offset;
41364 - /* protect the return value of writev() */
41365 - if (toSend > SSIZE_MAX ||
41366 - num_bytes + toSend > SSIZE_MAX) {
41367 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
41369 - num_chunks = i + 1;
41372 - chunks[i].iov_len = toSend;
41375 - num_bytes += toSend;
41379 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
41389 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41390 - "writev failed:", strerror(errno), fd);
41396 - /* check which chunks have been written */
41397 - cq->bytes_out += r;
41399 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
41401 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41402 - if (r >= (ssize_t)chunks[i].iov_len) {
41404 - r -= chunks[i].iov_len;
41405 - tc->offset += chunks[i].iov_len;
41407 + /* check which chunks are finished now */
41408 + for (tc = c; tc; tc = tc->next) {
41409 + /* finished the chunk */
41410 + if (tc->offset == tc->mem->used - 1) {
41411 + /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
41412 if (chunk_finished) {
41413 - /* skip the chunks from further touches */
41414 - chunks_written++;
41417 - /* chunks_written + c = c->next is done in the for()*/
41418 - chunk_finished++;
41419 + chunk_finished = 1;
41422 - /* partially written */
41425 - chunk_finished = 0;
41432 + if (ret != NETWORK_STATUS_SUCCESS) {
41442 stat_cache_entry *sce = NULL;
41445 offset = c->file.start + c->offset;
41446 /* limit the toSend to 2^31-1 bytes in a chunk */
41447 - toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41448 + toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41449 ((1 << 30) - 1) : c->file.length - c->offset;
41451 - /* open file if not already opened */
41453 + /* open file if not already opened */
41454 if (-1 == c->file.fd) {
41455 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
41456 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41463 /* tell the kernel that we want to stream the file */
41464 if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
41465 if (ENOSYS != errno) {
41466 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41467 + log_error_write(srv, __FILE__, __LINE__, "ssd",
41468 "posix_fadvise failed:", strerror(errno), c->file.fd);
41471 @@ -168,7 +100,7 @@
41475 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41476 + log_error_write(srv, __FILE__, __LINE__, "ssd",
41477 "sendfile failed:", strerror(errno), fd);
41480 @@ -179,7 +111,7 @@
41482 * - the file shrinked -> error
41483 * - the remote side closed inbetween -> remote-close */
41486 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41487 /* file is gone ? */
41489 @@ -196,22 +128,22 @@
41490 #ifdef HAVE_POSIX_FADVISE
41493 -#define M * 1024 K
41494 +#define M * 1024 K
41495 #define READ_AHEAD 4 M
41496 /* check if we need a new chunk */
41497 if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
41498 /* tell the kernel that we want to stream the file */
41499 if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
41500 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41501 + log_error_write(srv, __FILE__, __LINE__, "ssd",
41502 "posix_fadvise failed:", strerror(errno), c->file.fd);
41510 cq->bytes_out += r;
41513 if (c->offset == c->file.length) {
41514 chunk_finished = 1;
41516 @@ -222,24 +154,24 @@
41527 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41534 if (!chunk_finished) {
41535 /* not finished yet */
41542 - return chunks_written;
41543 + return NETWORK_STATUS_SUCCESS;
41547 --- ../lighttpd-1.4.11/src/network_openssl.c 2005-11-17 14:53:29.000000000 +0200
41548 +++ lighttpd-1.4.12/src/network_openssl.c 2006-07-11 22:07:52.000000000 +0300
41549 @@ -23,17 +23,87 @@
41551 #include "stat_cache.h"
41553 -# include <openssl/ssl.h>
41554 -# include <openssl/err.h>
41555 +# include <openssl/ssl.h>
41556 +# include <openssl/err.h>
41558 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
41559 +NETWORK_BACKEND_READ_SSL(openssl) {
41563 + b = chunkqueue_get_append_buffer(cq);
41564 + buffer_prepare_copy(b, 8192);
41565 + len = SSL_read(ssl, b->ptr, b->size - 1);
41567 + log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
41572 + switch ((r = SSL_get_error(con->ssl, len))) {
41573 + case SSL_ERROR_WANT_READ:
41574 + return NETWORK_STATUS_WAIT_FOR_EVENT;
41575 + case SSL_ERROR_SYSCALL:
41577 + * man SSL_get_error()
41579 + * SSL_ERROR_SYSCALL
41580 + * Some I/O error occurred. The OpenSSL error queue may contain more
41581 + * information on the error. If the error queue is empty (i.e.
41582 + * ERR_get_error() returns 0), ret can be used to find out more about
41583 + * the error: If ret == 0, an EOF was observed that violates the
41584 + * protocol. If ret == -1, the underlying BIO reported an I/O error
41585 + * (for socket I/O on Unix systems, consult errno for details).
41588 + while((ssl_err = ERR_get_error())) {
41589 + /* get all errors from the error-queue */
41590 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41591 + r, ERR_error_string(ssl_err, NULL));
41596 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41598 + strerror(errno));
41603 + case SSL_ERROR_ZERO_RETURN:
41604 + /* clean shutdown on the remote side */
41607 + /* FIXME: later */
41610 + /* fall thourgh */
41612 + while((ssl_err = ERR_get_error())) {
41613 + /* get all errors from the error-queue */
41614 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41615 + r, ERR_error_string(ssl_err, NULL));
41623 + b->ptr[b->used - 1] = '\0';
41625 + return NETWORK_STATUS_SUCCESS;
41629 +NETWORK_BACKEND_WRITE_SSL(openssl) {
41632 size_t chunks_written = 0;
41634 /* this is a 64k sendbuffer
41636 - * it has to stay at the same location all the time to satisfy the needs
41637 + * it has to stay at the same location all the time to satisfy the needs
41638 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
41640 * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
41641 @@ -43,14 +113,14 @@
41642 * In reality we would like to use mmap() but we don't have a guarantee that
41643 * we get the same mmap() address for each call. On openbsd the mmap() address
41645 - * That means either we keep the mmap() open or we do a read() into a
41646 - * constant buffer
41647 + * That means either we keep the mmap() open or we do a read() into a
41648 + * constant buffer
41650 #define LOCAL_SEND_BUFSIZE (64 * 1024)
41651 static char *local_send_buffer = NULL;
41653 /* the remote side closed the connection before without shutdown request
41657 * if keep-alive is disabled */
41659 @@ -60,32 +130,34 @@
41661 for(c = cq->first; c; c = c->next) {
41662 int chunk_finished = 0;
41673 if (c->mem->used == 0) {
41674 chunk_finished = 1;
41679 offset = c->mem->ptr + c->offset;
41680 toSend = c->mem->used - 1 - c->offset;
41684 * SSL_write man-page
41688 * When an SSL_write() operation has to be repeated because of
41689 * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
41690 * repeated with the same arguments.
41693 + * SSL_write(..., 0) return 0 which is handle as an error (Success)
41694 + * checking toSend and not calling SSL_write() is simpler
41697 - if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
41699 + if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
41702 switch ((ssl_r = SSL_get_error(ssl, r))) {
41704 /* perhaps we have error waiting in our error-queue */
41705 if (0 != (err = ERR_get_error())) {
41707 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41708 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41710 ERR_error_string(err, NULL));
41711 } while((err = ERR_get_error()));
41712 @@ -105,43 +177,43 @@
41716 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41717 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41723 /* neither error-queue nor errno ? */
41724 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41725 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41732 case SSL_ERROR_ZERO_RETURN:
41733 /* clean shutdown on the remote side */
41736 if (r == 0) return -2;
41741 while((err = ERR_get_error())) {
41742 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41743 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41745 ERR_error_string(err, NULL));
41753 cq->bytes_out += r;
41757 if (c->offset == (off_t)c->mem->used - 1) {
41758 chunk_finished = 1;
41765 @@ -150,7 +222,7 @@
41766 stat_cache_entry *sce = NULL;
41768 int write_wait = 0;
41771 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41772 log_error_write(srv, __FILE__, __LINE__, "sb",
41773 strerror(errno), c->file.name);
41774 @@ -164,13 +236,13 @@
41777 off_t offset = c->file.start + c->offset;
41778 - off_t toSend = c->file.length - c->offset;
41779 + off_t toSend = c->file.length - c->offset;
41781 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
41784 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41785 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
41791 @@ -183,9 +255,9 @@
41794 s = local_send_buffer;
41800 if ((r = SSL_write(ssl, s, toSend)) <= 0) {
41803 @@ -197,7 +269,7 @@
41804 /* perhaps we have error waiting in our error-queue */
41805 if (0 != (err = ERR_get_error())) {
41807 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41808 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41810 ERR_error_string(err, NULL));
41811 } while((err = ERR_get_error()));
41812 @@ -207,58 +279,58 @@
41816 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41817 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41823 /* neither error-queue nor errno ? */
41824 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41825 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41832 case SSL_ERROR_ZERO_RETURN:
41833 /* clean shutdown on the remote side */
41836 if (r == 0) return -2;
41841 while((err = ERR_get_error())) {
41842 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41843 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41845 ERR_error_string(err, NULL));
41853 cq->bytes_out += r;
41857 if (c->offset == c->file.length) {
41858 chunk_finished = 1;
41860 } while(!chunk_finished && !write_wait);
41866 log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
41873 if (!chunk_finished) {
41874 /* not finished yet */
41884 --- ../lighttpd-1.4.11/src/network_solaris_sendfilev.c 2005-10-22 12:28:27.000000000 +0300
41885 +++ lighttpd-1.4.12/src/network_solaris_sendfilev.c 2006-07-11 22:07:53.000000000 +0300
41886 @@ -29,114 +29,34 @@
41890 - * a very simple sendfilev() interface for solaris which can be optimised a lot more
41891 + * a very simple sendfilev() interface for solaris which can be optimised a lot more
41892 * as solaris sendfilev() supports 'sending everythin in one syscall()'
41894 - * If you want such an interface and need the performance, just give me an account on
41897 + * If you want such an interface and need the performance, just give me an account on
41899 * - jan@kneschke.de
41903 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
41904 +NETWORK_BACKEND_WRITE(solarissendfilev) {
41906 size_t chunks_written = 0;
41909 for(c = cq->first; c; c = c->next, chunks_written++) {
41910 int chunk_finished = 0;
41912 + network_status_t ret;
41915 - case MEM_CHUNK: {
41920 - size_t num_chunks, i;
41921 - struct iovec chunks[UIO_MAXIOV];
41924 - size_t num_bytes = 0;
41926 - /* we can't send more then SSIZE_MAX bytes in one chunk */
41928 - /* build writev list
41930 - * 1. limit: num_chunks < UIO_MAXIOV
41931 - * 2. limit: num_bytes < SSIZE_MAX
41933 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41935 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41936 - if (tc->mem->used == 0) {
41937 - chunks[i].iov_base = tc->mem->ptr;
41938 - chunks[i].iov_len = 0;
41940 - offset = tc->mem->ptr + tc->offset;
41941 - toSend = tc->mem->used - 1 - tc->offset;
41943 - chunks[i].iov_base = offset;
41945 - /* protect the return value of writev() */
41946 - if (toSend > SSIZE_MAX ||
41947 - num_bytes + toSend > SSIZE_MAX) {
41948 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
41950 - num_chunks = i + 1;
41953 - chunks[i].iov_len = toSend;
41956 - num_bytes += toSend;
41960 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
41970 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41971 - "writev failed:", strerror(errno), fd);
41977 - /* check which chunks have been written */
41978 - cq->bytes_out += r;
41980 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41981 - if (r >= (ssize_t)chunks[i].iov_len) {
41983 - r -= chunks[i].iov_len;
41984 - tc->offset += chunks[i].iov_len;
41986 - if (chunk_finished) {
41987 - /* skip the chunks from further touches */
41988 - chunks_written++;
41991 - /* chunks_written + c = c->next is done in the for()*/
41992 - chunk_finished++;
41995 - /* partially written */
41998 - chunk_finished = 0;
42003 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
42005 + if (ret != NETWORK_STATUS_SUCCESS) {
42010 + chunk_finished = 1;
42017 @@ -144,25 +64,25 @@
42018 sendfilevec_t fvec;
42019 stat_cache_entry *sce = NULL;
42023 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42024 log_error_write(srv, __FILE__, __LINE__, "sb",
42025 strerror(errno), c->file.name);
42030 offset = c->file.start + c->offset;
42031 toSend = c->file.length - c->offset;
42034 if (offset > sce->st.st_size) {
42035 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42041 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42042 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42048 @@ -170,44 +90,43 @@
42050 fvec.sfv_off = offset;
42051 fvec.sfv_len = toSend;
42054 /* Solaris sendfilev() */
42055 if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
42056 if (errno != EAGAIN) {
42057 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
42062 + return NETWORK_STATUS_FATAL_ERROR;
42071 c->offset += written;
42072 cq->bytes_out += written;
42075 if (c->offset == c->file.length) {
42076 chunk_finished = 1;
42084 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42088 + return NETWORK_STATUS_FATAL_ERROR;
42092 if (!chunk_finished) {
42093 /* not finished yet */
42100 - return chunks_written;
42101 + return NETWORK_STATUS_SUCCESS;
42105 --- ../lighttpd-1.4.11/src/network_write.c 2005-10-22 12:27:56.000000000 +0300
42106 +++ lighttpd-1.4.12/src/network_write.c 2006-07-15 22:43:21.000000000 +0300
42108 #include <sys/types.h>
42109 #include <sys/stat.h>
42110 -#include <sys/time.h>
42114 -#include <unistd.h>
42115 #include <string.h>
42116 #include <stdlib.h>
42117 +#include <assert.h>
42119 #include "network.h"
42120 #include "fdevent.h"
42122 #include "stat_cache.h"
42124 #include "sys-socket.h"
42125 +#include "sys-files.h"
42127 #include "network_backends.h"
42131 #ifdef HAVE_SYS_FILIO_H
42132 # include <sys/filio.h>
42134 @@ -24,47 +27,84 @@
42135 #include <sys/resource.h>
42138 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
42140 +* fill the chunkqueue will all the data that we can get
42142 +* this might be optimized into a readv() which uses the chunks
42145 +NETWORK_BACKEND_READ(read) {
42150 + /* use a chunk-size of 8k */
42154 + b = chunkqueue_get_append_buffer(cq);
42156 + buffer_prepare_copy(b, toread);
42158 + if (-1 == (r = read(fd, b->ptr, toread))) {
42161 + return NETWORK_STATUS_WAIT_FOR_EVENT;
42163 + log_error_write(srv, __FILE__, __LINE__, "sds",
42164 + "unexpected end-of-file (perhaps the proxy process died):",
42165 + fd, strerror(errno));
42166 + return NETWORK_STATUS_FATAL_ERROR;
42171 + return NETWORK_STATUS_CONNECTION_CLOSE;
42174 + /* this should be catched by the b > 0 above */
42176 + b->used += r + 1;
42177 + b->ptr[b->used - 1] = '\0';
42178 + } while (r == toread);
42180 + return NETWORK_STATUS_SUCCESS;
42183 +NETWORK_BACKEND_WRITE(write) {
42185 size_t chunks_written = 0;
42188 for(c = cq->first; c; c = c->next) {
42189 int chunk_finished = 0;
42199 if (c->mem->used == 0) {
42200 chunk_finished = 1;
42205 offset = c->mem->ptr + c->offset;
42206 toSend = c->mem->used - 1 - c->offset;
42208 - if ((r = send(fd, offset, toSend, 0)) < 0) {
42209 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42215 if ((r = write(fd, offset, toSend)) < 0) {
42216 log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42220 + return NETWORK_STATUS_FATAL_ERROR;
42226 cq->bytes_out += r;
42229 if (c->offset == (off_t)c->mem->used - 1) {
42230 chunk_finished = 1;
42237 @@ -76,93 +116,89 @@
42239 stat_cache_entry *sce = NULL;
42243 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42244 log_error_write(srv, __FILE__, __LINE__, "sb",
42245 strerror(errno), c->file.name);
42247 + return NETWORK_STATUS_FATAL_ERROR;
42251 offset = c->file.start + c->offset;
42252 toSend = c->file.length - c->offset;
42255 if (offset > sce->st.st_size) {
42256 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42260 + return NETWORK_STATUS_FATAL_ERROR;
42263 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42264 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42268 + return NETWORK_STATUS_FATAL_ERROR;
42272 #if defined USE_MMAP
42273 if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
42274 log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
42280 + return NETWORK_STATUS_FATAL_ERROR;
42284 if ((r = write(fd, p + offset, toSend)) <= 0) {
42285 log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
42286 munmap(p, sce->st.st_size);
42288 + return NETWORK_STATUS_FATAL_ERROR;
42292 munmap(p, sce->st.st_size);
42294 buffer_prepare_copy(srv->tmp_buf, toSend);
42297 lseek(ifd, offset, SEEK_SET);
42298 if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
42299 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
42304 + return NETWORK_STATUS_FATAL_ERROR;
42308 if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
42309 log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
42313 + return NETWORK_STATUS_FATAL_ERROR;
42317 cq->bytes_out += r;
42320 if (c->offset == c->file.length) {
42321 chunk_finished = 1;
42330 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42334 + return NETWORK_STATUS_FATAL_ERROR;
42338 if (!chunk_finished) {
42339 /* not finished yet */
42349 - return chunks_written;
42350 + return NETWORK_STATUS_SUCCESS;
42354 -network_write_init(void) {
42355 - p->write = network_write_write_chunkset;
42358 --- ../lighttpd-1.4.11/src/network_writev.c 2006-02-15 01:02:36.000000000 +0200
42359 +++ lighttpd-1.4.12/src/network_writev.c 2006-07-15 22:43:21.000000000 +0300
42360 @@ -28,10 +28,10 @@
42363 # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
42364 -/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42365 +/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42366 # define UIO_MAXIOV 1024
42367 # elif defined(__sgi)
42368 -/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42369 +/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42370 # define UIO_MAXIOV 512
42371 # elif defined(__sun)
42372 /* Solaris (and SunOS?) defines IOV_MAX instead */
42373 @@ -51,105 +51,121 @@
42374 #define LOCAL_BUFFERING 1
42377 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
42379 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
42384 + size_t num_chunks, i;
42385 + struct iovec chunks[UIO_MAXIOV];
42386 + chunk *tc; /* transfer chunks */
42387 + size_t num_bytes = 0;
42389 + /* we can't send more then SSIZE_MAX bytes in one chunk */
42391 + /* build writev list
42393 + * 1. limit: num_chunks < UIO_MAXIOV
42394 + * 2. limit: num_bytes < SSIZE_MAX
42396 + for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42398 + for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42399 + if (tc->mem->used == 0) {
42400 + chunks[i].iov_base = tc->mem->ptr;
42401 + chunks[i].iov_len = 0;
42403 + offset = tc->mem->ptr + tc->offset;
42404 + toSend = tc->mem->used - 1 - tc->offset;
42406 + chunks[i].iov_base = offset;
42408 + /* protect the return value of writev() */
42409 + if (toSend > SSIZE_MAX ||
42410 + num_bytes + toSend > SSIZE_MAX) {
42411 + chunks[i].iov_len = SSIZE_MAX - num_bytes;
42413 + num_chunks = i + 1;
42416 + chunks[i].iov_len = toSend;
42419 + num_bytes += toSend;
42423 + if ((r = writev(fd, chunks, num_chunks)) < 0) {
42426 + return NETWORK_STATUS_WAIT_FOR_EVENT;
42428 + return NETWORK_STATUS_INTERRUPTED;
42431 + return NETWORK_STATUS_CONNECTION_CLOSE;
42433 + log_error_write(srv, __FILE__, __LINE__, "ssd",
42434 + "writev failed:", strerror(errno), fd);
42436 + return NETWORK_STATUS_FATAL_ERROR;
42440 + cq->bytes_out += r;
42442 + /* check which chunks have been written */
42444 + for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42445 + if (r >= (ssize_t)chunks[i].iov_len) {
42447 + r -= chunks[i].iov_len;
42448 + tc->offset += chunks[i].iov_len;
42450 + /* partially written */
42454 + return NETWORK_STATUS_WAIT_FOR_EVENT;
42458 + /* all chunks have been pushed out */
42459 + return NETWORK_STATUS_SUCCESS;
42462 +NETWORK_BACKEND_WRITE(writev) {
42464 size_t chunks_written = 0;
42467 for(c = cq->first; c; c = c->next) {
42468 int chunk_finished = 0;
42470 + network_status_t ret;
42473 - case MEM_CHUNK: {
42478 - size_t num_chunks, i;
42479 - struct iovec chunks[UIO_MAXIOV];
42481 - size_t num_bytes = 0;
42483 - /* we can't send more then SSIZE_MAX bytes in one chunk */
42485 - /* build writev list
42487 - * 1. limit: num_chunks < UIO_MAXIOV
42488 - * 2. limit: num_bytes < SSIZE_MAX
42490 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42492 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42493 - if (tc->mem->used == 0) {
42494 - chunks[i].iov_base = tc->mem->ptr;
42495 - chunks[i].iov_len = 0;
42497 - offset = tc->mem->ptr + tc->offset;
42498 - toSend = tc->mem->used - 1 - tc->offset;
42500 - chunks[i].iov_base = offset;
42502 - /* protect the return value of writev() */
42503 - if (toSend > SSIZE_MAX ||
42504 - num_bytes + toSend > SSIZE_MAX) {
42505 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
42507 - num_chunks = i + 1;
42510 - chunks[i].iov_len = toSend;
42513 - num_bytes += toSend;
42517 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
42527 - log_error_write(srv, __FILE__, __LINE__, "ssd",
42528 - "writev failed:", strerror(errno), fd);
42534 - cq->bytes_out += r;
42536 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
42538 - /* check which chunks have been written */
42540 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42541 - if (r >= (ssize_t)chunks[i].iov_len) {
42543 - r -= chunks[i].iov_len;
42544 - tc->offset += chunks[i].iov_len;
42546 + /* check which chunks are finished now */
42547 + for (tc = c; tc; tc = tc->next) {
42548 + /* finished the chunk */
42549 + if (tc->offset == tc->mem->used - 1) {
42550 + /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
42551 if (chunk_finished) {
42552 - /* skip the chunks from further touches */
42553 - chunks_written++;
42556 - /* chunks_written + c = c->next is done in the for()*/
42557 - chunk_finished++;
42558 + chunk_finished = 1;
42561 - /* partially written */
42564 - chunk_finished = 0;
42571 + if (ret != NETWORK_STATUS_SUCCESS) {
42580 @@ -159,26 +175,26 @@
42581 #define KByte * 1024
42582 #define MByte * 1024 KByte
42583 #define GByte * 1024 MByte
42584 - const off_t we_want_to_mmap = 512 KByte;
42585 + const off_t we_want_to_mmap = 512 KByte;
42586 char *start = NULL;
42588 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42589 log_error_write(srv, __FILE__, __LINE__, "sb",
42590 strerror(errno), c->file.name);
42592 + return NETWORK_STATUS_FATAL_ERROR;
42595 abs_offset = c->file.start + c->offset;
42598 if (abs_offset > sce->st.st_size) {
42599 - log_error_write(srv, __FILE__, __LINE__, "sb",
42600 + log_error_write(srv, __FILE__, __LINE__, "sb",
42601 "file was shrinked:", c->file.name);
42605 + return NETWORK_STATUS_FATAL_ERROR;
42608 - /* mmap the buffer
42610 + /* mmap the buffer
42612 * - new mmap as the we are at the end of the last one */
42613 if (c->file.mmap.start == MAP_FAILED ||
42614 abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
42615 @@ -188,7 +204,7 @@
42616 * adaptive mem-mapping
42618 * we mmap() the whole file. If someone has alot large files and 32bit
42619 - * machine the virtual address area will be unrun and we will have a failing
42620 + * machine the virtual address area will be unrun and we will have a failing
42623 * only mmap 16M in one chunk and move the window as soon as we have finished
42624 @@ -234,8 +250,8 @@
42625 if (-1 == c->file.fd) { /* open the file if not already open */
42626 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
42627 log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
42631 + return NETWORK_STATUS_FATAL_ERROR;
42634 fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
42635 @@ -245,10 +261,10 @@
42636 if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
42637 /* close it here, otherwise we'd have to set FD_CLOEXEC */
42639 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
42640 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
42641 strerror(errno), c->file.name, c->file.fd);
42644 + return NETWORK_STATUS_FATAL_ERROR;
42647 c->file.mmap.length = to_mmap;
42648 @@ -258,7 +274,7 @@
42649 #ifdef HAVE_MADVISE
42650 /* don't advise files < 64Kb */
42651 if (c->file.mmap.length > (64 KByte)) {
42652 - /* darwin 7 is returning EINVAL all the time and I don't know how to
42653 + /* darwin 7 is returning EINVAL all the time and I don't know how to
42654 * detect this at runtime.i
42656 * ignore the return value for now */
42657 @@ -274,12 +290,12 @@
42658 toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
42661 - log_error_write(srv, __FILE__, __LINE__, "soooo",
42662 + log_error_write(srv, __FILE__, __LINE__, "soooo",
42663 "toSend is negative:",
42665 c->file.mmap.length,
42667 - c->file.mmap.offset);
42668 + c->file.mmap.offset);
42669 assert(toSend < 0);
42672 @@ -297,18 +313,18 @@
42677 + return NETWORK_STATUS_CONNECTION_CLOSE;
42679 - log_error_write(srv, __FILE__, __LINE__, "ssd",
42680 + log_error_write(srv, __FILE__, __LINE__, "ssd",
42681 "write failed:", strerror(errno), fd);
42685 + return NETWORK_STATUS_FATAL_ERROR;
42691 cq->bytes_out += r;
42694 if (c->offset == c->file.length) {
42695 chunk_finished = 1;
42697 @@ -318,26 +334,26 @@
42698 c->file.mmap.start = MAP_FAILED;
42708 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42712 + return NETWORK_STATUS_FATAL_ERROR;
42716 if (!chunk_finished) {
42717 /* not finished yet */
42727 - return chunks_written;
42728 + return NETWORK_STATUS_SUCCESS;
42732 --- ../lighttpd-1.4.11/src/plugin.c 2006-02-08 14:00:54.000000000 +0200
42733 +++ lighttpd-1.4.12/src/plugin.c 2006-07-11 22:07:52.000000000 +0300
42734 @@ -13,27 +13,27 @@
42735 #include <valgrind/valgrind.h>
42745 * if you change this enum to add a new callback, be sure
42746 * - that PLUGIN_FUNC_SIZEOF is the last entry
42747 * - that you add PLUGIN_TO_SLOT twice:
42748 - * 1. as callback-dispatcher
42749 + * 1. as callback-dispatcher
42750 * 2. in plugins_call_init()
42762 - PLUGIN_FUNC_HANDLE_URI_CLEAN,
42763 - PLUGIN_FUNC_HANDLE_URI_RAW,
42764 + PLUGIN_FUNC_HANDLE_URI_CLEAN,
42765 + PLUGIN_FUNC_HANDLE_URI_RAW,
42766 PLUGIN_FUNC_HANDLE_REQUEST_DONE,
42767 PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
42768 PLUGIN_FUNC_HANDLE_TRIGGER,
42769 @@ -44,38 +44,42 @@
42770 PLUGIN_FUNC_HANDLE_DOCROOT,
42771 PLUGIN_FUNC_HANDLE_PHYSICAL,
42772 PLUGIN_FUNC_CONNECTION_RESET,
42773 - PLUGIN_FUNC_INIT,
42774 + PLUGIN_FUNC_INIT,
42775 PLUGIN_FUNC_CLEANUP,
42776 PLUGIN_FUNC_SET_DEFAULTS,
42782 static plugin *plugin_init(void) {
42786 p = calloc(1, sizeof(*p));
42789 + p->required_plugins = array_init();
42794 static void plugin_free(plugin *p) {
42795 int use_dlclose = 1;
42796 if (p->name) buffer_free(p->name);
42798 + array_free(p->required_plugins);
42799 #ifdef HAVE_VALGRIND_VALGRIND_H
42800 /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
42803 #ifndef LIGHTTPD_STATIC
42804 - if (use_dlclose && p->lib) {
42806 + if (use_dlclose && p->lib) {
42808 FreeLibrary(p->lib);
42819 @@ -89,17 +93,17 @@
42820 srv->plugins.size += 4;
42821 srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
42825 ps = srv->plugins.ptr;
42826 ps[srv->plugins.used++] = p;
42841 #ifdef LIGHTTPD_STATIC
42842 @@ -121,30 +125,35 @@
42844 int plugins_load(server *srv) {
42849 int (*init)(plugin *pl);
42857 for (i = 0; i < srv->srvconf.modules->used; i++) {
42858 data_string *d = (data_string *)srv->srvconf.modules->data[i];
42859 char *modules = d->value->ptr;
42862 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
42864 buffer_append_string(srv->tmp_buf, "/");
42865 buffer_append_string(srv->tmp_buf, modules);
42866 -#if defined(__WIN32) || defined(__CYGWIN__)
42867 +#if defined(_WIN32) || defined(__CYGWIN__)
42868 buffer_append_string(srv->tmp_buf, ".dll");
42870 buffer_append_string(srv->tmp_buf, ".so");
42877 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
42880 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
42881 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
42882 FORMAT_MESSAGE_FROM_SYSTEM,
42885 @@ -152,36 +161,36 @@
42886 (LPTSTR) &lpMsgBuf,
42889 - log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
42890 + log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
42891 lpMsgBuf, srv->tmp_buf);
42902 if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
42903 - log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
42904 + log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
42905 srv->tmp_buf, dlerror());
42916 buffer_reset(srv->tmp_buf);
42917 buffer_copy_string(srv->tmp_buf, modules);
42918 buffer_append_string(srv->tmp_buf, "_plugin_init");
42922 init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
42924 if (init == NULL) {
42927 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
42928 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
42929 FORMAT_MESSAGE_FROM_SYSTEM,
42932 @@ -190,7 +199,7 @@
42935 log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
42941 @@ -203,24 +212,43 @@
42943 if ((error = dlerror()) != NULL) {
42944 log_error_write(srv, __FILE__, __LINE__, "s", error);
42954 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
42961 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
42963 + /* check if the required plugin is loaded */
42964 + for (k = 0; k < p->required_plugins->used; k++) {
42965 + data_string *req = (data_string *)p->required_plugins->data[k];
42967 + for (j = 0; j < i; j++) {
42968 + data_string *mod = (data_string *)srv->srvconf.modules->data[j];
42970 + if (buffer_is_equal(req->value, mod->value)) break;
42975 + log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
42982 plugins_register(srv, p);
42989 @@ -253,8 +281,8 @@
42993 - * plugins that use
42995 + * plugins that use
42998 * - connection *con
42999 * - void *p_d (plugin_data *)
43000 @@ -301,12 +329,12 @@
43004 - * plugins that use
43006 + * plugins that use
43009 * - void *p_d (plugin_data *)
43013 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
43014 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
43015 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
43016 @@ -314,18 +342,18 @@
43018 #undef PLUGIN_TO_SLOT
43029 handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
43034 ps = srv->plugins.ptr;
43037 for (i = 0; i < srv->plugins.used; i++) {
43039 if (p->handle_fdevent) {
43040 @@ -344,34 +372,34 @@
43046 return HANDLER_GO_ON;
43052 * - call init function of all plugins to init the plugin-internals
43053 * - added each plugin that supports has callback to the corresponding slot
43056 * - is only called once.
43059 handler_t plugins_call_init(server *srv) {
43064 ps = srv->plugins.ptr;
43070 srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
43073 for (i = 0; i < srv->plugins.used; i++) {
43075 /* check which calls are supported */
43081 #define PLUGIN_TO_SLOT(x, y) \
43083 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
43084 @@ -384,11 +412,11 @@
43091 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
43092 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
43096 + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
43097 + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
43098 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
43099 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
43100 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
43101 @@ -402,19 +430,19 @@
43102 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
43103 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
43104 #undef PLUGIN_TO_SLOT
43108 if (NULL == (p->data = p->init())) {
43109 - log_error_write(srv, __FILE__, __LINE__, "sb",
43110 + log_error_write(srv, __FILE__, __LINE__, "sb",
43111 "plugin-init failed for module", p->name);
43112 return HANDLER_ERROR;
43116 /* used for con->mode, DIRECT == 0, plugins above that */
43117 ((plugin_data *)(p->data))->id = i + 1;
43120 if (p->version != LIGHTTPD_VERSION_ID) {
43121 - log_error_write(srv, __FILE__, __LINE__, "sb",
43122 + log_error_write(srv, __FILE__, __LINE__, "sb",
43123 "plugin-version doesn't match lighttpd-version for", p->name);
43124 return HANDLER_ERROR;
43126 @@ -422,29 +450,46 @@
43132 return HANDLER_GO_ON;
43136 + * get the config-storage of the named plugin
43138 +void *plugin_get_config(server *srv, const char *name) {
43141 + for (i = 0; i < srv->plugins.used; i++) {
43142 + plugin *p = ((plugin **)srv->plugins.ptr)[i];
43144 + if (buffer_is_equal_string(p->name, name, strlen(name))) {
43152 void plugins_free(server *srv) {
43154 plugins_call_cleanup(srv);
43157 for (i = 0; i < srv->plugins.used; i++) {
43158 plugin *p = ((plugin **)srv->plugins.ptr)[i];
43165 for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
43166 plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
43169 if (slot) free(slot);
43173 free(srv->plugin_slots);
43174 srv->plugin_slots = NULL;
43177 free(srv->plugins.ptr);
43178 srv->plugins.ptr = NULL;
43179 srv->plugins.used = 0;
43180 --- ../lighttpd-1.4.11/src/plugin.h 2005-08-15 12:28:56.000000000 +0300
43181 +++ lighttpd-1.4.12/src/plugin.h 2006-07-11 22:07:52.000000000 +0300
43184 #define INIT_FUNC(x) \
43187 + * The PATCH_OPTION() macro is used in the patch_connection() functions
43188 + * of the modules to update the config object for the current request.
43190 +#define PATCH_OPTION(x) \
43193 #define FREE_FUNC SERVER_FUNC
43194 #define TRIGGER_FUNC SERVER_FUNC
43195 @@ -25,19 +31,19 @@
43196 #define URIHANDLER_FUNC CONNECTION_FUNC
43198 #define PLUGIN_DATA size_t id
43205 buffer *name; /* name of the plugin */
43209 handler_t (* set_defaults) (server *srv, void *p_d);
43210 handler_t (* cleanup) (server *srv, void *p_d);
43211 /* is called ... */
43212 handler_t (* handle_trigger) (server *srv, void *p_d); /* once a second */
43213 handler_t (* handle_sighup) (server *srv, void *p_d); /* at a signup */
43216 handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d); /* after uri_raw is set */
43217 handler_t (* handle_uri_clean) (server *srv, connection *con, void *p_d); /* after uri is set */
43218 handler_t (* handle_docroot) (server *srv, connection *con, void *p_d); /* getting the document-root */
43219 @@ -45,20 +51,22 @@
43220 handler_t (* handle_request_done) (server *srv, connection *con, void *p_d); /* at the end of a request */
43221 handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d); /* at the end of a connection */
43222 handler_t (* handle_joblist) (server *srv, connection *con, void *p_d); /* after all events are handled */
43226 - handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43228 - /* when a handler for the request
43232 + handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43234 + /* when a handler for the request
43237 handler_t (* handle_subrequest) (server *srv, connection *con, void *p_d); /* */
43238 handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* */
43242 /* dlopen handle */
43245 + array *required_plugins;
43248 int plugins_load(server *srv);
43250 int config_patch_connection(server *srv, connection *con, comp_key_t comp);
43251 int config_check_cond(server *srv, connection *con, data_config *dc);
43252 int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
43253 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
43255 +void *plugin_get_config(server *srv, const char *name);
43258 --- ../lighttpd-1.4.11/src/proc_open.c 2005-08-11 01:26:39.000000000 +0300
43259 +++ lighttpd-1.4.12/src/proc_open.c 2006-07-11 22:07:53.000000000 +0300
43260 @@ -13,13 +13,13 @@
43266 /* {{{ win32 stuff */
43267 # define SHELLENV "ComSpec"
43268 # define SECURITY_DC , SECURITY_ATTRIBUTES *security
43269 # define SECURITY_CC , security
43270 # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
43271 -static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43272 +static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43274 HANDLE copy, self = GetCurrentProcess();
43276 @@ -148,11 +148,14 @@
43279 SECURITY_ATTRIBUTES security;
43280 - const char *shell;
43281 + const char *shell = NULL;
43282 + const char *windir = NULL;
43285 - if (NULL == (shell = getenv(SHELLENV))) {
43286 - fprintf(stderr, "env %s is required", SHELLENV);
43287 + if (NULL == (shell = getenv(SHELLENV)) &&
43288 + NULL == (windir = getenv("SystemRoot")) &&
43289 + NULL == (windir = getenv("windir"))) {
43290 + fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
43294 @@ -177,17 +180,23 @@
43295 memset(&pi, 0, sizeof(pi));
43297 cmdline = buffer_init();
43298 - buffer_append_string(cmdline, shell);
43300 + buffer_append_string(cmdline, shell);
43302 + buffer_append_string(cmdline, windir);
43303 + buffer_append_string(cmdline, "\\system32\\cmd.exe");
43305 buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
43306 buffer_append_string(cmdline, command);
43307 procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
43308 NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
43309 - buffer_free(cmdline);
43311 if (FALSE == procok) {
43312 - fprintf(stderr, "failed to CreateProcess");
43313 + fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
43314 + buffer_free(cmdline);
43317 + buffer_free(cmdline);
43319 proc->child = pi.hProcess;
43320 CloseHandle(pi.hThread);
43321 @@ -226,8 +235,7 @@
43324 if (NULL == (shell = getenv(SHELLENV))) {
43325 - fprintf(stderr, "env %s is required", SHELLENV);
43327 + shell = "/bin/sh";
43330 if (proc_open_pipes(proc) != 0) {
43331 @@ -262,11 +270,11 @@
43335 -#endif /* WIN32 */
43336 +#endif /* _WIN32 */
43338 /* {{{ proc_read_fd_to_buffer */
43339 static void proc_read_fd_to_buffer(int fd, buffer *b) {
43341 + int s; /* win32 has not ssize_t */
43344 buffer_prepare_append(b, 512);
43345 --- ../lighttpd-1.4.11/src/proc_open.h 2005-08-11 01:26:39.000000000 +0300
43346 +++ lighttpd-1.4.12/src/proc_open.h 2006-07-11 22:07:53.000000000 +0300
43349 #include "buffer.h"
43353 #include <windows.h>
43354 typedef HANDLE descriptor_t;
43355 typedef HANDLE proc_pid_t;
43356 --- ../lighttpd-1.4.11/src/request.c 2006-03-05 11:58:09.000000000 +0200
43357 +++ lighttpd-1.4.12/src/request.c 2006-07-11 22:07:52.000000000 +0300
43358 @@ -10,15 +10,17 @@
43359 #include "keyvalue.h"
43362 +#include "sys-strings.h"
43364 static int request_check_hostname(server *srv, connection *con, buffer *host) {
43365 enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
43370 - int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
43371 + int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
43378 @@ -32,17 +34,17 @@
43379 * IPv6address = "[" ... "]"
43385 if (!host || host->used == 0) return 0;
43388 host_len = host->used - 1;
43392 if (host->ptr[0] == '[') {
43393 char *c = host->ptr + 1;
43397 /* check portnumber */
43398 for (; *c && *c != ']'; c++) {
43400 @@ -53,12 +55,12 @@
43413 if (*(c+1) == ':') {
43414 for (c += 2; *c; c++) {
43415 @@ -69,39 +71,39 @@
43421 if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
43422 char *c = colon + 1;
43425 /* check portnumber */
43427 if (!light_isdigit(*c)) return -1;
43431 /* remove the port from the host-len */
43432 host_len = colon - host->ptr;
43436 /* Host is empty */
43437 if (host_len == 0) return -1;
43440 /* scan from the right and skip the \0 */
43441 for (i = host_len - 1; i + 1 > 0; i--) {
43442 const char c = host->ptr[i];
43448 /* only switch stage, if this is not the last character */
43449 if (i != host_len - 1) {
43450 if (label_len == 0) {
43455 /* check the first character at right of the dot */
43457 if (!light_isalpha(host->ptr[i+1])) {
43461 } else if (!light_isdigit(host->ptr[i+1])) {
43463 @@ -111,9 +113,9 @@
43469 stage = DOMAINLABEL;
43474 } else if (i == 0) {
43475 @@ -135,7 +137,7 @@
43484 @@ -143,7 +145,7 @@
43485 if (label_len == 0) {
43492 } else if (!light_isdigit(c)) {
43493 @@ -156,12 +158,12 @@
43494 if (label_len == 0) {
43499 /* c is either - or alphanum here */
43500 if ('-' == host->ptr[i+1]) {
43507 } else if (i == 0) {
43508 @@ -176,20 +178,20 @@
43519 /* a IP has to consist of 4 parts */
43520 if (is_ip == 1 && level != 3) {
43525 if (label_len == 0) {
43533 @@ -201,53 +203,53 @@
43543 * val1, val2, val3, val4
43546 * into a array (more or less a explode() incl. striping of whitespaces
43550 if (b->used == 0) return 0;
43556 for (i =0; i < b->used - 1; ) {
43557 char *start = NULL, *end = NULL;
43566 for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
43573 case 1: /* value */
43577 for (; *s != ',' && i < b->used - 1; i++, s++);
43581 for (; (*end == ' ' || *end == '\t') && end > start; end--);
43584 if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
43585 ds = data_string_init();
43588 buffer_copy_string_len(ds->value, start, end-start+1);
43589 array_insert_unique(vals, (data_unset *)ds);
43597 /* end of string */
43603 @@ -263,7 +265,7 @@
43604 if (c <= 32) return 0;
43605 if (c == 127) return 0;
43606 if (c == 255) return 0;
43612 @@ -271,28 +273,28 @@
43613 char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
43614 int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
43615 char *value = NULL, *key = NULL;
43618 enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
43624 int request_line_stage = 0;
43631 data_string *ds = NULL;
43634 - * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43635 - * Option : "^([-a-zA-Z]+): (.+)$"
43638 + * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43639 + * Option : "^([-a-zA-Z]+): (.+)$"
43643 if (con->conf.log_request_header) {
43644 - log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43646 - "request-len:", con->request.request->used,
43647 + log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43649 + "request-len:", con->request.request->used,
43650 "\n", con->request.request);
43653 @@ -300,13 +302,13 @@
43654 con->request.request->ptr[0] == '\r' &&
43655 con->request.request->ptr[1] == '\n') {
43656 /* we are in keep-alive and might get \r\n after a previous POST request.*/
43659 buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
43661 /* fill the local request buffer */
43662 buffer_copy_string_buffer(con->parse_request, con->request.request);
43666 keep_alive_set = 0;
43667 con_length_set = 0;
43669 @@ -318,25 +320,25 @@
43671 for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
43672 char *cur = con->parse_request->ptr + i;
43678 if (con->parse_request->ptr[i+1] == '\n') {
43685 con->parse_request->ptr[i] = '\0';
43686 con->parse_request->ptr[i+1] = '\0';
43689 buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
43692 if (request_line_stage != 2) {
43693 con->http_status = 400;
43694 con->response.keep_alive = 0;
43695 con->keep_alive = 0;
43698 if (srv->srvconf.log_request_header_on_error) {
43699 log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
43700 log_error_write(srv, __FILE__, __LINE__, "Sb",
43701 @@ -345,36 +347,36 @@
43707 proto = con->parse_request->ptr + first;
43711 *(proto - 1) = '\0';
43714 /* we got the first one :) */
43715 if (-1 == (r = get_http_method_key(method))) {
43716 con->http_status = 501;
43717 con->response.keep_alive = 0;
43718 con->keep_alive = 0;
43721 if (srv->srvconf.log_request_header_on_error) {
43722 log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
43723 log_error_write(srv, __FILE__, __LINE__, "Sb",
43724 "request-header:\n",
43725 con->request.request);
43733 con->request.http_method = r;
43740 * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
43744 if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
43745 char * major = proto + sizeof("HTTP/") - 1;
43746 char * minor = strchr(major, '.');
43747 @@ -413,10 +415,10 @@
43750 if (major_num == 1 && minor_num == 1) {
43751 - con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
43752 + con->request.http_version = HTTP_VERSION_1_1;
43753 } else if (major_num == 1 && minor_num == 0) {
43754 con->request.http_version = HTTP_VERSION_1_0;
43757 con->http_status = 505;
43759 if (srv->srvconf.log_request_header_on_error) {
43760 @@ -439,30 +441,30 @@
43766 if (0 == strncmp(uri, "http://", 7) &&
43767 NULL != (nuri = strchr(uri + 7, '/'))) {
43768 /* ignore the host-part */
43771 buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
43773 /* everything looks good so far */
43774 buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
43778 /* check uri for invalid characters */
43779 for (j = 0; j < con->request.uri->used - 1; j++) {
43780 if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
43781 unsigned char buf[2];
43782 con->http_status = 400;
43783 con->keep_alive = 0;
43786 if (srv->srvconf.log_request_header_on_error) {
43787 buf[0] = con->request.uri->ptr[j];
43791 if (con->request.uri->ptr[j] > 32 &&
43792 - con->request.uri->ptr[j] != 127) {
43793 + con->request.uri->ptr[j] != 127) {
43794 /* the character is printable -> print it */
43795 log_error_write(srv, __FILE__, __LINE__, "ss",
43796 "invalid character in URI -> 400",
43797 @@ -473,20 +475,20 @@
43798 "invalid character in URI -> 400",
43799 con->request.uri->ptr[j]);
43803 log_error_write(srv, __FILE__, __LINE__, "Sb",
43804 "request-header:\n",
43805 con->request.request);
43814 buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
43817 con->http_status = 0;
43823 @@ -494,14 +496,14 @@
43826 switch(request_line_stage) {
43830 - method = con->parse_request->ptr + first;
43831 + method = con->parse_request->ptr + first;
43836 - uri = con->parse_request->ptr + first;
43837 + uri = con->parse_request->ptr + first;
43841 @@ -509,7 +511,7 @@
43842 con->http_status = 400;
43843 con->response.keep_alive = 0;
43844 con->keep_alive = 0;
43847 if (srv->srvconf.log_request_header_on_error) {
43848 log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
43849 log_error_write(srv, __FILE__, __LINE__, "Sb",
43850 @@ -518,12 +520,12 @@
43856 request_line_stage++;
43864 if (con->request.uri->used == 1) {
43865 @@ -540,30 +542,30 @@
43871 for (; i < con->parse_request->used && !done; i++) {
43872 char *cur = con->parse_request->ptr + i;
43881 * 1*<any CHAR except CTLs or separators>
43882 * CTLs == 0-31 + 127
43894 if (is_ws_after_key == 0) {
43895 key_len = i - first;
43897 is_ws_after_key = 0;
43903 @@ -584,8 +586,8 @@
43904 con->http_status = 400;
43905 con->keep_alive = 0;
43906 con->response.keep_alive = 0;
43908 - log_error_write(srv, __FILE__, __LINE__, "sbsds",
43910 + log_error_write(srv, __FILE__, __LINE__, "sbsds",
43911 "invalid character in key", con->request.request, cur, *cur, "-> 400");
43914 @@ -594,13 +596,13 @@
43926 key_len = i - first;
43929 /* skip every thing up to the : */
43930 for (j = 1; !got_colon; j++) {
43931 switch(con->parse_request->ptr[j + i]) {
43932 @@ -610,40 +612,40 @@
43947 if (srv->srvconf.log_request_header_on_error) {
43948 log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
43949 log_error_write(srv, __FILE__, __LINE__, "Sb",
43950 "request-header:\n",
43951 con->request.request);
43955 con->http_status = 400;
43956 con->response.keep_alive = 0;
43957 con->keep_alive = 0;
43967 if (con->parse_request->ptr[i+1] == '\n' && i == first) {
43968 /* End of Header */
43969 con->parse_request->ptr[i] = '\0';
43970 con->parse_request->ptr[i+1] = '\0';
43981 if (srv->srvconf.log_request_header_on_error) {
43982 @@ -652,7 +654,7 @@
43983 "request-header:\n",
43984 con->request.request);
43988 con->http_status = 400;
43989 con->keep_alive = 0;
43990 con->response.keep_alive = 0;
43991 @@ -693,16 +695,16 @@
43992 con->http_status = 400;
43993 con->keep_alive = 0;
43994 con->response.keep_alive = 0;
43997 if (srv->srvconf.log_request_header_on_error) {
43998 - log_error_write(srv, __FILE__, __LINE__, "sbsds",
43999 + log_error_write(srv, __FILE__, __LINE__, "sbsds",
44000 "CTL character in key", con->request.request, cur, *cur, "-> 400");
44002 log_error_write(srv, __FILE__, __LINE__, "Sb",
44003 "request-header:\n",
44004 con->request.request);
44011 @@ -710,25 +712,25 @@
44017 if (con->parse_request->ptr[i+1] == '\n') {
44018 /* End of Headerline */
44019 con->parse_request->ptr[i] = '\0';
44020 con->parse_request->ptr[i+1] = '\0';
44028 if (srv->srvconf.log_request_header_on_error) {
44029 log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
44032 log_error_write(srv, __FILE__, __LINE__, "Sb",
44033 "request-header:\n",
44034 con->request.request);
44039 con->http_status = 400;
44040 con->keep_alive = 0;
44041 con->response.keep_alive = 0;
44042 @@ -738,9 +740,9 @@
44045 key = con->parse_request->ptr + first;
44048 s_len = cur - value;
44053 if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
44054 @@ -748,86 +750,87 @@
44056 buffer_copy_string_len(ds->key, key, key_len);
44057 buffer_copy_string_len(ds->value, value, s_len);
44059 - /* retreive values
44063 + /* retreive values
44066 * the list of options is sorted to simplify the search
44070 if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
44078 vals = srv->split_vals;
44083 http_request_split_value(vals, ds->value);
44086 for (vi = 0; vi < vals->used; vi++) {
44087 data_string *dsv = (data_string *)vals->data[vi];
44090 if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
44091 keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
44095 } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
44096 keep_alive_set = HTTP_CONNECTION_CLOSE;
44104 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
44106 unsigned long int r;
44110 if (con_length_set) {
44111 con->http_status = 400;
44112 con->keep_alive = 0;
44115 if (srv->srvconf.log_request_header_on_error) {
44116 - log_error_write(srv, __FILE__, __LINE__, "s",
44117 + log_error_write(srv, __FILE__, __LINE__, "s",
44118 "duplicate Content-Length-header -> 400");
44119 log_error_write(srv, __FILE__, __LINE__, "Sb",
44120 "request-header:\n",
44121 con->request.request);
44123 + ds->free((data_unset *) ds);
44128 if (ds->value->used == 0) SEGFAULT();
44131 for (j = 0; j < ds->value->used - 1; j++) {
44132 char c = ds->value->ptr[j];
44133 if (!isdigit((unsigned char)c)) {
44134 - log_error_write(srv, __FILE__, __LINE__, "sbs",
44135 + log_error_write(srv, __FILE__, __LINE__, "sbs",
44136 "content-length broken:", ds->value, "-> 400");
44139 con->http_status = 400;
44140 con->keep_alive = 0;
44143 array_insert_unique(con->request.headers, (data_unset *)ds);
44149 r = strtoul(ds->value->ptr, &err, 10);
44152 if (*err == '\0') {
44153 con_length_set = 1;
44154 con->request.content_length = r;
44156 - log_error_write(srv, __FILE__, __LINE__, "sbs",
44157 + log_error_write(srv, __FILE__, __LINE__, "sbs",
44158 "content-length broken:", ds->value, "-> 400");
44161 con->http_status = 400;
44162 con->keep_alive = 0;
44165 array_insert_unique(con->request.headers, (data_unset *)ds);
44168 @@ -838,23 +841,24 @@
44170 con->http_status = 400;
44171 con->keep_alive = 0;
44174 if (srv->srvconf.log_request_header_on_error) {
44175 - log_error_write(srv, __FILE__, __LINE__, "s",
44176 + log_error_write(srv, __FILE__, __LINE__, "s",
44177 "duplicate Content-Type-header -> 400");
44178 log_error_write(srv, __FILE__, __LINE__, "Sb",
44179 "request-header:\n",
44180 con->request.request);
44182 + ds->free((data_unset *) ds);
44185 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
44186 - /* HTTP 2616 8.2.3
44187 + /* HTTP 2616 8.2.3
44188 * Expect: 100-continue
44191 * -> (10.1.1) 100 (read content, process request, send final status-code)
44192 * -> (10.4.18) 417 (close)
44195 * (not handled at all yet, we always send 417 here)
44197 * What has to be added ?
44198 @@ -863,10 +867,10 @@
44204 con->http_status = 417;
44205 con->keep_alive = 0;
44208 array_insert_unique(con->request.headers, (data_unset *)ds);
44210 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
44211 @@ -875,14 +879,15 @@
44213 con->http_status = 400;
44214 con->keep_alive = 0;
44217 if (srv->srvconf.log_request_header_on_error) {
44218 - log_error_write(srv, __FILE__, __LINE__, "s",
44219 + log_error_write(srv, __FILE__, __LINE__, "s",
44220 "duplicate Host-header -> 400");
44221 log_error_write(srv, __FILE__, __LINE__, "Sb",
44222 "request-header:\n",
44223 con->request.request);
44225 + ds->free((data_unset *) ds);
44228 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
44229 @@ -897,14 +902,15 @@
44231 con->http_status = 400;
44232 con->keep_alive = 0;
44235 if (srv->srvconf.log_request_header_on_error) {
44236 - log_error_write(srv, __FILE__, __LINE__, "s",
44237 + log_error_write(srv, __FILE__, __LINE__, "s",
44238 "duplicate If-Modified-Since header -> 400");
44239 log_error_write(srv, __FILE__, __LINE__, "Sb",
44240 "request-header:\n",
44241 con->request.request);
44243 + ds->free((data_unset *) ds);
44246 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
44247 @@ -914,47 +920,49 @@
44249 con->http_status = 400;
44250 con->keep_alive = 0;
44253 if (srv->srvconf.log_request_header_on_error) {
44254 - log_error_write(srv, __FILE__, __LINE__, "s",
44255 + log_error_write(srv, __FILE__, __LINE__, "s",
44256 "duplicate If-None-Match-header -> 400");
44257 log_error_write(srv, __FILE__, __LINE__, "Sb",
44258 "request-header:\n",
44259 con->request.request);
44261 + ds->free((data_unset *) ds);
44264 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
44265 if (!con->request.http_range) {
44269 if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
44270 NULL != strchr(ds->value->ptr+6, '-')) {
44273 /* if dup, only the first one will survive */
44274 con->request.http_range = ds->value->ptr + 6;
44277 con->http_status = 400;
44278 con->keep_alive = 0;
44281 if (srv->srvconf.log_request_header_on_error) {
44282 - log_error_write(srv, __FILE__, __LINE__, "s",
44283 + log_error_write(srv, __FILE__, __LINE__, "s",
44284 "duplicate Range-header -> 400");
44285 log_error_write(srv, __FILE__, __LINE__, "Sb",
44286 "request-header:\n",
44287 con->request.request);
44289 + ds->free((data_unset *) ds);
44295 array_insert_unique(con->request.headers, (data_unset *)ds);
44297 /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
44305 @@ -963,10 +971,10 @@
44308 if (srv->srvconf.log_request_header_on_error) {
44309 - log_error_write(srv, __FILE__, __LINE__, "sbs",
44310 + log_error_write(srv, __FILE__, __LINE__, "sbs",
44311 "CR without LF", con->request.request, "-> 400");
44315 con->http_status = 400;
44316 con->keep_alive = 0;
44317 con->response.keep_alive = 0;
44318 @@ -982,28 +990,28 @@
44324 con->header_len = i;
44327 /* do some post-processing */
44329 if (con->request.http_version == HTTP_VERSION_1_1) {
44330 if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
44331 /* no Connection-Header sent */
44334 /* HTTP/1.1 -> keep-alive default TRUE */
44335 con->keep_alive = 1;
44337 con->keep_alive = 0;
44341 /* RFC 2616, 14.23 */
44342 if (con->request.http_host == NULL ||
44343 buffer_is_empty(con->request.http_host)) {
44344 con->http_status = 400;
44345 con->response.keep_alive = 0;
44346 con->keep_alive = 0;
44349 if (srv->srvconf.log_request_header_on_error) {
44350 log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
44351 log_error_write(srv, __FILE__, __LINE__, "Sb",
44352 @@ -1015,18 +1023,18 @@
44354 if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
44355 /* no Connection-Header sent */
44358 /* HTTP/1.0 -> keep-alive default FALSE */
44359 con->keep_alive = 1;
44361 con->keep_alive = 0;
44366 /* check hostname field if it is set */
44367 if (NULL != con->request.http_host &&
44368 0 != request_check_hostname(srv, con, con->request.http_host)) {
44371 if (srv->srvconf.log_request_header_on_error) {
44372 log_error_write(srv, __FILE__, __LINE__, "s",
44373 "Invalid Hostname -> 400");
44374 @@ -1038,7 +1046,7 @@
44375 con->http_status = 400;
44376 con->response.keep_alive = 0;
44377 con->keep_alive = 0;
44383 @@ -1048,7 +1056,7 @@
44384 /* content-length is forbidden for those */
44385 if (con_length_set && con->request.content_length != 0) {
44386 /* content-length is missing */
44387 - log_error_write(srv, __FILE__, __LINE__, "s",
44388 + log_error_write(srv, __FILE__, __LINE__, "s",
44389 "GET/HEAD with content-length -> 400");
44391 con->keep_alive = 0;
44392 @@ -1060,7 +1068,7 @@
44393 /* content-length is required for them */
44394 if (!con_length_set) {
44395 /* content-length is missing */
44396 - log_error_write(srv, __FILE__, __LINE__, "s",
44397 + log_error_write(srv, __FILE__, __LINE__, "s",
44398 "POST-request, but content-length missing -> 411");
44400 con->keep_alive = 0;
44401 @@ -1073,16 +1081,16 @@
44402 /* the may have a content-length */
44409 /* check if we have read post data */
44410 if (con_length_set) {
44411 /* don't handle more the SSIZE_MAX bytes in content-length */
44412 if (con->request.content_length > SSIZE_MAX) {
44413 - con->http_status = 413;
44414 + con->http_status = 413;
44415 con->keep_alive = 0;
44417 - log_error_write(srv, __FILE__, __LINE__, "sds",
44418 + log_error_write(srv, __FILE__, __LINE__, "sds",
44419 "request-size too long:", con->request.content_length, "-> 413");
44422 @@ -1090,25 +1098,25 @@
44423 /* divide by 1024 as srvconf.max_request_size is in kBytes */
44424 if (srv->srvconf.max_request_size != 0 &&
44425 (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
44426 - /* the request body itself is larger then
44427 + /* the request body itself is larger then
44428 * our our max_request_size
44432 con->http_status = 413;
44433 con->keep_alive = 0;
44435 - log_error_write(srv, __FILE__, __LINE__, "sds",
44437 + log_error_write(srv, __FILE__, __LINE__, "sds",
44438 "request-size too long:", con->request.content_length, "-> 413");
44445 /* we have content */
44446 if (con->request.content_length != 0) {
44455 @@ -1116,9 +1124,9 @@
44458 if (con->request.request->used < 5) return 0;
44461 if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
44462 if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
44467 --- ../lighttpd-1.4.11/src/response.c 2006-03-04 16:41:39.000000000 +0200
44468 +++ lighttpd-1.4.12/src/response.c 2006-07-11 22:07:52.000000000 +0300
44470 #include <stdlib.h>
44471 #include <string.h>
44473 -#include <unistd.h>
44475 #include <assert.h>
44477 @@ -24,15 +23,17 @@
44478 #include "plugin.h"
44480 #include "sys-socket.h"
44481 +#include "sys-files.h"
44482 +#include "sys-strings.h"
44484 int http_response_write_header(server *srv, connection *con) {
44488 int have_server = 0;
44491 b = chunkqueue_get_prepend_buffer(con->write_queue);
44494 if (con->request.http_version == HTTP_VERSION_1_1) {
44495 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
44497 @@ -41,25 +42,26 @@
44498 buffer_append_long(b, con->http_status);
44499 BUFFER_APPEND_STRING_CONST(b, " ");
44500 buffer_append_string(b, get_http_status_name(con->http_status));
44503 if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
44504 BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
44505 buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
44509 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
44510 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
44516 /* add all headers */
44517 for (i = 0; i < con->response.headers->used; i++) {
44521 ds = (data_string *)con->response.headers->data[i];
44524 if (ds->value->used && ds->key->used &&
44525 - 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
44526 + 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
44527 + 0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
44528 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
44529 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
44531 @@ -68,28 +70,28 @@
44532 BUFFER_APPEND_STRING_CONST(b, ": ");
44533 buffer_append_string_buffer(b, ds->value);
44535 - log_error_write(srv, __FILE__, __LINE__, "bb",
44536 + log_error_write(srv, __FILE__, __LINE__, "bb",
44537 ds->key, ds->value);
44544 /* HTTP/1.1 requires a Date: header */
44545 BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
44548 /* cache the generated timestamp */
44549 if (srv->cur_ts != srv->last_generated_date_ts) {
44550 buffer_prepare_copy(srv->ts_date_str, 255);
44552 - strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
44554 + strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
44555 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
44558 srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
44561 srv->last_generated_date_ts = srv->cur_ts;
44565 buffer_append_string_buffer(b, srv->ts_date_str);
44568 @@ -101,16 +103,16 @@
44569 buffer_append_string_buffer(b, con->conf.server_tag);
44574 BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
44579 con->bytes_header = b->used - 1;
44582 if (con->conf.log_response_header) {
44583 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
44590 @@ -118,71 +120,71 @@
44592 handler_t http_response_prepare(server *srv, connection *con) {
44595 - /* looks like someone has already done a decision */
44596 - if (con->mode == DIRECT &&
44598 + /* looks like someone has already made a decision */
44599 + if (con->mode == DIRECT &&
44600 (con->http_status != 0 && con->http_status != 200)) {
44601 /* remove a packets in the queue */
44602 if (con->file_finished == 0) {
44603 chunkqueue_reset(con->write_queue);
44607 return HANDLER_FINISHED;
44611 /* no decision yet, build conf->filename */
44612 if (con->mode == DIRECT && con->physical.path->used == 0) {
44615 - /* we only come here when we have the parse the full request again
44617 - * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44618 + /* we only come here when we have to parse the full request again
44620 + * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44621 * problem here as mod_setenv might get called multiple times
44623 * fastcgi-auth might lead to a COMEBACK too
44624 * fastcgi again dead server too
44626 * mod_compress might add headers twice too
44632 if (con->conf.log_condition_handling) {
44633 log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
44635 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
44644 * - uri.path (secure)
44653 * Name according to RFC 2396
44662 * (scheme)://(authority)(path)?(query)
44670 buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
44671 buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
44672 buffer_to_lower(con->uri.authority);
44675 config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */
44676 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */
44677 config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
44678 config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */
44679 config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */
44682 /** extract query string from request.uri */
44683 if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
44684 buffer_copy_string (con->uri.query, qstr + 1);
44685 @@ -200,22 +202,22 @@
44686 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path_raw);
44687 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-query : ", con->uri.query);
44691 /* disable keep-alive if requested */
44694 if (con->request_count > con->conf.max_keep_alive_requests) {
44695 con->keep_alive = 0;
44708 * - based on the raw URL
44714 switch(r = plugins_call_handle_uri_raw(srv, con)) {
44715 case HANDLER_GO_ON:
44717 @@ -229,14 +231,14 @@
44721 - /* build filename
44722 + /* build filename
44724 * - decode url-encodings (e.g. %20 -> ' ')
44725 * - remove path-modifiers (e.g. /../)
44733 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44734 con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44735 /* OPTIONS * ... */
44736 @@ -253,15 +255,20 @@
44746 * - based on the clean URL
44752 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
44755 + /* do we have to downgrade to 1.0 ? */
44756 + if (!con->conf.allow_http11) {
44757 + con->request.http_version = HTTP_VERSION_1_0;
44760 switch(r = plugins_call_handle_uri_clean(srv, con)) {
44761 case HANDLER_GO_ON:
44763 @@ -274,11 +281,11 @@
44764 log_error_write(srv, __FILE__, __LINE__, "");
44769 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44770 con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44771 - /* option requests are handled directly without checking of the path */
44773 + /* option requests are handled directly without checking the path */
44775 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
44777 con->http_status = 200;
44778 @@ -288,46 +295,47 @@
44788 * logical filename (URI) becomes a physical filename here
44805 * ... ISREG() -> ok, go on
44806 * ... ISDIR() -> index-file -> redirect
44821 * SEARCH DOCUMENT ROOT
44825 /* set a default */
44828 buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
44829 buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
44831 -#if defined(__WIN32) || defined(__CYGWIN__)
44832 - /* strip dots from the end and spaces
44834 + filename_unix2local(con->physical.rel_path);
44835 +#if defined(_WIN32) || defined(__CYGWIN__)
44836 + /* strip dots and spaces from the end
44838 * windows/dos handle those filenames as the same file
44840 * foo == foo. == foo..... == "foo... " == "foo.. ./"
44842 - * This will affect in some cases PATHINFO
44843 + * This will affect PATHINFO in some cases
44845 * on native windows we could prepend the filename with \\?\ to circumvent
44846 * this behaviour. I have no idea how to push this through cygwin
44847 @@ -377,36 +385,41 @@
44848 log_error_write(srv, __FILE__, __LINE__, "");
44852 - /* MacOS X and Windows can't distiguish between upper and lower-case
44854 - * convert to lower-case
44856 + /* The default Mac OS X and Windows filesystems can't distiguish between
44857 + * upper- and lowercase, so convert to lowercase
44859 if (con->conf.force_lowercase_filenames) {
44860 buffer_to_lower(con->physical.rel_path);
44863 - /* the docroot plugins might set the servername, if they don't we take http-host */
44864 + /* the docroot plugins might set the servername; if they don't we take http-host */
44865 if (buffer_is_empty(con->server_name)) {
44866 buffer_copy_string_buffer(con->server_name, con->uri.authority);
44870 - * create physical filename
44873 + * create physical filename
44874 * -> physical.path = docroot + rel_path
44880 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
44881 - BUFFER_APPEND_SLASH(con->physical.path);
44882 + PATHNAME_APPEND_SLASH(con->physical.path);
44883 buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
44884 if (con->physical.rel_path->used &&
44885 - con->physical.rel_path->ptr[0] == '/') {
44886 + con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
44887 buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
44889 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
44892 + /* win32: directories can't have a trailing slash */
44893 + if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
44894 + con->physical.path->ptr[con->physical.path->used - 2] = '\0';
44895 + con->physical.path->used--;
44898 if (con->conf.log_request_handling) {
44899 log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root");
44900 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
44901 @@ -426,7 +439,7 @@
44902 log_error_write(srv, __FILE__, __LINE__, "");
44907 if (con->conf.log_request_handling) {
44908 log_error_write(srv, __FILE__, __LINE__, "s", "-- logical -> physical");
44909 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
44910 @@ -434,38 +447,38 @@
44911 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44916 - * Noone catched away the file from normal path of execution yet (like mod_access)
44920 + * No one took the file away from the normal path of execution yet (like mod_access)
44922 * Go on and check of the file exists at all
44926 if (con->mode == DIRECT) {
44927 char *slash = NULL;
44928 char *pathinfo = NULL;
44930 stat_cache_entry *sce = NULL;
44933 if (con->conf.log_request_handling) {
44934 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path");
44935 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44939 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
44943 if (con->conf.log_request_handling) {
44944 log_error_write(srv, __FILE__, __LINE__, "s", "-- file found");
44945 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44949 if (S_ISDIR(sce->st.st_mode)) {
44950 - if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
44951 + if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
44952 /* redirect to .../ */
44955 http_response_redirect_to_directory(srv, con);
44958 return HANDLER_FINISHED;
44960 } else if (!S_ISREG(sce->st.st_mode)) {
44961 @@ -477,12 +490,12 @@
44964 con->http_status = 403;
44967 if (con->conf.log_request_handling) {
44968 log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied");
44969 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
44973 buffer_reset(con->physical.path);
44974 return HANDLER_FINISHED;
44976 @@ -499,77 +512,77 @@
44977 /* PATH_INFO ! :) */
44980 - /* we have no idea what happend. let's tell the user so. */
44981 + /* we have no idea what happened, so tell the user. */
44982 con->http_status = 500;
44983 buffer_reset(con->physical.path);
44986 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
44987 "file not found ... or so: ", strerror(errno),
44989 "->", con->physical.path);
44992 return HANDLER_FINISHED;
44996 /* not found, perhaps PATHINFO */
44999 buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
45007 buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
45009 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
45013 if (0 == stat(con->physical.path->ptr, &(st)) &&
45014 S_ISREG(st.st_mode)) {
45020 if (pathinfo != NULL) {
45023 slash = strrchr(srv->tmp_buf->ptr, '/');
45026 if (pathinfo != NULL) {
45032 if (slash) pathinfo = slash;
45033 } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
45037 - /* no it really doesn't exists */
45038 + /* no, it really doesn't exists */
45039 con->http_status = 404;
45042 if (con->conf.log_file_not_found) {
45043 log_error_write(srv, __FILE__, __LINE__, "sbsb",
45044 "file not found:", con->uri.path,
45045 "->", con->physical.path);
45049 buffer_reset(con->physical.path);
45052 return HANDLER_FINISHED;
45056 /* we have a PATHINFO */
45058 buffer_copy_string(con->request.pathinfo, pathinfo);
45066 con->uri.path->used -= strlen(pathinfo);
45067 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
45071 if (con->conf.log_request_handling) {
45072 log_error_write(srv, __FILE__, __LINE__, "s", "-- after pathinfo check");
45073 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
45074 @@ -577,12 +590,12 @@
45075 log_error_write(srv, __FILE__, __LINE__, "sb", "Pathinfo :", con->request.pathinfo);
45080 if (con->conf.log_request_handling) {
45081 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling subrequest");
45082 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
45086 /* call the handlers */
45087 switch(r = plugins_call_handle_subrequest_start(srv, con)) {
45088 case HANDLER_GO_ON:
45089 @@ -593,32 +606,32 @@
45090 if (con->conf.log_request_handling) {
45091 log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished");
45094 - /* something strange happend */
45096 + /* something strange happened */
45100 - /* if we are still here, no one wanted the file, status 403 is ok I think */
45103 + /* if we are still here, no one wanted the file; status 403 is ok I think */
45105 if (con->mode == DIRECT) {
45106 con->http_status = 403;
45109 return HANDLER_FINISHED;
45116 switch(r = plugins_call_handle_subrequest(srv, con)) {
45117 case HANDLER_GO_ON:
45118 - /* request was not handled, looks like we are done */
45119 + /* request was not handled; looks like we are done */
45120 return HANDLER_FINISHED;
45121 case HANDLER_FINISHED:
45122 /* request is finished */
45124 - /* something strange happend */
45125 + /* something strange happened */
45131 return HANDLER_COMEBACK;
45133 --- ../lighttpd-1.4.11/src/server.c 2006-03-04 19:12:17.000000000 +0200
45134 +++ lighttpd-1.4.12/src/server.c 2006-07-11 22:07:53.000000000 +0300
45136 #include <sys/types.h>
45137 -#include <sys/time.h>
45138 #include <sys/stat.h>
45140 #include <string.h>
45143 -#include <unistd.h>
45144 #include <stdlib.h>
45146 #include <signal.h>
45148 #include "plugin.h"
45149 #include "joblist.h"
45150 #include "network_backends.h"
45153 +/* use local getopt implementation */
45154 +# undef HAVE_GETOPT_H
45156 #ifdef HAVE_GETOPT_H
45157 #include <getopt.h>
45159 +#include "getopt.h"
45162 #ifdef HAVE_VALGRIND_VALGRIND_H
45164 /* #define USE_ALARM */
45168 +#undef HAVE_SIGNAL
45171 +#include "sys-files.h"
45172 +#include "sys-process.h"
45174 static volatile sig_atomic_t srv_shutdown = 0;
45175 static volatile sig_atomic_t graceful_shutdown = 0;
45176 +static volatile sig_atomic_t graceful_restart = 0;
45177 static volatile sig_atomic_t handle_sig_alarm = 1;
45178 static volatile sig_atomic_t handle_sig_hup = 0;
45183 case SIGTERM: srv_shutdown = 1; break;
45186 if (graceful_shutdown) srv_shutdown = 1;
45187 - else graceful_shutdown = 1;
45188 + else graceful_shutdown = 1;
45191 case SIGALRM: handle_sig_alarm = 1; break;
45193 static void signal_handler(int sig) {
45195 case SIGTERM: srv_shutdown = 1; break;
45198 if (graceful_shutdown) srv_shutdown = 1;
45199 - else graceful_shutdown = 1;
45200 + else graceful_shutdown = 1;
45203 case SIGALRM: handle_sig_alarm = 1; break;
45204 @@ -110,25 +121,26 @@
45205 signal(SIGTSTP, SIG_IGN);
45207 if (0 != fork()) exit(0);
45210 if (-1 == setsid()) exit(0);
45212 signal(SIGHUP, SIG_IGN);
45214 if (0 != fork()) exit(0);
45217 if (0 != chdir("/")) exit(0);
45221 static server *server_init(void) {
45225 server *srv = calloc(1, sizeof(*srv));
45227 + srv->max_fds = 1024;
45229 srv->x = buffer_init();
45232 CLEAN(response_header);
45233 CLEAN(parse_full_path);
45234 CLEAN(ts_debug_str);
45235 @@ -138,7 +150,7 @@
45237 srv->empty_string = buffer_init_string("");
45238 CLEAN(cond_check_buf);
45241 CLEAN(srvconf.errorlog_file);
45242 CLEAN(srvconf.groupname);
45243 CLEAN(srvconf.username);
45244 @@ -146,58 +158,58 @@
45245 CLEAN(srvconf.bindhost);
45246 CLEAN(srvconf.event_handler);
45247 CLEAN(srvconf.pid_file);
45250 CLEAN(tmp_chunk_len);
45255 srv->x = array_init();
45258 CLEAN(config_context);
45259 CLEAN(config_touched);
45264 for (i = 0; i < FILE_CACHE_MAX; i++) {
45265 srv->mtime_cache[i].str = buffer_init();
45269 srv->cur_ts = time(NULL);
45270 srv->startup_ts = srv->cur_ts;
45273 srv->conns = calloc(1, sizeof(*srv->conns));
45274 assert(srv->conns);
45277 srv->joblist = calloc(1, sizeof(*srv->joblist));
45278 assert(srv->joblist);
45281 srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
45282 assert(srv->fdwaitqueue);
45285 srv->srvconf.modules = array_init();
45286 srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
45287 srv->srvconf.network_backend = buffer_init();
45288 srv->srvconf.upload_tempdirs = array_init();
45292 srv->errorlog_fd = -1;
45293 srv->errorlog_mode = ERRORLOG_STDERR;
45295 srv->split_vals = array_init();
45301 static void server_free(server *srv) {
45305 for (i = 0; i < FILE_CACHE_MAX; i++) {
45306 buffer_free(srv->mtime_cache[i].str);
45311 buffer_free(srv->x);
45314 CLEAN(response_header);
45315 CLEAN(parse_full_path);
45316 CLEAN(ts_debug_str);
45317 @@ -207,7 +219,7 @@
45319 CLEAN(empty_string);
45320 CLEAN(cond_check_buf);
45323 CLEAN(srvconf.errorlog_file);
45324 CLEAN(srvconf.groupname);
45325 CLEAN(srvconf.username);
45326 @@ -217,7 +229,7 @@
45327 CLEAN(srvconf.pid_file);
45328 CLEAN(srvconf.modules_dir);
45329 CLEAN(srvconf.network_backend);
45332 CLEAN(tmp_chunk_len);
45335 @@ -225,15 +237,15 @@
45336 fdevent_unregister(srv->ev, srv->fd);
45338 fdevent_free(srv->ev);
45344 if (srv->config_storage) {
45345 for (i = 0; i < srv->config_context->used; i++) {
45346 specific_config *s = srv->config_storage[i];
45351 buffer_free(s->document_root);
45352 buffer_free(s->server_name);
45353 buffer_free(s->server_tag);
45354 @@ -242,32 +254,32 @@
45355 buffer_free(s->error_handler);
45356 buffer_free(s->errorfile_prefix);
45357 array_free(s->mimetypes);
45362 free(srv->config_storage);
45363 srv->config_storage = NULL;
45368 array_free(srv->x);
45371 CLEAN(config_context);
45372 CLEAN(config_touched);
45374 CLEAN(srvconf.upload_tempdirs);
45378 joblist_free(srv, srv->joblist);
45379 fdwaitqueue_free(srv, srv->fdwaitqueue);
45382 if (srv->stat_cache) {
45383 stat_cache_free(srv->stat_cache);
45386 array_free(srv->srvconf.modules);
45387 array_free(srv->split_vals);
45393 @@ -281,14 +293,12 @@
45394 " - a light and fast webserver\n" \
45395 "Build-Date: " __DATE__ " " __TIME__ "\n";
45399 write(STDOUT_FILENO, b, strlen(b));
45402 static void show_features (void) {
45404 - printf("\nEvent Handlers:\n\n%s",
45406 + const char *s = ""
45408 "\t+ select (generic)\n"
45410 @@ -355,11 +365,6 @@
45412 "\t- crypt support\n"
45415 - "\t+ PAM support\n"
45417 - "\t- PAM support\n"
45420 "\t+ SSL Support\n"
45422 @@ -371,9 +376,9 @@
45423 "\t- PCRE support\n"
45426 - "\t+ mySQL support\n"
45427 + "\t+ MySQL support\n"
45429 - "\t- mySQL support\n"
45430 + "\t- MySQL support\n"
45432 #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
45433 "\t+ LDAP support\n"
45434 @@ -410,8 +415,11 @@
45436 "\t- GDBM support\n"
45444 + printf("\nEvent Handlers:\n\n%s", s);
45447 static void show_help (void) {
45448 @@ -433,12 +441,12 @@
45449 " -h show this help\n" \
45455 write(STDOUT_FILENO, b, strlen(b));
45458 -int main (int argc, char **argv) {
45459 +int main (int argc, char **argv, char **envp) {
45460 server *srv = NULL;
45461 int print_config = 0;
45462 int test_config = 0;
45463 @@ -447,33 +455,37 @@
45464 int num_childs = 0;
45465 int pid_fd = -1, fd;
45468 + char *optarg = NULL;
45471 #ifdef HAVE_SIGACTION
45472 struct sigaction act;
45474 #ifdef HAVE_GETRLIMIT
45475 struct rlimit rlim;
45480 struct itimerval interval;
45483 interval.it_interval.tv_sec = 1;
45484 interval.it_interval.tv_usec = 0;
45485 interval.it_value.tv_sec = 1;
45486 interval.it_value.tv_usec = 0;
45492 /* for nice %b handling in strfime() */
45493 setlocale(LC_TIME, "C");
45496 if (NULL == (srv = server_init())) {
45497 fprintf(stderr, "did this really happen?\n");
45502 /* init structs done */
45505 srv->srvconf.port = 0;
45507 i_am_root = (getuid() == 0);
45508 @@ -481,14 +493,19 @@
45511 srv->srvconf.dont_daemonize = 0;
45514 while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
45517 - if (config_read(srv, optarg)) {
45520 + /* evil HACK for windows, optarg is not set */
45521 + optarg = argv[optind-1];
45523 + if (config_read(srv, optarg)) {
45530 buffer_copy_string(srv->srvconf.modules_dir, optarg);
45531 @@ -497,23 +514,23 @@
45532 case 't': test_config = 1; break;
45533 case 'D': srv->srvconf.dont_daemonize = 1; break;
45534 case 'v': show_version(); return 0;
45535 - case 'V': show_features(); return 0;
45536 + case 'V': show_features(); return 0;
45537 case 'h': show_help(); return 0;
45547 if (!srv->config_storage) {
45548 log_error_write(srv, __FILE__, __LINE__, "s",
45549 "No configuration available. Try using -f option.");
45557 if (print_config) {
45558 data_unset *dc = srv->config_context->data[0];
45560 @@ -533,7 +550,7 @@
45566 /* close stdin and stdout, as they are not needed */
45567 /* move stdin to /dev/null */
45568 if (-1 != (fd = open("/dev/null", O_RDONLY))) {
45569 @@ -541,54 +558,55 @@
45570 dup2(fd, STDIN_FILENO);
45575 /* move stdout to /dev/null */
45576 if (-1 != (fd = open("/dev/null", O_WRONLY))) {
45577 close(STDOUT_FILENO);
45578 dup2(fd, STDOUT_FILENO);
45583 if (0 != config_set_defaults(srv)) {
45584 - log_error_write(srv, __FILE__, __LINE__, "s",
45585 + log_error_write(srv, __FILE__, __LINE__, "s",
45586 "setting default values failed");
45594 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
45595 /* we are setuid-root */
45597 - log_error_write(srv, __FILE__, __LINE__, "s",
45599 + log_error_write(srv, __FILE__, __LINE__, "s",
45600 "Are you nuts ? Don't apply a SUID bit to this binary");
45609 /* check document-root */
45610 if (srv->config_storage[0]->document_root->used <= 1) {
45611 - log_error_write(srv, __FILE__, __LINE__, "s",
45612 + log_error_write(srv, __FILE__, __LINE__, "s",
45613 "document-root is not set\n");
45623 if (plugins_load(srv)) {
45624 log_error_write(srv, __FILE__, __LINE__, "s",
45625 "loading plugins finally failed");
45637 /* open pid file BEFORE chroot */
45638 if (srv->srvconf.pid_file->used) {
45639 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))) {
45640 @@ -598,18 +616,18 @@
45641 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45646 if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
45647 log_error_write(srv, __FILE__, __LINE__, "sbs",
45648 "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45652 if (!S_ISREG(st.st_mode)) {
45653 log_error_write(srv, __FILE__, __LINE__, "sb",
45654 "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
45659 if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
45660 log_error_write(srv, __FILE__, __LINE__, "sbs",
45661 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45662 @@ -617,13 +635,14 @@
45668 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45669 /* select limits itself
45671 * as it is a hard limit and will lead to a segfault we add some safety
45673 - srv->max_fds = FD_SETSIZE - 200;
45674 + fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
45675 + srv->max_fds = FD_SETSIZE - 4;
45677 srv->max_fds = 4096;
45679 @@ -636,7 +655,7 @@
45680 #ifdef HAVE_VALGRIND_VALGRIND_H
45681 if (RUNNING_ON_VALGRIND) use_rlimit = 0;
45685 #ifdef HAVE_GETRLIMIT
45686 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
45687 log_error_write(srv, __FILE__, __LINE__,
45688 @@ -644,13 +663,13 @@
45694 if (use_rlimit && srv->srvconf.max_fds) {
45698 rlim.rlim_cur = srv->srvconf.max_fds;
45699 rlim.rlim_max = srv->srvconf.max_fds;
45702 if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
45703 log_error_write(srv, __FILE__, __LINE__,
45704 "ss", "couldn't set 'max filedescriptors'",
45705 @@ -659,7 +678,7 @@
45709 - /* #372: solaris need some fds extra for devpoll */
45710 + /* #372: solaris need some fds extra for devpoll */
45711 if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
45713 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45714 @@ -677,33 +696,33 @@
45715 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45716 /* don't raise the limit above FD_SET_SIZE */
45717 if (srv->max_fds > FD_SETSIZE - 200) {
45718 - log_error_write(srv, __FILE__, __LINE__, "sd",
45719 + log_error_write(srv, __FILE__, __LINE__, "sd",
45720 "can't raise max filedescriptors above", FD_SETSIZE - 200,
45721 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45729 /* set user and group */
45730 if (srv->srvconf.username->used) {
45731 if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
45732 - log_error_write(srv, __FILE__, __LINE__, "sb",
45733 + log_error_write(srv, __FILE__, __LINE__, "sb",
45734 "can't find username", srv->srvconf.username);
45739 if (pwd->pw_uid == 0) {
45740 log_error_write(srv, __FILE__, __LINE__, "s",
45741 "I will not set uid to 0\n");
45747 if (srv->srvconf.groupname->used) {
45748 if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
45749 - log_error_write(srv, __FILE__, __LINE__, "sb",
45750 + log_error_write(srv, __FILE__, __LINE__, "sb",
45751 "can't find groupname", srv->srvconf.groupname);
45754 @@ -713,15 +732,15 @@
45760 /* we need root-perms for port < 1024 */
45761 if (0 != network_init(srv)) {
45768 -#ifdef HAVE_CHROOT
45769 +#ifdef HAVE_CHROOT
45770 if (srv->srvconf.changeroot->used) {
45773 @@ -761,7 +780,7 @@
45776 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45777 - srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
45778 + srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
45780 srv->max_fds = rlim.rlim_cur;
45782 @@ -775,18 +794,18 @@
45784 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45785 /* don't raise the limit above FD_SET_SIZE */
45786 - if (srv->max_fds > FD_SETSIZE - 200) {
45787 - log_error_write(srv, __FILE__, __LINE__, "sd",
45788 - "can't raise max filedescriptors above", FD_SETSIZE - 200,
45789 + if (srv->max_fds > FD_SETSIZE - 4) {
45790 + log_error_write(srv, __FILE__, __LINE__, "sd",
45791 + "can't raise max filedescriptors above", FD_SETSIZE - 4,
45792 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45798 if (0 != network_init(srv)) {
45806 @@ -802,25 +821,27 @@
45807 /* or use the default */
45808 srv->max_conns = srv->max_fds;
45812 if (HANDLER_GO_ON != plugins_call_init(srv)) {
45813 log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
45817 network_close(srv);
45826 /* network is up, let's deamonize ourself */
45827 if (srv->srvconf.dont_daemonize == 0) daemonize();
45831 srv->gid = getgid();
45832 srv->uid = getuid();
45836 /* write pid file */
45837 if (pid_fd != -1) {
45838 buffer_copy_long(srv->tmp_buf, getpid());
45839 @@ -829,17 +850,17 @@
45845 if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
45846 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
45850 network_close(srv);
45858 /* dump unused config-keys */
45859 for (i = 0; i < srv->config_context->used; i++) {
45860 array *config = ((data_config *)srv->config_context->data[i])->value;
45861 @@ -847,43 +868,42 @@
45863 for (j = 0; config && j < config->used; j++) {
45864 data_unset *du = config->data[j];
45867 /* all var.* is known as user defined variable */
45868 if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
45872 if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
45873 - log_error_write(srv, __FILE__, __LINE__, "sbs",
45874 + log_error_write(srv, __FILE__, __LINE__, "sbs",
45875 "WARNING: unknown config-key:",
45883 if (srv->config_deprecated) {
45884 - log_error_write(srv, __FILE__, __LINE__, "s",
45885 + log_error_write(srv, __FILE__, __LINE__, "s",
45886 "Configuration contains deprecated keys. Going down.");
45890 network_close(srv);
45898 if (-1 == log_error_open(srv)) {
45899 - log_error_write(srv, __FILE__, __LINE__, "s",
45900 + log_error_write(srv, __FILE__, __LINE__, "s",
45901 "opening errorlog failed, dying");
45905 network_close(srv);
45912 #ifdef HAVE_SIGACTION
45913 memset(&act, 0, sizeof(act));
45914 act.sa_handler = SIG_IGN;
45915 @@ -903,7 +923,7 @@
45916 sigaction(SIGHUP, &act, NULL);
45917 sigaction(SIGALRM, &act, NULL);
45918 sigaction(SIGCHLD, &act, NULL);
45921 #elif defined(HAVE_SIGNAL)
45922 /* ignore the SIGPIPE from sendfile() */
45923 signal(SIGPIPE, SIG_IGN);
45924 @@ -914,20 +934,20 @@
45925 signal(SIGCHLD, signal_handler);
45926 signal(SIGINT, signal_handler);
45931 signal(SIGALRM, signal_handler);
45934 /* setup periodic timer (1 second) */
45935 if (setitimer(ITIMER_REAL, &interval, NULL)) {
45936 log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
45941 getitimer(ITIMER_REAL, &interval);
45946 /* start watcher and workers */
45947 num_childs = srv->srvconf.max_worker;
45948 if (num_childs > 0) {
45949 @@ -957,13 +977,13 @@
45953 - if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
45954 + if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
45955 log_error_write(srv, __FILE__, __LINE__,
45956 "s", "fdevent_init failed");
45960 - * kqueue() is called here, select resets its internals,
45962 + * kqueue() is called here, select resets its internals,
45963 * all server sockets get their handlers
45966 @@ -971,7 +991,7 @@
45968 network_close(srv);
45975 @@ -986,7 +1006,7 @@
45977 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
45978 if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
45979 - log_error_write(srv, __FILE__, __LINE__, "s",
45980 + log_error_write(srv, __FILE__, __LINE__, "s",
45981 "could not open a fam connection, dieing.");
45984 @@ -1018,16 +1038,40 @@
45990 if (handle_sig_hup) {
45994 /* reset notification */
45995 handle_sig_hup = 0;
46002 + /* send the old process into a graceful-shutdown and start a
46003 + * new process right away
46006 + * - if webserver is running on port < 1024 (e.g. 80, 433)
46007 + * we don't have the permissions to bind to that port anymore
46011 + if (0 == (pid = fork())) {
46012 + execve(argv[0], argv, envp);
46015 + } else if (pid == -1) {
46020 + graceful_shutdown = 1; /* shutdown without killing running connections */
46021 + graceful_restart = 1; /* don't delete pid file */
46024 /* cycle logfiles */
46027 switch(r = plugins_call_handle_sighup(srv)) {
46028 case HANDLER_GO_ON:
46030 @@ -1035,30 +1079,31 @@
46031 log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
46036 if (-1 == log_error_cycle(srv)) {
46037 log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
46046 if (handle_sig_alarm) {
46051 /* reset notification */
46052 handle_sig_alarm = 0;
46056 /* get current time */
46057 min_ts = time(NULL);
46060 if (min_ts != srv->cur_ts) {
46062 connections *conns = srv->conns;
46066 switch(r = plugins_call_handle_trigger(srv)) {
46067 case HANDLER_GO_ON:
46069 @@ -1069,21 +1114,21 @@
46070 log_error_write(srv, __FILE__, __LINE__, "d", r);
46075 /* trigger waitpid */
46076 srv->cur_ts = min_ts;
46078 - /* cleanup stat-cache */
46080 + /* cleanup stat-cache */
46081 stat_cache_trigger_cleanup(srv);
46083 - * check all connections for timeouts
46085 + * check all connections for timeouts
46088 for (ndx = 0; ndx < conns->used; ndx++) {
46094 con = conns->ptr[ndx];
46096 if (con->state == CON_STATE_READ ||
46097 @@ -1092,7 +1137,7 @@
46098 if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
46101 - log_error_write(srv, __FILE__, __LINE__, "sd",
46102 + log_error_write(srv, __FILE__, __LINE__, "sd",
46103 "connection closed - read-timeout:", con->fd);
46105 connection_set_state(srv, con, CON_STATE_ERROR);
46106 @@ -1102,7 +1147,7 @@
46107 if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
46110 - log_error_write(srv, __FILE__, __LINE__, "sd",
46111 + log_error_write(srv, __FILE__, __LINE__, "sd",
46112 "connection closed - read-timeout:", con->fd);
46114 connection_set_state(srv, con, CON_STATE_ERROR);
46115 @@ -1110,20 +1155,20 @@
46121 if ((con->state == CON_STATE_WRITE) &&
46122 - (con->write_request_ts != 0)) {
46123 + (con->write_request_ts != 0)) {
46125 if (srv->cur_ts - con->write_request_ts > 60) {
46126 - log_error_write(srv, __FILE__, __LINE__, "sdd",
46127 + log_error_write(srv, __FILE__, __LINE__, "sdd",
46128 "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
46133 if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
46136 - log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46137 + log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46138 "NOTE: a request for",
46140 "timed out after writing",
46141 @@ -1138,35 +1183,35 @@
46143 /* we don't like div by zero */
46144 if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
46146 - if (con->traffic_limit_reached &&
46147 - (con->conf.kbytes_per_second == 0 ||
46149 + if (con->traffic_limit_reached &&
46150 + (con->conf.kbytes_per_second == 0 ||
46151 ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
46152 /* enable connection again */
46153 con->traffic_limit_reached = 0;
46161 connection_state_machine(srv, con);
46163 con->bytes_written_cur_second = 0;
46164 *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
46169 fprintf(stderr, "connection-state: ");
46174 fprintf(stderr, "c[%d,%d]: %s ",
46177 connection_get_state(con->state));
46182 if (cs == 1) fprintf(stderr, "\n");
46185 @@ -1181,18 +1226,18 @@
46186 server_socket *srv_socket = srv->srv_sockets.ptr[i];
46187 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
46191 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
46194 srv->sockets_disabled = 0;
46197 if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
46198 (srv->conns->used > srv->max_conns) || /* out of connections */
46199 - (graceful_shutdown)) { /* graceful_shutdown */
46200 + (graceful_shutdown)) { /* graceful_shutdown */
46202 /* disable server-fds */
46205 for (i = 0; i < srv->srv_sockets.used; i++) {
46206 server_socket *srv_socket = srv->srv_sockets.ptr[i];
46207 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
46208 @@ -1211,7 +1256,7 @@
46209 /* network_close() will cleanup after us */
46214 if (graceful_shutdown) {
46215 log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
46216 } else if (srv->conns->used > srv->max_conns) {
46217 @@ -1219,7 +1264,7 @@
46219 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
46223 srv->sockets_disabled = 1;
46226 @@ -1229,16 +1274,16 @@
46227 * we are ready to terminate without harming anyone */
46232 /* we still have some fds to share */
46233 - if (srv->want_fds) {
46234 + if (srv->want_fds) {
46235 /* check the fdwaitqueue for waiting fds */
46236 int free_fds = srv->max_fds - srv->cur_fds - 16;
46240 for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
46241 connection_state_machine(srv, con);
46247 @@ -1249,27 +1294,27 @@
46251 - log_error_write(srv, __FILE__, __LINE__, "sd",
46252 + log_error_write(srv, __FILE__, __LINE__, "sd",
46259 fdevent_handler handler;
46264 fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx);
46265 revents = fdevent_event_get_revent (srv->ev, fd_ndx);
46266 fd = fdevent_event_get_fd (srv->ev, fd_ndx);
46267 handler = fdevent_get_handler(srv->ev, fd);
46268 context = fdevent_get_context(srv->ev, fd);
46271 /* connection_handle_fdevent needs a joblist_append */
46273 - log_error_write(srv, __FILE__, __LINE__, "sdd",
46274 + log_error_write(srv, __FILE__, __LINE__, "sdd",
46275 "event for", fd, revents);
46278 switch (r = (*handler)(srv, context, revents)) {
46279 case HANDLER_FINISHED:
46280 case HANDLER_GO_ON:
46281 @@ -1286,17 +1331,17 @@
46284 } else if (n < 0 && errno != EINTR) {
46285 - log_error_write(srv, __FILE__, __LINE__, "ss",
46286 - "fdevent_poll failed:",
46287 + log_error_write(srv, __FILE__, __LINE__, "ss",
46288 + "fdevent_poll failed:",
46293 for (ndx = 0; ndx < srv->joblist->used; ndx++) {
46294 connection *con = srv->joblist->ptr[ndx];
46298 connection_state_machine(srv, con);
46301 switch(r = plugins_call_handle_joblist(srv, con)) {
46302 case HANDLER_FINISHED:
46303 case HANDLER_GO_ON:
46304 @@ -1305,32 +1350,33 @@
46305 log_error_write(srv, __FILE__, __LINE__, "d", r);
46310 con->in_joblist = 0;
46314 srv->joblist->used = 0;
46317 - if (srv->srvconf.pid_file->used &&
46319 + if (0 == graceful_restart &&
46320 + srv->srvconf.pid_file->used &&
46321 srv->srvconf.changeroot->used == 0) {
46322 if (0 != unlink(srv->srvconf.pid_file->ptr)) {
46323 if (errno != EACCES && errno != EPERM) {
46324 - log_error_write(srv, __FILE__, __LINE__, "sbds",
46325 - "unlink failed for:",
46326 + log_error_write(srv, __FILE__, __LINE__, "sbds",
46327 + "unlink failed for:",
46328 srv->srvconf.pid_file,
46337 log_error_close(srv);
46338 network_close(srv);
46339 connections_free(srv);
46346 --- ../lighttpd-1.4.11/src/settings.h 2005-08-11 01:26:41.000000000 +0300
46347 +++ lighttpd-1.4.12/src/settings.h 2006-07-11 22:07:53.000000000 +0300
46350 * max size of a buffer which will just be reset
46351 * to ->used = 0 instead of really freeing the buffer
46354 * 64kB (no real reason, just a guess)
46356 #define BUFFER_MAX_REUSE_SIZE (4 * 1024)
46359 * max size of the HTTP request header
46362 * 32k should be enough for everything (just a guess)
46366 #define MAX_HTTP_REQUEST_HEADER (32 * 1024)
46368 -typedef enum { HANDLER_UNSET,
46370 +typedef enum { HANDLER_UNSET,
46373 - HANDLER_COMEBACK,
46374 - HANDLER_WAIT_FOR_EVENT,
46375 + HANDLER_COMEBACK,
46376 + HANDLER_WAIT_FOR_EVENT,
46378 HANDLER_WAIT_FOR_FD
46380 --- ../lighttpd-1.4.11/src/spawn-fcgi.c 2006-03-07 14:18:10.000000000 +0200
46381 +++ lighttpd-1.4.12/src/spawn-fcgi.c 2006-07-11 22:07:53.000000000 +0300
46383 #include <sys/types.h>
46384 -#include <sys/time.h>
46385 #include <sys/stat.h>
46387 #include <stdlib.h>
46388 #include <string.h>
46391 -#include <unistd.h>
46395 #ifdef HAVE_CONFIG_H
46396 #include "config.h"
46406 #include "sys-socket.h"
46407 +#include "sys-files.h"
46409 #ifdef HAVE_SYS_WAIT_H
46410 #include <sys/wait.h>
46411 @@ -45,28 +43,28 @@
46413 int socket_type, status;
46414 struct timeval tv = { 0, 100 * 1000 };
46417 struct sockaddr_un fcgi_addr_un;
46418 struct sockaddr_in fcgi_addr_in;
46419 struct sockaddr *fcgi_addr;
46425 if (child_count < 2) {
46430 if (child_count > 256) {
46438 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
46441 fcgi_addr_un.sun_family = AF_UNIX;
46442 strcpy(fcgi_addr_un.sun_path, unixsocket);
46446 servlen = SUN_LEN(&fcgi_addr_un);
46448 @@ -84,50 +82,50 @@
46450 fcgi_addr_in.sin_port = htons(port);
46451 servlen = sizeof(fcgi_addr_in);
46454 socket_type = AF_INET;
46455 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
46459 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46460 - fprintf(stderr, "%s.%d\n",
46461 + fprintf(stderr, "%s.%d\n",
46462 __FILE__, __LINE__);
46467 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
46468 /* server is not up, spawn in */
46473 if (unixsocket) unlink(unixsocket);
46479 /* reopen socket */
46480 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46481 - fprintf(stderr, "%s.%d\n",
46482 + fprintf(stderr, "%s.%d\n",
46483 __FILE__, __LINE__);
46488 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
46489 - fprintf(stderr, "%s.%d\n",
46490 + fprintf(stderr, "%s.%d\n",
46491 __FILE__, __LINE__);
46495 /* create socket */
46496 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
46497 - fprintf(stderr, "%s.%d: bind failed: %s\n",
46498 + fprintf(stderr, "%s.%d: bind failed: %s\n",
46499 __FILE__, __LINE__,
46505 if (-1 == listen(fcgi_fd, 1024)) {
46506 - fprintf(stderr, "%s.%d: fd = -1\n",
46507 + fprintf(stderr, "%s.%d: fd = -1\n",
46508 __FILE__, __LINE__);
46511 @@ -137,42 +135,45 @@
46519 char cgi_childs[64];
46526 + /* loose control terminal */
46529 /* is save as we limit to 256 childs */
46530 sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
46533 if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
46534 close(FCGI_LISTENSOCK_FILENO);
46535 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
46540 /* we don't need the client socket */
46541 for (i = 3; i < 256; i++) {
46546 /* create environment */
46549 putenv(cgi_childs);
46552 /* fork and replace shell */
46553 b = malloc(strlen("exec ") + strlen(appPath) + 1);
46554 strcpy(b, "exec ");
46555 strcat(b, appPath);
46559 execl("/bin/sh", "sh", "-c", b, NULL);
46568 @@ -180,47 +181,47 @@
46575 select(0, NULL, NULL, NULL, &tv);
46578 switch (waitpid(child, &status, WNOHANG)) {
46580 - fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
46581 + fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
46582 __FILE__, __LINE__,
46586 /* write pid file */
46587 if (pid_fd != -1) {
46588 /* assume a 32bit pid_t */
46592 snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
46595 write(pid_fd, pidbuf, strlen(pidbuf));
46605 if (WIFEXITED(status)) {
46606 - fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
46607 + fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
46608 __FILE__, __LINE__,
46609 WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
46610 } else if (WIFSIGNALED(status)) {
46611 - fprintf(stderr, "%s.%d: child signaled: %d\n",
46612 + fprintf(stderr, "%s.%d: child signaled: %d\n",
46613 __FILE__, __LINE__,
46616 - fprintf(stderr, "%s.%d: child died somehow: %d\n",
46617 + fprintf(stderr, "%s.%d: child died somehow: %d\n",
46618 __FILE__, __LINE__,
46627 @@ -228,16 +229,16 @@
46628 __FILE__, __LINE__);
46640 void show_version () {
46641 char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
46642 -" - spawns fastcgi processes\n"
46643 +" - spawns fastcgi processes\n"
46645 write(1, b, strlen(b));
46647 @@ -265,7 +266,7 @@
46650 int main(int argc, char **argv) {
46651 - char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
46652 + char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
46653 *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
46655 unsigned short port = 0;
46656 @@ -273,9 +274,9 @@
46662 i_am_root = (getuid() == 0);
46665 while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
46667 case 'f': fcgi_app = optarg; break;
46668 @@ -290,137 +291,137 @@
46669 case 'P': pid_file = optarg; /* PID file */ break;
46670 case 'v': show_version(); return 0;
46671 case 'h': show_help(); return 0;
46680 if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
46686 if (unixsocket && port) {
46687 - fprintf(stderr, "%s.%d: %s\n",
46688 + fprintf(stderr, "%s.%d: %s\n",
46689 __FILE__, __LINE__,
46690 "either a unix domain socket or a tcp-port, but not both\n");
46697 if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) {
46698 - fprintf(stderr, "%s.%d: %s\n",
46699 + fprintf(stderr, "%s.%d: %s\n",
46700 __FILE__, __LINE__,
46701 "path of the unix socket is too long\n");
46708 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
46709 /* we are setuid-root */
46711 - fprintf(stderr, "%s.%d: %s\n",
46713 + fprintf(stderr, "%s.%d: %s\n",
46714 __FILE__, __LINE__,
46715 "Are you nuts ? Don't apply a SUID bit to this binary\n");
46724 (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
46726 if (errno != EEXIST) {
46727 - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46728 + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46729 __FILE__, __LINE__,
46730 pid_file, strerror(errno));
46737 /* ok, file exists */
46740 if (0 != stat(pid_file, &st)) {
46741 - fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
46742 + fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
46743 __FILE__, __LINE__,
46744 pid_file, strerror(errno));
46751 /* is it a regular file ? */
46754 if (!S_ISREG(st.st_mode)) {
46755 - fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
46756 + fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
46757 __FILE__, __LINE__,
46765 if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
46766 - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46767 + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46768 __FILE__, __LINE__,
46769 pid_file, strerror(errno));
46778 struct group *grp = NULL;
46779 struct passwd *pwd = NULL;
46782 /* set user and group */
46786 if (NULL == (pwd = getpwnam(username))) {
46787 - fprintf(stderr, "%s.%d: %s, %s\n",
46788 + fprintf(stderr, "%s.%d: %s, %s\n",
46789 __FILE__, __LINE__,
46790 "can't find username", username);
46795 if (pwd->pw_uid == 0) {
46796 - fprintf(stderr, "%s.%d: %s\n",
46797 + fprintf(stderr, "%s.%d: %s\n",
46798 __FILE__, __LINE__,
46799 "I will not set uid to 0\n");
46806 if (NULL == (grp = getgrnam(groupname))) {
46807 - fprintf(stderr, "%s.%d: %s %s\n",
46808 + fprintf(stderr, "%s.%d: %s %s\n",
46809 __FILE__, __LINE__,
46810 - "can't find groupname",
46811 + "can't find groupname",
46815 if (grp->gr_gid == 0) {
46816 - fprintf(stderr, "%s.%d: %s\n",
46817 + fprintf(stderr, "%s.%d: %s\n",
46818 __FILE__, __LINE__,
46819 "I will not set gid to 0\n");
46826 if (-1 == chroot(changeroot)) {
46827 - fprintf(stderr, "%s.%d: %s %s\n",
46828 + fprintf(stderr, "%s.%d: %s %s\n",
46829 __FILE__, __LINE__,
46830 "chroot failed: ", strerror(errno));
46833 if (-1 == chdir("/")) {
46834 - fprintf(stderr, "%s.%d: %s %s\n",
46835 + fprintf(stderr, "%s.%d: %s %s\n",
46836 __FILE__, __LINE__,
46837 "chdir failed: ", strerror(errno));
46843 /* drop root privs */
46845 setgid(grp->gr_gid);
46846 @@ -428,7 +429,7 @@
46848 if (username) setuid(pwd->pw_uid);
46852 return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
46855 --- ../lighttpd-1.4.11/src/splaytree.c 2005-09-12 21:51:28.000000000 +0300
46856 +++ lighttpd-1.4.12/src/splaytree.c 2006-07-11 22:07:51.000000000 +0300
46857 @@ -56,19 +56,19 @@
46859 #define node_size splaytree_size
46861 -/* Splay using the key i (which may or may not be in the tree.)
46862 - * The starting root is t, and the tree used is defined by rat
46863 +/* Splay using the key i (which may or may not be in the tree.)
46864 + * The starting root is t, and the tree used is defined by rat
46865 * size fields are maintained */
46866 splay_tree * splaytree_splay (splay_tree *t, int i) {
46867 splay_tree N, *l, *r, *y;
46868 int comp, root_size, l_size, r_size;
46871 if (t == NULL) return t;
46872 N.left = N.right = NULL;
46874 root_size = node_size(t);
46875 l_size = r_size = 0;
46879 comp = compare(i, t->key);
46881 @@ -120,7 +120,7 @@
46883 r_size -= 1+node_size(y->right);
46887 l->right = t->left; /* assemble */
46888 r->left = t->right;
46890 --- ../lighttpd-1.4.11/src/splaytree.h 2005-09-12 21:51:13.000000000 +0300
46891 +++ lighttpd-1.4.12/src/splaytree.h 2006-07-11 22:07:51.000000000 +0300
46893 /* This macro returns the size of a node. Unlike "x->size", */
46894 /* it works even if x=NULL. The test could be avoided by using */
46895 /* a special version of NULL which was a real node with size 0. */
46900 --- ../lighttpd-1.4.11/src/stat_cache.c 2005-11-22 15:23:51.000000000 +0200
46901 +++ lighttpd-1.4.12/src/stat_cache.c 2006-07-15 22:43:21.000000000 +0300
46903 #include <stdlib.h>
46904 #include <string.h>
46906 -#include <unistd.h>
46909 #include <assert.h>
46913 #include "sys-mmap.h"
46915 -/* NetBSD 1.3.x needs it */
46916 -#ifndef MAP_FAILED
46917 -# define MAP_FAILED -1
46920 -#ifndef O_LARGEFILE
46921 -# define O_LARGEFILE 0
46924 -#ifndef HAVE_LSTAT
46925 -#define lstat stat
46927 +#include "sys-files.h"
46928 +#include "sys-strings.h"
46931 /* enables debug code for testing if all nodes in the stat-cache as accessable */
46934 * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
46936 - * if the stat()-cache is queried we check if the version id for the directory is the
46937 - * same and return immediatly.
46938 + * if the stat()-cache is queried we check if the version id for the directory is the
46939 + * same and return immediatly.
46943 @@ -62,17 +50,17 @@
46944 * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
46946 * stat <<-> directory <-> FAMRequest
46948 - * if file is deleted, directory is dirty, file is rechecked ...
46950 + * if file is deleted, directory is dirty, file is rechecked ...
46951 * if directory is deleted, directory mapping is removed
46965 @@ -83,16 +71,16 @@
46967 * - the hash-key is used as sorting criteria for a tree
46968 * - a splay-tree is used as we can use the caching effect of it
46972 /* we want to cleanup the stat-cache every few seconds, let's say 10
46974 * - remove entries which are outdated since 30s
46975 * - remove entries which are fresh but havn't been used since 60s
46976 * - if we don't have a stat-cache entry for a directory, release it from the monitor
46980 -#ifdef DEBUG_STAT_CACHE
46981 +#ifdef DEBUG_STAT_CACHE
46985 @@ -105,15 +93,15 @@
46987 stat_cache *stat_cache_init(void) {
46988 stat_cache *fc = NULL;
46991 fc = calloc(1, sizeof(*fc));
46994 fc->dir_name = buffer_init();
46996 fc->fam = calloc(1, sizeof(*fc->fam));
46999 -#ifdef DEBUG_STAT_CACHE
47000 +#ifdef DEBUG_STAT_CACHE
47004 @@ -122,24 +110,24 @@
47006 static stat_cache_entry * stat_cache_entry_init(void) {
47007 stat_cache_entry *sce = NULL;
47010 sce = calloc(1, sizeof(*sce));
47013 sce->name = buffer_init();
47014 sce->etag = buffer_init();
47015 sce->content_type = buffer_init();
47021 static void stat_cache_entry_free(void *data) {
47022 stat_cache_entry *sce = data;
47026 buffer_free(sce->etag);
47027 buffer_free(sce->name);
47028 buffer_free(sce->content_type);
47034 @@ -148,22 +136,22 @@
47035 fam_dir_entry *fam_dir = NULL;
47037 fam_dir = calloc(1, sizeof(*fam_dir));
47040 fam_dir->name = buffer_init();
47046 static void fam_dir_entry_free(void *data) {
47047 fam_dir_entry *fam_dir = data;
47050 if (!fam_dir) return;
47053 FAMCancelMonitor(fam_dir->fc, fam_dir->req);
47056 buffer_free(fam_dir->name);
47057 free(fam_dir->req);
47063 @@ -174,7 +162,7 @@
47064 splay_tree *node = sc->files;
47066 osize = sc->files->size;
47069 stat_cache_entry_free(node->data);
47070 sc->files = splaytree_delete(sc->files, node->key);
47072 @@ -187,12 +175,12 @@
47075 splay_tree *node = sc->dirs;
47078 osize = sc->dirs->size;
47080 fam_dir_entry_free(node->data);
47081 sc->dirs = splaytree_delete(sc->dirs, node->key);
47085 assert(NULL == sc->dirs);
47087 @@ -212,7 +200,7 @@
47088 static int stat_cache_attr_get(buffer *buf, char *name) {
47094 buffer_prepare_copy(buf, attrlen);
47096 @@ -251,15 +239,15 @@
47099 events = FAMPending(sc->fam);
47102 for (i = 0; i < events; i++) {
47104 fam_dir_entry *fam_dir;
47109 FAMNextEvent(sc->fam, &fe);
47115 @@ -280,7 +268,7 @@
47117 sc->dirs = splaytree_splay(sc->dirs, ndx);
47121 if (node && (node->key == ndx)) {
47122 int osize = splaytree_size(sc->dirs);
47124 @@ -308,7 +296,7 @@
47130 return HANDLER_GO_ON;
47133 @@ -332,7 +320,7 @@
47139 * - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
47140 * - HANDLER_ERROR on stat() failed -> see errno for problem
47142 @@ -348,16 +336,16 @@
47146 -#ifdef DEBUG_STAT_CACHE
47147 +#ifdef DEBUG_STAT_CACHE
47152 splay_tree *file_node = NULL;
47159 * check if the directory for this file has changed
47162 @@ -366,23 +354,23 @@
47163 file_ndx = hashme(name);
47164 sc->files = splaytree_splay(sc->files, file_ndx);
47166 -#ifdef DEBUG_STAT_CACHE
47167 +#ifdef DEBUG_STAT_CACHE
47168 for (i = 0; i < ctrl.used; i++) {
47169 if (ctrl.ptr[i] == file_ndx) break;
47173 if (sc->files && (sc->files->key == file_ndx)) {
47174 -#ifdef DEBUG_STAT_CACHE
47175 +#ifdef DEBUG_STAT_CACHE
47176 /* it was in the cache */
47177 assert(i < ctrl.used);
47180 - /* we have seen this file already and
47182 + /* we have seen this file already and
47183 * don't stat() it again in the same second */
47185 file_node = sc->files;
47188 sce = file_node->data;
47190 /* check if the name is the same, we might have a collision */
47191 @@ -390,7 +378,7 @@
47192 if (buffer_is_equal(name, sce->name)) {
47193 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
47194 if (sce->stat_ts == srv->cur_ts) {
47197 return HANDLER_GO_ON;
47200 @@ -400,15 +388,15 @@
47201 * file_node is used by the FAM check below to see if we know this file
47202 * and if we can save a stat().
47204 - * BUT, the sce is not reset here as the entry into the cache is ok, we
47205 + * BUT, the sce is not reset here as the entry into the cache is ok, we
47206 * it is just not pointing to our requested file.
47214 -#ifdef DEBUG_STAT_CACHE
47215 +#ifdef DEBUG_STAT_CACHE
47216 if (i != ctrl.used) {
47217 fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr);
47219 @@ -424,23 +412,23 @@
47222 dir_ndx = hashme(sc->dir_name);
47225 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
47228 if (sc->dirs && (sc->dirs->key == dir_ndx)) {
47229 dir_node = sc->dirs;
47233 if (dir_node && file_node) {
47234 /* we found a file */
47237 sce = file_node->data;
47238 fam_dir = dir_node->data;
47241 if (fam_dir->version == sce->dir_version) {
47242 /* the stat()-cache entry is still ok */
47247 return HANDLER_GO_ON;
47250 @@ -448,7 +436,7 @@
47256 * - open() + fstat() on a named-pipe results in a (intended) hang.
47257 * - stat() if regualar file + open() to see if we can read from it is better
47259 @@ -469,16 +457,16 @@
47266 osize = sc->files->size;
47269 sce = stat_cache_entry_init();
47270 buffer_copy_string_buffer(sce->name, name);
47272 - sc->files = splaytree_insert(sc->files, file_ndx, sce);
47273 -#ifdef DEBUG_STAT_CACHE
47275 + sc->files = splaytree_insert(sc->files, file_ndx, sce);
47276 +#ifdef DEBUG_STAT_CACHE
47277 if (ctrl.size == 0) {
47280 @@ -499,29 +487,29 @@
47282 sce->stat_ts = srv->cur_ts;
47284 - /* catch the obvious symlinks
47285 + /* catch the obvious symlinks
47287 * this is not a secure check as we still have a race-condition between
47288 - * the stat() and the open. We can only solve this by
47289 + * the stat() and the open. We can only solve this by
47290 * 1. open() the file
47291 * 2. fstat() the fd
47293 * and keeping the file open for the rest of the time. But this can
47294 * only be done at network level.
47298 if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
47299 return HANDLER_ERROR;
47302 - if (S_ISREG(st.st_mode)) {
47303 + if (S_ISREG(st.st_mode)) {
47304 /* determine mimetype */
47305 buffer_reset(sce->content_type);
47308 for (k = 0; k < con->conf.mimetypes->used; k++) {
47309 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
47310 buffer *type = ds->key;
47313 if (type->used == 0) continue;
47315 /* check if the right side is the same */
47316 @@ -538,8 +526,10 @@
47317 stat_cache_attr_get(sce->content_type, name->ptr);
47320 + } else if (S_ISDIR(st.st_mode)) {
47321 + etag_create(sce->etag, &(sce->st));
47327 (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
47328 @@ -549,19 +539,19 @@
47329 fam_dir->fc = sc->fam;
47331 buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
47334 fam_dir->version = 1;
47337 fam_dir->req = calloc(1, sizeof(FAMRequest));
47339 - if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47341 + if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47342 fam_dir->req, fam_dir)) {
47344 - log_error_write(srv, __FILE__, __LINE__, "sbs",
47345 - "monitoring dir failed:",
47348 + log_error_write(srv, __FILE__, __LINE__, "sbs",
47349 + "monitoring dir failed:",
47351 FamErrlist[FAMErrno]);
47354 fam_dir_entry_free(fam_dir);
47357 @@ -570,7 +560,7 @@
47358 osize = sc->dirs->size;
47361 - sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47362 + sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47364 assert(sc->dirs->data == fam_dir);
47365 assert(osize == (sc->dirs->size - 1));
47366 @@ -578,9 +568,9 @@
47368 fam_dir = dir_node->data;
47372 /* bind the fam_fc to the stat() cache entry */
47376 sce->dir_version = fam_dir->version;
47377 sce->dir_ndx = dir_ndx;
47378 @@ -594,11 +584,11 @@
47382 - * remove stat() from cache which havn't been stat()ed for
47383 + * remove stat() from cache which havn't been stat()ed for
47384 * more than 10 seconds
47387 - * walk though the stat-cache, collect the ids which are too old
47389 + * walk though the stat-cache, collect the ids which are too old
47390 * and remove them in a second loop
47393 @@ -639,9 +629,9 @@
47394 sc->files = splaytree_splay(sc->files, ndx);
47399 if (node && (node->key == ndx)) {
47400 -#ifdef DEBUG_STAT_CACHE
47401 +#ifdef DEBUG_STAT_CACHE
47403 int osize = splaytree_size(sc->files);
47404 stat_cache_entry *sce = node->data;
47405 @@ -649,7 +639,7 @@
47406 stat_cache_entry_free(node->data);
47407 sc->files = splaytree_delete(sc->files, ndx);
47409 -#ifdef DEBUG_STAT_CACHE
47410 +#ifdef DEBUG_STAT_CACHE
47411 for (j = 0; j < ctrl.used; j++) {
47412 if (ctrl.ptr[j] == ndx) {
47413 ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
47414 --- ../lighttpd-1.4.11/src/stream.c 2005-09-23 21:50:15.000000000 +0300
47415 +++ lighttpd-1.4.12/src/stream.c 2006-07-11 22:07:53.000000000 +0300
47417 #include <sys/types.h>
47418 #include <sys/stat.h>
47420 -#include <unistd.h>
47423 #include "stream.h"
47427 #include "sys-mmap.h"
47428 +#include "sys-files.h"
47431 # define O_BINARY 0
47432 @@ -19,39 +19,39 @@
47436 -#elif defined __WIN32
47437 +#elif defined _WIN32
47445 if (-1 == stat(fn->ptr, &st)) {
47450 f->size = st.st_size;
47453 if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
47458 f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
47464 if (MAP_FAILED == f->start) {
47468 -#elif defined __WIN32
47469 - fh = CreateFile(fn->ptr,
47474 - FILE_ATTRIBUTE_READONLY,
47475 +#elif defined _WIN32
47476 + fh = CreateFile(fn->ptr,
47481 + FILE_ATTRIBUTE_READONLY,
47484 if (!fh) return -1;
47489 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
47490 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
47491 FORMAT_MESSAGE_FROM_SYSTEM,
47500 p = MapViewOfFile(mh,
47507 -# error no mmap found
47508 +# error no mmap found
47515 --- ../lighttpd-1.4.11/src/sys-files.h 1970-01-01 03:00:00.000000000 +0300
47516 +++ lighttpd-1.4.12/src/sys-files.h 2006-07-11 22:07:53.000000000 +0300
47518 +#ifndef _SYS_FILES_H_
47519 +#define _SYS_FILES_H_
47521 +#define DIR_SEPERATOR_UNIX '/'
47522 +#define DIR_SEPERATOR_WIN '\\'
47525 +#include <windows.h>
47526 +#include <io.h> /* open */
47527 +#include <direct.h> /* chdir */
47529 +#include "buffer.h"
47531 +#define DIR_SEPERATOR DIR_SEPERATOR_WIN
47533 +#define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
47535 +#define S_ISDIR(mode) __S_ISTYPE((mode), _S_IFDIR)
47536 +#define S_ISCHR(mode) __S_ISTYPE((mode), _S_IFCHR)
47537 +#define S_ISBLK(mode) __S_ISTYPE((mode), _S_IFBLK)
47538 +#define S_ISREG(mode) __S_ISTYPE((mode), _S_IFREG)
47539 +/* we don't support symlinks */
47540 +#define S_ISLNK(mode) 0
47542 +#define lstat stat
47543 +#define mkstemp mktemp
47544 +#define mkdir(x, y) mkdir(x)
47547 + const char *d_name;
47552 + WIN32_FIND_DATA finddata;
47553 + struct dirent dent;
47556 +DIR *opendir(const char *dn);
47557 +struct dirent *readdir(DIR *d);
47558 +void closedir(DIR *d);
47560 +buffer *filename_unix2local(buffer *b);
47561 +buffer *pathname_unix2local(buffer *b);
47564 +#include <unistd.h>
47565 +#include <dirent.h>
47567 +#define DIR_SEPERATOR DIR_SEPERATOR_UNIX
47569 +#define filename_unix2local(x) (x)
47570 +#define pathname_unix2local(x) (x)
47573 +#define PATHNAME_APPEND_SLASH(x) \
47574 + if (x->used > 1 && x->ptr[x->used - 2] != DIR_SEPERATOR) { \
47575 + char sl[2] = { DIR_SEPERATOR, 0 }; \
47576 + BUFFER_APPEND_STRING_CONST(x, sl); \
47579 +#ifndef O_LARGEFILE
47580 +# define O_LARGEFILE 0
47585 --- ../lighttpd-1.4.11/src/sys-mmap.h 2005-08-11 01:26:34.000000000 +0300
47586 +++ lighttpd-1.4.12/src/sys-mmap.h 2006-07-11 22:07:52.000000000 +0300
47588 #ifndef WIN32_MMAP_H
47589 #define WIN32_MMAP_H
47594 #define MAP_FAILED -1
47595 #define PROT_SHARED 0
47596 --- ../lighttpd-1.4.11/src/sys-process.h 1970-01-01 03:00:00.000000000 +0300
47597 +++ lighttpd-1.4.12/src/sys-process.h 2006-07-15 22:43:21.000000000 +0300
47599 +#ifndef _SYS_PROCESS_H_
47600 +#define _SYS_PROCESS_H_
47603 +#include <process.h>
47605 +/* win32 has no fork() */
47606 +#define kill(x, y)
47607 +#define getpid() 0
47610 +#include <sys/wait.h>
47611 +#include <unistd.h>
47616 --- ../lighttpd-1.4.11/src/sys-socket.h 2005-08-11 01:26:39.000000000 +0300
47617 +++ lighttpd-1.4.12/src/sys-socket.h 2006-07-15 22:43:21.000000000 +0300
47619 #ifndef WIN32_SOCKET_H
47620 #define WIN32_SOCKET_H
47625 #include <winsock2.h>
47627 #define ECONNRESET WSAECONNRESET
47628 #define EINPROGRESS WSAEINPROGRESS
47629 #define EALREADY WSAEALREADY
47630 +#define ENOTCONN WSAENOTCONN
47631 +#define EWOULDBLOCK WSAEWOULDBLOCK
47632 #define ioctl ioctlsocket
47633 #define hstrerror(x) ""
47634 +#define STDIN_FILENO 0
47635 +#define STDOUT_FILENO 1
47636 +#define STDERR_FILENO 2
47637 +#define ssize_t int
47639 +int inet_aton(const char *cp, struct in_addr *inp);
47640 +#define HAVE_INET_ADDR
47641 +#undef HAVE_INET_ATON
47644 #include <sys/socket.h>
47645 #include <sys/ioctl.h>
47647 #include <sys/un.h>
47648 #include <arpa/inet.h>
47651 +#define SUN_LEN(su) \
47652 + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
47660 + struct sockaddr_in6 ipv6;
47662 + struct sockaddr_in ipv4;
47663 +#ifdef HAVE_SYS_UN_H
47664 + struct sockaddr_un un;
47666 + struct sockaddr plain;
47670 --- ../lighttpd-1.4.11/src/sys-strings.h 1970-01-01 03:00:00.000000000 +0300
47671 +++ lighttpd-1.4.12/src/sys-strings.h 2006-07-11 22:07:51.000000000 +0300
47673 +#ifndef _SYS_STRINGS_H_
47674 +#define _SYS_STRINGS_H_
47677 +#define strcasecmp stricmp
47678 +#define strncasecmp strnicmp
47679 +#define strtoll(p, e, b) _strtoi64(p, e, b)
47684 --- ../lighttpd-1.4.11/tests/LightyTest.pm 2006-01-14 20:32:31.000000000 +0200
47685 +++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-11 22:07:53.000000000 +0300
47686 @@ -87,14 +87,14 @@
47687 # pre-process configfile if necessary
47690 - unlink($self->{TESTDIR}."/tmp/cfg.file");
47691 - system("cat ".$self->{SRCDIR}."/".$self->{CONFIGFILE}.' | perl -pe "s#\@SRCDIR\@#'.$self->{BASEDIR}.'/tests/#" > '.$self->{TESTDIR}.'/tmp/cfg.file');
47692 + $ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
47693 + $ENV{'PORT'} = $self->{PORT};
47695 unlink($self->{LIGHTTPD_PIDFILE});
47697 - system($self->{LIGHTTPD_PATH}." -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH});
47698 + system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH});
47700 - 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}." &");
47701 + 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}." &");
47704 select(undef, undef, undef, 0.1);
47705 @@ -184,7 +184,7 @@
47706 (my $h = $1) =~ tr/[A-Z]/[a-z]/;
47708 if (defined $resp_hdr{$h}) {
47709 - diag(sprintf("header %s is duplicated: %s and %s\n",
47710 + diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
47711 $h, $resp_hdr{$h}, $2));
47713 $resp_hdr{$h} = $2;
47714 @@ -196,6 +196,9 @@
47718 + $t->{etag} = $resp_hdr{'etag'};
47719 + $t->{date} = $resp_hdr{'date'};
47722 if (defined $resp_hdr{"content-length"}) {
47723 $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
47724 --- ../lighttpd-1.4.11/tests/Makefile.am 2005-09-16 15:48:40.000000000 +0300
47725 +++ lighttpd-1.4.12/tests/Makefile.am 2006-07-15 22:43:22.000000000 +0300
47726 @@ -39,10 +39,18 @@
47741 + proxy-backend-1.conf \
47742 + proxy-backend-2.conf
47745 TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
47746 --- ../lighttpd-1.4.11/tests/bug-06.conf 2005-08-27 17:44:19.000000000 +0300
47747 +++ lighttpd-1.4.12/tests/bug-06.conf 2006-07-11 22:07:53.000000000 +0300
47749 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47750 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47751 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47752 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47754 ## bind to port (default: 80)
47758 ## bind to localhost (default: all interfaces)
47759 server.bind = "localhost"
47760 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47761 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47762 server.name = "www.example.org"
47763 server.tag = "Apache 1.3.29"
47766 ######################## MODULE CONFIG ############################
47769 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47770 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47772 mimetype.assign = ( ".png" => "image/png",
47773 ".jpg" => "image/jpeg",
47775 ".c" => "text/plain",
47776 ".conf" => "text/plain" )
47778 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47779 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47780 compress.filetype = ("text/plain", "text/html")
47782 setenv.add-environment = ( "TRAC_ENV" => "foo")
47784 "host" => "127.0.0.1",
47786 # "mode" => "authorizer",
47787 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47788 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47792 @@ -106,7 +106,7 @@
47793 ssl.pemfile = "server.pem"
47795 auth.backend = "plain"
47796 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47797 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47798 auth.backend.plain.groupfile = "lighttpd.group"
47800 auth.backend.ldap.hostname = "localhost"
47801 @@ -149,15 +149,15 @@
47802 status.config-url = "/server-config"
47804 simple-vhost.document-root = "pages"
47805 -simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
47806 +simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
47807 simple-vhost.default-host = "www.example.org"
47809 $HTTP["host"] == "vvv.example.org" {
47810 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47811 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47814 $HTTP["host"] == "zzz.example.org" {
47815 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47816 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47817 server.name = "zzz.example.org"
47820 --- ../lighttpd-1.4.11/tests/bug-12.conf 2005-08-27 17:44:19.000000000 +0300
47821 +++ lighttpd-1.4.12/tests/bug-12.conf 2006-07-11 22:07:53.000000000 +0300
47823 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47824 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47825 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47826 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47828 ## bind to port (default: 80)
47832 ## bind to localhost (default: all interfaces)
47833 server.bind = "localhost"
47834 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47835 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47836 server.name = "www.example.org"
47837 server.tag = "Apache 1.3.29"
47840 ######################## MODULE CONFIG ############################
47843 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47844 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47846 mimetype.assign = ( ".png" => "image/png",
47847 ".jpg" => "image/jpeg",
47849 ".c" => "text/plain",
47850 ".conf" => "text/plain" )
47852 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47853 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47854 compress.filetype = ("text/plain", "text/html")
47856 setenv.add-environment = ( "TRAC_ENV" => "foo")
47858 "host" => "127.0.0.1",
47860 # "mode" => "authorizer",
47861 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47862 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47866 @@ -108,7 +108,7 @@
47867 ssl.pemfile = "server.pem"
47869 auth.backend = "plain"
47870 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47871 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47872 auth.backend.plain.groupfile = "lighttpd.group"
47874 auth.backend.ldap.hostname = "localhost"
47875 @@ -151,15 +151,15 @@
47876 status.config-url = "/server-config"
47878 simple-vhost.document-root = "pages"
47879 -simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
47880 +simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
47881 simple-vhost.default-host = "www.example.org"
47883 $HTTP["host"] == "vvv.example.org" {
47884 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47885 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47888 $HTTP["host"] == "zzz.example.org" {
47889 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47890 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47891 server.name = "zzz.example.org"
47894 --- ../lighttpd-1.4.11/tests/cachable.t 1970-01-01 03:00:00.000000000 +0300
47895 +++ lighttpd-1.4.12/tests/cachable.t 2006-07-11 22:07:53.000000000 +0300
47897 +#!/usr/bin/env perl
47899 + # add current source dir to the include-path
47900 + # we need this for make distcheck
47901 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
47902 + unshift @INC, $srcdir;
47907 +use Test::More tests => 12;
47910 +my $tf = LightyTest->new();
47913 +$tf->{CONFIGFILE} = 'lighttpd.conf';
47915 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
47917 +## check if If-Modified-Since, If-None-Match works
47919 +$t->{REQUEST} = ( <<EOF
47921 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
47924 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47925 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
47927 +$t->{REQUEST} = ( <<EOF
47929 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47932 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47933 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
47935 +my $now = $t->{date};
47937 +$t->{REQUEST} = ( <<EOF
47939 +If-Modified-Since: $now
47942 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47943 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
47945 +$t->{REQUEST} = ( <<EOF
47947 +If-Modified-Since: $now; foo
47950 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47951 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
47953 +$t->{REQUEST} = ( <<EOF
47955 +If-None-Match: foo
47958 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47959 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47961 +my $etag = $t->{etag};
47963 +$t->{REQUEST} = ( <<EOF
47965 +If-None-Match: $etag
47968 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47969 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47971 +$t->{REQUEST} = ( <<EOF
47973 +If-None-Match: $etag
47974 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47977 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47978 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
47980 +$t->{REQUEST} = ( <<EOF
47982 +If-None-Match: $etag
47983 +If-Modified-Since: $now; foo
47986 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47987 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
47989 +$t->{REQUEST} = ( <<EOF
47991 +If-None-Match: Foo
47992 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47995 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47996 +ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
47998 +$t->{REQUEST} = ( <<EOF
48000 +If-None-Match: $etag
48001 +If-Modified-Since: $now foo
48004 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
48005 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
48007 +ok($tf->stop_proc == 0, "Stopping lighttpd");
48009 --- ../lighttpd-1.4.11/tests/condition.conf 2005-08-27 17:44:19.000000000 +0300
48010 +++ lighttpd-1.4.12/tests/condition.conf 2006-07-11 22:07:53.000000000 +0300
48012 debug.log-request-handling = "enable"
48013 debug.log-condition-handling = "enable"
48015 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48016 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48017 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48018 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48020 ## bind to port (default: 80)
48023 ## bind to localhost (default: all interfaces)
48024 server.bind = "localhost"
48025 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48026 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48027 server.name = "www.example.org"
48028 server.tag = "Apache 1.3.29"
48030 @@ -22,25 +22,25 @@
48031 ######################## MODULE CONFIG ############################
48034 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48035 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48037 mimetype.assign = ( ".html" => "text/html" )
48039 url.redirect = ("^" => "/default")
48041 $HTTP["host"] == "www.example.org" {
48042 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48043 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48044 server.name = "www.example.org"
48045 url.redirect = ("^" => "/match_1")
48047 else $HTTP["host"] == "test1.example.org" {
48048 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48049 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48050 server.name = "test1.example.org"
48051 url.redirect = ("^" => "/match_2")
48054 else $HTTP["host"] == "test2.example.org" {
48055 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48056 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48057 server.name = "test2.example.org"
48058 url.redirect = ("^" => "/match_3")
48063 else $HTTP["host"] == "test3.example.org" {
48064 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48065 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48066 server.name = "test3.example.org"
48067 url.redirect = ("^" => "/match_4")
48069 --- ../lighttpd-1.4.11/tests/core-keepalive.t 2005-11-17 15:54:19.000000000 +0200
48070 +++ lighttpd-1.4.12/tests/core-keepalive.t 2006-07-11 22:07:53.000000000 +0300
48073 GET /12345.txt HTTP/1.0
48074 Host: 123.example.org
48075 -Connection: keep-alive
48079 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48080 --- ../lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries 2006-03-09 19:21:49.000000000 +0200
48081 +++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries 2006-07-15 22:43:22.000000000 +0300
48085 uuid="152afb58-edef-0310-8abb-c4023f1b3aa9"
48086 - revision="1040"/>
48087 + repos="svn://svn.lighttpd.net/lighttpd"
48088 + revision="1173"/>
48090 --- ../lighttpd-1.4.11/tests/fastcgi-10.conf 2005-08-31 23:36:34.000000000 +0300
48091 +++ lighttpd-1.4.12/tests/fastcgi-10.conf 2006-07-11 22:07:53.000000000 +0300
48093 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48094 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48095 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48096 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48098 ## bind to port (default: 80)
48101 ## bind to localhost (default: all interfaces)
48102 server.bind = "localhost"
48103 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48104 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48105 server.name = "www.example.org"
48106 server.tag = "Apache 1.3.29"
48109 ######################## MODULE CONFIG ############################
48112 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48113 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48115 mimetype.assign = ( ".png" => "image/png",
48116 ".jpg" => "image/jpeg",
48118 ".c" => "text/plain",
48119 ".conf" => "text/plain" )
48121 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48122 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48123 compress.filetype = ("text/plain", "text/html")
48127 ssl.pemfile = "server.pem"
48129 auth.backend = "plain"
48130 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48131 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48132 auth.backend.plain.groupfile = "lighttpd.group"
48134 auth.backend.ldap.hostname = "localhost"
48135 @@ -128,11 +128,11 @@
48136 status.config-url = "/server-config"
48138 $HTTP["host"] == "vvv.example.org" {
48139 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48140 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48143 $HTTP["host"] == "zzz.example.org" {
48144 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48145 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48146 server.name = "zzz.example.org"
48149 --- ../lighttpd-1.4.11/tests/fastcgi-13.conf 2006-01-03 12:38:17.000000000 +0200
48150 +++ lighttpd-1.4.12/tests/fastcgi-13.conf 2006-07-11 22:07:53.000000000 +0300
48152 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48153 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48154 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48155 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48157 debug.log-request-header = "enable"
48158 debug.log-response-header = "enable"
48161 ## bind to localhost (default: all interfaces)
48162 server.bind = "localhost"
48163 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48164 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48165 server.name = "www.example.org"
48166 server.tag = "Apache 1.3.29"
48169 ######################## MODULE CONFIG ############################
48172 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48173 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48175 mimetype.assign = ( ".png" => "image/png",
48176 ".jpg" => "image/jpeg",
48178 ".c" => "text/plain",
48179 ".conf" => "text/plain" )
48181 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48182 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48183 compress.filetype = ("text/plain", "text/html")
48186 @@ -102,7 +102,7 @@
48187 ssl.pemfile = "server.pem"
48189 auth.backend = "plain"
48190 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48191 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48192 auth.backend.plain.groupfile = "lighttpd.group"
48194 auth.backend.ldap.hostname = "localhost"
48195 @@ -145,11 +145,11 @@
48196 status.config-url = "/server-config"
48198 $HTTP["host"] == "vvv.example.org" {
48199 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48200 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48203 $HTTP["host"] == "zzz.example.org" {
48204 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48205 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48206 server.name = "zzz.example.org"
48209 --- ../lighttpd-1.4.11/tests/fastcgi-auth.conf 2005-08-27 17:44:19.000000000 +0300
48210 +++ lighttpd-1.4.12/tests/fastcgi-auth.conf 2006-07-11 22:07:53.000000000 +0300
48212 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48213 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48214 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48215 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48217 debug.log-request-header = "enable"
48218 debug.log-response-header = "enable"
48221 ## bind to localhost (default: all interfaces)
48222 server.bind = "localhost"
48223 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48224 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48225 server.name = "www.example.org"
48226 server.tag = "Apache 1.3.29"
48229 ######################## MODULE CONFIG ############################
48232 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48233 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48235 mimetype.assign = ( ".png" => "image/png",
48236 ".jpg" => "image/jpeg",
48238 ".c" => "text/plain",
48239 ".conf" => "text/plain" )
48241 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48242 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48243 compress.filetype = ("text/plain", "text/html")
48248 "host" => "127.0.0.1",
48250 - "bin-path" => "@SRCDIR@/fcgi-auth",
48251 + "bin-path" => env.SRCDIR + "/fcgi-auth",
48252 "mode" => "authorizer",
48253 - "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
48254 + "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
48258 @@ -106,7 +106,7 @@
48259 ssl.pemfile = "server.pem"
48261 auth.backend = "plain"
48262 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48263 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48264 auth.backend.plain.groupfile = "lighttpd.group"
48266 auth.backend.ldap.hostname = "localhost"
48267 @@ -149,11 +149,11 @@
48268 status.config-url = "/server-config"
48270 $HTTP["host"] == "vvv.example.org" {
48271 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48272 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48275 $HTTP["host"] == "zzz.example.org" {
48276 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48277 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48278 server.name = "zzz.example.org"
48281 --- ../lighttpd-1.4.11/tests/fastcgi-responder.conf 2005-08-27 17:44:19.000000000 +0300
48282 +++ lighttpd-1.4.12/tests/fastcgi-responder.conf 2006-07-11 22:07:53.000000000 +0300
48284 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48285 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48286 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48287 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48289 #debug.log-request-header = "enable"
48290 #debug.log-response-header = "enable"
48293 ## bind to localhost (default: all interfaces)
48294 server.bind = "localhost"
48295 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48296 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48297 server.name = "www.example.org"
48298 server.tag = "Apache 1.3.29"
48301 ######################## MODULE CONFIG ############################
48304 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48305 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48307 mimetype.assign = ( ".png" => "image/png",
48308 ".jpg" => "image/jpeg",
48310 ".c" => "text/plain",
48311 ".conf" => "text/plain" )
48313 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48314 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48315 compress.filetype = ("text/plain", "text/html")
48318 @@ -90,10 +90,11 @@
48320 "host" => "127.0.0.1",
48322 - "bin-path" => "@SRCDIR@/fcgi-responder",
48323 + "bin-path" => env.SRCDIR + "/fcgi-responder",
48324 "check-local" => "disable",
48327 + "min-procs" => 1,
48328 + "allow-x-send-file" => "enable",
48332 @@ -109,7 +110,7 @@
48333 ssl.pemfile = "server.pem"
48335 auth.backend = "plain"
48336 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48337 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48338 auth.backend.plain.groupfile = "lighttpd.group"
48340 auth.backend.ldap.hostname = "localhost"
48341 @@ -152,11 +153,11 @@
48342 status.config-url = "/server-config"
48344 $HTTP["host"] == "vvv.example.org" {
48345 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48346 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48349 $HTTP["host"] == "zzz.example.org" {
48350 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48351 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48352 server.name = "zzz.example.org"
48355 --- ../lighttpd-1.4.11/tests/fcgi-responder.c 2005-08-11 01:26:55.000000000 +0300
48356 +++ lighttpd-1.4.12/tests/fcgi-responder.c 2006-07-11 22:07:53.000000000 +0300
48359 int num_requests = 2;
48361 - while (num_requests > 0 &&
48362 - FCGI_Accept() >= 0) {
48365 - if (NULL != (p = getenv("QUERY_STRING"))) {
48366 + while (num_requests > 0 && FCGI_Accept() >= 0) {
48368 + char* doc_root = NULL;
48369 + char fname[4096];
48370 + char* pfname = (char *)fname;
48372 + doc_root = getenv("DOCUMENT_ROOT");
48373 + p = getenv("QUERY_STRING");
48375 + if (NULL != p && NULL != doc_root) {
48376 + snprintf(pfname, sizeof(fname), "%s/phpinfo.php", doc_root);
48377 if (0 == strcmp(p, "lf")) {
48378 printf("Status: 200 OK\n\n");
48379 } else if (0 == strcmp(p, "crlf")) {
48381 printf("Status: 200 OK\r\n");
48384 + } else if (0 == strcmp(p,"x-lighttpd-send-file")) {
48385 + printf("Status: 200 OK\r\n");
48386 + printf("X-LIGHTTPD-send-file: %s\r\n", pfname);
48388 + } else if (0 == strcmp(p,"xsendfile")) {
48389 + printf("Status: 200 OK\r\n");
48390 + printf("X-Sendfile: %s\r\n", pfname);
48392 + } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
48393 + printf("Status: 200 OK\r\n");
48394 + printf("X-SeNdFiLe: %s\r\n", pfname);
48396 } else if (0 == strcmp(p, "die-at-end")) {
48397 printf("Status: 200 OK\r\n\r\n");
48399 --- ../lighttpd-1.4.11/tests/lighttpd.conf 2006-03-09 15:26:58.000000000 +0200
48400 +++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-11 22:07:53.000000000 +0300
48402 -debug.log-request-handling = "enable"
48403 -debug.log-condition-handling = "enable"
48404 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48405 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48406 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48407 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48408 +server.tag = "Apache 1.3.29"
48410 ## 64 Mbyte ... nice limit
48411 server.max-request-size = 65000
48413 -## bind to port (default: 80)
48414 -server.port = 2048
48415 +include "default.conf"
48417 -## bind to localhost (default: all interfaces)
48418 -server.bind = "localhost"
48419 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48420 -server.name = "www.example.org"
48421 -server.tag = "Apache 1.3.29"
48423 -server.dir-listing = "enable"
48425 -#server.event-handler = "linux-sysepoll"
48426 -#server.event-handler = "linux-rtsig"
48428 -#server.modules.path = ""
48429 -server.modules = (
48432 - "mod_secdownload",
48438 - "mod_simple_vhost",
48441 -# "mod_localizer",
48447 - "mod_accesslog" )
48449 -server.indexfiles = ( "index.php", "index.html",
48450 - "index.htm", "default.htm" )
48453 -######################## MODULE CONFIG ############################
48455 -ssi.extension = ( ".shtml" )
48457 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48459 -mimetype.assign = ( ".png" => "image/png",
48460 - ".jpg" => "image/jpeg",
48461 - ".jpeg" => "image/jpeg",
48462 - ".gif" => "image/gif",
48463 - ".html" => "text/html",
48464 - ".htm" => "text/html",
48465 - ".pdf" => "application/pdf",
48466 - ".swf" => "application/x-shockwave-flash",
48467 - ".spl" => "application/futuresplash",
48468 - ".txt" => "text/plain",
48469 - ".tar.gz" => "application/x-tgz",
48470 - ".tgz" => "application/x-tgz",
48471 - ".gz" => "application/x-gzip",
48472 - ".c" => "text/plain",
48473 - ".conf" => "text/plain" )
48474 +setenv.add-request-header = ( "FOO" => "foo")
48475 +setenv.add-response-header = ( "BAR" => "foo")
48477 $HTTP["host"] == "cache.example.org" {
48478 - compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48479 + compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48481 -compress.filetype = ("text/plain", "text/html")
48483 -setenv.add-environment = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
48484 -setenv.add-request-header = ( "FOO" => "foo")
48485 -setenv.add-response-header = ( "BAR" => "foo")
48487 $HTTP["url"] =~ "\.pdf$" {
48488 server.range-requests = "disable"
48489 @@ -85,76 +23,31 @@
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 -userdir.include-user = ( "jan" )
48499 -userdir.path = "/"
48501 -ssl.engine = "disable"
48502 -ssl.pemfile = "server.pem"
48504 $HTTP["host"] == "auth-htpasswd.example.org" {
48505 auth.backend = "htpasswd"
48508 -auth.backend = "plain"
48509 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48511 -auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
48514 -auth.require = ( "/server-status" =>
48516 - "method" => "digest",
48517 - "realm" => "download archiv",
48518 - "require" => "group=www|user=jan|host=192.168.2.10"
48520 - "/server-config" =>
48522 - "method" => "basic",
48523 - "realm" => "download archiv",
48524 - "require" => "valid-user"
48528 -url.access-deny = ( "~", ".inc")
48530 -url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
48531 - "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48533 -expire.url = ( "/expire/access" => "access 2 hours",
48534 - "/expire/modification" => "access plus 1 seconds 2 minutes")
48536 -#cache.cache-dir = "/home/weigon/wwwroot/cache/"
48538 -#### status module
48539 -status.status-url = "/server-status"
48540 -status.config-url = "/server-config"
48542 $HTTP["host"] == "vvv.example.org" {
48543 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48544 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48545 secdownload.secret = "verysecret"
48546 - secdownload.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48547 + secdownload.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48548 secdownload.uri-prefix = "/sec/"
48549 secdownload.timeout = 120
48552 $HTTP["host"] == "zzz.example.org" {
48553 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48554 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48555 server.name = "zzz.example.org"
48558 $HTTP["host"] == "no-simple.example.org" {
48559 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
48560 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/123.example.org/pages/"
48561 server.name = "zzz.example.org"
48564 $HTTP["host"] !~ "(no-simple\.example\.org)" {
48565 simple-vhost.document-root = "pages"
48566 - simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
48567 + simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
48568 simple-vhost.default-host = "www.example.org"
48571 --- ../lighttpd-1.4.11/tests/lowercase.conf 1970-01-01 03:00:00.000000000 +0300
48572 +++ lighttpd-1.4.12/tests/lowercase.conf 2006-07-11 22:07:53.000000000 +0300
48574 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48575 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48577 +## bind to port (default: 80)
48578 +server.port = 2048
48580 +## bind to localhost (default: all interfaces)
48581 +server.bind = "localhost"
48582 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48584 +server.force-lowercase-filenames = "enable"
48586 +server.dir-listing = "enable"
48588 +server.modules = (
48591 + "mod_secdownload",
48600 +server.indexfiles = ( "index.php", "index.html",
48601 + "index.htm", "default.htm" )
48604 +######################## MODULE CONFIG ############################
48606 +mimetype.assign = ( ".png" => "image/png",
48607 + ".jpg" => "image/jpeg",
48608 + ".jpeg" => "image/jpeg",
48609 + ".gif" => "image/gif",
48610 + ".html" => "text/html",
48611 + ".htm" => "text/html",
48612 + ".pdf" => "application/pdf",
48613 + ".swf" => "application/x-shockwave-flash",
48614 + ".spl" => "application/futuresplash",
48615 + ".txt" => "text/plain",
48616 + ".tar.gz" => "application/x-tgz",
48617 + ".tgz" => "application/x-tgz",
48618 + ".gz" => "application/x-gzip",
48619 + ".c" => "text/plain",
48620 + ".conf" => "text/plain" )
48623 +fastcgi.server = ( ".php" => ( ( "host" => "127.0.0.1", "port" => 1026, "broken-scriptfilename" => "enable" ) ),
48624 + "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48628 +cgi.assign = ( ".pl" => "/usr/bin/perl",
48629 + ".cgi" => "/usr/bin/perl",
48630 + ".py" => "/usr/bin/python" )
48632 +auth.backend = "plain"
48633 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48635 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
48637 +$HTTP["host"] == "lowercase-auth" {
48638 + auth.require = ( "/image.jpg" =>
48640 + "method" => "digest",
48641 + "realm" => "download archiv",
48642 + "require" => "valid-user"
48647 +$HTTP["host"] == "lowercase-deny" {
48648 + url.access-deny = ( ".jpg")
48651 +$HTTP["host"] == "lowercase-exclude" {
48652 + static-file.exclude-extensions = ( ".jpg" )
48654 --- ../lighttpd-1.4.11/tests/lowercase.t 1970-01-01 03:00:00.000000000 +0300
48655 +++ lighttpd-1.4.12/tests/lowercase.t 2006-07-11 22:07:53.000000000 +0300
48657 +#!/usr/bin/env perl
48659 + # add current source dir to the include-path
48660 + # we need this for make distcheck
48661 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
48662 + unshift @INC, $srcdir;
48667 +use Test::More tests => 10;
48670 +my $tf = LightyTest->new();
48673 +$tf->{CONFIGFILE} = 'lowercase.conf';
48675 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
48677 +## check if lower-casing works
48679 +$t->{REQUEST} = ( <<EOF
48680 +GET /image.JPG HTTP/1.0
48683 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48684 +ok($tf->handle_http($t) == 0, 'uppercase access');
48686 +$t->{REQUEST} = ( <<EOF
48687 +GET /image.jpg HTTP/1.0
48690 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48691 +ok($tf->handle_http($t) == 0, 'lowercase access');
48693 +## check that mod-auth works
48695 +$t->{REQUEST} = ( <<EOF
48696 +GET /image.JPG HTTP/1.0
48697 +Host: lowercase-auth
48700 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48701 +ok($tf->handle_http($t) == 0, 'uppercase access');
48703 +$t->{REQUEST} = ( <<EOF
48704 +GET /image.jpg HTTP/1.0
48705 +Host: lowercase-auth
48708 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48709 +ok($tf->handle_http($t) == 0, 'lowercase access');
48712 +## check that mod-staticfile exclude works
48713 +$t->{REQUEST} = ( <<EOF
48714 +GET /image.JPG HTTP/1.0
48715 +Host: lowercase-exclude
48718 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48719 +ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
48721 +$t->{REQUEST} = ( <<EOF
48722 +GET /image.jpg HTTP/1.0
48723 +Host: lowercase-exclude
48726 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48727 +ok($tf->handle_http($t) == 0, 'lowercase access');
48730 +## check that mod-access exclude works
48731 +$t->{REQUEST} = ( <<EOF
48732 +GET /image.JPG HTTP/1.0
48733 +Host: lowercase-deny
48736 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48737 +ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
48739 +$t->{REQUEST} = ( <<EOF
48740 +GET /image.jpg HTTP/1.0
48741 +Host: lowercase-deny
48744 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48745 +ok($tf->handle_http($t) == 0, 'lowercase access');
48749 +ok($tf->stop_proc == 0, "Stopping lighttpd");
48751 --- ../lighttpd-1.4.11/tests/mod-fastcgi.t 2006-03-09 15:30:45.000000000 +0200
48752 +++ lighttpd-1.4.12/tests/mod-fastcgi.t 2006-07-11 22:07:53.000000000 +0300
48757 -use Test::More tests => 47;
48758 +use Test::More tests => 49;
48761 my $tf = LightyTest->new();
48766 - skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
48767 + skip "no PHP running on port 1026", 29 unless $tf->listening_on(1026);
48769 ok($tf->start_proc == 0, "Starting lighttpd") or die();
48771 @@ -223,7 +223,7 @@
48775 - skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48776 + skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48777 $tf->{CONFIGFILE} = 'fastcgi-13.conf';
48778 ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
48779 $t->{REQUEST} = ( <<EOF
48780 @@ -285,6 +285,34 @@
48781 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
48782 ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
48784 + # X-LIGHTTPD-send-file
48785 + $t->{REQUEST} = ( <<EOF
48786 +GET /index.fcgi?x-lighttpd-send-file HTTP/1.0
48787 +Host: www.example.org
48790 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48792 + ok($tf->handle_http($t) == 0, 'X-LIGHTTPD-send-file');
48794 + $t->{REQUEST} = ( <<EOF
48795 +GET /index.fcgi?xsendfile HTTP/1.0
48796 +Host: www.example.org
48799 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48801 + ok($tf->handle_http($t) == 0, 'X-Sendfile');
48803 + $t->{REQUEST} = ( <<EOF
48804 +GET /index.fcgi?xsendfile-mixed-case HTTP/1.0
48805 +Host: www.example.org
48808 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48810 + ok($tf->handle_http($t) == 0, 'X-SeNdFiLe in mixed case');
48812 $t->{REQUEST} = ( <<EOF
48813 GET /index.fcgi?die-at-end HTTP/1.0
48814 Host: www.example.org
48815 --- ../lighttpd-1.4.11/tests/mod-proxy.t 1970-01-01 03:00:00.000000000 +0300
48816 +++ lighttpd-1.4.12/tests/mod-proxy.t 2006-07-11 22:07:53.000000000 +0300
48818 +#!/usr/bin/env perl
48820 + # add current source dir to the include-path
48821 + # we need this for make distcheck
48822 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
48823 + unshift @INC, $srcdir;
48828 +use Test::More tests => 21;
48831 +my $tf_proxy = LightyTest->new();
48832 +my $tf_backend1 = LightyTest->new();
48833 +my $tf_backend2 = LightyTest->new();
48837 +## we need two procs
48838 +## 1. the real webserver
48839 +## 2. the proxy server
48841 +$tf_proxy->{PORT} = 2048;
48842 +$tf_proxy->{CONFIGFILE} = 'proxy.conf';
48843 +$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
48845 +$tf_backend1->{PORT} = 2050;
48846 +$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
48847 +$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
48849 +$tf_backend2->{PORT} = 2051;
48850 +$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
48851 +$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
48854 +ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
48856 +ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
48860 +$t->{REQUEST} = ( <<EOF
48861 +GET /index.html HTTP/1.0
48862 +Host: www.example.org
48865 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48866 +ok($tf_proxy->handle_http($t) == 0, 'valid request');
48868 +$t->{REQUEST} = ( <<EOF
48869 +GET /index.html HTTP/1.0
48870 +Host: www.example.org
48873 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'proxy-backend-1' } ];
48874 +ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
48876 +$t->{REQUEST} = ( <<EOF
48877 +GET /balance-rr/foo HTTP/1.0
48878 +Host: www.example.org
48881 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48882 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
48884 +$t->{REQUEST} = ( <<EOF
48885 +GET /balance-rr/foo HTTP/1.0
48886 +Host: www.example.org
48889 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48890 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
48892 +$t->{REQUEST} = ( <<EOF
48893 +GET /balance-fair/foo HTTP/1.0
48894 +Host: www.example.org
48897 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48898 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
48900 +## backend 2 starting
48901 +ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
48903 +$t->{REQUEST} = ( <<EOF
48904 +GET /balance-rr/foo HTTP/1.0
48905 +Host: www.example.org
48908 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48909 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
48911 +$t->{REQUEST} = ( <<EOF
48912 +GET /balance-rr/foo HTTP/1.0
48913 +Host: www.example.org
48916 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48917 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
48919 +$t->{REQUEST} = ( <<EOF
48920 +GET /balance-hash/foo HTTP/1.0
48921 +Host: www.example.org
48924 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48925 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
48927 +$t->{REQUEST} = ( <<EOF
48928 +GET /balance-hash/foo HTTP/1.0
48929 +Host: www.example.org
48932 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
48933 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
48935 +$t->{REQUEST} = ( <<EOF
48936 +GET /balance-hash/bar HTTP/1.0
48937 +Host: www.example.org
48940 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48941 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
48943 +$t->{REQUEST} = ( <<EOF
48944 +GET /balance-hash/bar HTTP/1.0
48945 +Host: www.example.org
48948 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48949 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
48951 +## backend 1 stopping, failover
48952 +ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
48954 +$t->{REQUEST} = ( <<EOF
48955 +GET /balance-hash/foo HTTP/1.0
48956 +Host: www.example.org
48959 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48960 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
48962 +$t->{REQUEST} = ( <<EOF
48963 +GET /balance-hash/bar HTTP/1.0
48964 +Host: www.example.org
48967 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48968 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
48970 +$t->{REQUEST} = ( <<EOF
48971 +GET /balance-rr/foo HTTP/1.0
48972 +Host: www.example.org
48975 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48976 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
48978 +$t->{REQUEST} = ( <<EOF
48979 +GET /balance-fair/foo HTTP/1.0
48980 +Host: www.example.org
48983 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
48984 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
48987 +ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
48989 +ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
48991 --- ../lighttpd-1.4.11/tests/proxy.conf 1970-01-01 03:00:00.000000000 +0300
48992 +++ lighttpd-1.4.12/tests/proxy.conf 2006-07-11 22:07:53.000000000 +0300
48994 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48995 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
48996 +server.tag = "proxy"
48998 +include "default.conf"
49000 +## 127.0.0.1 and 127.0.0.2 are the same host
49002 + "" => (( "host" => "127.0.0.1",
49003 + "port" => 2050 ),
49004 + ( "host" => "127.0.0.2",
49008 +$HTTP["url"] =~ "^/balance-rr/" {
49009 + proxy.balance = "round-robin"
49012 +$HTTP["url"] =~ "^/balance-hash/" {
49013 + proxy.balance = "hash"
49016 +$HTTP["url"] =~ "^/balance-fair/" {
49017 + proxy.balance = "fair"
49020 --- ../lighttpd-1.4.11/tests/var-include.conf 2005-08-27 17:44:19.000000000 +0300
49021 +++ lighttpd-1.4.12/tests/var-include.conf 2006-07-11 22:07:53.000000000 +0300
49023 debug.log-request-handling = "enable"
49024 debug.log-condition-handling = "enable"
49026 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49027 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
49028 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49029 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
49031 ## bind to port (default: 80)
49034 ## bind to localhost (default: all interfaces)
49035 server.bind = "localhost"
49036 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
49037 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
49038 server.name = "www.example.org"
49039 server.tag = "Apache 1.3.29"
49041 @@ -21,19 +21,19 @@
49042 ######################## MODULE CONFIG ############################
49045 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
49046 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
49048 mimetype.assign = ( ".html" => "text/html" )
49050 url.redirect = ("^" => "/default")
49052 $HTTP["host"] == "www.example.org" {
49053 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49054 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49055 server.name = "www.example.org"
49056 url.redirect = ("^" => "/redirect")
49058 $HTTP["host"] == "test.example.org" {
49059 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49060 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49061 server.name = "test.example.org"